diff --git a/src/router/index.js b/src/router/index.js index d2d5e52..702b97d 100644 --- a/src/router/index.js +++ b/src/router/index.js @@ -7,6 +7,7 @@ import { getMenuAccess, getDefaultLandingPath, getEffectiveVisiblePaths, + isLocallyDefinedMenuPathAllowed, isMenuSessionFresh, hasMerchantOrderPerm, JITUAN_API, @@ -230,6 +231,11 @@ const routes = [ component: () => import('@/views/product/TypeZone.vue'), meta: { title: '商品类型专区管理' } }, + { + path: 'product/turntable', + component: () => import('@/views/product/Turntable.vue'), + meta: { title: '转盘活动' } + }, { path: 'product/data', component: () => import('@/views/product/Data.vue'), @@ -358,6 +364,10 @@ function isRouteAllowed(path, access) { return visiblePaths.some((p) => parents.includes(p)) } } + // 新菜单仅写在前端时:侧栏能显示则允许进入,避免被踢到板块配置等默认页 + if (isLocallyDefinedMenuPathAllowed(path)) { + return true + } return false } diff --git a/src/utils/club-context.js b/src/utils/club-context.js index 5897450..f10fc85 100644 --- a/src/utils/club-context.js +++ b/src/utils/club-context.js @@ -3,7 +3,7 @@ const CLUB_SCOPE_KEY = 'admin_club_scope'; const CLUB_CONTEXT_KEY = 'admin_club_context'; const MENU_ACCESS_KEY = 'kefu_menu_access'; const MENU_SESSION_KEY = 'kefu_menu_session_v'; -const MENU_SESSION_VERSION = '24'; +const MENU_SESSION_VERSION = '25'; const DEFAULT_CLUB_ID = 'xq'; let menuAccessInflight = null; @@ -146,8 +146,9 @@ const KEFU_MENU_ROWS = [ { page_id: 'gongdan', parent_id: '', path: '/gongdan', sort_order: 81, perm_codes: ['gdck666', 'gdcl666'] }, { page_id: 'product.list', parent_id: 'product', path: '/product/list', sort_order: 91, perm_codes: ['2200a'] }, { page_id: 'product.type-zone', parent_id: 'product', path: '/product/type-zone', sort_order: 92, perm_codes: ['7007a'] }, - { page_id: 'product.data', parent_id: 'product', path: '/product/data', sort_order: 93, perm_codes: ['2200a'] }, - { page_id: 'product.fake-orders', parent_id: 'product', path: '/product/fake-orders', sort_order: 94, perm_codes: ['2200a'] }, + { page_id: 'product.turntable', parent_id: 'product', path: '/product/turntable', sort_order: 93, perm_codes: ['2200a'] }, + { page_id: 'product.data', parent_id: 'product', path: '/product/data', sort_order: 94, perm_codes: ['2200a'] }, + { page_id: 'product.fake-orders', parent_id: 'product', path: '/product/fake-orders', sort_order: 95, perm_codes: ['2200a'] }, { page_id: 'member.list', parent_id: 'member', path: '/member/list', sort_order: 101, perm_codes: ['3300a'] }, { page_id: 'member.data', parent_id: 'member', path: '/member/data', sort_order: 102, perm_codes: ['3300a'] }, { page_id: 'miniapp.carousel', parent_id: 'miniapp', path: '/miniapp/carousel', sort_order: 111, perm_codes: ['8080a'] }, @@ -170,7 +171,7 @@ const KEFU_MENU_PARENT_IDS = { 'cross-platform': ['cross-platform.order', 'cross-platform.settings', 'cross-platform.data', 'cross-platform.pre'], user: ['user.player', 'user.guanli', 'user.shangjia', 'user.zuzhang', 'user.identity-tag'], withdraw: ['withdraw.audit', 'withdraw.data', 'withdraw.settings'], - product: ['product.list', 'product.type-zone', 'product.data', 'product.fake-orders'], + product: ['product.list', 'product.type-zone', 'product.turntable', 'product.data', 'product.fake-orders'], member: ['member.list', 'member.data'], miniapp: ['miniapp.carousel', 'miniapp.assets', 'miniapp.popup', 'miniapp.leixing', 'miniapp.kaohe-tags', 'miniapp.dashou-exam', 'miniapp.withdraw-settings'], shop: ['shop.list', 'shop.withdraw', 'shop.products'], @@ -205,6 +206,19 @@ export function getEffectiveVisiblePaths(access = null) { return Array.isArray(paths) ? paths : []; } +/** + * 兼容尚未 seed 到服务端的新菜单:本地已定义且 canShowMenuPage 通过即可进路由。 + * 避免「侧栏看得见、点进去却被踢到默认页(如板块配置)」。 + */ +export function isLocallyDefinedMenuPathAllowed(path) { + if (!path) return false; + const row = KEFU_MENU_ROWS.find( + (r) => r.path && (path === r.path || path.startsWith(`${r.path}/`)), + ); + if (!row) return false; + return canShowMenuPage(row.page_id); +} + export function hasPermCode(access, ...codes) { if (!access || !codes.length) return false; const list = access.permission_codes || []; diff --git a/src/views/Layout.vue b/src/views/Layout.vue index eb50db3..7d64e81 100644 --- a/src/views/Layout.vue +++ b/src/views/Layout.vue @@ -123,6 +123,7 @@ 商品列表 商品类型专区管理 + 转盘活动 商品数据分析 假单管理 diff --git a/src/views/miniapp/CarouselManage.vue b/src/views/miniapp/CarouselManage.vue index 3343da4..ad1797c 100644 --- a/src/views/miniapp/CarouselManage.vue +++ b/src/views/miniapp/CarouselManage.vue @@ -109,9 +109,11 @@ const hasPermission = ref(true) const pageKey = ref('order_pool') const pageOptions = ref([ { key: 'order_pool', label: '抢单池' }, - { key: 'accept_order', label: '点单页' }, + { key: 'accept_order', label: '点单页主轮播' }, + { key: 'accept_order_banner2', label: '点单页横幅轮播' }, { key: 'merchant_home', label: '商家首页' }, { key: 'dashou_center', label: '打手个人中心背景' }, + { key: 'boss_center', label: '点单个人中心背景' }, ]) const gonggaoTitle = computed(() => { const opt = pageOptions.value.find((o) => o.key === pageKey.value) @@ -169,9 +171,11 @@ const fetchLunbo = async () => { if (!pageOptions.value.length) { pageOptions.value = [ { key: 'order_pool', label: '抢单池' }, - { key: 'accept_order', label: '点单页' }, + { key: 'accept_order', label: '点单页主轮播' }, + { key: 'accept_order_banner2', label: '点单页横幅轮播' }, { key: 'merchant_home', label: '商家首页' }, { key: 'dashou_center', label: '打手个人中心背景' }, + { key: 'boss_center', label: '点单个人中心背景' }, ] } } else if (res.code === 403) { diff --git a/src/views/product/Turntable.vue b/src/views/product/Turntable.vue new file mode 100644 index 0000000..7ae8801 --- /dev/null +++ b/src/views/product/Turntable.vue @@ -0,0 +1,269 @@ + + + + + diff --git a/src/views/product/TypeZone.vue b/src/views/product/TypeZone.vue index c9a0a40..e92e8c8 100644 --- a/src/views/product/TypeZone.vue +++ b/src/views/product/TypeZone.vue @@ -213,6 +213,9 @@ + + + { id: zone.id, mingzi: zone.mingzi, leixing_id: zone.leixing_id, - shenhezhuangtai: Number(zone.shenhezhuangtai) + shenhezhuangtai: Number(zone.shenhezhuangtai), + tupian_url: zone.tupian_url || '' }) zoneDialogVisible.value = true } const resetZoneForm = () => { - Object.assign(zoneForm, { id: null, mingzi: '', leixing_id: null, shenhezhuangtai: 1 }) + Object.assign(zoneForm, { id: null, mingzi: '', leixing_id: null, shenhezhuangtai: 1, tupian_url: '' }) zoneFormRef.value?.clearValidate() } const submitZone = async () => { @@ -646,7 +650,8 @@ const submitZone = async () => { id: zoneForm.id, mingzi: zoneForm.mingzi, leixing_id: zoneForm.leixing_id, - shenhezhuangtai: zoneForm.shenhezhuangtai + shenhezhuangtai: zoneForm.shenhezhuangtai, + tupian_url: zoneForm.tupian_url || '' }) if (res.code === 0) { ElMessage.success(isZoneEdit.value ? '修改成功' : '添加成功')