fix:修复bug

This commit is contained in:
2026-03-09 09:06:33 +08:00
parent 40665dda67
commit e855ecde78
8 changed files with 267 additions and 136 deletions
+3 -1
View File
@@ -428,7 +428,9 @@
"name": "name:",
"nameRequired": "Name is required",
"setDefaultDays": "Set the default days and times this menu will be available",
"submit": "submit"
"submit": "submit",
"sort": "Sort position",
"sortPlaceholder": "Please enter sort number"
},
"message": {
"readAll": "One-click read",
+3 -1
View File
@@ -428,7 +428,9 @@
"name": "名称:",
"nameRequired": "名称不能为空",
"setDefaultDays": "设置此菜单可用的默认天数和时间",
"submit": "提交"
"submit": "提交",
"sort": "排序位置",
"sortPlaceholder": "请输入排序数字"
},
"message": {
"readAll": "一键已读",
+2 -2
View File
@@ -2,8 +2,8 @@
"name" : "CHEFLINK Merchant",
"appid" : "__UNI__BB8E3C9",
"description" : "美国外卖商户端",
"versionName" : "1.0.13",
"versionCode" : 113,
"versionName" : "1.0.16",
"versionCode" : 116,
"transformPx" : false,
/* 5+App */
"app-plus" : {
+40 -19
View File
@@ -130,28 +130,49 @@ onLoad((options) => {
getMenuListByMerchant()
})
const menuList = ref([])
// 默认分页配置(避免一次请求 1000 条)
const DEFAULT_PAGE_SIZE = 10;
const DEFAULT_PAGE_NUM = 1;
function getMenuListByMerchant() {
appMerchantMenuMenuListByMerchantPost({
params: {
pageSize: 1000,
pageNum: 1
}
}).then(res => {
menuList.value = res.rows
selectedMenu.value = menuList.value[0].id
const menuList = ref<any[]>([])
if (res.rows.length === 0) {
uni.showToast({
title: t('pages-user.food.add-food.tips'),
icon: 'none'
})
} else {
// 回显menu
formData.value.menu = menuList.value.find(item => item.id === formData.value.menuId)?.menuName
async function getMenuListByMerchant() {
const allRows: any[] = []
let pageNum = DEFAULT_PAGE_NUM
while (true) {
const res = await appMerchantMenuMenuListByMerchantPost({
params: {
pageSize: DEFAULT_PAGE_SIZE,
pageNum
}
})
const rows = res.rows || []
allRows.push(...rows)
if ((typeof res.total === 'number' && allRows.length >= res.total) || rows.length < DEFAULT_PAGE_SIZE) {
break
}
})
pageNum += 1
if (pageNum > 200) break
}
menuList.value = allRows
if (menuList.value.length === 0) {
uni.showToast({
title: t('pages-user.food.add-food.tips'),
icon: 'none'
})
return
}
selectedMenu.value = menuList.value[0]?.id
// 回显 menu
formData.value.menu = menuList.value.find(item => item.id === formData.value.menuId)?.menuName
}
// 获取菜品详情
+26
View File
@@ -17,6 +17,8 @@ const formData = reactive({
id: '',
menuName: '',
scheduleTimes: '',
// 排序
sort: 0,
isActive: true
})
// 提交表单
@@ -94,6 +96,8 @@ function getMenuDetail() {
formData.menuName = res.data.menuName
formData.scheduleTimes = res.data.scheduleTimes
formData.isActive = +res.data.delFlag === 1
// 排序
formData.sort = res.data.sort ?? 0
})
}
@@ -152,6 +156,28 @@ function deleteMenu() {
</view>
</view>
<!-- 排序 -->
<view class="mb-44rpx">
<text class="text-36rpx text-#333 font-500 mb-20rpx block">
{{ t('pages-user.menu.sort') }}
</text>
<view class="bg-#F6F6F6 rounded-16rpx h-98rpx px-24rpx flex items-center">
<wd-input
type="number"
:focus-when-clear="false"
:modelValue="formData.sort"
:placeholder="t('pages-user.menu.sortPlaceholder')"
clearable
confirm-type="done"
custom-class="!text-30rpx !bg-transparent flex-1"
no-border
placeholderStyle="font-size: 30rpx;color: #999;"
@update:modelValue="formData.sort = Number($event || 0)"
>
</wd-input>
</view>
</view>
<!-- 菜单激活状态 -->
<view class="form-section mb-60rpx">
<view class="flex items-center justify-between mb-20rpx">
@@ -15,6 +15,10 @@ const {t} = useI18n()
const message = useMessage();
// 默认分页配置(菜单相关接口仍然依赖)
const DEFAULT_PAGE_SIZE = 10;
const DEFAULT_PAGE_NUM = 1;
const props = defineProps<{
tabIndex: number | string
currentIndex: number | string
@@ -25,46 +29,76 @@ function changeMenu() {
emits('changeMenu')
}
watch(() => props.currentIndex, (newVal) => {
console.log('111', newVal, props.tabIndex)
if (+newVal === props.tabIndex && +props.tabIndex === 1) {
getMenuListByMerchant()
}
if (+newVal === props.tabIndex && +props.tabIndex === 2) {
getMenuListByMerchant()
} else if (+newVal === props.tabIndex && +props.tabIndex === 3) {
// 获取菜品列表
console.log('获取菜品列表')
getDishList()
}
}, {immediate: true})
const tabIndexNum = computed(() => +props.tabIndex)
const paging = ref(null)
const dataList = ref([])
const queryList = (pageNo, pageSize) => {
return new Promise((resolve, reject) => {
paging.value.complete([
{
title: '订单1'
watch(
() => props.currentIndex,
(newVal) => {
console.log('111', newVal, props.tabIndex)
if (+newVal === props.tabIndex) {
// 切换到当前tab,触发分页加载(pageNum会由z-paging自动递增)
paging.value?.reload()
}
},
{immediate: true},
)
// 分页数据源:tab1=菜单详情内dishList(本地分页)tab2=菜单列表(后端分页),tab3=菜品列表(后端分页)
function queryByTab(pageNum: number, pageSize: number) {
// tab1:菜单概览-菜单下菜品(本地分页)
if (tabIndexNum.value === 1) {
return new Promise<IResData<any>>(async (resolve) => {
await ensureMenuListLoaded()
await ensureMenuDetailLoaded()
const all = menuDishListData.value || []
const start = (pageNum - 1) * pageSize
resolve({
rows: all.slice(start, start + pageSize),
total: all.length,
} as any)
})
}
// tab2:周菜单管理-菜单列表(后端分页)
if (tabIndexNum.value === 2) {
return new Promise<IResData<any>>((resolve) => {
if (!userStore.isLogin) return resolve({rows: [], total: 0} as any)
appMerchantMenuMenuListByMerchantPost({
params: {
pageNum,
pageSize,
},
}).then((res: any) => {
resolve({
...(res as any),
rows: (res as any).rows || [],
total: (res as any).total || 0,
})
})
})
}
// tab3:菜品列表(后端分页)
return new Promise<IResData<any>>((resolve) => {
if (!userStore.isLogin) return resolve({rows: [], total: 0} as any)
appMerchantDishListPost({
params: {
pageNum,
pageSize,
},
{
title: '订单2'
},
{
title: '订单3'
},
]);
// @ts-ignore 后端 body 暂无筛选条件,这里传空对象
body: {},
}).then((res: any) => {
resolve({
...(res as any),
rows: (res as any).rows || [],
total: (res as any).total || 0,
})
})
})
}
// 加载状态
const loading = ref(true)
// 模拟数据加载
onMounted(() => {
loading.value = true
setTimeout(() => {
loading.value = false
}, 300)
})
const {paging, dataList, loading, queryList} = usePage<any>(queryByTab)
function navigateTo(url: string) {
uni.navigateTo({url})
@@ -72,76 +106,85 @@ function navigateTo(url: string) {
// 获取当前商户的菜单列表
const menuList = ref([])
const menuList = ref<any[]>([])
// 当前选中的菜单索引
const currentMenuIndex = ref(0)
// 当前选中的菜单数据
const currentMenu = computed(() => {
return menuList.value[currentMenuIndex.value]
return menuList.value[currentMenuIndex.value] || {}
})
function getMenuListByMerchant() {
async function ensureMenuListLoaded() {
// 仅tab1需要完整menuList用于头部展示 & indexChangeMenu定位
if (tabIndexNum.value !== 1) return
if (!userStore.isLogin) return
appMerchantMenuMenuListByMerchantPost({
params: {
pageSize: 1000,
pageNum: 1
if (menuList.value.length > 0) return
const allRows: any[] = []
let pageNum = DEFAULT_PAGE_NUM
while (true) {
const res: any = await appMerchantMenuMenuListByMerchantPost({
params: {
pageSize: DEFAULT_PAGE_SIZE,
pageNum,
},
})
const rows = res.rows || []
allRows.push(...rows)
if ((typeof res.total === 'number' && allRows.length >= res.total) || rows.length < DEFAULT_PAGE_SIZE) {
break
}
}).then(res => {
menuList.value = res.rows || []
if (res.rows && res.rows.length > 0) {
// 设置当前选中的菜单索引
currentMenuIndex.value = 0
if (+props.currentIndex === 1) {
// 获取菜单详情
getMenuDetail()
}
}
})
pageNum += 1
if (pageNum > 200) break
}
menuList.value = allRows
if (menuList.value.length > 0) {
currentMenuIndex.value = 0
}
}
const findIndexById = (array, targetId) =>
array.findIndex(item => item.id === targetId);
const findIndexById = (array: any[], targetId: string | number) =>
array.findIndex((item) => item.id === targetId);
function indexChangeMenu(id: string) {
// 最新的菜单ID
console.log('indexChangeMenu', id)
currentMenuIndex.value = findIndexById(menuList.value, id)
console.log('当前选中的菜单索引', currentMenuIndex.value)
getMenuDetail()
getMenuDetail().then(() => {
paging.value?.reload()
})
}
// 菜单下面的菜品数据
// 菜单下面的菜品数据(完整数据,用于tab1本地分页与搜索)
const menuDishListData = ref<MerchantDishVo[]>([])
function getMenuDetail() {
appMerchantMenuMenuDetailPost({
async function getMenuDetail() {
return appMerchantMenuMenuDetailPost({
params: {
recipeId: currentMenu.value.id || ''
}
}).then(res => {
}).then((res: any) => {
console.log('获取菜单详情', res)
if (res.data && res.data.dishList) {
menuDishListData.value = res.data.dishList || []
if (res.data && (res.data as any).dishList) {
menuDishListData.value = (res.data as any).dishList || []
}
}).catch(err => {
console.error('获取菜单详情失败', err)
})
}
const dishList = ref<MerchantDishVo[]>([])
function getDishList() {
appMerchantDishListPost({
params: {
pageSize: 1000,
pageNum: 1
}
}).then(res => {
console.log('res', res)
dishList.value = res.rows
console.log('dishList', dishList.value)
})
async function ensureMenuDetailLoaded() {
if (tabIndexNum.value !== 1) return
if (!currentMenu.value?.id) return
// 没有数据时才请求,避免每次上拉都重复打接口
if (menuDishListData.value.length > 0) return
await getMenuDetail()
}
function handleClickMenu(item: any) {
@@ -157,12 +200,21 @@ function handleClickDish(item: MerchantDishVo) {
})
}
// 库存文案相关辅助方法
function hasStock(item: any) {
return !!(item as any)?.stock
}
function getStock(item: any) {
const stock = (item as any)?.stock
if (stock === undefined || stock === null) return ''
return Number(stock).toFixed(0)
}
function initData() {
console.log('页面回来的时候获取最新的数据', props.currentIndex)
if (+props.currentIndex === 2 || +props.currentIndex === 1) {
getMenuListByMerchant()
} else if (+props.currentIndex === 3) {
getDishList()
if (+props.currentIndex === +props.tabIndex) {
paging.value?.reload()
}
}
@@ -182,11 +234,14 @@ function handleSearch() {
isShowSearch.value = true
}
const searchResult = ref([]);
type DishSearchResult = {
item: MerchantDishVo
}
const searchResult = ref<DishSearchResult[]>([]);
function handleConfirmSearch() {
console.log('handleConfirmSearch', keyword.value)
const fuse = new Fuse(menuDishListData.value, {
const fuse = new Fuse<MerchantDishVo>(menuDishListData.value, {
threshold: 0.2,
keys: ["dishName", "dishDescription"],
});
@@ -199,7 +254,7 @@ function inputClear() {
}
// 删除菜品
function deleteRecipe(item) {
function deleteRecipe(item: MerchantDishVo) {
message
.confirm({
title: t("common.prompt.system-prompt"),
@@ -217,7 +272,7 @@ function deleteRecipe(item) {
})
.then(async () => {
appMerchantDishRemovePost({
body: [item.id]
body: [item.id as number],
}).then((res) => {
uni.showToast({
title: t('toast.deleteSuccess'),
@@ -324,7 +379,7 @@ const isMerchant = computed(() => {
<!--搜索结果数据-->
<template v-if="isShowSearch">
<template v-if="searchResult.length>0">
<template v-for="(item, index) in searchResult">
<template v-for="(item, index) in searchResult" :key="item.item.id || index">
<view :class="[index === 0 ? '' : 'mt-46rpx']" @click="handleClickDish(item.item)">
<view class="flex-center-sb">
<image
@@ -354,12 +409,13 @@ const isMerchant = computed(() => {
</template>
</template>
<template v-else>
<template v-for="(item, index) in menuDishListData">
<!-- tab1 使用本地分页后的 dataList 渲染menuDishListData 仅用于搜索与总数据缓存 -->
<template v-for="(item, index) in dataList" :key="item.id || index">
<view :class="[index === 0 ? '' : 'mt-46rpx']">
<wd-swipe-action v-model="swipeActionValue">
<view class="flex-center-sb" @click="handleClickDish(item)">
<image
:src="item.dishImage.split(',')[0]"
:src="item.dishImage ? item.dishImage.split(',')[0] : ''"
class="w-176rpx h-176rpx mr-28rpx shrink-0 rounded-24rpx"
mode="aspectFill"
></image>
@@ -411,7 +467,7 @@ const isMerchant = computed(() => {
<!-- 菜单列表 -->
<view class="">
<!-- Monday Menu Item -->
<template v-for="item in menuList">
<template v-for="item in dataList" :key="item.id">
<view class="flex-center-sb border-b-1rpx border-b-solid border-b-#F6F6F6 h-170rpx"
@click="handleClickMenu(item)">
<view class="flex-1">
@@ -421,7 +477,7 @@ const isMerchant = computed(() => {
<image class="w-32rpx h-32rpx shrink-0 rotate-0" src="@img/chef/115.png"></image>
</view>
</template>
<template v-if="menuList.length === 0">
<template v-if="dataList.length === 0">
<view class="py-100rpx center">
<image class="w-250rpx h-250rpx" src="@img/chef/16033@2x.png"></image>
</view>
@@ -437,10 +493,10 @@ const isMerchant = computed(() => {
<image class="w-28rpx h-28rpx shrink-0 mr-10rpx" src="@img/chef/107.png"></image>
<text class="text-26rpx text-#333 font-500">{{ t('pages.menu.add') }}</text>
</view>
<template v-for="(item, index) in dishList">
<template v-for="(item, index) in dataList" :key="item.id || index">
<view :class="[index === 0 ? '' : 'mt-46rpx']" class="flex-center-sb" @click="handleClickDish(item)">
<image
:src="item.dishImage.split(',')[0]"
:src="item.dishImage ? item.dishImage.split(',')[0] : ''"
class="w-176rpx h-176rpx mr-28rpx shrink-0 rounded-24rpx bg-common"
mode="aspectFill"
></image>
@@ -456,8 +512,8 @@ const isMerchant = computed(() => {
${{ item.originalPrice }}
</view>
<view class="mt-63rpx text-#333 text-30rpx font-500">
<template v-if="item.stock">
{{ t('common.stock') }}: {{ Number(item.stock).toFixed(0) }}
<template v-if="hasStock(item)">
{{ t('common.stock') }}: {{ getStock(item) }}
</template>
</view>
</view>
@@ -465,7 +521,7 @@ const isMerchant = computed(() => {
</view>
</template>
<template v-if="dishList.length === 0">
<template v-if="dataList.length === 0">
<view class="py-100rpx center">
<image class="w-250rpx h-250rpx" src="@img/chef/16033@2x.png"></image>
</view>
@@ -8,27 +8,53 @@ const show = ref(false);
const pickerValue = ref(0)
const emits = defineEmits(['confirm'])
// 默认分页配置(避免一次请求 1000 条)
const DEFAULT_PAGE_SIZE = 10;
const DEFAULT_PAGE_NUM = 1;
type MenuColumnItem = {
value: string | number
label: string
}
function onOpen(value: number) {
getMenuListByMerchant()
show.value = true;
}
function getMenuListByMerchant() {
appMerchantMenuMenuListByMerchantPost({
params: {
pageSize: 1000,
pageNum: 1
const columns = ref<MenuColumnItem[]>([])
async function getMenuListByMerchant() {
if (!userStore.isLogin) return
const allRows: any[] = []
let pageNum = DEFAULT_PAGE_NUM
while (true) {
const res = await appMerchantMenuMenuListByMerchantPost({
params: {
pageSize: DEFAULT_PAGE_SIZE,
pageNum
}
})
const rows = res.rows || []
allRows.push(...rows)
// 按 total 或 “本页不足 pageSize” 判断结束,保证符合分页语义
if ((typeof res.total === 'number' && allRows.length >= res.total) || rows.length < DEFAULT_PAGE_SIZE) {
break
}
}).then(res => {
if (res.rows && res.rows.length > 0) {
columns.value = res.rows.map((item) => {
return {
value: item.id,
label: item.menuName,
}
})
}
})
pageNum += 1
// 安全阈值,避免后端异常导致死循环
if (pageNum > 200) break
}
columns.value = allRows.map((item) => ({
value: item.id,
label: item.menuName,
}))
}
@@ -42,8 +68,6 @@ function handleSubmit() {
handleClose()
}
const columns = ref([])
defineExpose({
onOpen,
});