Merge remote-tracking branch 'origin/huangzhenbao-admin' into comclib-analytics
This commit is contained in:
@@ -63,7 +63,8 @@
|
|||||||
<!-- 内容展示区 (内部路由渲染) -->
|
<!-- 内容展示区 (内部路由渲染) -->
|
||||||
<view class="content-scroll">
|
<view class="content-scroll">
|
||||||
<view class="content-inner" :class="{ 'is-mobile': isMobile }">
|
<view class="content-inner" :class="{ 'is-mobile': isMobile }">
|
||||||
<component :is="currentComponent" v-if="!isPageLoading" />
|
<slot></slot>
|
||||||
|
<component :is="currentComponent" v-if="!isPageLoading && currentComponent != null" />
|
||||||
<AdminPageLoading v-if="isPageLoading" />
|
<AdminPageLoading v-if="isPageLoading" />
|
||||||
</view>
|
</view>
|
||||||
<AdminFooter />
|
<AdminFooter />
|
||||||
@@ -118,6 +119,13 @@ import type { TabItem } from '@/layouts/admin/store/adminNavStore.uts'
|
|||||||
|
|
||||||
import { getComponent } from '@/layouts/admin/router/adminComponentMap.uts'
|
import { getComponent } from '@/layouts/admin/router/adminComponentMap.uts'
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
currentPage: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
// 侧边栏宽度配置 (CRMEB 1:1)
|
// 侧边栏宽度配置 (CRMEB 1:1)
|
||||||
const ASIDE_W = 70
|
const ASIDE_W = 70
|
||||||
const SUB_W = 200
|
const SUB_W = 200
|
||||||
@@ -388,6 +396,9 @@ onMounted(async () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
initNavState()
|
initNavState()
|
||||||
|
if (props.currentPage != '') {
|
||||||
|
openRoute(props.currentPage as string)
|
||||||
|
}
|
||||||
|
|
||||||
// 初始化窗口宽度
|
// 初始化窗口宽度
|
||||||
windowWidth.value = uni.getWindowInfo().windowWidth
|
windowWidth.value = uni.getWindowInfo().windowWidth
|
||||||
|
|||||||
@@ -92,8 +92,20 @@ function isActive(node: MenuNode): boolean {
|
|||||||
// 只有非分组项才能被视为“激活”变色 (1:1 复刻 screenshot 效果)
|
// 只有非分组项才能被视为“激活”变色 (1:1 复刻 screenshot 效果)
|
||||||
if (node.type === 'group') return false
|
if (node.type === 'group') return false
|
||||||
|
|
||||||
if (props.activeId != '' && node.id === props.activeId) return true
|
// 核心逻辑:优先匹配 ID,ID 是唯一的
|
||||||
if (props.currentPath != '' && node.path === props.currentPath) return true
|
// 如果当前选中的 ID 就是这个节点的 ID,那它肯定是激活的
|
||||||
|
if (props.activeId != '' && node.id === props.activeId) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果 ID 没匹配上,但路径匹配上了,且当前没有 activeId (例如首次进入或刷新)
|
||||||
|
// 或者当前 ID 对应的路径跟这个路径一样
|
||||||
|
// 但为了防止 Path 相同导致多选,我们加一个额外判断:
|
||||||
|
// 如果 activeId 已经指向了一个有效的路由,我们通常不再通过 Path 来高亮其他项
|
||||||
|
if (props.activeId === '' && props.currentPath != '' && node.path === props.currentPath) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -125,14 +125,15 @@ export const componentMap: Map<string, any> = new Map([
|
|||||||
|
|
||||||
// 设置模块
|
// 设置模块
|
||||||
['SettingSystemConfig', defineAsyncComponent(() => import('@/pages/mall/admin/setting/system/config.uvue'))],
|
['SettingSystemConfig', defineAsyncComponent(() => import('@/pages/mall/admin/setting/system/config.uvue'))],
|
||||||
['SettingMessage', defineAsyncComponent(() => import('@/pages/mall/admin/setting/message.uvue'))],
|
['SettingMessageIndex', defineAsyncComponent(() => import('@/pages/mall/admin/setting/message.uvue'))],
|
||||||
['SettingAgreement', defineAsyncComponent(() => import('@/pages/mall/admin/setting/agreement.uvue'))],
|
['SettingProtocolIndex', defineAsyncComponent(() => import('@/pages/mall/admin/setting/agreement.uvue'))],
|
||||||
['SettingTicket', defineAsyncComponent(() => import('@/pages/mall/admin/setting/ticket.uvue'))],
|
['SettingTicketIndex', defineAsyncComponent(() => import('@/pages/mall/admin/setting/ticket.uvue'))],
|
||||||
['SettingAuthRole', defineAsyncComponent(() => import('@/pages/mall/admin/setting/auth/role.uvue'))],
|
['SettingAuthRole', defineAsyncComponent(() => import('@/pages/mall/admin/setting/auth/role.uvue'))],
|
||||||
['SettingAuthAdmin', defineAsyncComponent(() => import('@/pages/mall/admin/setting/auth/admin.uvue'))],
|
['SettingAuthAdmin', defineAsyncComponent(() => import('@/pages/mall/admin/setting/auth/admin.uvue'))],
|
||||||
['SettingAuthPermission', defineAsyncComponent(() => import('@/pages/mall/admin/setting/auth/permission.uvue'))],
|
['SettingAuthPermission', defineAsyncComponent(() => import('@/pages/mall/admin/setting/auth/permission.uvue'))],
|
||||||
['SettingDeliveryStaff', defineAsyncComponent(() => import('@/pages/mall/admin/setting/delivery/staff.uvue'))],
|
['SettingDeliveryStaff', defineAsyncComponent(() => import('@/pages/mall/admin/setting/delivery/staff.uvue'))],
|
||||||
['SettingDeliveryStation', defineAsyncComponent(() => import('@/pages/mall/admin/setting/delivery/station.uvue'))],
|
['SettingDeliveryStation', defineAsyncComponent(() => import('@/pages/mall/admin/setting/delivery/station.uvue'))],
|
||||||
|
['SettingDeliveryVerifier', defineAsyncComponent(() => import('@/pages/mall/admin/setting/delivery/verifier.uvue'))],
|
||||||
['SettingDeliveryTemplate', defineAsyncComponent(() => import('@/pages/mall/admin/setting/delivery/template.uvue'))],
|
['SettingDeliveryTemplate', defineAsyncComponent(() => import('@/pages/mall/admin/setting/delivery/template.uvue'))],
|
||||||
['SettingInterfaceOnepassConfig', defineAsyncComponent(() => import('@/pages/mall/admin/setting/interface/onepass/config.uvue'))],
|
['SettingInterfaceOnepassConfig', defineAsyncComponent(() => import('@/pages/mall/admin/setting/interface/onepass/config.uvue'))],
|
||||||
['SettingInterfaceOnepassIndex', defineAsyncComponent(() => import('@/pages/mall/admin/setting/interface/onepass/index.uvue'))],
|
['SettingInterfaceOnepassIndex', defineAsyncComponent(() => import('@/pages/mall/admin/setting/interface/onepass/index.uvue'))],
|
||||||
@@ -169,32 +170,42 @@ export const componentMap: Map<string, any> = new Map([
|
|||||||
['DecorationLink', defineAsyncComponent(() => import('@/pages/mall/admin/design/link-management.uvue'))],
|
['DecorationLink', defineAsyncComponent(() => import('@/pages/mall/admin/design/link-management.uvue'))],
|
||||||
|
|
||||||
// 应用模块
|
// 应用模块
|
||||||
['AppStatistic', PlaceholderPage],
|
['AppWechatMenu', defineAsyncComponent(() => import('@/pages/mall/admin/app/wechat/menu.uvue'))],
|
||||||
['AppList', PlaceholderPage],
|
['AppWechatNews', defineAsyncComponent(() => import('@/pages/mall/admin/app/wechat/news.uvue'))],
|
||||||
|
['AppWechatReplyFollow', defineAsyncComponent(() => import('@/pages/mall/admin/app/wechat/reply/follow.uvue'))],
|
||||||
|
['AppWechatReplyKeyword', defineAsyncComponent(() => import('@/pages/mall/admin/app/wechat/reply/keyword.uvue'))],
|
||||||
|
['AppWechatReplyInvalid', defineAsyncComponent(() => import('@/pages/mall/admin/app/wechat/reply/invalid.uvue'))],
|
||||||
|
['AppWechatConfig', defineAsyncComponent(() => import('@/pages/mall/admin/app/wechat/config.uvue'))],
|
||||||
|
['AppRoutineDownload', defineAsyncComponent(() => import('@/pages/mall/admin/app/routine/download.uvue'))],
|
||||||
|
['AppRoutineConfig', defineAsyncComponent(() => import('@/pages/mall/admin/app/routine/config.uvue'))],
|
||||||
|
['AppMobileConfig', defineAsyncComponent(() => import('@/pages/mall/admin/app/mobile/config.uvue'))],
|
||||||
|
['AppMobileVersion', defineAsyncComponent(() => import('@/pages/mall/admin/app/mobile/version.uvue'))],
|
||||||
|
['AppPcDesign', defineAsyncComponent(() => import('@/pages/mall/admin/app/pc/design.uvue'))],
|
||||||
|
['AppPcConfig', defineAsyncComponent(() => import('@/pages/mall/admin/app/pc/config.uvue'))],
|
||||||
|
|
||||||
// 维护模块
|
// 维护模块
|
||||||
['MaintainDevConfig', defineAsyncComponent(() => import('@/pages/mall/admin/maintain/dev/config.uvue'))],
|
['MaintainDevConfig', defineAsyncComponent(() => import('@/pages/mall/admin/maintain/dev-config/category.uvue'))],
|
||||||
['MaintainDevData', PlaceholderPage],
|
['MaintainDevData', defineAsyncComponent(() => import('@/pages/mall/admin/maintain/dev-config/combination-data.uvue'))],
|
||||||
['MaintainDevTask', PlaceholderPage],
|
['MaintainDevTask', defineAsyncComponent(() => import('@/pages/mall/admin/maintain/dev-config/cron-job.uvue'))],
|
||||||
['MaintainDevAuth', PlaceholderPage],
|
['MaintainDevAuth', defineAsyncComponent(() => import('@/pages/mall/admin/maintain/dev-config/permission.uvue'))],
|
||||||
['MaintainDevModule', PlaceholderPage],
|
['MaintainDevModule', defineAsyncComponent(() => import('@/pages/mall/admin/maintain/dev-config/module-config.uvue'))],
|
||||||
['MaintainDevEvent', PlaceholderPage],
|
['MaintainDevEvent', defineAsyncComponent(() => import('@/pages/mall/admin/maintain/dev-config/custom-event.uvue'))],
|
||||||
['MaintainSecurityCache', PlaceholderPage],
|
['MaintainSecurityCache', defineAsyncComponent(() => import('@/pages/mall/admin/maintain/security/refresh-cache.uvue'))],
|
||||||
['MaintainSecurityLog', PlaceholderPage],
|
['MaintainSecurityLog', defineAsyncComponent(() => import('@/pages/mall/admin/maintain/security/system-log.uvue'))],
|
||||||
['MaintainSecurityUpgrade', PlaceholderPage],
|
['MaintainSecurityUpgrade', defineAsyncComponent(() => import('@/pages/mall/admin/maintain/security/online-upgrade.uvue'))],
|
||||||
['MaintainDataLogistics', PlaceholderPage],
|
['MaintainDataLogistics', defineAsyncComponent(() => import('@/pages/mall/admin/maintain/data/logistics.uvue'))],
|
||||||
['MaintainDataCity', PlaceholderPage],
|
['MaintainDataCity', defineAsyncComponent(() => import('@/pages/mall/admin/maintain/data/city.uvue'))],
|
||||||
['MaintainDataClear', PlaceholderPage],
|
['MaintainDataClear', defineAsyncComponent(() => import('@/pages/mall/admin/maintain/data/clear.uvue'))],
|
||||||
['MaintainApiAccount', PlaceholderPage],
|
['MaintainApiAccount', defineAsyncComponent(() => import('@/pages/mall/admin/maintain/api/account.uvue'))],
|
||||||
['MaintainLangList', PlaceholderPage],
|
['MaintainLangList', defineAsyncComponent(() => import('@/pages/mall/admin/maintain/lang/list.uvue'))],
|
||||||
['MaintainLangDetail', PlaceholderPage],
|
['MaintainLangDetail', defineAsyncComponent(() => import('@/pages/mall/admin/maintain/lang/detail.uvue'))],
|
||||||
['MaintainLangRegion', PlaceholderPage],
|
['MaintainLangRegion', defineAsyncComponent(() => import('@/pages/mall/admin/maintain/lang/region.uvue'))],
|
||||||
['MaintainLangConfig', PlaceholderPage],
|
['MaintainLangConfig', defineAsyncComponent(() => import('@/pages/mall/admin/maintain/lang/config.uvue'))],
|
||||||
['MaintainToolDb', PlaceholderPage],
|
['MaintainToolDb', defineAsyncComponent(() => import('@/pages/mall/admin/maintain/dev-tools/database.uvue'))],
|
||||||
['MaintainToolFile', PlaceholderPage],
|
['MaintainToolFile', defineAsyncComponent(() => import('@/pages/mall/admin/maintain/dev-tools/file.uvue'))],
|
||||||
['MaintainToolApi', PlaceholderPage],
|
['MaintainToolApi', defineAsyncComponent(() => import('@/pages/mall/admin/maintain/dev-tools/api.uvue'))],
|
||||||
['MaintainToolDic', PlaceholderPage],
|
['MaintainToolDic', defineAsyncComponent(() => import('@/pages/mall/admin/maintain/dev-tools/data-dict.uvue'))],
|
||||||
['MaintainSysInfo', PlaceholderPage]
|
['MaintainSysInfo', defineAsyncComponent(() => import('@/pages/mall/admin/maintain/sys/info.uvue'))]
|
||||||
])
|
])
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -173,10 +173,13 @@ export const topMenus: TopMenu[] = [
|
|||||||
id: 'app',
|
id: 'app',
|
||||||
title: '应用',
|
title: '应用',
|
||||||
icon: 'app',
|
icon: 'app',
|
||||||
path: '/pages/mall/admin/app/statistic',
|
path: '/pages/mall/admin/app/wechat/menu',
|
||||||
order: 11,
|
order: 11,
|
||||||
groups: [
|
groups: [
|
||||||
{ id: 'app-manage', title: '', order: 1 }
|
{ id: 'app-wechat', title: '公众号', order: 1 },
|
||||||
|
{ id: 'app-routine', title: '小程序', order: 2 },
|
||||||
|
{ id: 'app-mobile', title: 'APP', order: 3 },
|
||||||
|
{ id: 'app-pc', title: 'PC端', order: 4 }
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -197,7 +200,7 @@ export const topMenus: TopMenu[] = [
|
|||||||
id: 'maintain',
|
id: 'maintain',
|
||||||
title: '维护',
|
title: '维护',
|
||||||
icon: 'tool',
|
icon: 'tool',
|
||||||
path: '/pages/mall/admin/maintain/dev/config',
|
path: '/pages/mall/admin/maintain/dev-config/category',
|
||||||
order: 13,
|
order: 13,
|
||||||
groups: [
|
groups: [
|
||||||
{ id: 'maintain-dev', title: '开发配置', order: 1 },
|
{ id: 'maintain-dev', title: '开发配置', order: 1 },
|
||||||
@@ -894,180 +897,6 @@ export const routes: RouteRecord[] = [
|
|||||||
order: 1
|
order: 1
|
||||||
},
|
},
|
||||||
|
|
||||||
// ========== 设置模块 ==========
|
|
||||||
// 1. 系统设置
|
|
||||||
{
|
|
||||||
id: 'setting_systemConfig',
|
|
||||||
title: '系统设置',
|
|
||||||
path: '/pages/mall/admin/setting/system/config',
|
|
||||||
componentKey: 'SettingSystemConfig',
|
|
||||||
parentId: 'setting',
|
|
||||||
groupId: 'setting-system',
|
|
||||||
auth: ['admin-setting-system-config'],
|
|
||||||
order: 1
|
|
||||||
},
|
|
||||||
|
|
||||||
// 2. 通知管理
|
|
||||||
{
|
|
||||||
id: 'setting_message',
|
|
||||||
title: '消息管理',
|
|
||||||
path: '/pages/mall/admin/setting/message',
|
|
||||||
componentKey: 'SettingMessage',
|
|
||||||
parentId: 'setting',
|
|
||||||
groupId: 'setting-message',
|
|
||||||
order: 1
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'setting_agreement',
|
|
||||||
title: '协议管理',
|
|
||||||
path: '/pages/mall/admin/setting/agreement',
|
|
||||||
componentKey: 'SettingAgreement',
|
|
||||||
parentId: 'setting',
|
|
||||||
groupId: 'setting-message',
|
|
||||||
order: 2
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'setting_ticket',
|
|
||||||
title: '客服设置',
|
|
||||||
path: '/pages/mall/admin/setting/ticket',
|
|
||||||
componentKey: 'SettingTicket',
|
|
||||||
parentId: 'setting',
|
|
||||||
groupId: 'setting-message',
|
|
||||||
order: 3
|
|
||||||
},
|
|
||||||
|
|
||||||
// 3. 权限管理
|
|
||||||
{
|
|
||||||
id: 'setting_auth_role',
|
|
||||||
title: '角色管理',
|
|
||||||
path: '/pages/mall/admin/setting/auth/role',
|
|
||||||
componentKey: 'SettingAuthRole',
|
|
||||||
parentId: 'setting',
|
|
||||||
groupId: 'setting-auth',
|
|
||||||
order: 1
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'setting_auth_admin',
|
|
||||||
title: '管理员管理',
|
|
||||||
path: '/pages/mall/admin/setting/auth/admin',
|
|
||||||
componentKey: 'SettingAuthAdmin',
|
|
||||||
parentId: 'setting',
|
|
||||||
groupId: 'setting-auth',
|
|
||||||
order: 2
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'setting_auth_permission',
|
|
||||||
title: '权限管理',
|
|
||||||
path: '/pages/mall/admin/setting/auth/permission',
|
|
||||||
componentKey: 'SettingAuthPermission',
|
|
||||||
parentId: 'setting',
|
|
||||||
groupId: 'setting-auth',
|
|
||||||
order: 3
|
|
||||||
},
|
|
||||||
|
|
||||||
// 4. 物流设置
|
|
||||||
{
|
|
||||||
id: 'setting_delivery_staff',
|
|
||||||
title: '配送员管理',
|
|
||||||
path: '/pages/mall/admin/setting/delivery/staff',
|
|
||||||
componentKey: 'SettingDeliveryStaff',
|
|
||||||
parentId: 'setting',
|
|
||||||
groupId: 'setting-delivery',
|
|
||||||
order: 1
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'setting_delivery_station',
|
|
||||||
title: '提货点管理',
|
|
||||||
path: '/pages/mall/admin/setting/delivery/station',
|
|
||||||
componentKey: 'SettingDeliveryStation',
|
|
||||||
parentId: 'setting',
|
|
||||||
groupId: 'setting-delivery',
|
|
||||||
order: 2
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'setting_delivery_template',
|
|
||||||
title: '运费模板',
|
|
||||||
path: '/pages/mall/admin/setting/delivery/template',
|
|
||||||
componentKey: 'SettingDeliveryTemplate',
|
|
||||||
parentId: 'setting',
|
|
||||||
groupId: 'setting-delivery',
|
|
||||||
order: 3
|
|
||||||
},
|
|
||||||
|
|
||||||
// 5. 接口设置
|
|
||||||
{
|
|
||||||
id: 'setting_interface_onepass_config',
|
|
||||||
title: '总平台配置',
|
|
||||||
path: '/pages/mall/admin/setting/interface/onepass/config',
|
|
||||||
componentKey: 'SettingInterfaceOnepassConfig',
|
|
||||||
parentId: 'setting',
|
|
||||||
groupId: 'setting-interface',
|
|
||||||
order: 1
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'setting_interface_onepass_index',
|
|
||||||
title: '账号列表',
|
|
||||||
path: '/pages/mall/admin/setting/interface/onepass/index',
|
|
||||||
componentKey: 'SettingInterfaceOnepassIndex',
|
|
||||||
parentId: 'setting',
|
|
||||||
groupId: 'setting-interface',
|
|
||||||
order: 2
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'setting_interface_storage',
|
|
||||||
title: '存储配置',
|
|
||||||
path: '/pages/mall/admin/setting/interface/storage',
|
|
||||||
componentKey: 'SettingInterfaceStorage',
|
|
||||||
parentId: 'setting',
|
|
||||||
groupId: 'setting-interface',
|
|
||||||
order: 3
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'setting_interface_collect',
|
|
||||||
title: '商品采集',
|
|
||||||
path: '/pages/mall/admin/setting/interface/collect',
|
|
||||||
componentKey: 'SettingInterfaceCollect',
|
|
||||||
parentId: 'setting',
|
|
||||||
groupId: 'setting-interface',
|
|
||||||
order: 4
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'setting_interface_logistics',
|
|
||||||
title: '物流查询',
|
|
||||||
path: '/pages/mall/admin/setting/interface/logistics',
|
|
||||||
componentKey: 'SettingInterfaceLogistics',
|
|
||||||
parentId: 'setting',
|
|
||||||
groupId: 'setting-interface',
|
|
||||||
order: 5
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'setting_interface_esheet',
|
|
||||||
title: '电子面单',
|
|
||||||
path: '/pages/mall/admin/setting/interface/e-sheet',
|
|
||||||
componentKey: 'SettingInterfaceESheet',
|
|
||||||
parentId: 'setting',
|
|
||||||
groupId: 'setting-interface',
|
|
||||||
order: 6
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'setting_interface_sms',
|
|
||||||
title: '短信接口',
|
|
||||||
path: '/pages/mall/admin/setting/interface/sms',
|
|
||||||
componentKey: 'SettingInterfaceSms',
|
|
||||||
parentId: 'setting',
|
|
||||||
groupId: 'setting-interface',
|
|
||||||
order: 7
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'setting_interface_payment',
|
|
||||||
title: '商城支付',
|
|
||||||
path: '/pages/mall/admin/setting/interface/payment',
|
|
||||||
componentKey: 'SettingInterfacePayment',
|
|
||||||
parentId: 'setting',
|
|
||||||
groupId: 'setting-interface',
|
|
||||||
order: 8
|
|
||||||
},
|
|
||||||
|
|
||||||
// ========== 分销模块 ==========
|
// ========== 分销模块 ==========
|
||||||
{
|
{
|
||||||
id: 'distribution_statistic',
|
id: 'distribution_statistic',
|
||||||
@@ -1246,65 +1075,69 @@ export const routes: RouteRecord[] = [
|
|||||||
},
|
},
|
||||||
|
|
||||||
// ========== 设置模块 (1:1 复刻 CRMEB 路由结构) ==========
|
// ========== 设置模块 (1:1 复刻 CRMEB 路由结构) ==========
|
||||||
// 通知管理
|
// 1. 系统设置
|
||||||
|
{ id: 'setting_system_config', title: '系统配置', path: '/pages/mall/admin/setting/system/config', componentKey: 'SettingSystemConfig', parentId: 'setting', groupId: 'setting-system', order: 1 },
|
||||||
|
|
||||||
|
// 2. 通知管理
|
||||||
{ id: 'setting_message_index', title: '消息管理', path: '/pages/mall/admin/setting/message', componentKey: 'SettingMessageIndex', parentId: 'setting', groupId: 'setting-message', order: 1 },
|
{ id: 'setting_message_index', title: '消息管理', path: '/pages/mall/admin/setting/message', componentKey: 'SettingMessageIndex', parentId: 'setting', groupId: 'setting-message', order: 1 },
|
||||||
{ id: 'setting_protocol_index', title: '协议设置', path: '/pages/mall/admin/setting/agreement', componentKey: 'SettingProtocolIndex', parentId: 'setting', groupId: 'setting-message', order: 2 },
|
{ id: 'setting_protocol_index', title: '协议设置', path: '/pages/mall/admin/setting/agreement', componentKey: 'SettingProtocolIndex', parentId: 'setting', groupId: 'setting-message', order: 2 },
|
||||||
{ id: 'setting_ticket_index', title: '小票配置', path: '/pages/mall/admin/setting/ticket', componentKey: 'SettingTicketIndex', parentId: 'setting', groupId: 'setting-message', order: 3 },
|
{ id: 'setting_ticket_index', title: '小票配置', path: '/pages/mall/admin/setting/ticket', componentKey: 'SettingTicketIndex', parentId: 'setting', groupId: 'setting-message', order: 3 },
|
||||||
|
|
||||||
// 权限管理
|
// 3. 权限管理
|
||||||
{ id: 'setting_auth_admin', title: '管理员管理', path: '/pages/mall/admin/setting/auth/admin', componentKey: 'SettingAuthAdmin', parentId: 'setting', groupId: 'setting-auth', order: 1 },
|
{ id: 'setting_auth_admin', title: '管理员管理', path: '/pages/mall/admin/setting/auth/admin', componentKey: 'SettingAuthAdmin', parentId: 'setting', groupId: 'setting-auth', order: 1 },
|
||||||
{ id: 'setting_auth_role', title: '角色管理', path: '/pages/mall/admin/setting/auth/role', componentKey: 'SettingAuthRole', parentId: 'setting', groupId: 'setting-auth', order: 2 },
|
{ id: 'setting_auth_role', title: '角色管理', path: '/pages/mall/admin/setting/auth/role', componentKey: 'SettingAuthRole', parentId: 'setting', groupId: 'setting-auth', order: 2 },
|
||||||
{ id: 'setting_auth_menu', title: '菜单管理', path: '/pages/mall/admin/setting/auth/permission', componentKey: 'SettingAuthMenu', parentId: 'setting', groupId: 'setting-auth', order: 3 },
|
{ id: 'setting_auth_menu', title: '菜单管理', path: '/pages/mall/admin/setting/auth/permission', componentKey: 'SettingAuthPermission', parentId: 'setting', groupId: 'setting-auth', order: 3 },
|
||||||
|
|
||||||
// 物流设置
|
// 4. 物流设置
|
||||||
{ id: 'setting_delivery_courier', title: '配送员管理', path: '/pages/mall/admin/setting/delivery/staff', componentKey: 'SettingDeliveryCourier', parentId: 'setting', groupId: 'setting-delivery', order: 1 },
|
{ id: 'setting_delivery_courier', title: '配送员管理', path: '/pages/mall/admin/setting/delivery/staff', componentKey: 'SettingDeliveryStaff', parentId: 'setting', groupId: 'setting-delivery', order: 1 },
|
||||||
{ id: 'setting_delivery_pickup_list', title: '提货点', path: '/pages/mall/admin/setting/delivery/station', componentKey: 'SettingDeliveryPickupList', parentId: 'setting', groupId: 'setting-delivery', order: 2 },
|
{ id: 'setting_delivery_pickup_list', title: '提货点', path: '/pages/mall/admin/setting/delivery/station', componentKey: 'SettingDeliveryStation', parentId: 'setting', groupId: 'setting-delivery', order: 2 },
|
||||||
{ id: 'setting_delivery_verifier', title: '核销员', path: '/pages/mall/admin/setting/delivery/station', componentKey: 'SettingDeliveryVerifier', parentId: 'setting', groupId: 'setting-delivery', order: 3 },
|
{ id: 'setting_delivery_verifier', title: '核销员', path: '/pages/mall/admin/setting/delivery/verifier', componentKey: 'SettingDeliveryVerifier', parentId: 'setting', groupId: 'setting-delivery', order: 3 },
|
||||||
{ id: 'setting_delivery_freight', title: '运费模板', path: '/pages/mall/admin/setting/delivery/template', componentKey: 'SettingDeliveryFreight', parentId: 'setting', groupId: 'setting-delivery', order: 4 },
|
{ id: 'setting_delivery_freight', title: '运费模板', path: '/pages/mall/admin/setting/delivery/template', componentKey: 'SettingDeliveryTemplate', parentId: 'setting', groupId: 'setting-delivery', order: 4 },
|
||||||
|
|
||||||
// 接口设置
|
// 5. 接口设置
|
||||||
{ id: 'setting_api_yht_page', title: '一号通页面', path: '/pages/mall/admin/setting/interface/onepass/index', componentKey: 'SettingApiYhtPage', parentId: 'setting', groupId: 'setting-interface', order: 1 },
|
{ id: 'setting_api_yht_page', title: '一号通页面', path: '/pages/mall/admin/setting/interface/onepass/index', componentKey: 'SettingInterfaceOnepassIndex', parentId: 'setting', groupId: 'setting-interface', order: 1 },
|
||||||
{ id: 'setting_api_yht_config', title: '一号通配置', path: '/pages/mall/admin/setting/interface/onepass/config', componentKey: 'SettingApiYhtConfig', parentId: 'setting', groupId: 'setting-interface', order: 2 },
|
{ id: 'setting_api_yht_config', title: '一号通配置', path: '/pages/mall/admin/setting/interface/onepass/config', componentKey: 'SettingInterfaceOnepassConfig', parentId: 'setting', groupId: 'setting-interface', order: 2 },
|
||||||
{ id: 'setting_api_storage', title: '系统存储配置', path: '/pages/mall/admin/setting/interface/storage', componentKey: 'SettingApiStorage', parentId: 'setting', groupId: 'setting-interface', order: 3 },
|
{ id: 'setting_api_storage', title: '系统存储配置', path: '/pages/mall/admin/setting/interface/storage', componentKey: 'SettingInterfaceStorage', parentId: 'setting', groupId: 'setting-interface', order: 3 },
|
||||||
{ id: 'setting_api_collect', title: '商品采集配置', path: '/pages/mall/admin/setting/interface/collect', componentKey: 'SettingApiCollect', parentId: 'setting', groupId: 'setting-interface', order: 4 },
|
{ id: 'setting_api_collect', title: '商品采集配置', path: '/pages/mall/admin/setting/interface/collect', componentKey: 'SettingInterfaceCollect', parentId: 'setting', groupId: 'setting-interface', order: 4 },
|
||||||
{ id: 'setting_api_logistics', title: '物流查询配置', path: '/pages/mall/admin/setting/interface/logistics', componentKey: 'SettingApiLogistics', parentId: 'setting', groupId: 'setting-interface', order: 5 },
|
{ id: 'setting_api_logistics', title: '物流查询配置', path: '/pages/mall/admin/setting/interface/logistics', componentKey: 'SettingInterfaceLogistics', parentId: 'setting', groupId: 'setting-interface', order: 5 },
|
||||||
{ id: 'setting_api_waybill', title: '电子面单配置', path: '/pages/mall/admin/setting/interface/e-sheet', componentKey: 'SettingApiWaybill', parentId: 'setting', groupId: 'setting-interface', order: 6 },
|
{ id: 'setting_api_waybill', title: '电子面单配置', path: '/pages/mall/admin/setting/interface/e-sheet', componentKey: 'SettingInterfaceESheet', parentId: 'setting', groupId: 'setting-interface', order: 6 },
|
||||||
{ id: 'setting_api_sms', title: '短信接口配置', path: '/pages/mall/admin/setting/interface/sms', componentKey: 'SettingApiSms', parentId: 'setting', groupId: 'setting-interface', order: 7 },
|
{ id: 'setting_api_sms', title: '短信接口配置', path: '/pages/mall/admin/setting/interface/sms', componentKey: 'SettingInterfaceSms', parentId: 'setting', groupId: 'setting-interface', order: 7 },
|
||||||
{ id: 'setting_api_pay', title: '商城支付配置', path: '/pages/mall/admin/setting/interface/payment', componentKey: 'SettingApiPay', parentId: 'setting', groupId: 'setting-interface', order: 8 },
|
{ id: 'setting_api_pay', title: '商城支付配置', path: '/pages/mall/admin/setting/interface/payment', componentKey: 'SettingInterfacePayment', parentId: 'setting', groupId: 'setting-interface', order: 8 },
|
||||||
|
|
||||||
// ========== 应用模块 ==========
|
// ========== 应用模块 ==========
|
||||||
{
|
// 1. 公众号
|
||||||
id: 'app_statistic',
|
{ id: 'app_wechat_menu', title: '微信菜单', path: '/pages/mall/admin/app/wechat/menu', componentKey: 'AppWechatMenu', parentId: 'app', groupId: 'app-wechat', order: 1 },
|
||||||
title: '应用统计',
|
{ id: 'app_wechat_news', title: '图文管理', path: '/pages/mall/admin/app/wechat/news', componentKey: 'AppWechatNews', parentId: 'app', groupId: 'app-wechat', order: 2 },
|
||||||
path: '/pages/mall/admin/app/statistic',
|
{ id: 'app_wechat_reply_follow', title: '关注回复', path: '/pages/mall/admin/app/wechat/reply/follow', componentKey: 'AppWechatReplyFollow', parentId: 'app', groupId: 'app-wechat', order: 3 },
|
||||||
componentKey: 'AppStatistic',
|
{ id: 'app_wechat_reply_keyword', title: '关键字回复', path: '/pages/mall/admin/app/wechat/reply/keyword', componentKey: 'AppWechatReplyKeyword', parentId: 'app', groupId: 'app-wechat', order: 4 },
|
||||||
parentId: 'app',
|
{ id: 'app_wechat_reply_invalid', title: '无效词回复', path: '/pages/mall/admin/app/wechat/reply/invalid', componentKey: 'AppWechatReplyInvalid', parentId: 'app', groupId: 'app-wechat', order: 5 },
|
||||||
groupId: 'app-manage',
|
{ id: 'app_wechat_config', title: '公众号配置', path: '/pages/mall/admin/app/wechat/config', componentKey: 'AppWechatConfig', parentId: 'app', groupId: 'app-wechat', order: 6 },
|
||||||
order: 1
|
|
||||||
},
|
// 2. 小程序
|
||||||
{
|
{ id: 'app_routine_download', title: '小程序下载', path: '/pages/mall/admin/app/routine/download', componentKey: 'AppRoutineDownload', parentId: 'app', groupId: 'app-routine', order: 1 },
|
||||||
id: 'app_list',
|
{ id: 'app_routine_config', title: '小程序配置', path: '/pages/mall/admin/app/routine/config', componentKey: 'AppRoutineConfig', parentId: 'app', groupId: 'app-routine', order: 2 },
|
||||||
title: '应用列表',
|
|
||||||
path: '/pages/mall/admin/app/list',
|
// 3. APP
|
||||||
componentKey: 'AppList',
|
{ id: 'app_mobile_config', title: 'APP配置', path: '/pages/mall/admin/app/mobile/config', componentKey: 'AppMobileConfig', parentId: 'app', groupId: 'app-mobile', order: 1 },
|
||||||
parentId: 'app',
|
{ id: 'app_mobile_version', title: '版本管理', path: '/pages/mall/admin/app/mobile/version', componentKey: 'AppMobileVersion', parentId: 'app', groupId: 'app-mobile', order: 2 },
|
||||||
groupId: 'app-manage',
|
|
||||||
order: 2
|
// 4. PC端
|
||||||
},
|
{ id: 'app_pc_design', title: 'PC端装修', path: '/pages/mall/admin/app/pc/design', componentKey: 'AppPcDesign', parentId: 'app', groupId: 'app-pc', order: 1 },
|
||||||
|
{ id: 'app_pc_config', title: 'PC端配置', path: '/pages/mall/admin/app/pc/config', componentKey: 'AppPcConfig', parentId: 'app', groupId: 'app-pc', order: 2 },
|
||||||
|
|
||||||
// ========== 维护模块 ==========
|
// ========== 维护模块 ==========
|
||||||
// 开发配置
|
// 开发配置
|
||||||
{ id: 'maintain_dev_config', title: '配置分类', path: '/pages/mall/admin/maintain/dev/config', componentKey: 'MaintainDevConfig', parentId: 'maintain', groupId: 'maintain-dev', order: 1 },
|
{ id: 'maintain_dev_config', title: '配置分类', path: '/pages/mall/admin/maintain/dev-config/category', componentKey: 'MaintainDevConfig', parentId: 'maintain', groupId: 'maintain-dev', order: 1 },
|
||||||
{ id: 'maintain_dev_data', title: '组合数据', path: '/pages/mall/admin/maintain/dev/data', componentKey: 'MaintainDevData', parentId: 'maintain', groupId: 'maintain-dev', order: 2 },
|
{ id: 'maintain_dev_data', title: '组合数据', path: '/pages/mall/admin/maintain/dev-config/combination-data', componentKey: 'MaintainDevData', parentId: 'maintain', groupId: 'maintain-dev', order: 2 },
|
||||||
{ id: 'maintain_dev_task', title: '定时任务', path: '/pages/mall/admin/maintain/dev/task', componentKey: 'MaintainDevTask', parentId: 'maintain', groupId: 'maintain-dev', order: 3 },
|
{ id: 'maintain_dev_task', title: '定时任务', path: '/pages/mall/admin/maintain/dev-config/cron-job', componentKey: 'MaintainDevTask', parentId: 'maintain', groupId: 'maintain-dev', order: 3 },
|
||||||
{ id: 'maintain_dev_auth', title: '权限维护', path: '/pages/mall/admin/maintain/dev/auth', componentKey: 'MaintainDevAuth', parentId: 'maintain', groupId: 'maintain-dev', order: 4 },
|
{ id: 'maintain_dev_auth', title: '权限维护', path: '/pages/mall/admin/maintain/dev-config/permission', componentKey: 'MaintainDevAuth', parentId: 'maintain', groupId: 'maintain-dev', order: 4 },
|
||||||
{ id: 'maintain_dev_module', title: '模块配置', path: '/pages/mall/admin/maintain/dev/module', componentKey: 'MaintainDevModule', parentId: 'maintain', groupId: 'maintain-dev', order: 5 },
|
{ id: 'maintain_dev_module', title: '模块配置', path: '/pages/mall/admin/maintain/dev-config/module-config', componentKey: 'MaintainDevModule', parentId: 'maintain', groupId: 'maintain-dev', order: 5 },
|
||||||
{ id: 'maintain_dev_event', title: '自定事件', path: '/pages/mall/admin/maintain/dev/event', componentKey: 'MaintainDevEvent', parentId: 'maintain', groupId: 'maintain-dev', order: 6 },
|
{ id: 'maintain_dev_event', title: '自定事件', path: '/pages/mall/admin/maintain/dev-config/custom-event', componentKey: 'MaintainDevEvent', parentId: 'maintain', groupId: 'maintain-dev', order: 6 },
|
||||||
|
|
||||||
// 安全维护
|
// 安全维护
|
||||||
{ id: 'maintain_security_cache', title: '刷新缓存', path: '/pages/mall/admin/maintain/security/cache', componentKey: 'MaintainSecurityCache', parentId: 'maintain', groupId: 'maintain-security', order: 1 },
|
{ id: 'maintain_security_cache', title: '刷新缓存', path: '/pages/mall/admin/maintain/security/refresh-cache', componentKey: 'MaintainSecurityCache', parentId: 'maintain', groupId: 'maintain-security', order: 1 },
|
||||||
{ id: 'maintain_security_log', title: '系统日志', path: '/pages/mall/admin/maintain/security/log', componentKey: 'MaintainSecurityLog', parentId: 'maintain', groupId: 'maintain-security', order: 2 },
|
{ id: 'maintain_security_log', title: '系统日志', path: '/pages/mall/admin/maintain/security/system-log', componentKey: 'MaintainSecurityLog', parentId: 'maintain', groupId: 'maintain-security', order: 2 },
|
||||||
{ id: 'maintain_security_upgrade', title: '在线升级', path: '/pages/mall/admin/maintain/security/upgrade', componentKey: 'MaintainSecurityUpgrade', parentId: 'maintain', groupId: 'maintain-security', order: 3 },
|
{ id: 'maintain_security_upgrade', title: '在线升级', path: '/pages/mall/admin/maintain/security/online-upgrade', componentKey: 'MaintainSecurityUpgrade', parentId: 'maintain', groupId: 'maintain-security', order: 3 },
|
||||||
|
|
||||||
// 数据维护
|
// 数据维护
|
||||||
{ id: 'maintain_data_logistics', title: '物流公司', path: '/pages/mall/admin/maintain/data/logistics', componentKey: 'MaintainDataLogistics', parentId: 'maintain', groupId: 'maintain-data', order: 1 },
|
{ id: 'maintain_data_logistics', title: '物流公司', path: '/pages/mall/admin/maintain/data/logistics', componentKey: 'MaintainDataLogistics', parentId: 'maintain', groupId: 'maintain-data', order: 1 },
|
||||||
@@ -1321,10 +1154,10 @@ export const routes: RouteRecord[] = [
|
|||||||
{ id: 'maintain_lang_config', title: '翻译配置', path: '/pages/mall/admin/maintain/lang/config', componentKey: 'MaintainLangConfig', parentId: 'maintain', groupId: 'maintain-lang', order: 4 },
|
{ id: 'maintain_lang_config', title: '翻译配置', path: '/pages/mall/admin/maintain/lang/config', componentKey: 'MaintainLangConfig', parentId: 'maintain', groupId: 'maintain-lang', order: 4 },
|
||||||
|
|
||||||
// 开发工具
|
// 开发工具
|
||||||
{ id: 'maintain_tool_db', title: '数据库管理', path: '/pages/mall/admin/maintain/tool/db', componentKey: 'MaintainToolDb', parentId: 'maintain', groupId: 'maintain-tool', order: 1 },
|
{ id: 'maintain_tool_db', title: '数据库管理', path: '/pages/mall/admin/maintain/dev-tools/database', componentKey: 'MaintainToolDb', parentId: 'maintain', groupId: 'maintain-tool', order: 1 },
|
||||||
{ id: 'maintain_tool_file', title: '文件管理', path: '/pages/mall/admin/maintain/tool/file', componentKey: 'MaintainToolFile', parentId: 'maintain', groupId: 'maintain-tool', order: 2 },
|
{ id: 'maintain_tool_file', title: '文件管理', path: '/pages/mall/admin/maintain/dev-tools/file', componentKey: 'MaintainToolFile', parentId: 'maintain', groupId: 'maintain-tool', order: 2 },
|
||||||
{ id: 'maintain_tool_api', title: '接口管理', path: '/pages/mall/admin/maintain/tool/api', componentKey: 'MaintainToolApi', parentId: 'maintain', groupId: 'maintain-tool', order: 3 },
|
{ id: 'maintain_tool_api', title: '接口管理', path: '/pages/mall/admin/maintain/dev-tools/api', componentKey: 'MaintainToolApi', parentId: 'maintain', groupId: 'maintain-tool', order: 3 },
|
||||||
{ id: 'maintain_tool_dic', title: '数据字典', path: '/pages/mall/admin/maintain/tool/dic', componentKey: 'MaintainToolDic', parentId: 'maintain', groupId: 'maintain-tool', order: 4 },
|
{ id: 'maintain_tool_dic', title: '数据字典', path: '/pages/mall/admin/maintain/dev-tools/data-dict', componentKey: 'MaintainToolDic', parentId: 'maintain', groupId: 'maintain-tool', order: 4 },
|
||||||
|
|
||||||
// 系统信息
|
// 系统信息
|
||||||
{ id: 'maintain_sys_info', title: '系统信息', path: '/pages/mall/admin/maintain/sys/info', componentKey: 'MaintainSysInfo', parentId: 'maintain', groupId: 'maintain-sys', order: 1 }
|
{ id: 'maintain_sys_info', title: '系统信息', path: '/pages/mall/admin/maintain/sys/info', componentKey: 'MaintainSysInfo', parentId: 'maintain', groupId: 'maintain-sys', order: 1 }
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ export const settingSubSiderMenu: MenuNode[] = [
|
|||||||
{ id: 'setting_delivery_courier', title: '配送员管理', type: 'page', path: '/pages/mall/admin/setting/delivery/staff' },
|
{ id: 'setting_delivery_courier', title: '配送员管理', type: 'page', path: '/pages/mall/admin/setting/delivery/staff' },
|
||||||
{ id: 'pickup_order_group', title: '提货点设置', type: 'group', children: [
|
{ id: 'pickup_order_group', title: '提货点设置', type: 'group', children: [
|
||||||
{ id: 'setting_delivery_pickup_list', title: '提货点', type: 'page', path: '/pages/mall/admin/setting/delivery/station' },
|
{ id: 'setting_delivery_pickup_list', title: '提货点', type: 'page', path: '/pages/mall/admin/setting/delivery/station' },
|
||||||
{ id: 'setting_delivery_verifier', title: '核销员', type: 'page', path: '/pages/mall/admin/setting/delivery/station' },
|
{ id: 'setting_delivery_verifier', title: '核销员', type: 'page', path: '/pages/mall/admin/setting/delivery/verifier' },
|
||||||
{ id: 'setting_delivery_freight', title: '运费模板', type: 'page', path: '/pages/mall/admin/setting/delivery/template' }
|
{ id: 'setting_delivery_freight', title: '运费模板', type: 'page', path: '/pages/mall/admin/setting/delivery/template' }
|
||||||
]}
|
]}
|
||||||
]
|
]
|
||||||
|
|||||||
238
pages.json
238
pages.json
@@ -605,6 +605,244 @@
|
|||||||
"style": {
|
"style": {
|
||||||
"navigationBarTitleText": "签到记录"
|
"navigationBarTitleText": "签到记录"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "maintain/dev-tools/database",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "数据库管理",
|
||||||
|
"navigationStyle": "custom"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "maintain/dev-tools/file",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "文件管理",
|
||||||
|
"navigationStyle": "custom"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "maintain/dev-tools/api",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "接口管理",
|
||||||
|
"navigationStyle": "custom"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "maintain/dev-tools/data-dict",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "数据字典",
|
||||||
|
"navigationStyle": "custom"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "setting/message",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "消息管理",
|
||||||
|
"navigationStyle": "custom"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "setting/agreement",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "协议设置",
|
||||||
|
"navigationStyle": "custom"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "setting/ticket",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "小票配置",
|
||||||
|
"navigationStyle": "custom"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "setting/auth/admin",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "管理员管理",
|
||||||
|
"navigationStyle": "custom"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "setting/auth/role",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "角色管理",
|
||||||
|
"navigationStyle": "custom"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "setting/auth/permission",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "权限规则",
|
||||||
|
"navigationStyle": "custom"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "setting/delivery/staff",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "配送员管理",
|
||||||
|
"navigationStyle": "custom"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "setting/delivery/station",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "提货点",
|
||||||
|
"navigationStyle": "custom"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "setting/delivery/verifier",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "核销员",
|
||||||
|
"navigationStyle": "custom"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "setting/delivery/template",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "运费模板",
|
||||||
|
"navigationStyle": "custom"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "setting/interface/onepass/index",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "一号通账户",
|
||||||
|
"navigationStyle": "custom"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "setting/interface/onepass/config",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "一号通配置",
|
||||||
|
"navigationStyle": "custom"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "setting/interface/storage",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "系统存储配置",
|
||||||
|
"navigationStyle": "custom"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "setting/interface/collect",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "商品采集配置",
|
||||||
|
"navigationStyle": "custom"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "setting/interface/logistics",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "物流查询配置",
|
||||||
|
"navigationStyle": "custom"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "setting/interface/e-sheet",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "电子面单配置",
|
||||||
|
"navigationStyle": "custom"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "setting/interface/sms",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "短信功能配置",
|
||||||
|
"navigationStyle": "custom"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "setting/interface/payment",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "商城支付配置",
|
||||||
|
"navigationStyle": "custom"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "app/wechat/menu",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "微信菜单",
|
||||||
|
"navigationStyle": "custom"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "app/wechat/news",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "图文管理",
|
||||||
|
"navigationStyle": "custom"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "app/wechat/reply/follow",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "微信关注回复",
|
||||||
|
"navigationStyle": "custom"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "app/wechat/reply/keyword",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "关键字回复",
|
||||||
|
"navigationStyle": "custom"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "app/wechat/reply/invalid",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "无效关键词回复",
|
||||||
|
"navigationStyle": "custom"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "app/wechat/config",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "公众号配置",
|
||||||
|
"navigationStyle": "custom"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "app/routine/download",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "小程序下载",
|
||||||
|
"navigationStyle": "custom"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "app/routine/config",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "小程序配置",
|
||||||
|
"navigationStyle": "custom"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "app/mobile/config",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "APP配置",
|
||||||
|
"navigationStyle": "custom"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "app/mobile/version",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "版本管理",
|
||||||
|
"navigationStyle": "custom"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "app/pc/design",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "PC端装修",
|
||||||
|
"navigationStyle": "custom"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "app/pc/config",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "PC端配置",
|
||||||
|
"navigationStyle": "custom"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|||||||
70
pages/mall/admin/app/mobile/config.uvue
Normal file
70
pages/mall/admin/app/mobile/config.uvue
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
<template>
|
||||||
|
<view class="admin-page">
|
||||||
|
<view class="admin-card content-card">
|
||||||
|
<view class="tabs-row">
|
||||||
|
<view class="tab-item active">APP配置</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="config-form">
|
||||||
|
<view class="form-item">
|
||||||
|
<text class="label">APPID:</text>
|
||||||
|
<input class="form-input" value="wx277a269f3d736d67" />
|
||||||
|
<text class="tip">微信开放平台申请移动应用后给予的APPID</text>
|
||||||
|
</view>
|
||||||
|
<view class="form-item">
|
||||||
|
<text class="label">AppSecret:</text>
|
||||||
|
<input class="form-input" value="bd08741a055c2ecac5826ff1c048464b" />
|
||||||
|
<text class="tip">微信开放平台申请移动应用后给予的AppSecret</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="form-btns">
|
||||||
|
<button class="btn primary">提交</button>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="uts">
|
||||||
|
// APP配置逻辑
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.config-form {
|
||||||
|
padding: 40px 10%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-item {
|
||||||
|
margin-bottom: 30px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-item .label {
|
||||||
|
font-weight: bold;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
color: #303133;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-input {
|
||||||
|
border: 1px solid #dcdfe6;
|
||||||
|
padding: 10px 15px;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tip {
|
||||||
|
font-size: 12px;
|
||||||
|
color: #909399;
|
||||||
|
margin-top: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-btns {
|
||||||
|
margin-top: 50px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn.primary {
|
||||||
|
width: 80px;
|
||||||
|
background-color: #2d8cf0;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
179
pages/mall/admin/app/mobile/version.uvue
Normal file
179
pages/mall/admin/app/mobile/version.uvue
Normal file
@@ -0,0 +1,179 @@
|
|||||||
|
|
||||||
|
<template>
|
||||||
|
<view class="admin-page">
|
||||||
|
<view class="action-bar">
|
||||||
|
<button class="btn primary" @click="handlePublish">发布版本</button>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="admin-card content-card">
|
||||||
|
<view class="admin-table">
|
||||||
|
<!-- 表头 -->
|
||||||
|
<view class="table-header">
|
||||||
|
<view class="col col-version"><text>版本号</text></view>
|
||||||
|
<view class="col col-platform"><text>平台类型</text></view>
|
||||||
|
<view class="col col-info"><text>升级信息</text></view>
|
||||||
|
<view class="col col-force"><text>是否强制</text></view>
|
||||||
|
<view class="col col-date"><text>发布日期</text></view>
|
||||||
|
<view class="col col-url"><text>下载地址</text></view>
|
||||||
|
<view class="col col-ops"><text>操作</text></view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 表格内容 -->
|
||||||
|
<view class="table-body">
|
||||||
|
<view v-if="versionList.length === 0" class="table-empty">
|
||||||
|
<text class="empty-txt">暂无数据</text>
|
||||||
|
</view>
|
||||||
|
<view v-for="item in versionList" :key="item.id" class="table-row">
|
||||||
|
<view class="col col-version"><text>{{ item.version }}</text></view>
|
||||||
|
<view class="col col-platform"><text>{{ item.platform }}</text></view>
|
||||||
|
<view class="col col-info"><text>{{ item.info }}</text></view>
|
||||||
|
<view class="col col-force"><text>{{ item.isForce ? '是' : '否' }}</text></view>
|
||||||
|
<view class="col col-date"><text>{{ item.date }}</text></view>
|
||||||
|
<view class="col col-url"><text class="link">{{ item.url }}</text></view>
|
||||||
|
<view class="col col-ops">
|
||||||
|
<text class="op-link" @click="handleEdit(item)">编辑</text>
|
||||||
|
<text class="op-split">|</text>
|
||||||
|
<text class="op-link delete" @click="handleDelete(item)">删除</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="uts">
|
||||||
|
import { ref } from 'vue'
|
||||||
|
|
||||||
|
interface VersionItem {
|
||||||
|
id: number
|
||||||
|
version: string
|
||||||
|
platform: string
|
||||||
|
info: string
|
||||||
|
isForce: boolean
|
||||||
|
date: string
|
||||||
|
url: string
|
||||||
|
}
|
||||||
|
|
||||||
|
const versionList = ref<VersionItem[]>([])
|
||||||
|
|
||||||
|
const handlePublish = () => {
|
||||||
|
uni.showToast({ title: '暂不支持发布', icon: 'none' })
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleEdit = (item: VersionItem) => {
|
||||||
|
console.log('Edit', item)
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleDelete = (item: VersionItem) => {
|
||||||
|
uni.showModal({
|
||||||
|
title: '提示',
|
||||||
|
content: '确定要删除该版本吗?',
|
||||||
|
success: (res) => {
|
||||||
|
if (res.confirm) {
|
||||||
|
uni.showToast({ title: '删除成功', icon: 'success' })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.admin-page {
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-bar {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn.primary {
|
||||||
|
width: 100px !important;
|
||||||
|
height: 36px !important;
|
||||||
|
line-height: 36px !important;
|
||||||
|
background: #1890ff !important;
|
||||||
|
color: #fff !important;
|
||||||
|
font-size: 14px !important;
|
||||||
|
border-radius: 4px !important;
|
||||||
|
text-align: center !important;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content-card {
|
||||||
|
background: #fff;
|
||||||
|
border-radius: 4px;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-table {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-header {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
background: #fafafa;
|
||||||
|
border-bottom: 1px solid #f0f0f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.col {
|
||||||
|
padding: 12px 15px;
|
||||||
|
font-size: 14px;
|
||||||
|
color: #333;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
&.col-version { width: 100px; }
|
||||||
|
&.col-platform { width: 120px; }
|
||||||
|
&.col-info { flex: 1; }
|
||||||
|
&.col-force { width: 100px; }
|
||||||
|
&.col-date { width: 150px; }
|
||||||
|
&.col-url { width: 200px; }
|
||||||
|
&.col-ops { width: 120px; justify-content: center; }
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-header .col {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-row {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
border-bottom: 1px solid #f0f0f0;
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-empty {
|
||||||
|
padding: 100px 0;
|
||||||
|
text-align: center;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
.empty-txt {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.link {
|
||||||
|
color: #1890ff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.op-link {
|
||||||
|
color: #1890ff;
|
||||||
|
font-size: 14px;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
&.delete {
|
||||||
|
color: #ff4d4f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.op-split {
|
||||||
|
margin: 0 8px;
|
||||||
|
color: #e8e8e8;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
311
pages/mall/admin/app/pc/config.uvue
Normal file
311
pages/mall/admin/app/pc/config.uvue
Normal file
@@ -0,0 +1,311 @@
|
|||||||
|
|
||||||
|
<template>
|
||||||
|
<view class="admin-page">
|
||||||
|
<view class="admin-card content-card">
|
||||||
|
<view class="tabs-row">
|
||||||
|
<view class="tab-item active">
|
||||||
|
<text class="tab-text">PC站点配置</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="config-form">
|
||||||
|
<view class="form-item row">
|
||||||
|
<text class="label">PC端LOGO:</text>
|
||||||
|
<view class="form-content">
|
||||||
|
<view class="logo-upload" @click="handleUploadLogo">
|
||||||
|
<image v-if="config.logo" :src="config.logo" mode="aspectFit" class="logo-preview" />
|
||||||
|
<view v-else class="upload-placeholder">
|
||||||
|
<text class="plus">+</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<text class="tip">PC端LOGO</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="form-item row">
|
||||||
|
<text class="label">联系电话:</text>
|
||||||
|
<view class="form-content">
|
||||||
|
<input class="form-input" v-model="config.phone" placeholder="400-8888-794" />
|
||||||
|
<text class="tip">PC底部显示的联系电话</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="form-item row">
|
||||||
|
<text class="label">公司地址:</text>
|
||||||
|
<view class="form-content">
|
||||||
|
<input class="form-input" v-model="config.address" placeholder="陕西省西安市..." />
|
||||||
|
<text class="tip">PC底部显示的公司地址</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="form-item row">
|
||||||
|
<text class="label">关键词:</text>
|
||||||
|
<view class="form-content">
|
||||||
|
<input class="form-input" v-model="config.keywords" placeholder="请输入关键词" />
|
||||||
|
<text class="tip">网站关键词</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="form-item row">
|
||||||
|
<text class="label">网站描述:</text>
|
||||||
|
<view class="form-content">
|
||||||
|
<textarea class="form-textarea" v-model="config.description" placeholder="网站描述" />
|
||||||
|
<text class="tip">网站描述</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="form-item row">
|
||||||
|
<text class="label">二维码类型:</text>
|
||||||
|
<view class="form-content">
|
||||||
|
<view class="radio-group">
|
||||||
|
<view class="radio-item" @click="config.qrCodeType = 'official'">
|
||||||
|
<view class="radio-circle" :class="{ active: config.qrCodeType === 'official' }"></view>
|
||||||
|
<text class="radio-text">公众号</text>
|
||||||
|
</view>
|
||||||
|
<view class="radio-item" @click="config.qrCodeType = 'routine'">
|
||||||
|
<view class="radio-circle" :class="{ active: config.qrCodeType === 'routine' }"></view>
|
||||||
|
<text class="radio-text">小程序</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<text class="tip">商品详情手机购买显示公众号或者小程序码</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="form-item row">
|
||||||
|
<text class="label">精品推荐个数:</text>
|
||||||
|
<view class="form-content">
|
||||||
|
<input class="form-input" type="number" v-model="config.recommendCount" placeholder="3" />
|
||||||
|
<text class="tip">首页配置精品推荐个数</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="form-item row">
|
||||||
|
<text class="label">首发新品个数:</text>
|
||||||
|
<view class="form-content">
|
||||||
|
<input class="form-input" type="number" v-model="config.newProductCount" placeholder="5" />
|
||||||
|
<text class="tip">首页配置首发新品个数</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="form-btns">
|
||||||
|
<button class="btn primary" @click="handleSubmit">提交</button>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="uts">
|
||||||
|
import { ref } from 'vue'
|
||||||
|
|
||||||
|
const config = ref({
|
||||||
|
logo: 'https://v5.crmeb.net/uploads/attach/2022/05/20220516/6198f7e6f8a8b.png',
|
||||||
|
phone: '400-8888-794',
|
||||||
|
address: '陕西省西安市西咸新区洋东新城能源金融贸易区金湾大厦3层',
|
||||||
|
keywords: '',
|
||||||
|
description: '',
|
||||||
|
qrCodeType: 'routine',
|
||||||
|
recommendCount: 3,
|
||||||
|
newProductCount: 5
|
||||||
|
})
|
||||||
|
|
||||||
|
const handleUploadLogo = () => {
|
||||||
|
uni.chooseImage({
|
||||||
|
count: 1,
|
||||||
|
success: (res) => {
|
||||||
|
config.value.logo = res.tempFilePaths[0]
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleSubmit = () => {
|
||||||
|
uni.showToast({ title: '保存成功', icon: 'success' })
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.admin-page {
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content-card {
|
||||||
|
background: #fff;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tabs-row {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
border-bottom: 1px solid #f0f0f0;
|
||||||
|
padding: 0 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-item {
|
||||||
|
padding: 15px 20px;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
&.active {
|
||||||
|
.tab-text {
|
||||||
|
color: #1890ff;
|
||||||
|
}
|
||||||
|
&::after {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
height: 2px;
|
||||||
|
background: #1890ff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-text {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.config-form {
|
||||||
|
padding: 30px 20px;
|
||||||
|
max-width: 800px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-item {
|
||||||
|
margin-bottom: 25px;
|
||||||
|
|
||||||
|
&.row {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: flex-start;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.label {
|
||||||
|
width: 140px;
|
||||||
|
text-align: right;
|
||||||
|
font-size: 14px;
|
||||||
|
color: #333;
|
||||||
|
padding-top: 8px;
|
||||||
|
margin-right: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-content {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.logo-upload {
|
||||||
|
width: 80px;
|
||||||
|
height: 80px;
|
||||||
|
border: 1px dashed #dcdee2;
|
||||||
|
border-radius: 4px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
border-color: #1890ff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.logo-preview {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.upload-placeholder {
|
||||||
|
.plus {
|
||||||
|
font-size: 24px;
|
||||||
|
color: #ccc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-input {
|
||||||
|
width: 100%;
|
||||||
|
max-width: 460px;
|
||||||
|
height: 36px;
|
||||||
|
border: 1px solid #dcdee2;
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 0 12px;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-textarea {
|
||||||
|
width: 100%;
|
||||||
|
max-width: 460px;
|
||||||
|
height: 100px;
|
||||||
|
border: 1px solid #dcdee2;
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 8px 12px;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tip {
|
||||||
|
display: block;
|
||||||
|
font-size: 12px;
|
||||||
|
color: #999;
|
||||||
|
margin-top: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.radio-group {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
height: 36px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.radio-item {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
margin-right: 25px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.radio-circle {
|
||||||
|
width: 16px;
|
||||||
|
height: 16px;
|
||||||
|
border: 1px solid #dcdee2;
|
||||||
|
border-radius: 50%;
|
||||||
|
margin-right: 6px;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
&.active {
|
||||||
|
border-color: #1890ff;
|
||||||
|
&::after {
|
||||||
|
content: '';
|
||||||
|
width: 8px;
|
||||||
|
height: 8px;
|
||||||
|
background: #1890ff;
|
||||||
|
border-radius: 50%;
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.radio-text {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-btns {
|
||||||
|
margin-top: 40px;
|
||||||
|
padding-left: 155px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn.primary {
|
||||||
|
width: 64px;
|
||||||
|
height: 32px;
|
||||||
|
line-height: 32px;
|
||||||
|
background: #1890ff;
|
||||||
|
color: #fff;
|
||||||
|
font-size: 14px;
|
||||||
|
border-radius: 4px;
|
||||||
|
text-align: center;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
223
pages/mall/admin/app/pc/design.uvue
Normal file
223
pages/mall/admin/app/pc/design.uvue
Normal file
@@ -0,0 +1,223 @@
|
|||||||
|
<template>
|
||||||
|
<view class="admin-page">
|
||||||
|
<view class="admin-card header-card">
|
||||||
|
<view class="title-row">
|
||||||
|
<view class="breadcrumb">
|
||||||
|
<text class="back">返回</text>
|
||||||
|
<text class="sep">/</text>
|
||||||
|
<text class="current">PC端装修</text>
|
||||||
|
</view>
|
||||||
|
<button class="btn primary">保存</button>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="admin-card content-card pc-design-container">
|
||||||
|
<!-- 左侧二级菜单 -->
|
||||||
|
<view class="side-menu">
|
||||||
|
<view
|
||||||
|
v-for="item in menuItems"
|
||||||
|
:key="item.id"
|
||||||
|
class="menu-item"
|
||||||
|
:class="{ active: activeMenu === item.id }"
|
||||||
|
@click="activeMenu = item.id"
|
||||||
|
>
|
||||||
|
{{ item.title }}
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 中间预览区 -->
|
||||||
|
<view class="preview-area">
|
||||||
|
<view class="preview-header">
|
||||||
|
<view class="dot-wrap">
|
||||||
|
<view class="dot"></view>
|
||||||
|
<view class="dot"></view>
|
||||||
|
<view class="dot"></view>
|
||||||
|
</view>
|
||||||
|
<view class="search-bar-sim"></view>
|
||||||
|
</view>
|
||||||
|
<view class="preview-body">
|
||||||
|
<image
|
||||||
|
class="mock-pc"
|
||||||
|
src="/static/placeholder.png"
|
||||||
|
mode="aspectFit"
|
||||||
|
></image>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 右侧设置区 -->
|
||||||
|
<view class="setting-area">
|
||||||
|
<view class="box-title">
|
||||||
|
<view class="line"></view>
|
||||||
|
<text class="text">页面设置</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="setting-form">
|
||||||
|
<view class="setting-item">
|
||||||
|
<text class="label">建议尺寸:140px * 60px</text>
|
||||||
|
<text class="desc">除LOGO图标外,页面其他内容仅供参考</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="logo-uploader">
|
||||||
|
<image class="logo-preview" src="/static/placeholder.png"></image>
|
||||||
|
<view class="upload-mask">更换图片</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="uts">
|
||||||
|
import { ref } from 'vue'
|
||||||
|
|
||||||
|
const activeMenu = ref('logo')
|
||||||
|
|
||||||
|
const menuItems = [
|
||||||
|
{ id: 'logo', title: '网站LOGO' },
|
||||||
|
{ id: 'banner', title: '首页轮播图' },
|
||||||
|
{ id: 'ad', title: '客服页面广告' },
|
||||||
|
{ id: 'menu', title: '顶部菜单配置' },
|
||||||
|
{ id: 'friend', title: '友情链接配置' },
|
||||||
|
{ id: 'about', title: '关于我们' }
|
||||||
|
]
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.pc-design-container {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
height: 700px;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.side-menu {
|
||||||
|
width: 160px;
|
||||||
|
border-right: 1px solid #ebeef5;
|
||||||
|
padding: 20px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.menu-item {
|
||||||
|
height: 50px;
|
||||||
|
line-height: 50px;
|
||||||
|
padding: 0 25px;
|
||||||
|
font-size: 14px;
|
||||||
|
color: #2d8cf0;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.menu-item.active {
|
||||||
|
background-color: #f0f7ff;
|
||||||
|
border-right: 2px solid #2d8cf0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.preview-area {
|
||||||
|
flex: 1;
|
||||||
|
background-color: #f5f7fa;
|
||||||
|
padding: 40px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.preview-header {
|
||||||
|
height: 30px;
|
||||||
|
background-color: #fff;
|
||||||
|
border-radius: 4px 4px 0 0;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
padding: 0 10px;
|
||||||
|
gap: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dot-wrap {
|
||||||
|
display: flex;
|
||||||
|
gap: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dot {
|
||||||
|
width: 8px;
|
||||||
|
height: 8px;
|
||||||
|
border-radius: 50%;
|
||||||
|
background-color: #ddd;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-bar-sim {
|
||||||
|
width: 200px;
|
||||||
|
height: 14px;
|
||||||
|
background-color: #f5f5f5;
|
||||||
|
border-radius: 7px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mock-pc {
|
||||||
|
width: 100%;
|
||||||
|
flex: 1;
|
||||||
|
background-color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.setting-area {
|
||||||
|
width: 300px;
|
||||||
|
border-left: 1px solid #ebeef5;
|
||||||
|
padding: 25px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.box-title {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 25px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.box-title .line {
|
||||||
|
width: 2px;
|
||||||
|
height: 14px;
|
||||||
|
background-color: #2d8cf0;
|
||||||
|
margin-right: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.box-title .text {
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.setting-item {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.setting-item .label {
|
||||||
|
display: block;
|
||||||
|
font-size: 12px;
|
||||||
|
color: #909399;
|
||||||
|
margin-bottom: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.setting-item .desc {
|
||||||
|
display: block;
|
||||||
|
font-size: 12px;
|
||||||
|
color: #c0c4cc;
|
||||||
|
}
|
||||||
|
|
||||||
|
.logo-uploader {
|
||||||
|
width: 120px;
|
||||||
|
height: 80px;
|
||||||
|
border: 1px dashed #dcdfe6;
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.logo-preview {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.upload-mask {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 24px;
|
||||||
|
line-height: 24px;
|
||||||
|
background-color: rgba(0,0,0,0.5);
|
||||||
|
color: #fff;
|
||||||
|
font-size: 12px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
379
pages/mall/admin/app/routine/config.uvue
Normal file
379
pages/mall/admin/app/routine/config.uvue
Normal file
@@ -0,0 +1,379 @@
|
|||||||
|
|
||||||
|
<template>
|
||||||
|
<view class="admin-page">
|
||||||
|
<view class="admin-card content-card">
|
||||||
|
<!-- Tabs (1:1 CRMEB Style) -->
|
||||||
|
<view class="tabs-row">
|
||||||
|
<view
|
||||||
|
class="tab-item"
|
||||||
|
:class="{ active: activeTab === 'config' }"
|
||||||
|
@click="activeTab = 'config'"
|
||||||
|
>
|
||||||
|
<text class="tab-text">小程序配置</text>
|
||||||
|
</view>
|
||||||
|
<view
|
||||||
|
class="tab-item"
|
||||||
|
:class="{ active: activeTab === 'message' }"
|
||||||
|
@click="activeTab = 'message'"
|
||||||
|
>
|
||||||
|
<text class="tab-text">消息推送配置</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- Form Area -->
|
||||||
|
<view class="config-content">
|
||||||
|
<!-- Tab 1: 小程序配置 (Image 1) -->
|
||||||
|
<view v-if="activeTab === 'config'" class="form-body">
|
||||||
|
<view class="form-item row">
|
||||||
|
<text class="label">小程序名称:</text>
|
||||||
|
<view class="form-content">
|
||||||
|
<input class="form-input" v-model="config.name" placeholder="请输入小程序名称" />
|
||||||
|
<text class="tip">小程序名称</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="form-item row">
|
||||||
|
<text class="label">客服类型:</text>
|
||||||
|
<view class="form-content">
|
||||||
|
<view class="radio-group">
|
||||||
|
<view class="radio-item" @click="config.kefuType = 'system'">
|
||||||
|
<view class="radio-circle" :class="{ checked: config.kefuType === 'system' }"></view>
|
||||||
|
<text class="radio-text">跟随系统</text>
|
||||||
|
</view>
|
||||||
|
<view class="radio-item" @click="config.kefuType = 'routine'">
|
||||||
|
<view class="radio-circle" :class="{ checked: config.kefuType === 'routine' }"></view>
|
||||||
|
<text class="radio-text">小程序客服</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<text class="tip line-height-tip">跟随系统:跟随系统使用默认客服、电话或者跳转链接;小程序客服:需要在小程序后台配置客服用户;</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="form-item row">
|
||||||
|
<text class="label">手机号获取方式:</text>
|
||||||
|
<view class="form-content">
|
||||||
|
<view class="checkbox-group">
|
||||||
|
<view class="checkbox-item" @click="config.authPhone = !config.authPhone">
|
||||||
|
<view class="checkbox-box" :class="{ checked: config.authPhone }">
|
||||||
|
<text v-if="config.authPhone" class="check-ic">v</text>
|
||||||
|
</view>
|
||||||
|
<text class="checkbox-text">微信授权</text>
|
||||||
|
</view>
|
||||||
|
<view class="checkbox-item" @click="config.manualPhone = !config.manualPhone">
|
||||||
|
<view class="checkbox-box" :class="{ checked: config.manualPhone }">
|
||||||
|
<text v-if="config.manualPhone" class="check-ic">v</text>
|
||||||
|
</view>
|
||||||
|
<text class="checkbox-text">手动填写</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<text class="tip">小程序获取手机号的方式,微信授权和手机号验证码</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="form-item row">
|
||||||
|
<text class="label">强制获取昵称头像:</text>
|
||||||
|
<view class="form-content">
|
||||||
|
<view class="radio-group">
|
||||||
|
<view class="radio-item" @click="config.forceUserInfo = true">
|
||||||
|
<view class="radio-circle" :class="{ checked: config.forceUserInfo }"></view>
|
||||||
|
<text class="radio-text">开启</text>
|
||||||
|
</view>
|
||||||
|
<view class="radio-item" @click="config.forceUserInfo = false">
|
||||||
|
<view class="radio-circle" :class="{ checked: !config.forceUserInfo }"></view>
|
||||||
|
<text class="radio-text">关闭</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<text class="tip">是否在小程序用户授权之后,弹窗获取用户的昵称和头像</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="form-item row">
|
||||||
|
<text class="label">发货信息管理:</text>
|
||||||
|
<view class="form-content">
|
||||||
|
<view class="radio-group">
|
||||||
|
<view class="radio-item" @click="config.deliveryInfo = true">
|
||||||
|
<view class="radio-circle" :class="{ checked: config.deliveryInfo }"></view>
|
||||||
|
<text class="radio-text">开启</text>
|
||||||
|
</view>
|
||||||
|
<view class="radio-item" @click="config.deliveryInfo = false">
|
||||||
|
<view class="radio-circle" :class="{ checked: !config.deliveryInfo }"></view>
|
||||||
|
<text class="radio-text">关闭</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<text class="tip line-height-tip">小程序有订单发货管理时,请打开此开关,否则会导致订单资金冻结</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="form-btns">
|
||||||
|
<button class="btn primary" @click="handleSubmit">提交</button>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- Tab 2: 消息推送配置 (Image 2) -->
|
||||||
|
<view v-if="activeTab === 'message'" class="form-body">
|
||||||
|
<view class="form-item row">
|
||||||
|
<text class="label">接口地址:</text>
|
||||||
|
<view class="form-content">
|
||||||
|
<input class="form-input readonly" v-model="messageConfig.apiUrl" readonly />
|
||||||
|
<text class="tip">配置小程序消息推送使用的接口地址,直接复制输入框内容(此项系统生成,无法修改)</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="form-item row">
|
||||||
|
<text class="label">小程序验证TOKEN:</text>
|
||||||
|
<view class="form-content">
|
||||||
|
<input class="form-input" v-model="messageConfig.token" placeholder="请输入小程序验证TOKEN" />
|
||||||
|
<text class="tip">小程序验证TOKEN</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="form-item row">
|
||||||
|
<text class="label">消息加解密方式:</text>
|
||||||
|
<view class="form-content">
|
||||||
|
<view class="radio-group">
|
||||||
|
<view class="radio-item" @click="messageConfig.encryptMode = 'plain'">
|
||||||
|
<view class="radio-circle" :class="{ checked: messageConfig.encryptMode === 'plain' }"></view>
|
||||||
|
<text class="radio-text">明文模式</text>
|
||||||
|
</view>
|
||||||
|
<view class="radio-item" @click="messageConfig.encryptMode = 'compat'">
|
||||||
|
<view class="radio-circle" :class="{ checked: messageConfig.encryptMode === 'compat' }"></view>
|
||||||
|
<text class="radio-text">兼容模式</text>
|
||||||
|
</view>
|
||||||
|
<view class="radio-item" @click="messageConfig.encryptMode = 'safe'">
|
||||||
|
<view class="radio-circle" :class="{ checked: messageConfig.encryptMode === 'safe' }"></view>
|
||||||
|
<text class="radio-text">安全模式</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<text class="tip">小程序消息推送中的消息加密方式,暂时仅支持明文模式</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="form-item row">
|
||||||
|
<text class="label">EncodingAESKey:</text>
|
||||||
|
<view class="form-content">
|
||||||
|
<input class="form-input" v-model="messageConfig.aesKey" placeholder="请输入EncodingAESKey" />
|
||||||
|
<text class="tip">消息加密密钥由43位字符组成,字符范围为A-Z,a-z,0-9</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="form-btns">
|
||||||
|
<button class="btn primary" @click="handleSubmit">提交</button>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="uts">
|
||||||
|
import { ref } from 'vue'
|
||||||
|
|
||||||
|
const activeTab = ref('config')
|
||||||
|
|
||||||
|
const config = ref({
|
||||||
|
name: 'CRMEB标准版',
|
||||||
|
kefuType: 'system',
|
||||||
|
authPhone: true,
|
||||||
|
manualPhone: false,
|
||||||
|
forceUserInfo: true,
|
||||||
|
deliveryInfo: true
|
||||||
|
})
|
||||||
|
|
||||||
|
const messageConfig = ref({
|
||||||
|
apiUrl: 'https://v5.crmeb.net/api/wechat/miniServe',
|
||||||
|
token: '',
|
||||||
|
encryptMode: 'plain',
|
||||||
|
aesKey: ''
|
||||||
|
})
|
||||||
|
|
||||||
|
function handleSubmit() {
|
||||||
|
uni.showToast({
|
||||||
|
title: '保存成功',
|
||||||
|
icon: 'success'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.admin-page {
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content-card {
|
||||||
|
background: #fff;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tabs-row {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
border-bottom: 1px solid #f0f0f0;
|
||||||
|
padding: 0 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-item {
|
||||||
|
padding: 16px 20px;
|
||||||
|
cursor: pointer;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
&.active {
|
||||||
|
.tab-text {
|
||||||
|
color: #1890ff;
|
||||||
|
}
|
||||||
|
&::after {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
height: 2px;
|
||||||
|
background: #1890ff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-text {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
|
||||||
|
.config-content {
|
||||||
|
padding: 30px 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-body {
|
||||||
|
max-width: 800px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-item {
|
||||||
|
margin-bottom: 25px;
|
||||||
|
|
||||||
|
&.row {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: flex-start;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.label {
|
||||||
|
width: 140px;
|
||||||
|
text-align: right;
|
||||||
|
font-size: 14px;
|
||||||
|
color: #333;
|
||||||
|
padding-top: 8px;
|
||||||
|
margin-right: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-content {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-input {
|
||||||
|
width: 100%;
|
||||||
|
max-width: 460px;
|
||||||
|
height: 34px;
|
||||||
|
border: 1px solid #dcdee2;
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 0 12px;
|
||||||
|
font-size: 14px;
|
||||||
|
|
||||||
|
&.readonly {
|
||||||
|
background-color: #f3f3f3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.tip {
|
||||||
|
display: block;
|
||||||
|
font-size: 12px;
|
||||||
|
color: #999;
|
||||||
|
margin-top: 8px;
|
||||||
|
|
||||||
|
&.line-height-tip {
|
||||||
|
line-height: 1.6;
|
||||||
|
max-width: 460px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.radio-group, .checkbox-group {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
height: 34px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.radio-item, .checkbox-item {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
margin-right: 25px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.radio-circle {
|
||||||
|
width: 14px;
|
||||||
|
height: 14px;
|
||||||
|
border: 1px solid #dcdee2;
|
||||||
|
border-radius: 50%;
|
||||||
|
margin-right: 6px;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
&.checked {
|
||||||
|
border-color: #1890ff;
|
||||||
|
&::after {
|
||||||
|
content: '';
|
||||||
|
width: 8px;
|
||||||
|
height: 8px;
|
||||||
|
background: #1890ff;
|
||||||
|
border-radius: 50%;
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.checkbox-box {
|
||||||
|
width: 14px;
|
||||||
|
height: 14px;
|
||||||
|
border: 1px solid #dcdee2;
|
||||||
|
border-radius: 2px;
|
||||||
|
margin-right: 6px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
|
&.checked {
|
||||||
|
background-color: #1890ff;
|
||||||
|
border-color: #1890ff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.check-ic {
|
||||||
|
color: #fff;
|
||||||
|
font-size: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.radio-text, .checkbox-text {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-btns {
|
||||||
|
margin-top: 40px;
|
||||||
|
padding-left: 155px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn.primary {
|
||||||
|
width: 64px;
|
||||||
|
height: 32px;
|
||||||
|
line-height: 32px;
|
||||||
|
background: #1890ff;
|
||||||
|
color: #fff;
|
||||||
|
font-size: 14px;
|
||||||
|
border-radius: 4px;
|
||||||
|
text-align: center;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
137
pages/mall/admin/app/routine/download.uvue
Normal file
137
pages/mall/admin/app/routine/download.uvue
Normal file
@@ -0,0 +1,137 @@
|
|||||||
|
<template>
|
||||||
|
<view class="admin-page">
|
||||||
|
<view class="admin-card header-card">
|
||||||
|
<view class="title-row">
|
||||||
|
<text class="title">小程序下载</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="admin-card content-card routine-download-container">
|
||||||
|
<view class="box-title">
|
||||||
|
<view class="line"></view>
|
||||||
|
<text class="text">小程序设置</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="download-form">
|
||||||
|
<view class="form-item">
|
||||||
|
<text class="label">小程序名称:</text>
|
||||||
|
<text class="value">CRMEB标准版</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="form-item">
|
||||||
|
<text class="label">小程序码:</text>
|
||||||
|
<button class="btn primary mid">下载小程序码</button>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="form-item">
|
||||||
|
<text class="label">小程序包:</text>
|
||||||
|
<view class="radio-wrap">
|
||||||
|
<radio-group class="radio-group">
|
||||||
|
<label class="radio-label"><radio value="0" />未开通</label>
|
||||||
|
<label class="radio-label"><radio value="1" checked />已开通</label>
|
||||||
|
</radio-group>
|
||||||
|
<text class="desc">是否已开通小程序直播</text>
|
||||||
|
<text class="warning">请谨慎选择是否有开通小程序直播功能,否则将影响小程序的发布 可前往 <text class="link">帮助文档</text> 查看如何开通直播功能</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="form-item no-label">
|
||||||
|
<button class="btn primary mid">下载小程序包</button>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="uts">
|
||||||
|
// 小程序下载逻辑
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.routine-download-container {
|
||||||
|
padding: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.box-title {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.box-title .line {
|
||||||
|
width: 3px;
|
||||||
|
height: 16px;
|
||||||
|
background-color: #2d8cf0;
|
||||||
|
margin-right: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.box-title .text {
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.download-form {
|
||||||
|
padding-left: 100px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-item {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
margin-bottom: 30px;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-item.no-label {
|
||||||
|
padding-left: 100px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-item .label {
|
||||||
|
width: 100px;
|
||||||
|
color: #606266;
|
||||||
|
text-align: right;
|
||||||
|
margin-right: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-item .value {
|
||||||
|
color: #303133;
|
||||||
|
}
|
||||||
|
|
||||||
|
.radio-wrap {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.radio-group {
|
||||||
|
margin-bottom: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.radio-label {
|
||||||
|
margin-right: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.desc {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #c0c4cc;
|
||||||
|
}
|
||||||
|
|
||||||
|
.warning {
|
||||||
|
margin-top: 10px;
|
||||||
|
font-size: 13px;
|
||||||
|
color: #909399;
|
||||||
|
max-width: 400px;
|
||||||
|
line-height: 1.6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.link {
|
||||||
|
color: #2d8cf0;
|
||||||
|
margin: 0 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn.mid {
|
||||||
|
width: auto;
|
||||||
|
padding: 0 20px;
|
||||||
|
height: 36px;
|
||||||
|
line-height: 36px;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
136
pages/mall/admin/app/wechat/config.uvue
Normal file
136
pages/mall/admin/app/wechat/config.uvue
Normal file
@@ -0,0 +1,136 @@
|
|||||||
|
<template>
|
||||||
|
<view class="admin-page">
|
||||||
|
<view class="admin-card content-card">
|
||||||
|
<view class="tabs-row">
|
||||||
|
<view
|
||||||
|
v-for="tab in tabs"
|
||||||
|
:key="tab.key"
|
||||||
|
class="tab-item"
|
||||||
|
:class="{ active: currentTab === tab.key }"
|
||||||
|
@click="currentTab = tab.key"
|
||||||
|
>
|
||||||
|
{{ tab.label }}
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view v-if="currentTab === 'basic'" class="config-form">
|
||||||
|
<view class="form-item">
|
||||||
|
<text class="label">AppID:</text>
|
||||||
|
<input class="form-input" value="wxa815e4f2ef7bdb0b" />
|
||||||
|
<text class="tip">微信公众号的AppID</text>
|
||||||
|
</view>
|
||||||
|
<view class="form-item">
|
||||||
|
<text class="label">AppSecret:</text>
|
||||||
|
<input class="form-input" value="2c9f1ef4cc695c05c4462fef4e081120" />
|
||||||
|
<text class="tip">微信公众号的AppSecret</text>
|
||||||
|
</view>
|
||||||
|
<view class="form-item">
|
||||||
|
<text class="label">关注二维码:</text>
|
||||||
|
<view class="upload-box">
|
||||||
|
<text class="plus">+</text>
|
||||||
|
</view>
|
||||||
|
<text class="tip">引导关注公众号显示的公众号关注二维码</text>
|
||||||
|
</view>
|
||||||
|
<view class="form-item">
|
||||||
|
<text class="label">微信校验文件:</text>
|
||||||
|
<view class="upload-btn">
|
||||||
|
<text class="icon">⤒</text>
|
||||||
|
<text>点击上传</text>
|
||||||
|
</view>
|
||||||
|
<text class="tip">配置微信网页授权域名时候下载的微信校验文件,在此处上传</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="form-btns">
|
||||||
|
<button class="btn primary">提交</button>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view v-else class="config-form">
|
||||||
|
<view class="form-item">
|
||||||
|
<text class="label">接口地址:</text>
|
||||||
|
<input class="form-input" readonly value="https://v5.crmeb.net/api/wechat/serve" />
|
||||||
|
<text class="tip">配置服务器域名使用的接口地址,直接复制输入框内容(此项系统生成,无法修改)</text>
|
||||||
|
</view>
|
||||||
|
<view class="form-item">
|
||||||
|
<text class="label">消息加解密方式:</text>
|
||||||
|
<radio-group class="radio-group">
|
||||||
|
<label><radio value="1" checked />明文模式</label>
|
||||||
|
<label><radio value="2" />兼容模式</label>
|
||||||
|
<label><radio value="3" />安全模式</label>
|
||||||
|
</radio-group>
|
||||||
|
<text class="tip">如需使用安全模式请在管理中心修改,仅限服务号和认证订阅号</text>
|
||||||
|
</view>
|
||||||
|
<view class="form-btns">
|
||||||
|
<button class="btn primary">提交</button>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="uts">
|
||||||
|
import { ref } from 'vue'
|
||||||
|
|
||||||
|
const currentTab = ref('basic')
|
||||||
|
const tabs = [
|
||||||
|
{ key: 'basic', label: '公众号配置' },
|
||||||
|
{ key: 'server', label: '服务器域名配置' }
|
||||||
|
]
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.config-form {
|
||||||
|
padding: 30px 10%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-item {
|
||||||
|
margin-bottom: 30px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-item .label {
|
||||||
|
font-weight: bold;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
color: #303133;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-input {
|
||||||
|
border: 1px solid #dcdfe6;
|
||||||
|
padding: 10px 15px;
|
||||||
|
border-radius: 4px;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tip {
|
||||||
|
font-size: 12px;
|
||||||
|
color: #909399;
|
||||||
|
margin-top: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.upload-box {
|
||||||
|
width: 80px;
|
||||||
|
height: 80px;
|
||||||
|
border: 1px dashed #dcdfe6;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
font-size: 30px;
|
||||||
|
background-color: #fafafa;
|
||||||
|
}
|
||||||
|
|
||||||
|
.upload-btn {
|
||||||
|
width: 120px;
|
||||||
|
height: 40px;
|
||||||
|
border: 1px solid #dcdfe6;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
border-radius: 4px;
|
||||||
|
gap: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.radio-group label {
|
||||||
|
margin-right: 30px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
129
pages/mall/admin/app/wechat/menu.uvue
Normal file
129
pages/mall/admin/app/wechat/menu.uvue
Normal file
@@ -0,0 +1,129 @@
|
|||||||
|
<template>
|
||||||
|
<view class="admin-page">
|
||||||
|
<view class="admin-card header-card">
|
||||||
|
<text class="title">微信菜单</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="admin-card content-card menu-editor-wrap">
|
||||||
|
<!-- 微信菜单编辑器的模拟界面 -->
|
||||||
|
<view class="phone-preview">
|
||||||
|
<view class="phone-header">
|
||||||
|
<text class="status-bar">1:21 AM</text>
|
||||||
|
<view class="nav-bar">
|
||||||
|
<text class="back">返回</text>
|
||||||
|
<text class="user-icon">👤</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="phone-body">
|
||||||
|
<!-- 菜单展示区域 -->
|
||||||
|
<view class="menu-display">
|
||||||
|
<view class="menu-bottom">
|
||||||
|
<view class="keyboard-icon">⌨️</view>
|
||||||
|
<view class="menu-items">
|
||||||
|
<view class="menu-item">手机111</view>
|
||||||
|
<view class="menu-item active">商品分类</view>
|
||||||
|
<view class="menu-item">+</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="menu-settings">
|
||||||
|
<view class="tip-box">
|
||||||
|
<text>点击左侧菜单进行编辑</text>
|
||||||
|
</view>
|
||||||
|
<!-- 这里将来可以放菜单编辑表单 -->
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="uts">
|
||||||
|
// 微信菜单页面逻辑
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.menu-editor-wrap {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
padding: 40px;
|
||||||
|
gap: 40px;
|
||||||
|
min-height: 600px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.phone-preview {
|
||||||
|
width: 320px;
|
||||||
|
height: 560px;
|
||||||
|
border: 1px solid #ddd;
|
||||||
|
border-radius: 30px;
|
||||||
|
overflow: hidden;
|
||||||
|
background-color: #f5f5f5;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.phone-header {
|
||||||
|
background-color: #333;
|
||||||
|
color: #fff;
|
||||||
|
padding: 10px 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-bar {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.phone-body {
|
||||||
|
flex: 1;
|
||||||
|
position: relative;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: flex-end;
|
||||||
|
}
|
||||||
|
|
||||||
|
.menu-bottom {
|
||||||
|
height: 50px;
|
||||||
|
background-color: #fff;
|
||||||
|
border-top: 1px solid #eee;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.keyboard-icon {
|
||||||
|
width: 50px;
|
||||||
|
text-align: center;
|
||||||
|
border-right: 1px solid #eee;
|
||||||
|
}
|
||||||
|
|
||||||
|
.menu-items {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.menu-item {
|
||||||
|
flex: 1;
|
||||||
|
text-align: center;
|
||||||
|
line-height: 50px;
|
||||||
|
border-right: 1px solid #eee;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.menu-item.active {
|
||||||
|
border: 2px solid #2d8cf0;
|
||||||
|
background-color: #f0f7ff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.menu-settings {
|
||||||
|
flex: 1;
|
||||||
|
background-color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tip-box {
|
||||||
|
padding: 20px;
|
||||||
|
background-color: #f8f8f9;
|
||||||
|
border-radius: 4px;
|
||||||
|
color: #808695;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
82
pages/mall/admin/app/wechat/news.uvue
Normal file
82
pages/mall/admin/app/wechat/news.uvue
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
<template>
|
||||||
|
<view class="admin-page">
|
||||||
|
<view class="admin-card filter-card">
|
||||||
|
<view class="filter-row">
|
||||||
|
<view class="filter-item">
|
||||||
|
<text class="label">图文搜索:</text>
|
||||||
|
<input class="filter-input" placeholder="请输入图文名称" />
|
||||||
|
</view>
|
||||||
|
<view class="filter-btns">
|
||||||
|
<button class="btn primary">查询</button>
|
||||||
|
<button class="btn success">添加图文消息</button>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="admin-card content-card">
|
||||||
|
<view class="news-list">
|
||||||
|
<!-- 模拟图文卡片 -->
|
||||||
|
<view class="news-item">
|
||||||
|
<image class="cover" src="/static/placeholder.png" mode="aspectFill"></image>
|
||||||
|
<view class="news-info">
|
||||||
|
<text class="title">hahah</text>
|
||||||
|
<text class="id">207</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="uts">
|
||||||
|
// 图文管理逻辑
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.news-list {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 20px;
|
||||||
|
padding: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.news-item {
|
||||||
|
width: 240px;
|
||||||
|
border: 1px solid #ebeef5;
|
||||||
|
border-radius: 4px;
|
||||||
|
overflow: hidden;
|
||||||
|
transition: all 0.3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.news-item:hover {
|
||||||
|
box-shadow: 0 2px 12px 0 rgba(0,0,0,.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.cover {
|
||||||
|
width: 100%;
|
||||||
|
height: 140px;
|
||||||
|
background-color: #f5f7fa;
|
||||||
|
}
|
||||||
|
|
||||||
|
.news-info {
|
||||||
|
padding: 10px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title {
|
||||||
|
font-size: 16px;
|
||||||
|
color: #303133;
|
||||||
|
}
|
||||||
|
|
||||||
|
.id {
|
||||||
|
font-size: 12px;
|
||||||
|
color: #2d8cf0;
|
||||||
|
margin-top: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn.success {
|
||||||
|
background-color: #2d8cf0;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
144
pages/mall/admin/app/wechat/reply/follow.uvue
Normal file
144
pages/mall/admin/app/wechat/reply/follow.uvue
Normal file
@@ -0,0 +1,144 @@
|
|||||||
|
<template>
|
||||||
|
<view class="admin-page">
|
||||||
|
<view class="admin-card header-card">
|
||||||
|
<view class="breadcrumb">
|
||||||
|
<text class="back" @click="goBack">返回</text>
|
||||||
|
<text class="sep">/</text>
|
||||||
|
<text class="current">微信关注回复</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="admin-card content-card reply-editor-wrap">
|
||||||
|
<view class="phone-preview">
|
||||||
|
<!-- 简化的手机预览 -->
|
||||||
|
<view class="phone-header">
|
||||||
|
<text class="time">9:36</text>
|
||||||
|
</view>
|
||||||
|
<view class="phone-body">
|
||||||
|
<view class="chat-item">
|
||||||
|
<view class="avatar">🐷</view>
|
||||||
|
<view class="bubble">{{ replyContent }}</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="reply-form">
|
||||||
|
<view class="form-item">
|
||||||
|
<text class="label">消息状态:</text>
|
||||||
|
<radio-group class="radio-group">
|
||||||
|
<label><radio value="1" checked />启用</label>
|
||||||
|
<label><radio value="0" />禁用</label>
|
||||||
|
</radio-group>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="form-item">
|
||||||
|
<text class="label">消息类型:</text>
|
||||||
|
<view class="filter-select">
|
||||||
|
<text>文字消息</text>
|
||||||
|
<text class="arrow">▼</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="form-item">
|
||||||
|
<text class="label">消息内容:</text>
|
||||||
|
<textarea v-model="replyContent" class="reply-textarea" placeholder="请输入内容"></textarea>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="form-btns">
|
||||||
|
<button class="btn primary">保存并发布</button>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="uts">
|
||||||
|
import { ref } from 'vue'
|
||||||
|
|
||||||
|
const replyContent = ref('567856875687')
|
||||||
|
|
||||||
|
const goBack = () => {
|
||||||
|
// 返回逻辑
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.reply-editor-wrap {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
padding: 40px;
|
||||||
|
gap: 60px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.phone-preview {
|
||||||
|
width: 320px;
|
||||||
|
height: 560px;
|
||||||
|
border: 1px solid #ddd;
|
||||||
|
border-radius: 8px;
|
||||||
|
background-color: #f5f5f5;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.phone-header {
|
||||||
|
height: 60px;
|
||||||
|
background-color: #333;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chat-item {
|
||||||
|
display: flex;
|
||||||
|
padding: 15px;
|
||||||
|
gap: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.avatar {
|
||||||
|
font-size: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bubble {
|
||||||
|
background-color: #fff;
|
||||||
|
padding: 10px;
|
||||||
|
border-radius: 4px;
|
||||||
|
position: relative;
|
||||||
|
max-width: 200px;
|
||||||
|
word-break: break-all;
|
||||||
|
}
|
||||||
|
|
||||||
|
.reply-form {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-item {
|
||||||
|
margin-bottom: 25px;
|
||||||
|
display: flex;
|
||||||
|
align-items: flex-start;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-item .label {
|
||||||
|
width: 100px;
|
||||||
|
padding-top: 5px;
|
||||||
|
color: #606266;
|
||||||
|
}
|
||||||
|
|
||||||
|
.radio-group label {
|
||||||
|
margin-right: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.reply-textarea {
|
||||||
|
flex: 1;
|
||||||
|
height: 120px;
|
||||||
|
border: 1px solid #dcdfe6;
|
||||||
|
padding: 10px;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn.primary {
|
||||||
|
margin-left: 100px;
|
||||||
|
background-color: #2d8cf0;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
63
pages/mall/admin/app/wechat/reply/invalid.uvue
Normal file
63
pages/mall/admin/app/wechat/reply/invalid.uvue
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
<template>
|
||||||
|
<view class="admin-page">
|
||||||
|
<view class="admin-card header-card">
|
||||||
|
<view class="breadcrumb">
|
||||||
|
<text class="back">返回</text>
|
||||||
|
<text class="sep">/</text>
|
||||||
|
<text class="current">无效关键词回复</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="admin-card content-card reply-editor-wrap">
|
||||||
|
<view class="phone-preview">
|
||||||
|
<view class="phone-header">
|
||||||
|
<text class="time">9:36</text>
|
||||||
|
</view>
|
||||||
|
<view class="phone-body">
|
||||||
|
<view class="chat-item">
|
||||||
|
<view class="avatar">🐷</view>
|
||||||
|
<view class="bubble empty"></view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="reply-form">
|
||||||
|
<view class="form-item">
|
||||||
|
<text class="label">消息状态:</text>
|
||||||
|
<radio-group class="radio-group">
|
||||||
|
<label><radio value="1" />启用</label>
|
||||||
|
<label><radio value="0" checked />禁用</label>
|
||||||
|
</radio-group>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="form-item">
|
||||||
|
<text class="label">消息类型:</text>
|
||||||
|
<view class="filter-select">
|
||||||
|
<text class="select-placeholder">请选择规则状态</text>
|
||||||
|
<text class="arrow">▼</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="form-btns">
|
||||||
|
<button class="btn primary">保存并发布</button>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="uts">
|
||||||
|
// 无效关键词回复逻辑
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.bubble.empty {
|
||||||
|
width: 40px;
|
||||||
|
height: 40px;
|
||||||
|
background-color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.select-placeholder {
|
||||||
|
color: #c0c4cc;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
57
pages/mall/admin/app/wechat/reply/keyword.uvue
Normal file
57
pages/mall/admin/app/wechat/reply/keyword.uvue
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
<template>
|
||||||
|
<view class="admin-page">
|
||||||
|
<view class="admin-card filter-card">
|
||||||
|
<view class="filter-row">
|
||||||
|
<view class="filter-item">
|
||||||
|
<text class="label">回复类型:</text>
|
||||||
|
<view class="filter-select">
|
||||||
|
<text class="select-placeholder">请选择</text>
|
||||||
|
<text class="arrow">▼</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="filter-item">
|
||||||
|
<text class="label">关键字:</text>
|
||||||
|
<input class="filter-input" placeholder="请输入关键字" />
|
||||||
|
</view>
|
||||||
|
<view class="filter-btns">
|
||||||
|
<button class="btn primary">查询</button>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="admin-card content-card">
|
||||||
|
<view class="table-toolbar">
|
||||||
|
<button class="btn primary">添加关键字</button>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="admin-table">
|
||||||
|
<view class="table-header">
|
||||||
|
<text class="cell id">ID</text>
|
||||||
|
<text class="cell">关键字</text>
|
||||||
|
<text class="cell">回复类型</text>
|
||||||
|
<text class="cell">是否显示</text>
|
||||||
|
<text class="cell actions">操作</text>
|
||||||
|
</view>
|
||||||
|
<view class="table-empty">
|
||||||
|
<text>暂无数据</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="uts">
|
||||||
|
// 关键字回复逻辑
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.table-toolbar {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-empty {
|
||||||
|
padding: 100px;
|
||||||
|
text-align: center;
|
||||||
|
color: #909399;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
278
pages/mall/admin/maintain/api/account.uvue
Normal file
278
pages/mall/admin/maintain/api/account.uvue
Normal file
@@ -0,0 +1,278 @@
|
|||||||
|
<template>
|
||||||
|
<view class="admin-page">
|
||||||
|
<view class="admin-sections">
|
||||||
|
<!-- 提示栏 -->
|
||||||
|
<view class="alert-warning">
|
||||||
|
<text class="alert-content">获取访问 Token 的接口:\n请求 URL:/outapi/access_token 请求方式:POST 请求参数:appid和appsecret 返回数据:access_token:访问令牌 exp_time:令牌过期时间 auth_info:授权信息\n使用获取到的 Token 访问对外接口:\n在 HTTP 请求头中添加 Authorization 字段 字段值为 Bearer access_token(注意 Bearer 后有一个空格)</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 操作栏 -->
|
||||||
|
<view class="action-bar header-actions">
|
||||||
|
<button class="btn primary" @click="addAccount">添加账号</button>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 表格内容 -->
|
||||||
|
<view class="admin-card content-card">
|
||||||
|
<view class="table-container list-table">
|
||||||
|
<view class="table-header">
|
||||||
|
<view class="col col-id"><text>编号</text></view>
|
||||||
|
<view class="col col-account"><text>账号</text></view>
|
||||||
|
<view class="col col-desc"><text>描述</text></view>
|
||||||
|
<view class="col col-add-time"><text>添加时间</text></view>
|
||||||
|
<view class="col col-last-time"><text>最后登录时间</text></view>
|
||||||
|
<view class="col col-last-ip"><text>最后登录ip</text></view>
|
||||||
|
<view class="col col-status"><text>状态</text></view>
|
||||||
|
<view class="col col-action"><text>操作</text></view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="table-body">
|
||||||
|
<view v-for="item in dataList" :key="item.id" class="table-row">
|
||||||
|
<view class="col col-id"><text>{{ item.id }}</text></view>
|
||||||
|
<view class="col col-account"><text>{{ item.account }}</text></view>
|
||||||
|
<view class="col col-desc"><text>{{ item.desc }}</text></view>
|
||||||
|
<view class="col col-add-time"><text>{{ item.addTime }}</text></view>
|
||||||
|
<view class="col col-last-time"><text>{{ item.lastTime }}</text></view>
|
||||||
|
<view class="col col-last-ip"><text>{{ item.lastIp }}</text></view>
|
||||||
|
<view class="col col-status">
|
||||||
|
<view :class="['status-tag', item.status ? 'active' : 'inactive']" @click="toggleStatus(item)">
|
||||||
|
<text class="tag-text">{{ item.status ? '开启' : '关闭' }}</text>
|
||||||
|
<view class="tag-dot"></view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="col col-action">
|
||||||
|
<text class="action-btn" @click="setConfig(item)">设置</text>
|
||||||
|
<text class="action-btn divider">|</text>
|
||||||
|
<text class="action-btn" @click="editItem(item)">编辑</text>
|
||||||
|
<text class="action-btn divider">|</text>
|
||||||
|
<text class="action-btn danger" @click="deleteItem(item)">删除</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 分页 (模拟) -->
|
||||||
|
<view class="pagination">
|
||||||
|
<text class="page-info">共 2 条 20条/页</text>
|
||||||
|
<view class="page-btns">
|
||||||
|
<text class="p-btn disabled">˂</text>
|
||||||
|
<text class="p-btn active">1</text>
|
||||||
|
<text class="p-btn disabled">˃</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="uts">
|
||||||
|
import { ref } from 'vue'
|
||||||
|
|
||||||
|
const dataList = ref([
|
||||||
|
{ id: 9, account: 'ceshi', desc: 'ceshi', addTime: '2024-09-05 11:16:07', lastTime: '暂无', lastIp: '', status: true },
|
||||||
|
{ id: 10, account: 'tuoluojiang', desc: '', addTime: '2024-09-09 10:12:54', lastTime: '2024-09-10 19:15:01', lastIp: '124.221.49.234', status: true }
|
||||||
|
])
|
||||||
|
|
||||||
|
function addAccount() {
|
||||||
|
uni.showToast({ title: '添加账号', icon: 'none' })
|
||||||
|
}
|
||||||
|
|
||||||
|
function toggleStatus(item: any) {
|
||||||
|
item.status = !item.status
|
||||||
|
}
|
||||||
|
|
||||||
|
function setConfig(item: any) {
|
||||||
|
uni.showToast({ title: '参数设置: ' + item.account, icon: 'none' })
|
||||||
|
}
|
||||||
|
|
||||||
|
function editItem(item: any) {
|
||||||
|
uni.showToast({ title: '编辑: ' + item.account, icon: 'none' })
|
||||||
|
}
|
||||||
|
|
||||||
|
function deleteItem(item: any) {
|
||||||
|
uni.showModal({
|
||||||
|
title: '提示',
|
||||||
|
content: '确定要删除此账号吗?',
|
||||||
|
success: (res) => {
|
||||||
|
if (res.confirm) {
|
||||||
|
uni.showToast({ title: '删除成功' })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.admin-page {
|
||||||
|
padding: 24px;
|
||||||
|
background-color: #f5f7f9;
|
||||||
|
min-height: 100vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
.alert-warning {
|
||||||
|
background-color: #fff7e6;
|
||||||
|
border: 1px solid #ffe7ba;
|
||||||
|
padding: 16px 20px;
|
||||||
|
border-radius: 4px;
|
||||||
|
margin-bottom: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.alert-content {
|
||||||
|
color: #fa8c16;
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 1.8;
|
||||||
|
white-space: pre-wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-bar {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-card {
|
||||||
|
background-color: #fff;
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn {
|
||||||
|
height: 32px;
|
||||||
|
padding: 0 16px;
|
||||||
|
border-radius: 4px;
|
||||||
|
font-size: 14px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
cursor: pointer;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn.primary {
|
||||||
|
background-color: #1890ff;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-container {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-header {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
background-color: #fafafa;
|
||||||
|
border-bottom: 1px solid #f0f0f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-row {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
border-bottom: 1px solid #f0f0f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.col {
|
||||||
|
padding: 16px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
font-size: 14px;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.col-id { width: 80px; }
|
||||||
|
.col-account { width: 120px; }
|
||||||
|
.col-desc { flex: 1; }
|
||||||
|
.col-add-time { width: 180px; }
|
||||||
|
.col-last-time { width: 180px; }
|
||||||
|
.col-last-ip { width: 150px; }
|
||||||
|
.col-status { width: 100px; justify-content: center; }
|
||||||
|
.col-action { width: 200px; justify-content: flex-end; }
|
||||||
|
|
||||||
|
.status-tag {
|
||||||
|
width: 60px;
|
||||||
|
height: 24px;
|
||||||
|
border-radius: 12px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: 0 8px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.status-tag.active {
|
||||||
|
background-color: #1890ff;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.status-tag.inactive {
|
||||||
|
background-color: #d9d9d9;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tag-text {
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tag-dot {
|
||||||
|
width: 8px;
|
||||||
|
height: 8px;
|
||||||
|
background-color: #fff;
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-btn {
|
||||||
|
color: #1890ff;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-btn.danger {
|
||||||
|
color: #ff4d4f;
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-btn.divider {
|
||||||
|
margin: 0 8px;
|
||||||
|
color: #e8e8e8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pagination {
|
||||||
|
padding: 16px 24px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: flex-end;
|
||||||
|
gap: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-info {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-btns {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.p-btn {
|
||||||
|
width: 32px;
|
||||||
|
height: 32px;
|
||||||
|
border: 1px solid #d9d9d9;
|
||||||
|
border-radius: 4px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
font-size: 14px;
|
||||||
|
color: #666;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.p-btn.active {
|
||||||
|
background-color: #fff;
|
||||||
|
border-color: #1890ff;
|
||||||
|
color: #1890ff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.p-btn.disabled {
|
||||||
|
color: #bfbfbf;
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
200
pages/mall/admin/maintain/data/city.uvue
Normal file
200
pages/mall/admin/maintain/data/city.uvue
Normal file
@@ -0,0 +1,200 @@
|
|||||||
|
<template>
|
||||||
|
<view class="admin-page">
|
||||||
|
<view class="admin-sections">
|
||||||
|
<!-- 操作栏 -->
|
||||||
|
<view class="action-bar header-actions">
|
||||||
|
<view class="left-btns">
|
||||||
|
<button class="btn primary" @click="addProvince">添加省份</button>
|
||||||
|
<button class="btn ghost ml-12" @click="clearCache">清除缓存</button>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 表格内容 -->
|
||||||
|
<view class="admin-card content-card">
|
||||||
|
<view class="table-container list-table tree-table">
|
||||||
|
<view class="table-header">
|
||||||
|
<view class="col col-id"><text>编号</text></view>
|
||||||
|
<view class="col col-name"><text>地区名称</text></view>
|
||||||
|
<view class="col col-parent"><text>上级名称</text></view>
|
||||||
|
<view class="col col-action"><text>操作</text></view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="table-body">
|
||||||
|
<view v-for="item in dataList" :key="item.id" class="table-row">
|
||||||
|
<view class="col col-id"><text>{{ item.id }}</text></view>
|
||||||
|
<view class="col col-name">
|
||||||
|
<text class="expand-icon">˃</text>
|
||||||
|
<text>{{ item.name }}</text>
|
||||||
|
</view>
|
||||||
|
<view class="col col-parent"><text>{{ item.parentName }}</text></view>
|
||||||
|
<view class="col col-action">
|
||||||
|
<text class="action-btn" @click="addItem(item)">添加</text>
|
||||||
|
<text class="action-btn divider">|</text>
|
||||||
|
<text class="action-btn" @click="editItem(item)">编辑</text>
|
||||||
|
<text class="action-btn divider">|</text>
|
||||||
|
<text class="action-btn danger" @click="deleteItem(item)">删除</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="uts">
|
||||||
|
import { ref } from 'vue'
|
||||||
|
|
||||||
|
const dataList = ref([
|
||||||
|
{ id: 1, name: '北京市', parentName: '中国' },
|
||||||
|
{ id: 2, name: '天津市', parentName: '中国' },
|
||||||
|
{ id: 3, name: '河北省', parentName: '中国' },
|
||||||
|
{ id: 4, name: '山西省', parentName: '中国' },
|
||||||
|
{ id: 5, name: '内蒙古自治区', parentName: '中国' },
|
||||||
|
{ id: 6, name: '辽宁省', parentName: '中国' },
|
||||||
|
{ id: 7, name: '吉林省', parentName: '中国' },
|
||||||
|
{ id: 8, name: '黑龙江省', parentName: '中国' },
|
||||||
|
{ id: 9, name: '上海市', parentName: '中国' },
|
||||||
|
{ id: 10, name: '江苏省', parentName: '中国' },
|
||||||
|
{ id: 11, name: '浙江省', parentName: '中国' },
|
||||||
|
{ id: 12, name: '安徽省', parentName: '中国' },
|
||||||
|
{ id: 13, name: '福建省', parentName: '中国' },
|
||||||
|
{ id: 14, name: '江西省', parentName: '中国' }
|
||||||
|
])
|
||||||
|
|
||||||
|
function addProvince() {
|
||||||
|
uni.showToast({ title: '添加省份', icon: 'none' })
|
||||||
|
}
|
||||||
|
|
||||||
|
function clearCache() {
|
||||||
|
uni.showLoading({ title: '清理中...' })
|
||||||
|
setTimeout(() => {
|
||||||
|
uni.hideLoading()
|
||||||
|
uni.showToast({ title: '清理成功' })
|
||||||
|
}, 1000)
|
||||||
|
}
|
||||||
|
|
||||||
|
function addItem(item: any) {
|
||||||
|
uni.showToast({ title: '添加下级: ' + item.name, icon: 'none' })
|
||||||
|
}
|
||||||
|
|
||||||
|
function editItem(item: any) {
|
||||||
|
uni.showToast({ title: '编辑: ' + item.name, icon: 'none' })
|
||||||
|
}
|
||||||
|
|
||||||
|
function deleteItem(item: any) {
|
||||||
|
uni.showModal({
|
||||||
|
title: '提示',
|
||||||
|
content: '确定要删除该区域吗?',
|
||||||
|
success: (res) => {
|
||||||
|
if (res.confirm) {
|
||||||
|
uni.showToast({ title: '删除成功' })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.admin-page {
|
||||||
|
padding: 20px;
|
||||||
|
background-color: #f5f7f9;
|
||||||
|
min-height: 100vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header-actions {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.left-btns {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ml-12 {
|
||||||
|
margin-left: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-card {
|
||||||
|
background-color: #fff;
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 0; /* 表格一般不带卡片内边距 */
|
||||||
|
margin-bottom: 20px;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn {
|
||||||
|
height: 32px;
|
||||||
|
padding: 0 15px;
|
||||||
|
border-radius: 4px;
|
||||||
|
font-size: 14px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn.primary {
|
||||||
|
background-color: #1890ff;
|
||||||
|
color: #fff;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn.ghost {
|
||||||
|
background-color: #fff;
|
||||||
|
border: 1px solid #d9d9d9;
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-container {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-header {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
background-color: #fafafa;
|
||||||
|
border-bottom: 1px solid #f0f0f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-row {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
border-bottom: 1px solid #f0f0f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.col {
|
||||||
|
padding: 12px 16px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
font-size: 14px;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.col-id { width: 100px; }
|
||||||
|
.col-name { flex: 2; }
|
||||||
|
.col-parent { flex: 1; }
|
||||||
|
.col-action { width: 200px; justify-content: flex-end; }
|
||||||
|
|
||||||
|
.expand-icon {
|
||||||
|
margin-right: 8px;
|
||||||
|
color: #999;
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-btn {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #1890ff;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-btn.danger {
|
||||||
|
color: #ff4d4f;
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-btn.divider {
|
||||||
|
margin: 0 8px;
|
||||||
|
color: #e8e8e8;
|
||||||
|
cursor: default;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
177
pages/mall/admin/maintain/data/clear.uvue
Normal file
177
pages/mall/admin/maintain/data/clear.uvue
Normal file
@@ -0,0 +1,177 @@
|
|||||||
|
<template>
|
||||||
|
<view class="admin-page">
|
||||||
|
<view class="admin-sections">
|
||||||
|
<!-- 页面标题与提示 -->
|
||||||
|
<view class="page-header">
|
||||||
|
<text class="title">清除数据</text>
|
||||||
|
<view class="warning-tip">
|
||||||
|
<text class="warning-icon">⚠</text>
|
||||||
|
<text class="warning-text">清除数据请谨慎,清除就无法恢复哦!</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 卡片网格 -->
|
||||||
|
<view class="card-grid">
|
||||||
|
<view v-for="card in cards" :key="card.id" class="clear-card">
|
||||||
|
<view class="card-content">
|
||||||
|
<text class="card-title">{{ card.title }}</text>
|
||||||
|
<text class="card-desc">{{ card.desc }}</text>
|
||||||
|
</view>
|
||||||
|
<view class="card-footer">
|
||||||
|
<button :class="['btn', card.primary ? 'primary' : 'ghost']" @click="handleAction(card)">
|
||||||
|
{{ card.btnText }}
|
||||||
|
</button>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="uts">
|
||||||
|
import { ref } from 'vue'
|
||||||
|
|
||||||
|
const cards = ref([
|
||||||
|
{ id: 1, title: '更换域名', desc: '替换所有本地上传的图片域名', btnText: '立即更换', primary: true },
|
||||||
|
{ id: 2, title: '清除用户生成的临时附件', desc: '清除用户生成的临时附件,不会影响商品图', btnText: '立即清理', primary: false },
|
||||||
|
{ id: 3, title: '清除回收站商品', desc: '清除回收站商品,谨慎操作', btnText: '立即清理', primary: false },
|
||||||
|
{ id: 4, title: '清除用户数据', desc: '用户相关的所有表都将被清除,谨慎操作', btnText: '立即清理', primary: false },
|
||||||
|
{ id: 5, title: '清除商城数据', desc: '清除所有商城数据,谨慎操作', btnText: '立即清理', primary: false },
|
||||||
|
{ id: 6, title: '清除商品分类', desc: '会清除所有商品分类,谨慎操作', btnText: '立即清理', primary: false },
|
||||||
|
{ id: 7, title: '清除订单数据', desc: '清除用户所有订单数据,谨慎操作', btnText: '立即清理', primary: false },
|
||||||
|
{ id: 8, title: '清除客服数据', desc: '清除添加的客服数据,谨慎操作', btnText: '立即清理', primary: false },
|
||||||
|
{ id: 9, title: '清除微信数据', desc: '清除微信菜单保存数据,微信关键字无效回复', btnText: '立即清理', primary: false },
|
||||||
|
{ id: 10, title: '清除内容分类', desc: '清除添加的文章和文章分类,谨慎操作', btnText: '立即清理', primary: false },
|
||||||
|
{ id: 11, title: '清除所有附件', desc: '清除所有附件用户生成和后台上传,谨慎操作', btnText: '立即清理', primary: false },
|
||||||
|
{ id: 12, title: '清除系统记录', desc: '清除系统记录,谨慎操作', btnText: '立即清理', primary: false }
|
||||||
|
])
|
||||||
|
|
||||||
|
function handleAction(card: any) {
|
||||||
|
uni.showModal({
|
||||||
|
title: '极其危险的操作',
|
||||||
|
content: `您确定要对「${card.title}」执行此操作吗?数据清除后将无法恢复!`,
|
||||||
|
confirmColor: '#ff4d4f',
|
||||||
|
success: (res) => {
|
||||||
|
if (res.confirm) {
|
||||||
|
uni.showLoading({ title: '正在处理...' })
|
||||||
|
setTimeout(() => {
|
||||||
|
uni.hideLoading()
|
||||||
|
uni.showToast({ title: '操作完成' })
|
||||||
|
}, 2000)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.admin-page {
|
||||||
|
padding: 24px;
|
||||||
|
background-color: #f5f7f9;
|
||||||
|
min-height: 100vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-header {
|
||||||
|
background-color: #fff;
|
||||||
|
padding: 16px 24px;
|
||||||
|
border-radius: 4px;
|
||||||
|
margin-bottom: 24px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title {
|
||||||
|
font-size: 18px;
|
||||||
|
font-weight: 500;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.warning-tip {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.warning-icon {
|
||||||
|
color: #ff4d4f;
|
||||||
|
margin-right: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.warning-text {
|
||||||
|
color: #ff4d4f;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-grid {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.clear-card {
|
||||||
|
width: calc(25% - 15px); /* 4列布局 */
|
||||||
|
background-color: #fff;
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 30px 20px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
text-align: center;
|
||||||
|
border: 1px solid #f0f0f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-title {
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #333;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-desc {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #999;
|
||||||
|
line-height: 1.6;
|
||||||
|
margin-bottom: 24px;
|
||||||
|
height: 44px; /* 保持描述文字高度一致 */
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn {
|
||||||
|
height: 32px;
|
||||||
|
padding: 0 20px;
|
||||||
|
border-radius: 4px;
|
||||||
|
font-size: 14px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn.primary {
|
||||||
|
background-color: #1890ff;
|
||||||
|
color: #fff;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn.ghost {
|
||||||
|
background-color: #fff;
|
||||||
|
border: 1px solid #d9d9d9;
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 1400px) {
|
||||||
|
.clear-card {
|
||||||
|
width: calc(33.33% - 14px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@media screen and (max-width: 1000px) {
|
||||||
|
.clear-card {
|
||||||
|
width: calc(50% - 10px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
227
pages/mall/admin/maintain/data/logistics.uvue
Normal file
227
pages/mall/admin/maintain/data/logistics.uvue
Normal file
@@ -0,0 +1,227 @@
|
|||||||
|
<template>
|
||||||
|
<view class="admin-page">
|
||||||
|
<view class="admin-sections">
|
||||||
|
<!-- 搜索栏 -->
|
||||||
|
<view class="admin-card filter-card">
|
||||||
|
<view class="filter-row">
|
||||||
|
<view class="filter-item">
|
||||||
|
<text class="label">是否显示:</text>
|
||||||
|
<view class="filter-select">
|
||||||
|
<text class="select-text">全部</text>
|
||||||
|
<text class="arrow">▼</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="filter-item">
|
||||||
|
<text class="label">搜索:</text>
|
||||||
|
<input class="filter-input input-lg" placeholder="请输入物流公司名称或者编码" />
|
||||||
|
</view>
|
||||||
|
<button class="btn primary" @click="onSearch">查询</button>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 操作栏 -->
|
||||||
|
<view class="action-bar">
|
||||||
|
<button class="btn primary" @click="syncLogistics">同步物流公司</button>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 表格内容 -->
|
||||||
|
<view class="admin-card content-card">
|
||||||
|
<view class="table-container list-table">
|
||||||
|
<view class="table-header">
|
||||||
|
<view class="col col-id"><text>ID</text></view>
|
||||||
|
<view class="col col-name"><text>物流公司名称</text></view>
|
||||||
|
<view class="col col-code"><text>编码</text></view>
|
||||||
|
<view class="col col-sort"><text>排序</text></view>
|
||||||
|
<view class="col col-status"><text>是否显示</text></view>
|
||||||
|
<view class="col col-action"><text>操作</text></view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="table-body">
|
||||||
|
<view v-for="item in dataList" :key="item.id" class="table-row">
|
||||||
|
<view class="col col-id"><text>{{ item.id }}</text></view>
|
||||||
|
<view class="col col-name"><text>{{ item.name }}</text></view>
|
||||||
|
<view class="col col-code"><text>{{ item.code }}</text></view>
|
||||||
|
<view class="col col-sort"><text>{{ item.sort }}</text></view>
|
||||||
|
<view class="col col-status">
|
||||||
|
<switch :checked="item.show" color="#1890ff" @change="onStatusChange(item)" />
|
||||||
|
</view>
|
||||||
|
<view class="col col-action">
|
||||||
|
<text class="action-btn" @click="editItem(item)">编辑</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 分页 (模拟) -->
|
||||||
|
<view class="pagination">
|
||||||
|
<!-- 这里可以放分页组件 -->
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="uts">
|
||||||
|
import { ref } from 'vue'
|
||||||
|
|
||||||
|
const dataList = ref([
|
||||||
|
{ id: 2, name: '顺丰速运', code: 'shunfeng', sort: 0, show: true },
|
||||||
|
{ id: 3, name: '圆通速递', code: 'yuantong', sort: 0, show: true },
|
||||||
|
{ id: 4, name: '中通快递', code: 'zhongtong', sort: 0, show: true },
|
||||||
|
{ id: 5, name: '申通快递', code: 'shentong', sort: 0, show: true },
|
||||||
|
{ id: 6, name: '百世快递', code: 'huitongkuaidi', sort: 0, show: true },
|
||||||
|
{ id: 7, name: '京东物流', code: 'jd', sort: 0, show: true },
|
||||||
|
{ id: 8, name: '极兔速递', code: 'jtexpress', sort: 0, show: true },
|
||||||
|
{ id: 9, name: '邮政快递包裹', code: 'youzhengguonei', sort: 0, show: true },
|
||||||
|
{ id: 10, name: '天天快递', code: 'tiantian', sort: 0, show: true },
|
||||||
|
{ id: 11, name: 'EMS', code: 'ems', sort: 0, show: true },
|
||||||
|
{ id: 12, name: '德邦物流', code: 'debangwuliu', sort: 0, show: true },
|
||||||
|
{ id: 13, name: '德邦快递', code: 'debangkuaidi', sort: 0, show: true },
|
||||||
|
{ id: 14, name: '众邮快递', code: 'zhongyouex', sort: 0, show: true }
|
||||||
|
])
|
||||||
|
|
||||||
|
function onSearch() {
|
||||||
|
uni.showToast({ title: '查询中...', icon: 'none' })
|
||||||
|
}
|
||||||
|
|
||||||
|
function syncLogistics() {
|
||||||
|
uni.showLoading({ title: '同步中...' })
|
||||||
|
setTimeout(() => {
|
||||||
|
uni.hideLoading()
|
||||||
|
uni.showToast({ title: '同步成功' })
|
||||||
|
}, 1000)
|
||||||
|
}
|
||||||
|
|
||||||
|
function onStatusChange(item: any) {
|
||||||
|
item.show = !item.show
|
||||||
|
uni.showToast({ title: '状态已更新', icon: 'none' })
|
||||||
|
}
|
||||||
|
|
||||||
|
function editItem(item: any) {
|
||||||
|
uni.showToast({ title: '编辑: ' + item.name, icon: 'none' })
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.admin-page {
|
||||||
|
padding: 20px;
|
||||||
|
background-color: #f5f7f9;
|
||||||
|
min-height: 100vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-card {
|
||||||
|
background-color: #fff;
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 20px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.filter-row {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
gap: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.filter-item {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.label {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #333;
|
||||||
|
margin-right: 8px;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.filter-select {
|
||||||
|
width: 200px;
|
||||||
|
height: 32px;
|
||||||
|
border: 1px solid #d9d9d9;
|
||||||
|
border-radius: 4px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: 0 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.filter-input {
|
||||||
|
height: 32px;
|
||||||
|
border: 1px solid #d9d9d9;
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 0 10px;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-lg {
|
||||||
|
width: 300px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn {
|
||||||
|
height: 32px;
|
||||||
|
padding: 0 15px;
|
||||||
|
border-radius: 4px;
|
||||||
|
font-size: 14px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
cursor: pointer;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn.primary {
|
||||||
|
background-color: #1890ff;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-bar {
|
||||||
|
margin-bottom: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-container {
|
||||||
|
width: 100%;
|
||||||
|
border: 1px solid #f0f0f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-header {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
background-color: #fafafa;
|
||||||
|
border-bottom: 1px solid #f0f0f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-row {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
border-bottom: 1px solid #f0f0f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.col {
|
||||||
|
padding: 12px 16px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
font-size: 14px;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.col-id { width: 80px; }
|
||||||
|
.col-name { flex: 2; }
|
||||||
|
.col-code { flex: 2; }
|
||||||
|
.col-sort { width: 100px; }
|
||||||
|
.col-status { width: 120px; justify-content: center; }
|
||||||
|
.col-action { width: 100px; justify-content: center; }
|
||||||
|
|
||||||
|
.action-btn {
|
||||||
|
color: #1890ff;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pagination {
|
||||||
|
margin-top: 20px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -1,22 +1,268 @@
|
|||||||
<template>
|
<template>
|
||||||
<AdminLayout currentPage="dev-config-category">
|
<view class="admin-page">
|
||||||
<view class="page">
|
<view class="admin-sections">
|
||||||
<view class="header">
|
<!-- 搜索栏 -->
|
||||||
<text class="title">配置分类</text>
|
<view class="admin-card filter-card">
|
||||||
|
<view class="filter-row">
|
||||||
|
<view class="filter-item">
|
||||||
|
<text class="label">是否显示:</text>
|
||||||
|
<view class="filter-select">
|
||||||
|
<text class="select-placeholder">请选择</text>
|
||||||
|
<text class="arrow">▼</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="filter-item">
|
||||||
|
<text class="label">分类名称:</text>
|
||||||
|
<input class="filter-input" placeholder="请输入分类名称" />
|
||||||
|
</view>
|
||||||
|
<button class="btn primary" @click="onSearch">查询分类</button>
|
||||||
|
</view>
|
||||||
|
<view class="filter-row mt-12">
|
||||||
|
<view class="filter-item">
|
||||||
|
<text class="label">配置名称:</text>
|
||||||
|
<input class="filter-input" placeholder="请输入配置名称" />
|
||||||
|
</view>
|
||||||
|
<button class="btn primary" @click="onSearchConfig">查询配置</button>
|
||||||
|
</view>
|
||||||
</view>
|
</view>
|
||||||
<view class="content">
|
|
||||||
<text class="tip">TODO: 配置分类</text>
|
<!-- 内容区 -->
|
||||||
|
<view class="admin-card content-card">
|
||||||
|
<!-- 操作按钮行 -->
|
||||||
|
<view class="action-bar">
|
||||||
|
<button class="btn primary small" @click="onAdd">添加配置分类</button>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 表格 -->
|
||||||
|
<view class="table-container list-table">
|
||||||
|
<view class="table-header">
|
||||||
|
<view class="col col-id"><text>ID</text></view>
|
||||||
|
<view class="col col-name"><text>分类名称</text></view>
|
||||||
|
<view class="col col-field"><text>分类字段</text></view>
|
||||||
|
<view class="col col-status"><text>状态</text></view>
|
||||||
|
<view class="col col-ops"><text>操作</text></view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="table-body">
|
||||||
|
<view v-for="item in dataList" :key="item.id" class="table-row">
|
||||||
|
<view class="col col-id"><text>{{ item.id }}</text></view>
|
||||||
|
<view class="col col-name">
|
||||||
|
<text class="expand-icon" v-if="item.hasChildren">▶</text>
|
||||||
|
<text>{{ item.name }}</text>
|
||||||
|
</view>
|
||||||
|
<view class="col col-field"><text>{{ item.field }}</text></view>
|
||||||
|
<view class="col col-status">
|
||||||
|
<switch :checked="item.status" color="#1890ff" scale="0.8" />
|
||||||
|
</view>
|
||||||
|
<view class="col col-ops">
|
||||||
|
<text class="op-link" @click="onConfig(item)">配置列表</text>
|
||||||
|
<view class="op-divider">|</view>
|
||||||
|
<text class="op-link" @click="onEdit(item)">编辑</text>
|
||||||
|
<view class="op-divider">|</view>
|
||||||
|
<text class="op-link op-danger" @click="onDelete(item)">删除</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</AdminLayout>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="uts">
|
<script setup lang="uts">
|
||||||
import AdminLayout from '@/layouts/admin/AdminLayout.uvue'
|
import { ref } from 'vue'
|
||||||
</script>
|
|
||||||
<style scoped>
|
const dataList = ref([
|
||||||
.page { padding: 16px; }
|
{ id: 9, name: '分销配置', field: 'fenxiao', status: true, hasChildren: true },
|
||||||
.title { font-size: 18px; font-weight: 600; }
|
{ id: 65, name: '接口设置', field: 'system_serve', status: true, hasChildren: true },
|
||||||
.tip { color: #999; margin-top: 8px; display: block; }
|
{ id: 69, name: '客服配置', field: 'kefu_config', status: true, hasChildren: true },
|
||||||
|
{ id: 78, name: '应用配置', field: 'sys_app', status: true, hasChildren: true },
|
||||||
|
{ id: 100, name: '用户配置', field: 'system_user_config', status: true, hasChildren: true },
|
||||||
|
{ id: 113, name: '订单配置', field: 'order_config', status: true, hasChildren: true },
|
||||||
|
{ id: 129, name: '系统配置', field: 'system_config', status: true, hasChildren: true },
|
||||||
|
{ id: 136, name: '商品配置', field: 'product_config', status: true, hasChildren: true }
|
||||||
|
])
|
||||||
|
|
||||||
|
function onSearch() {
|
||||||
|
uni.showToast({ title: '查询分类', icon: 'none' })
|
||||||
|
}
|
||||||
|
|
||||||
|
function onSearchConfig() {
|
||||||
|
uni.showToast({ title: '查询配置', icon: 'none' })
|
||||||
|
}
|
||||||
|
|
||||||
|
function onAdd() {
|
||||||
|
uni.showToast({ title: '添加配置分类', icon: 'none' })
|
||||||
|
}
|
||||||
|
|
||||||
|
function onConfig(item: any) {
|
||||||
|
uni.showToast({ title: '配置列表: ' + item.name, icon: 'none' })
|
||||||
|
}
|
||||||
|
|
||||||
|
function onEdit(item: any) {
|
||||||
|
uni.showToast({ title: '编辑: ' + item.name, icon: 'none' })
|
||||||
|
}
|
||||||
|
|
||||||
|
function onDelete(item: any) {
|
||||||
|
uni.showModal({
|
||||||
|
title: '提示',
|
||||||
|
content: '确定要删除该分类吗?',
|
||||||
|
success: (res) => {
|
||||||
|
if (res.confirm) {
|
||||||
|
uni.showToast({ title: '已删除', icon: 'none' })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.admin-page {
|
||||||
|
padding: 20px;
|
||||||
|
background-color: #f5f7f9;
|
||||||
|
min-height: 100vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-card {
|
||||||
|
background-color: #fff;
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 20px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.filter-row {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mt-12 { margin-top: 12px; }
|
||||||
|
|
||||||
|
.filter-item {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
margin-right: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.label {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #333;
|
||||||
|
width: 80px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.filter-select {
|
||||||
|
width: 200px;
|
||||||
|
height: 32px;
|
||||||
|
border: 1px solid #d9d9d9;
|
||||||
|
border-radius: 2px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: 0 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.select-placeholder {
|
||||||
|
color: #bfbfbf;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.arrow {
|
||||||
|
font-size: 10px;
|
||||||
|
color: #bfbfbf;
|
||||||
|
}
|
||||||
|
|
||||||
|
.filter-input {
|
||||||
|
width: 200px;
|
||||||
|
height: 32px;
|
||||||
|
border: 1px solid #d9d9d9;
|
||||||
|
border-radius: 2px;
|
||||||
|
padding: 0 10px;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn {
|
||||||
|
height: 32px;
|
||||||
|
padding: 0 20px;
|
||||||
|
border-radius: 2px;
|
||||||
|
font-size: 14px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
cursor: pointer;
|
||||||
|
border: 1px solid #d9d9d9;
|
||||||
|
background-color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn.primary {
|
||||||
|
background-color: #1890ff;
|
||||||
|
border-color: #1890ff;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn.small {
|
||||||
|
height: 28px;
|
||||||
|
padding: 0 10px;
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-bar {
|
||||||
|
margin-bottom: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-container {
|
||||||
|
width: 100%;
|
||||||
|
border: 1px solid #f0f0f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-header {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
background-color: #fafafa;
|
||||||
|
border-bottom: 1px solid #f0f0f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-row {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
border-bottom: 1px solid #f0f0f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.col {
|
||||||
|
padding: 12px 16px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
font-size: 14px;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.col-id { width: 80px; }
|
||||||
|
.col-name { flex: 2; }
|
||||||
|
.col-field { flex: 2; }
|
||||||
|
.col-status { width: 100px; justify-content: center; }
|
||||||
|
.col-ops { flex: 2; justify-content: flex-end; }
|
||||||
|
|
||||||
|
.expand-icon {
|
||||||
|
margin-right: 8px;
|
||||||
|
font-size: 10px;
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
|
||||||
|
.op-link {
|
||||||
|
color: #1890ff;
|
||||||
|
cursor: pointer;
|
||||||
|
margin: 0 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.op-danger {
|
||||||
|
color: #ff4d4f;
|
||||||
|
}
|
||||||
|
|
||||||
|
.op-divider {
|
||||||
|
color: #f0f0f0;
|
||||||
|
margin: 0 4px;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,23 +1,223 @@
|
|||||||
<template>
|
<template>
|
||||||
<AdminLayout currentPage="dev-config-combo">
|
<view class="admin-page">
|
||||||
<view class="page">
|
<view class="admin-sections">
|
||||||
<view class="header">
|
<!-- 搜索栏 -->
|
||||||
<text class="title">组合数据</text>
|
<view class="admin-card filter-card">
|
||||||
|
<view class="filter-row">
|
||||||
|
<view class="filter-item">
|
||||||
|
<text class="label">数据搜索:</text>
|
||||||
|
<input class="filter-input input-large" placeholder="请输入ID,KEY,数据组名称,简介" />
|
||||||
|
</view>
|
||||||
|
<button class="btn primary" @click="onSearch">查询</button>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 内容区 -->
|
||||||
|
<view class="admin-card content-card">
|
||||||
|
<!-- 操作按钮行 -->
|
||||||
|
<view class="action-bar">
|
||||||
|
<button class="btn primary small" @click="onAdd">添加数据组</button>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 表格 -->
|
||||||
|
<view class="table-container">
|
||||||
|
<view class="table-header">
|
||||||
|
<view class="col col-id"><text>ID</text></view>
|
||||||
|
<view class="col col-key"><text>KEY</text></view>
|
||||||
|
<view class="col col-name"><text>数据组名称</text></view>
|
||||||
|
<view class="col col-desc"><text>简介</text></view>
|
||||||
|
<view class="col col-ops"><text>操作</text></view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="table-body">
|
||||||
|
<view v-for="item in dataList" :key="item.id" class="table-row">
|
||||||
|
<view class="col col-id"><text>{{ item.id }}</text></view>
|
||||||
|
<view class="col col-key"><text>{{ item.key }}</text></view>
|
||||||
|
<view class="col col-name"><text>{{ item.name }}</text></view>
|
||||||
|
<view class="col col-desc"><text>{{ item.desc }}</text></view>
|
||||||
|
<view class="col col-ops">
|
||||||
|
<text class="op-link" @click="onDataList(item)">数据列表</text>
|
||||||
|
<view class="op-divider">|</view>
|
||||||
|
<text class="op-link" @click="onEdit(item)">编辑</text>
|
||||||
|
<view class="op-divider">|</view>
|
||||||
|
<text class="op-link op-danger" @click="onDelete(item)">删除</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
</view>
|
</view>
|
||||||
<view class="content">
|
|
||||||
<text class="tip">TODO: 组合数据</text>
|
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</AdminLayout>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="uts">
|
<script setup lang="uts">
|
||||||
import AdminLayout from '@/layouts/admin/AdminLayout.uvue'
|
import { ref } from 'vue'
|
||||||
|
|
||||||
|
const dataList = ref([
|
||||||
|
{ id: 49, key: 'routine_seckill_time', name: '秒杀时间段', desc: '秒杀时间段' },
|
||||||
|
{ id: 52, key: 'routine_home_bast_banner', name: '首页精品推荐图片', desc: '首页精品推荐图片' },
|
||||||
|
{ id: 53, key: 'order_details_images', name: '订单详情状态图', desc: '订单详情状态图' },
|
||||||
|
{ id: 54, key: 'routine_my_menus', name: '个人中心菜单', desc: '个人中心菜单' },
|
||||||
|
{ id: 55, key: 'sign_day_num', name: '签到天数配置', desc: '签到天数配置' },
|
||||||
|
{ id: 57, key: 'routine_home_hot_banner', name: '热门榜单推荐图片', desc: '热门榜单推荐图片' },
|
||||||
|
{ id: 58, key: 'routine_home_new_banner', name: '首发新品推荐图片', desc: '首发新品推荐图片' },
|
||||||
|
{ id: 59, key: 'routine_home_benefit_banner', name: '促销单品推荐图片', desc: '促销单品推荐图片' },
|
||||||
|
{ id: 62, key: 'user_recharge_quota', name: '充值金额设置', desc: '设置充值金额额度选择' },
|
||||||
|
{ id: 65, key: 'admin_login_slide', name: '后台登录页面幻灯片', desc: '后台登录页面幻灯片' },
|
||||||
|
{ id: 66, key: 'uni_app_link', name: '前端页面链接', desc: '前端页面链接' },
|
||||||
|
{ id: 67, key: 'combination_banner', name: '拼团列表轮播图', desc: '拼团列表轮播图' },
|
||||||
|
{ id: 68, key: 'integral_shop_banner', name: '积分商城轮播图', desc: '积分商城轮播图' }
|
||||||
|
])
|
||||||
|
|
||||||
|
function onSearch() {
|
||||||
|
uni.showToast({ title: '查询中...', icon: 'none' })
|
||||||
|
}
|
||||||
|
|
||||||
|
function onAdd() {
|
||||||
|
uni.showToast({ title: '添加数据组', icon: 'none' })
|
||||||
|
}
|
||||||
|
|
||||||
|
function onDataList(item: any) {
|
||||||
|
uni.showToast({ title: '数据列表: ' + item.name, icon: 'none' })
|
||||||
|
}
|
||||||
|
|
||||||
|
function onEdit(item: any) {
|
||||||
|
uni.showToast({ title: '编辑: ' + item.name, icon: 'none' })
|
||||||
|
}
|
||||||
|
|
||||||
|
function onDelete(item: any) {
|
||||||
|
uni.showModal({
|
||||||
|
title: '提示',
|
||||||
|
content: '确定要删除该数据组吗?',
|
||||||
|
success: (res) => {
|
||||||
|
if (res.confirm) {
|
||||||
|
uni.showToast({ title: '已删除', icon: 'none' })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped lang="scss">
|
||||||
.page { padding: 16px; }
|
.admin-page {
|
||||||
.title { font-size: 18px; font-weight: 600; }
|
padding: 20px;
|
||||||
.tip { color: #999; margin-top: 8px; display: block; }
|
background-color: #f5f7f9;
|
||||||
</style>
|
min-height: 100vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-card {
|
||||||
|
background-color: #fff;
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 20px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.filter-row {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.filter-item {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
margin-right: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.label {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.filter-input {
|
||||||
|
width: 200px;
|
||||||
|
height: 32px;
|
||||||
|
border: 1px solid #d9d9d9;
|
||||||
|
border-radius: 2px;
|
||||||
|
padding: 0 10px;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-large {
|
||||||
|
width: 300px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn {
|
||||||
|
height: 32px;
|
||||||
|
padding: 0 20px;
|
||||||
|
border-radius: 2px;
|
||||||
|
font-size: 14px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
cursor: pointer;
|
||||||
|
border: 1px solid #d9d9d9;
|
||||||
|
background-color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn.primary {
|
||||||
|
background-color: #1890ff;
|
||||||
|
border-color: #1890ff;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn.small {
|
||||||
|
height: 28px;
|
||||||
|
padding: 0 10px;
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-bar {
|
||||||
|
margin-bottom: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-container {
|
||||||
|
width: 100%;
|
||||||
|
border: 1px solid #f0f0f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-header {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
background-color: #fafafa;
|
||||||
|
border-bottom: 1px solid #f0f0f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-row {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
border-bottom: 1px solid #f0f0f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.col {
|
||||||
|
padding: 12px 16px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
font-size: 14px;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.col-id { width: 80px; }
|
||||||
|
.col-key { flex: 2; }
|
||||||
|
.col-name { flex: 2; }
|
||||||
|
.col-desc { flex: 2; }
|
||||||
|
.col-ops { flex: 2; justify-content: flex-end; }
|
||||||
|
|
||||||
|
.op-link {
|
||||||
|
color: #1890ff;
|
||||||
|
cursor: pointer;
|
||||||
|
margin: 0 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.op-danger {
|
||||||
|
color: #ff4d4f;
|
||||||
|
}
|
||||||
|
|
||||||
|
.op-divider {
|
||||||
|
color: #f0f0f0;
|
||||||
|
margin: 0 4px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,22 +1,192 @@
|
|||||||
<template>
|
<template>
|
||||||
<AdminLayout currentPage="dev-config-cron">
|
<view class="admin-page">
|
||||||
<view class="page">
|
<view class="admin-sections">
|
||||||
<view class="header">
|
<!-- 顶部通知 -->
|
||||||
<text class="title">定时任务</text>
|
<view class="admin-card alert-card">
|
||||||
</view>
|
<view class="alert-content">
|
||||||
<view class="content">
|
<text class="alert-title">启动定时任务两种方式:</text>
|
||||||
<text class="tip">TODO: 定时任务</text>
|
<text class="alert-desc">1、使用命令行启动:php think timer start --d; 如果更改了执行周期、编辑是否开启、删除定时任务需要重新启动下定时任务确保生效;</text>
|
||||||
|
<text class="alert-desc">2、使用接口触发定时任务,建议每分钟调用一次,接口地址 https://v5.crmeb.net/api/crontab/run</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 操作卡片 -->
|
||||||
|
<view class="admin-card content-card">
|
||||||
|
<view class="tabs-row">
|
||||||
|
<view class="tab-item active"><text>系统任务</text></view>
|
||||||
|
<view class="tab-item"><text>自定义任务</text></view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 表格 -->
|
||||||
|
<view class="table-container list-table mt-16">
|
||||||
|
<view class="table-header">
|
||||||
|
<view class="col col-title"><text>标题</text></view>
|
||||||
|
<view class="col col-desc"><text>任务说明</text></view>
|
||||||
|
<view class="col col-cycle"><text>执行周期</text></view>
|
||||||
|
<view class="col col-status"><text>是否开启</text></view>
|
||||||
|
<view class="col col-ops"><text>操作</text></view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="table-body">
|
||||||
|
<view v-for="item in dataList" :key="item.id" class="table-row">
|
||||||
|
<view class="col col-title"><text>{{ item.title }}</text></view>
|
||||||
|
<view class="col col-desc"><text>{{ item.desc }}</text></view>
|
||||||
|
<view class="col col-cycle"><text>{{ item.cycle }}</text></view>
|
||||||
|
<view class="col col-status">
|
||||||
|
<switch :checked="item.status" color="#1890ff" scale="0.8" />
|
||||||
|
</view>
|
||||||
|
<view class="col col-ops">
|
||||||
|
<text class="op-link" @click="onEdit(item)">编辑</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 分页 -->
|
||||||
|
<view class="pagination">
|
||||||
|
<text class="page-info">共 10 条 15条/页</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</AdminLayout>
|
|
||||||
</template>
|
</template>
|
||||||
<script setup lang="uts">
|
|
||||||
import AdminLayout from '@/layouts/admin/AdminLayout.uvue'
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped>
|
<script setup lang="uts">
|
||||||
.page { padding: 16px; }
|
import { ref } from 'vue'
|
||||||
.title { font-size: 18px; font-weight: 600; }
|
|
||||||
.tip { color: #999; margin-top: 8px; display: block; }
|
const dataList = ref([
|
||||||
</style>
|
{ id: 1, title: '自动开具/冲红电子发票', desc: '每隔10分钟执行自动开具/冲红电子发票', cycle: '每隔10分钟执行一次', status: true },
|
||||||
|
{ id: 2, title: '清除昨日海报', desc: '每天0时30分0秒执行一次清除昨日海报', cycle: '每天0时30分0秒执行一次', status: true },
|
||||||
|
{ id: 3, title: '订单商品自动好评', desc: '每隔5分钟执行订单到期商品好评', cycle: '每隔5分钟执行一次', status: true },
|
||||||
|
{ id: 4, title: '预售商品到期自动下架', desc: '每隔5分钟执行预售商品到期下架', cycle: '每隔5分钟执行一次', status: true },
|
||||||
|
{ id: 5, title: '订单自动收货', desc: '每隔5分钟执行订单到期自动收货', cycle: '每隔5分钟执行一次', status: true },
|
||||||
|
{ id: 6, title: '自动更新直播间状态', desc: '每隔3分钟执行更新直播间状态', cycle: '每隔3分钟执行一次', status: true },
|
||||||
|
{ id: 7, title: '自动更新直播商品状态', desc: '每隔3分钟执行更新直播商品状态', cycle: '每隔3分钟执行一次', status: true },
|
||||||
|
{ id: 8, title: '到期自动解绑上级', desc: '每隔1分钟执行到期的绑定关系的解除', cycle: '每隔1分钟执行一次', status: true },
|
||||||
|
{ id: 9, title: '拼团到期订单处理', desc: '每隔1分钟拼团到期后的操作', cycle: '每隔1分钟执行一次', status: true },
|
||||||
|
{ id: 10, title: '未支付自动取消订单', desc: '每隔30秒执行自动取消到期未支付的订单', cycle: '每隔30秒执行一次', status: true }
|
||||||
|
])
|
||||||
|
|
||||||
|
function onEdit(item: any) {
|
||||||
|
uni.showToast({ title: '编辑: ' + item.title, icon: 'none' })
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.admin-page {
|
||||||
|
padding: 20px;
|
||||||
|
background-color: #f5f7f9;
|
||||||
|
min-height: 100vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-card {
|
||||||
|
background-color: #fff;
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 20px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.alert-card {
|
||||||
|
background-color: #fffbe6;
|
||||||
|
border: 1px solid #ffe58f;
|
||||||
|
}
|
||||||
|
|
||||||
|
.alert-content {
|
||||||
|
padding: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.alert-title {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #faad14;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.alert-desc {
|
||||||
|
font-size: 13px;
|
||||||
|
color: #faad14;
|
||||||
|
line-height: 20px;
|
||||||
|
margin-bottom: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tabs-row {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
border-bottom: 1px solid #f0f0f0;
|
||||||
|
margin-bottom: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-item {
|
||||||
|
padding: 12px 20px;
|
||||||
|
font-size: 14px;
|
||||||
|
color: #333;
|
||||||
|
cursor: pointer;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-item.active {
|
||||||
|
color: #1890ff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-item.active::after {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
bottom: -1px;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
height: 2px;
|
||||||
|
background-color: #1890ff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-container {
|
||||||
|
width: 100%;
|
||||||
|
border: 1px solid #f0f0f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-header {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
background-color: #fafafa;
|
||||||
|
border-bottom: 1px solid #f0f0f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-row {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
border-bottom: 1px solid #f0f0f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.col {
|
||||||
|
padding: 12px 16px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
font-size: 14px;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.col-title { flex: 2; }
|
||||||
|
.col-desc { flex: 3; }
|
||||||
|
.col-cycle { flex: 2; }
|
||||||
|
.col-status { width: 100px; justify-content: center; }
|
||||||
|
.col-ops { width: 80px; justify-content: center; }
|
||||||
|
|
||||||
|
.op-link {
|
||||||
|
color: #1890ff;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pagination {
|
||||||
|
margin-top: 20px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-info {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mt-16 { margin-top: 16px; }
|
||||||
|
</style>
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,22 +1,155 @@
|
|||||||
<template>
|
<template>
|
||||||
<AdminLayout currentPage="dev-config-event">
|
<view class="admin-page">
|
||||||
<view class="page">
|
<view class="admin-sections">
|
||||||
<view class="header">
|
<!-- 提示语 -->
|
||||||
<text class="title">自定事件</text>
|
<view class="admin-card alert-card">
|
||||||
</view>
|
<text class="alert-title">自定义事件说明:</text>
|
||||||
<view class="content">
|
<text class="alert-desc">1、新增的事件会在对应的事件类型相关的流程中触发,例:选择用户登录,则在用户登录时执行代码。</text>
|
||||||
<text class="tip">TODO: 自定事件</text>
|
<text class="alert-desc">2、可以使用对应事件类型中的参数,例:$data['nickname'], $data['phone']等。</text>
|
||||||
|
<text class="alert-desc">3、调用类的时请写入完整路径,例:\think\facade\Db、\app\services\other\CacheServices::class等。</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 内容区 -->
|
||||||
|
<view class="admin-card content-card">
|
||||||
|
<!-- 操作按钮行 -->
|
||||||
|
<view class="action-bar">
|
||||||
|
<button class="btn primary small" @click="onAdd">新增系统事件</button>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 表格(暂无数据) -->
|
||||||
|
<view class="table-container list-table">
|
||||||
|
<view class="table-header">
|
||||||
|
<view class="col col-id"><text>编号</text></view>
|
||||||
|
<view class="col col-name"><text>事件名</text></view>
|
||||||
|
<view class="col col-type"><text>事件类型</text></view>
|
||||||
|
<view class="col col-status"><text>是否开启</text></view>
|
||||||
|
<view class="col col-time"><text>创建时间</text></view>
|
||||||
|
<view class="col col-ops"><text>操作</text></view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="table-body">
|
||||||
|
<view class="empty-row">
|
||||||
|
<text class="empty-text">暂无数据</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</AdminLayout>
|
|
||||||
</template>
|
</template>
|
||||||
<script setup lang="uts">
|
|
||||||
import AdminLayout from '@/layouts/admin/AdminLayout.uvue'
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped>
|
<script setup lang="uts">
|
||||||
.page { padding: 16px; }
|
function onAdd() {
|
||||||
.title { font-size: 18px; font-weight: 600; }
|
uni.showToast({ title: '新增系统事件', icon: 'none' })
|
||||||
.tip { color: #999; margin-top: 8px; display: block; }
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.admin-page {
|
||||||
|
padding: 20px;
|
||||||
|
background-color: #f5f7f9;
|
||||||
|
min-height: 100vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-card {
|
||||||
|
background-color: #fff;
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 20px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.alert-card {
|
||||||
|
background-color: #fff7e6;
|
||||||
|
border: 1px solid #ffd591;
|
||||||
|
}
|
||||||
|
|
||||||
|
.alert-title {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #fa8c16;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.alert-desc {
|
||||||
|
font-size: 13px;
|
||||||
|
color: #fa8c16;
|
||||||
|
line-height: 20px;
|
||||||
|
margin-bottom: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-bar {
|
||||||
|
margin-bottom: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-container {
|
||||||
|
width: 100%;
|
||||||
|
border: 1px solid #f0f0f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-header {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
background-color: #fafafa;
|
||||||
|
border-bottom: 1px solid #f0f0f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-row {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
border-bottom: 1px solid #f0f0f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.col {
|
||||||
|
padding: 12px 16px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
font-size: 14px;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.col-id { width: 80px; }
|
||||||
|
.col-name { flex: 2; }
|
||||||
|
.col-type { flex: 2; }
|
||||||
|
.col-status { width: 100px; justify-content: center; }
|
||||||
|
.col-time { flex: 2; }
|
||||||
|
.col-ops { width: 100px; justify-content: center; }
|
||||||
|
|
||||||
|
.empty-row {
|
||||||
|
height: 200px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.empty-text {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #bfbfbf;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn {
|
||||||
|
height: 32px;
|
||||||
|
padding: 0 20px;
|
||||||
|
border-radius: 2px;
|
||||||
|
font-size: 14px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
cursor: pointer;
|
||||||
|
border: 1px solid #d9d9d9;
|
||||||
|
background-color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn.primary {
|
||||||
|
background-color: #1890ff;
|
||||||
|
border-color: #1890ff;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn.small {
|
||||||
|
height: 28px;
|
||||||
|
padding: 0 10px;
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,22 +1,122 @@
|
|||||||
<template>
|
<template>
|
||||||
<AdminLayout currentPage="dev-config-module">
|
<view class="admin-page">
|
||||||
<view class="page">
|
<view class="admin-sections">
|
||||||
<view class="header">
|
<view class="admin-card content-card">
|
||||||
<text class="title">模块配置</text>
|
<view class="form-container">
|
||||||
</view>
|
<view class="form-item">
|
||||||
<view class="content">
|
<view class="form-label">模块配置:</view>
|
||||||
<text class="tip">TODO: 模块配置</text>
|
<view class="form-content">
|
||||||
|
<label class="checkbox-item">
|
||||||
|
<checkbox color="#1890ff" checked />
|
||||||
|
<text class="checkbox-label">秒杀</text>
|
||||||
|
</label>
|
||||||
|
<label class="checkbox-item">
|
||||||
|
<checkbox color="#1890ff" checked />
|
||||||
|
<text class="checkbox-label">砍价</text>
|
||||||
|
</label>
|
||||||
|
<label class="checkbox-item">
|
||||||
|
<checkbox color="#1890ff" checked />
|
||||||
|
<text class="checkbox-label">拼团</text>
|
||||||
|
</label>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="form-tip">
|
||||||
|
模块配置,选中展示对应的模块,取消选中则前后端不展示模块相关内容
|
||||||
|
</view>
|
||||||
|
<view class="form-actions">
|
||||||
|
<button class="btn primary" @click="onSubmit">提交</button>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</AdminLayout>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="uts">
|
<script setup lang="uts">
|
||||||
import AdminLayout from '@/layouts/admin/AdminLayout.uvue'
|
function onSubmit() {
|
||||||
</script>
|
uni.showToast({ title: '已提交', icon: 'none' })
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.admin-page {
|
||||||
|
padding: 20px;
|
||||||
|
background-color: #f5f7f9;
|
||||||
|
min-height: 100vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-card {
|
||||||
|
background-color: #fff;
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 40px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-container {
|
||||||
|
max-width: 600px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-item {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-label {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #333;
|
||||||
|
width: 100px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-content {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.checkbox-item {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
margin-right: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.checkbox-label {
|
||||||
|
margin-left: 8px;
|
||||||
|
font-size: 14px;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-tip {
|
||||||
|
font-size: 12px;
|
||||||
|
color: #bfbfbf;
|
||||||
|
margin-left: 100px;
|
||||||
|
margin-bottom: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-actions {
|
||||||
|
margin-left: 100px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn {
|
||||||
|
height: 32px;
|
||||||
|
padding: 0 20px;
|
||||||
|
border-radius: 2px;
|
||||||
|
font-size: 14px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
cursor: pointer;
|
||||||
|
border: 1px solid #d9d9d9;
|
||||||
|
background-color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn.primary {
|
||||||
|
background-color: #1890ff;
|
||||||
|
border-color: #1890ff;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
.page { padding: 16px; }
|
|
||||||
.title { font-size: 18px; font-weight: 600; }
|
|
||||||
.tip { color: #999; margin-top: 8px; display: block; }
|
|
||||||
</style>
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,22 +1,263 @@
|
|||||||
<template>
|
<template>
|
||||||
<AdminLayout currentPage="dev-config-permission">
|
<view class="admin-page">
|
||||||
<view class="page">
|
<view class="admin-sections">
|
||||||
<view class="header">
|
<!-- 搜索栏 -->
|
||||||
<text class="title">权限维护</text>
|
<view class="admin-card filter-card">
|
||||||
</view>
|
<view class="filter-row">
|
||||||
<view class="content">
|
<view class="filter-item">
|
||||||
<text class="tip">TODO: 权限维护</text>
|
<text class="label">规则状态:</text>
|
||||||
|
<view class="filter-select">
|
||||||
|
<text class="select-placeholder">请选择</text>
|
||||||
|
<text class="arrow">▼</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="filter-item">
|
||||||
|
<text class="label">按钮名称:</text>
|
||||||
|
<input class="filter-input" placeholder="请输入按钮名称" />
|
||||||
|
</view>
|
||||||
|
<button class="btn primary" @click="onSearch">查询</button>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 内容区 -->
|
||||||
|
<view class="admin-card content-card">
|
||||||
|
<!-- 操作按钮行 -->
|
||||||
|
<view class="action-bar">
|
||||||
|
<button class="btn primary small" @click="onAdd">添加规则</button>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 表格 -->
|
||||||
|
<view class="table-container list-table">
|
||||||
|
<view class="table-header">
|
||||||
|
<view class="col col-name"><text>按钮名称</text></view>
|
||||||
|
<view class="col col-auth"><text>前项权限</text></view>
|
||||||
|
<view class="col col-route"><text>路由</text></view>
|
||||||
|
<view class="col col-status"><text>规则状态</text></view>
|
||||||
|
<view class="col col-memo"><text>备注</text></view>
|
||||||
|
<view class="col col-ops"><text>操作</text></view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="table-body">
|
||||||
|
<view v-for="item in dataList" :key="item.id" class="table-row">
|
||||||
|
<view class="col col-name">
|
||||||
|
<text class="expand-icon">▶</text>
|
||||||
|
<text>{{ item.name }}</text>
|
||||||
|
</view>
|
||||||
|
<view class="col col-auth"><text>{{ item.auth }}</text></view>
|
||||||
|
<view class="col col-route"><text>{{ item.route }}</text></view>
|
||||||
|
<view class="col col-status">
|
||||||
|
<switch :checked="item.status" color="#1890ff" scale="0.8" />
|
||||||
|
</view>
|
||||||
|
<view class="col col-memo"><text>{{ item.memo }}</text></view>
|
||||||
|
<view class="col col-ops">
|
||||||
|
<text class="op-link" @click="onSelectAuth(item)">选择权限</text>
|
||||||
|
<view class="op-divider">|</view>
|
||||||
|
<text class="op-link" @click="onAddSub(item)">添加下级</text>
|
||||||
|
<view class="op-divider">|</view>
|
||||||
|
<text class="op-link" @click="onEdit(item)">编辑</text>
|
||||||
|
<view class="op-divider">|</view>
|
||||||
|
<text class="op-link op-danger" @click="onDelete(item)">删除</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</AdminLayout>
|
|
||||||
</template>
|
</template>
|
||||||
<script setup lang="uts">
|
|
||||||
import AdminLayout from '@/layouts/admin/AdminLayout.uvue'
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped>
|
<script setup lang="uts">
|
||||||
.page { padding: 16px; }
|
import { ref } from 'vue'
|
||||||
.title { font-size: 18px; font-weight: 600; }
|
|
||||||
.tip { color: #999; margin-top: 8px; display: block; }
|
const dataList = ref([
|
||||||
|
{ id: 1, name: '主页', auth: 'admin-home', route: '菜单: /admin/index', status: true, memo: '主页' },
|
||||||
|
{ id: 2, name: '用户', auth: 'admin-user', route: '菜单: /admin/user', status: true, memo: '用户' },
|
||||||
|
{ id: 3, name: '订单', auth: 'admin-order', route: '菜单: /admin/order', status: true, memo: '订单' },
|
||||||
|
{ id: 4, name: '商品', auth: 'admin-product', route: '菜单: /admin/product', status: true, memo: '商品' },
|
||||||
|
{ id: 5, name: '营销', auth: 'admin-marketing', route: '菜单: /admin/marketing', status: true, memo: '营销' },
|
||||||
|
{ id: 6, name: '分销', auth: 'admin-agent', route: '菜单: /admin/agent', status: true, memo: '分销' },
|
||||||
|
{ id: 7, name: '客服', auth: 'setting-store-service', route: '菜单: /admin/kefu', status: true, memo: '客服' },
|
||||||
|
{ id: 8, name: '财务', auth: 'admin-finance', route: '菜单: /admin/finance', status: true, memo: '财务' },
|
||||||
|
{ id: 9, name: '内容', auth: 'admin-cms', route: '菜单: /admin/cms', status: true, memo: '内容' },
|
||||||
|
{ id: 10, name: '装修', auth: 'admin-setting-pages', route: '菜单: /admin/setting/pages', status: true, memo: '装修' },
|
||||||
|
{ id: 11, name: '应用', auth: 'admin-app', route: '菜单: /admin/app', status: true, memo: '应用' },
|
||||||
|
{ id: 12, name: '设置', auth: 'admin-setting', route: '菜单: /admin/setting', status: true, memo: '设置' },
|
||||||
|
{ id: 13, name: '维护', auth: 'admin-system', route: '菜单: /admin/system', status: true, memo: '维护' }
|
||||||
|
])
|
||||||
|
|
||||||
|
function onSearch() {
|
||||||
|
uni.showToast({ title: '查询中...', icon: 'none' })
|
||||||
|
}
|
||||||
|
|
||||||
|
function onAdd() {
|
||||||
|
uni.showToast({ title: '添加规则', icon: 'none' })
|
||||||
|
}
|
||||||
|
|
||||||
|
function onSelectAuth(item: any) {
|
||||||
|
uni.showToast({ title: '选择权限: ' + item.name, icon: 'none' })
|
||||||
|
}
|
||||||
|
|
||||||
|
function onAddSub(item: any) {
|
||||||
|
uni.showToast({ title: '添加下级: ' + item.name, icon: 'none' })
|
||||||
|
}
|
||||||
|
|
||||||
|
function onEdit(item: any) {
|
||||||
|
uni.showToast({ title: '编辑: ' + item.name, icon: 'none' })
|
||||||
|
}
|
||||||
|
|
||||||
|
function onDelete(item: any) {
|
||||||
|
uni.showModal({
|
||||||
|
title: '提示',
|
||||||
|
content: '确定要删除该规则吗?',
|
||||||
|
success: (res) => {
|
||||||
|
if (res.confirm) {
|
||||||
|
uni.showToast({ title: '已删除', icon: 'none' })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.admin-page {
|
||||||
|
padding: 20px;
|
||||||
|
background-color: #f5f7f9;
|
||||||
|
min-height: 100vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-card {
|
||||||
|
background-color: #fff;
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 20px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.filter-row {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.filter-item {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
margin-right: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.label {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.filter-select {
|
||||||
|
width: 150px;
|
||||||
|
height: 32px;
|
||||||
|
border: 1px solid #d9d9d9;
|
||||||
|
border-radius: 2px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: 0 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.select-placeholder {
|
||||||
|
color: #bfbfbf;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.filter-input {
|
||||||
|
width: 200px;
|
||||||
|
height: 32px;
|
||||||
|
border: 1px solid #d9d9d9;
|
||||||
|
border-radius: 2px;
|
||||||
|
padding: 0 10px;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn {
|
||||||
|
height: 32px;
|
||||||
|
padding: 0 20px;
|
||||||
|
border-radius: 2px;
|
||||||
|
font-size: 14px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
cursor: pointer;
|
||||||
|
border: 1px solid #d9d9d9;
|
||||||
|
background-color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn.primary {
|
||||||
|
background-color: #1890ff;
|
||||||
|
border-color: #1890ff;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn.small {
|
||||||
|
height: 28px;
|
||||||
|
padding: 0 10px;
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-bar {
|
||||||
|
margin-bottom: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-container {
|
||||||
|
width: 100%;
|
||||||
|
border: 1px solid #f0f0f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-header {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
background-color: #fafafa;
|
||||||
|
border-bottom: 1px solid #f0f0f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-row {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
border-bottom: 1px solid #f0f0f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.col {
|
||||||
|
padding: 12px 16px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
font-size: 14px;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.col-name { flex: 1.5; }
|
||||||
|
.col-auth { flex: 2; }
|
||||||
|
.col-route { flex: 3; }
|
||||||
|
.col-status { width: 100px; justify-content: center; }
|
||||||
|
.col-memo { flex: 1; }
|
||||||
|
.col-ops { flex: 3; justify-content: flex-end; }
|
||||||
|
|
||||||
|
.expand-icon {
|
||||||
|
margin-right: 8px;
|
||||||
|
font-size: 10px;
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
|
||||||
|
.op-link {
|
||||||
|
color: #1890ff;
|
||||||
|
cursor: pointer;
|
||||||
|
margin: 0 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.op-danger {
|
||||||
|
color: #ff4d4f;
|
||||||
|
}
|
||||||
|
|
||||||
|
.op-divider {
|
||||||
|
color: #f0f0f0;
|
||||||
|
margin: 0 4px;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,21 +1,330 @@
|
|||||||
<template>
|
<template>
|
||||||
<AdminLayout currentPage="dev-tools-api">
|
<view class="admin-page api-management">
|
||||||
<view class="page">
|
<!-- 左侧分类树 -->
|
||||||
<view class="header">
|
<view class="sidebar-tree">
|
||||||
<text class="title">接口管理</text>
|
<view class="sidebar-header">
|
||||||
</view>
|
<button class="btn-primary-sm">新增分类</button>
|
||||||
<view class="content">
|
<button class="btn-success-sm ml-10">同步</button>
|
||||||
<text class="tip">TODO: 接口管理</text>
|
</view>
|
||||||
</view>
|
<scroll-view class="tree-scroll" scroll-y="true">
|
||||||
</view>
|
<view class="tree-node" v-for="(group, gIndex) in apiGroups" :key="gIndex">
|
||||||
</AdminLayout>
|
<view class="node-label">
|
||||||
</template>
|
<text class="arrow">▼</text>
|
||||||
<script setup lang="uts">
|
<text class="folder-icon">📁</text>
|
||||||
import AdminLayout from '@/layouts/admin/AdminLayout.uvue'
|
<text class="label-text">{{ group.name }}</text>
|
||||||
</script>
|
</view>
|
||||||
<style scoped>
|
<view class="node-children">
|
||||||
.page { padding: 16px; }
|
<view
|
||||||
.title { font-size: 18px; font-weight: 600; }
|
class="child-item"
|
||||||
.tip { color: #999; margin-top: 8px; display: block; }
|
v-for="(api, aIndex) in group.children"
|
||||||
|
:key="aIndex"
|
||||||
|
:class="{ active: selectedApiId === api.id }"
|
||||||
|
@click="selectedApiId = api.id"
|
||||||
|
>
|
||||||
|
<text class="method-tag" :class="api.method.toLowerCase()">{{ api.method }}</text>
|
||||||
|
<text class="api-name">{{ api.name }}</text>
|
||||||
|
<text class="more-icon">...</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</scroll-view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 右侧接口详情 -->
|
||||||
|
<view class="api-content">
|
||||||
|
<view class="content-header">
|
||||||
|
<text class="current-api-title">分销员列表</text>
|
||||||
|
<view class="header-actions">
|
||||||
|
<button class="btn-secondary-sm">调试</button>
|
||||||
|
<button class="btn-primary-sm ml-10">编辑</button>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="info-section">
|
||||||
|
<view class="info-title">接口信息</view>
|
||||||
|
<view class="info-list">
|
||||||
|
<view class="info-item">
|
||||||
|
<text class="info-label">接口名称:</text>
|
||||||
|
<text class="info-value">分销员列表</text>
|
||||||
|
</view>
|
||||||
|
<view class="info-item">
|
||||||
|
<text class="info-label">请求类型:</text>
|
||||||
|
<text class="method-badge get">GET</text>
|
||||||
|
</view>
|
||||||
|
<view class="info-item">
|
||||||
|
<text class="info-label">功能描述:</text>
|
||||||
|
<text class="info-value">--</text>
|
||||||
|
</view>
|
||||||
|
<view class="info-item">
|
||||||
|
<text class="info-label">是否公共:</text>
|
||||||
|
<text class="info-value">否</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="info-section">
|
||||||
|
<view class="info-title">调用方式</view>
|
||||||
|
<view class="info-list">
|
||||||
|
<view class="info-item">
|
||||||
|
<text class="info-label">路由地址:</text>
|
||||||
|
<text class="info-value">agent/index</text>
|
||||||
|
</view>
|
||||||
|
<view class="info-item">
|
||||||
|
<text class="info-label">文件地址:</text>
|
||||||
|
<text class="info-value">app/adminapi/controller/v1/agent/AgentManage.php</text>
|
||||||
|
</view>
|
||||||
|
<view class="info-item">
|
||||||
|
<text class="info-label">方法名:</text>
|
||||||
|
<text class="info-value">index</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 参数表格 -->
|
||||||
|
<view class="params-section">
|
||||||
|
<view class="info-title">header参数:</view>
|
||||||
|
<view class="params-table">
|
||||||
|
<view class="table-head">
|
||||||
|
<view class="th p-attr">属性</view>
|
||||||
|
<view class="th p-type">类型</view>
|
||||||
|
<view class="th p-required">必须</view>
|
||||||
|
<view class="th p-desc">说明</view>
|
||||||
|
</view>
|
||||||
|
<view class="table-row">
|
||||||
|
<view class="td p-attr">Authori-zation</view>
|
||||||
|
<view class="td p-type">string</view>
|
||||||
|
<view class="td p-required">否</view>
|
||||||
|
<view class="td p-desc">--</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="params-section mt-20">
|
||||||
|
<view class="info-title">query参数:</view>
|
||||||
|
<view class="params-table">
|
||||||
|
<view class="table-head">
|
||||||
|
<view class="th p-attr">属性</view>
|
||||||
|
<view class="th p-type">类型</view>
|
||||||
|
<view class="th p-required">必须</view>
|
||||||
|
<view class="th p-desc">说明</view>
|
||||||
|
</view>
|
||||||
|
<view class="table-row" v-for="(p, i) in queryParams" :key="i">
|
||||||
|
<view class="td p-attr">{{ p.attr }}</view>
|
||||||
|
<view class="td p-type">{{ p.type }}</view>
|
||||||
|
<view class="td p-required">{{ p.required }}</view>
|
||||||
|
<view class="td p-desc">{{ p.desc }}</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view></template>
|
||||||
|
<script setup lang="uts">
|
||||||
|
import { ref } from 'vue'
|
||||||
|
|
||||||
|
const selectedApiId = ref('1-1')
|
||||||
|
|
||||||
|
const apiGroups = ref([
|
||||||
|
{
|
||||||
|
name: '分销员管理',
|
||||||
|
children: [
|
||||||
|
{ id: '1-1', name: '分销员列表', method: 'GET' },
|
||||||
|
{ id: '1-2', name: '修改上级推广人', method: 'PUT' },
|
||||||
|
{ id: '1-3', name: '分销员列表头部统计', method: 'GET' },
|
||||||
|
{ id: '1-4', name: '推广人列表', method: 'GET' },
|
||||||
|
{ id: '1-5', name: '推广订单列表', method: 'GET' }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '分销设置',
|
||||||
|
children: []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '分销等级',
|
||||||
|
children: []
|
||||||
|
}
|
||||||
|
])
|
||||||
|
|
||||||
|
const queryParams = ref([
|
||||||
|
{ attr: 'page', type: 'string', required: '是', desc: '页码' },
|
||||||
|
{ attr: 'limit', type: 'string', required: '是', desc: '每页条数' },
|
||||||
|
{ attr: 'nickname', type: 'string', required: '是', desc: '用户昵称/用户id/手机号码' }
|
||||||
|
])
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.api-management {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
height: calc(100vh - 64px);
|
||||||
|
background-color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar-tree {
|
||||||
|
width: 260px;
|
||||||
|
border-right: 1px solid #f0f0f0;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar-header {
|
||||||
|
padding: 15px;
|
||||||
|
border-bottom: 1px solid #f0f0f0;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tree-scroll {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tree-node {
|
||||||
|
padding: 5px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.node-label {
|
||||||
|
padding: 8px 15px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.label-text {
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 500;
|
||||||
|
margin-left: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.node-children {
|
||||||
|
padding-left: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.child-item {
|
||||||
|
padding: 8px 15px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
cursor: pointer;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.child-item.active {
|
||||||
|
background-color: #e6f7ff;
|
||||||
|
color: #1890ff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.method-tag {
|
||||||
|
font-size: 10px;
|
||||||
|
padding: 0 4px;
|
||||||
|
border-radius: 2px;
|
||||||
|
margin-right: 8px;
|
||||||
|
min-width: 30px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.method-tag.get { color: #52c41a; border: 1px solid #b7eb8f; background: #f6ffed; }
|
||||||
|
.method-tag.put { color: #faad14; border: 1px solid #ffe58f; background: #fffbe6; }
|
||||||
|
|
||||||
|
.api-name {
|
||||||
|
font-size: 13px;
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.api-content {
|
||||||
|
flex: 1;
|
||||||
|
padding: 20px;
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content-header {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 25px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.current-api-title {
|
||||||
|
font-size: 20px;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-section {
|
||||||
|
margin-bottom: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-title {
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 500;
|
||||||
|
margin-bottom: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-list {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 12px;
|
||||||
|
padding-left: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-item {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-label {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #666;
|
||||||
|
width: 80px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-value {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.method-badge {
|
||||||
|
font-size: 12px;
|
||||||
|
padding: 2px 8px;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.method-badge.get { background-color: #e6f7ff; color: #1890ff; }
|
||||||
|
|
||||||
|
.params-table {
|
||||||
|
border: 1px solid #f0f0f0;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-head {
|
||||||
|
background-color: #f8f8f9;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
border-bottom: 1px solid #f0f0f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-row {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
border-bottom: 1px solid #f0f0f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.th, .td {
|
||||||
|
padding: 12px;
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.p-attr { flex: 2; }
|
||||||
|
.p-type { flex: 1; }
|
||||||
|
.p-required { flex: 1; }
|
||||||
|
.p-desc { flex: 3; }
|
||||||
|
|
||||||
|
.btn-primary-sm { background-color: #1890ff; color: #fff; font-size: 12px; padding: 5px 10px; border-radius: 4px; border: none; }
|
||||||
|
.btn-success-sm { background-color: #52c41a; color: #fff; font-size: 12px; padding: 5px 10px; border-radius: 4px; border: none; }
|
||||||
|
.btn-secondary-sm { background-color: #fff; color: #666; border: 1px solid #d9d9d9; font-size: 12px; padding: 5px 10px; border-radius: 4px; }
|
||||||
|
|
||||||
|
.ml-10 { margin-left: 10px; }
|
||||||
|
.mt-20 { margin-top: 20px; }
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<AdminLayout currentPage="dev-tools-codegen">
|
<view class="admin-page">
|
||||||
<view class="page">
|
<view class="page">
|
||||||
|
|
||||||
<view class="header">
|
<view class="header">
|
||||||
<text class="title">代码生成</text>
|
<text class="title">代码生成</text>
|
||||||
</view>
|
</view>
|
||||||
@@ -9,5 +8,14 @@
|
|||||||
<text class="tip">TODO: 代码生成</text>
|
<text class="tip">TODO: 代码生成</text>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</AdminLayout>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="uts">
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.admin-page {
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|||||||
@@ -1,12 +1,200 @@
|
|||||||
<template>
|
<template>
|
||||||
<AdminLayout currentPage="dev-tools-dict">
|
<view class="admin-page data-dictionary">
|
||||||
<view class="page">
|
<view class="admin-sections">
|
||||||
<view class="header">
|
<view class="admin-card">
|
||||||
<text class="title">数据字典</text>
|
<!-- 搜索和添加 -->
|
||||||
</view>
|
<view class="header-tools">
|
||||||
<view class="content">
|
<view class="search-form">
|
||||||
<text class="tip">TODO: 数据字典</text>
|
<text class="label">字典名称:</text>
|
||||||
</view>
|
<input class="search-input" v-model="searchQuery" placeholder="请输入字典名称" />
|
||||||
</view>
|
<button class="btn-search" @click="handleSearch">查询</button>
|
||||||
</AdminLayout>
|
</view>
|
||||||
</template>
|
<button class="btn-primary" @click="handleAdd">添加数据字典</button>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 数据表格 -->
|
||||||
|
<view class="table-container">
|
||||||
|
<view class="table-header">
|
||||||
|
<view class="table-cell" style="flex: 0 0 60px;">ID</view>
|
||||||
|
<view class="table-cell" style="flex: 2;">字典名称</view>
|
||||||
|
<view class="table-cell" style="flex: 2;">数据标识</view>
|
||||||
|
<view class="table-cell" style="flex: 1;">类型</view>
|
||||||
|
<view class="table-cell" style="flex: 2;">添加时间</view>
|
||||||
|
<view class="table-cell action-cell" style="flex: 2;">操作</view>
|
||||||
|
</view>
|
||||||
|
<view class="table-body">
|
||||||
|
<view class="table-row" v-for="(item, index) in dictionaryList" :key="index">
|
||||||
|
<view class="table-cell" style="flex: 0 0 60px;">{{ item.id }}</view>
|
||||||
|
<view class="table-cell" style="flex: 2;">{{ item.name }}</view>
|
||||||
|
<view class="table-cell" style="flex: 2;">{{ item.tag }}</view>
|
||||||
|
<view class="table-cell" style="flex: 1;">{{ item.type }}</view>
|
||||||
|
<view class="table-cell" style="flex: 2;">{{ item.add_time }}</view>
|
||||||
|
<view class="table-cell action-cell" style="flex: 2;">
|
||||||
|
<text class="action-link" @click="handleEdit(item)">编辑</text>
|
||||||
|
<text class="action-link ml-10" @click="handleManage(item)">数据管理</text>
|
||||||
|
<text class="action-link link-danger ml-10" @click="handleDelete(item)">删除</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view></template>
|
||||||
|
<script setup lang="uts">
|
||||||
|
import { ref } from 'vue'
|
||||||
|
|
||||||
|
const searchQuery = ref('')
|
||||||
|
const dictionaryList = ref([
|
||||||
|
{ id: 8, name: '21', tag: '25425', type: '一级', add_time: '2024-08-23 17:37:08' },
|
||||||
|
{ id: 10, name: '相册', tag: 'xc', type: '多级', add_time: '2024-09-09 15:49:58' },
|
||||||
|
{ id: 11, name: '品类', tag: 'category', type: '多级', add_time: '2024-09-24 17:47:16' },
|
||||||
|
{ id: 12, name: '123', tag: '1', type: '一级', add_time: '2024-09-27 15:57:03' },
|
||||||
|
{ id: 13, name: '企业类型', tag: 'company_type', type: '多级', add_time: '2024-09-27 16:16:21' },
|
||||||
|
{ id: 14, name: '测试', tag: '343322222222234555343434', type: '多级', add_time: '2024-09-27 16:17:23' },
|
||||||
|
{ id: 16, name: '用户管理模块', tag: '123', type: '多级', add_time: '2024-10-22 09:30:46' },
|
||||||
|
{ id: 18, name: '类型', tag: '1', type: '多级', add_time: '2024-12-11 13:48:01' },
|
||||||
|
{ id: 19, name: '店铺', tag: 'shop', type: '多级', add_time: '2024-12-11 22:23:07' },
|
||||||
|
{ id: 20, name: 'ce', tag: 'zzz', type: '一级', add_time: '2024-12-14 12:19:17' }
|
||||||
|
])
|
||||||
|
|
||||||
|
function handleSearch() {
|
||||||
|
uni.showToast({ title: '搜索: ' + searchQuery.value, icon: 'none' })
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleAdd() {
|
||||||
|
uni.showToast({ title: '添加数据字典', icon: 'none' })
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleEdit(item: any) {
|
||||||
|
uni.showToast({ title: '编辑: ' + item.name, icon: 'none' })
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleManage(item: any) {
|
||||||
|
uni.showToast({ title: '数据管理: ' + item.name, icon: 'none' })
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleDelete(item: any) {
|
||||||
|
uni.showModal({
|
||||||
|
title: '提示',
|
||||||
|
content: '确定删除该数据字典吗?',
|
||||||
|
success: (res) => {
|
||||||
|
if (res.confirm) {
|
||||||
|
uni.showToast({ title: '已删除', icon: 'success' })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.admin-page {
|
||||||
|
padding: 20px;
|
||||||
|
background-color: #f5f7f9;
|
||||||
|
min-height: 100vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-card {
|
||||||
|
background-color: #fff;
|
||||||
|
padding: 24px;
|
||||||
|
border-radius: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header-tools {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-form {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.label {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #333;
|
||||||
|
margin-right: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-input {
|
||||||
|
width: 200px;
|
||||||
|
height: 32px;
|
||||||
|
border: 1px solid #d9d9d9;
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 0 12px;
|
||||||
|
font-size: 14px;
|
||||||
|
margin-right: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-search {
|
||||||
|
background-color: #1890ff;
|
||||||
|
color: #fff;
|
||||||
|
font-size: 14px;
|
||||||
|
height: 32px;
|
||||||
|
line-height: 32px;
|
||||||
|
padding: 0 15px;
|
||||||
|
border-radius: 4px;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-primary {
|
||||||
|
background-color: #1890ff;
|
||||||
|
color: #fff;
|
||||||
|
font-size: 14px;
|
||||||
|
height: 32px;
|
||||||
|
line-height: 32px;
|
||||||
|
padding: 0 20px;
|
||||||
|
border-radius: 4px;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-container {
|
||||||
|
border: 1px solid #f0f0f0;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-header {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
background-color: #f8f8f9;
|
||||||
|
border-bottom: 1px solid #f0f0f0;
|
||||||
|
padding: 12px 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-body {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-row {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
border-bottom: 1px solid #f0f0f0;
|
||||||
|
padding: 12px 10px;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-cell {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #666;
|
||||||
|
padding: 0 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-link {
|
||||||
|
color: #1890ff;
|
||||||
|
font-size: 13px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.link-danger {
|
||||||
|
color: #ff4d4f;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ml-10 {
|
||||||
|
margin-left: 10px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
|||||||
@@ -1,12 +1,146 @@
|
|||||||
<template>
|
<template>
|
||||||
<AdminLayout currentPage="dev-tools-db">
|
<view class="admin-page">
|
||||||
<view class="page">
|
<view class="admin-sections">
|
||||||
<view class="header">
|
<view class="admin-card">
|
||||||
<text class="title">数据库管理</text>
|
<view class="page-header">
|
||||||
</view>
|
<text class="page-title">数据库管理</text>
|
||||||
<view class="content">
|
<view class="header-btns">
|
||||||
<text class="tip">TODO: 数据库管理</text>
|
<button class="btn btn-primary btn-sm" @click="handleExport">备份数据库</button>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</AdminLayout>
|
|
||||||
|
<!-- 数据表格 -->
|
||||||
|
<view class="admin-table">
|
||||||
|
<view class="thead">
|
||||||
|
<view class="th col-name">表名</view>
|
||||||
|
<view class="th col-engine">引擎</view>
|
||||||
|
<view class="th col-rows">行数</view>
|
||||||
|
<view class="th col-size">数据大小</view>
|
||||||
|
<view class="th col-index">索引大小</view>
|
||||||
|
<view class="th col-comment">备注</view>
|
||||||
|
<view class="th col-op">操作</view>
|
||||||
|
</view>
|
||||||
|
<view class="tbody">
|
||||||
|
<view v-for="(item, index) in tableData" :key="index" class="tr">
|
||||||
|
<view class="td col-name">{{ item.name }}</view>
|
||||||
|
<view class="td col-engine">{{ item.engine }}</view>
|
||||||
|
<view class="td col-rows">{{ item.rows }}</view>
|
||||||
|
<view class="td col-size">{{ item.dataSize }}</view>
|
||||||
|
<view class="td col-index">{{ item.indexSize }}</view>
|
||||||
|
<view class="td col-comment">{{ item.comment }}</view>
|
||||||
|
<view class="td col-op">
|
||||||
|
<text class="op-link" @click="handleOptimize(item.name)">优化</text>
|
||||||
|
<text class="op-link" @click="handleRepair(item.name)">修复</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="uts">
|
||||||
|
import { ref } from 'vue'
|
||||||
|
|
||||||
|
const tableData = ref([
|
||||||
|
{ name: 'eb_system_admin', engine: 'InnoDB', rows: 5, dataSize: '16.00 KB', indexSize: '16.00 KB', comment: '后台管理员表' },
|
||||||
|
{ name: 'eb_user', engine: 'InnoDB', rows: 1250, dataSize: '320.00 KB', indexSize: '156.00 KB', comment: '用户表' },
|
||||||
|
{ name: 'eb_store_product', engine: 'InnoDB', rows: 86, dataSize: '1.20 MB', indexSize: '64.00 KB', comment: '商品表' },
|
||||||
|
{ name: 'eb_store_order', engine: 'InnoDB', rows: 4521, dataSize: '2.50 MB', indexSize: '512.00 KB', comment: '订单表' },
|
||||||
|
{ name: 'eb_system_config', engine: 'InnoDB', rows: 156, dataSize: '48.00 KB', indexSize: '16.00 KB', comment: '系统配置表' }
|
||||||
|
])
|
||||||
|
|
||||||
|
function handleExport() {
|
||||||
|
uni.showLoading({ title: '正在备份...' })
|
||||||
|
setTimeout(() => {
|
||||||
|
uni.hideLoading()
|
||||||
|
uni.showToast({ title: '备份成功' })
|
||||||
|
}, 1500)
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleOptimize(name: string) {
|
||||||
|
uni.showToast({ title: '优化表: ' + name, icon: 'none' })
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleRepair(name: string) {
|
||||||
|
uni.showToast({ title: '修复表: ' + name, icon: 'none' })
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.admin-page {
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
.admin-card {
|
||||||
|
background-color: #fff;
|
||||||
|
padding: 20px;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
.page-header {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
.page-title {
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
.btn-sm {
|
||||||
|
height: 32px;
|
||||||
|
line-height: 32px;
|
||||||
|
font-size: 14px;
|
||||||
|
padding: 0 15px;
|
||||||
|
}
|
||||||
|
.btn-primary {
|
||||||
|
background-color: #1890ff;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 表格样式 */
|
||||||
|
.admin-table {
|
||||||
|
border: 1px solid #e8eaec;
|
||||||
|
}
|
||||||
|
.thead {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
background-color: #f8f8f9;
|
||||||
|
border-bottom: 1px solid #e8eaec;
|
||||||
|
}
|
||||||
|
.tbody {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
.tr {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
border-bottom: 1px solid #e8eaec;
|
||||||
|
}
|
||||||
|
.tr:last-child {
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
.th, .td {
|
||||||
|
padding: 12px 10px;
|
||||||
|
font-size: 14px;
|
||||||
|
color: #515a6e;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
.th {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
.col-name { flex: 2; }
|
||||||
|
.col-engine { flex: 1; }
|
||||||
|
.col-rows { flex: 1; }
|
||||||
|
.col-size { flex: 1; }
|
||||||
|
.col-index { flex: 1; }
|
||||||
|
.col-comment { flex: 2; }
|
||||||
|
.col-op { width: 120px; justify-content: space-around; }
|
||||||
|
|
||||||
|
.op-link {
|
||||||
|
color: #1890ff;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|||||||
@@ -1,12 +1,144 @@
|
|||||||
<template>
|
<template>
|
||||||
<AdminLayout currentPage="dev-tools-file">
|
<view class="admin-page file-login-container">
|
||||||
<view class="page">
|
<view class="login-card">
|
||||||
<view class="header">
|
<view class="login-header">
|
||||||
<text class="title">文件管理</text>
|
<text class="login-title">文件管理登录</text>
|
||||||
</view>
|
</view>
|
||||||
<view class="content">
|
<view class="login-form">
|
||||||
<text class="tip">TODO: 文件管理</text>
|
<view class="form-item">
|
||||||
</view>
|
<input
|
||||||
</view>
|
class="login-input"
|
||||||
</AdminLayout>
|
type="password"
|
||||||
|
v-model="password"
|
||||||
|
placeholder="请输入密码"
|
||||||
|
/>
|
||||||
|
</view>
|
||||||
|
<view class="form-tip">
|
||||||
|
提示:密码配置在 /config/filesystem.php 文件中修改 'password' => '密码'
|
||||||
|
</view>
|
||||||
|
<button class="login-btn" @click="handleLogin">登录</button>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 底部备案/版本信息 (1:1 复刻 CRMEB) -->
|
||||||
|
<view class="login-footer">
|
||||||
|
<view class="footer-links">
|
||||||
|
<text class="footer-link">官网</text>
|
||||||
|
<text class="footer-link">社区</text>
|
||||||
|
<text class="footer-link">文档</text>
|
||||||
|
</view>
|
||||||
|
<view class="copyright">
|
||||||
|
Copyright © 2014-2025 CRMEB-BZ v5.6.4
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="uts">
|
||||||
|
import { ref } from 'vue'
|
||||||
|
|
||||||
|
const password = ref('')
|
||||||
|
|
||||||
|
const handleLogin = () => {
|
||||||
|
if (!password.value) {
|
||||||
|
uni.showToast({ title: '请输入密码', icon: 'none' })
|
||||||
|
return
|
||||||
|
}
|
||||||
|
uni.showLoading({ title: '正在登录...' })
|
||||||
|
setTimeout(() => {
|
||||||
|
uni.hideLoading()
|
||||||
|
uni.showToast({ title: '登录成功(演示)' })
|
||||||
|
}, 1000)
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.admin-page {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
min-height: calc(100vh - 120px);
|
||||||
|
background-color: #f5f7f9;
|
||||||
|
}
|
||||||
|
|
||||||
|
.login-card {
|
||||||
|
width: 400px;
|
||||||
|
background-color: #fff;
|
||||||
|
border-radius: 4px;
|
||||||
|
box-shadow: 0 2px 12px 0 rgba(0,0,0,.1);
|
||||||
|
padding: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.login-header {
|
||||||
|
text-align: center;
|
||||||
|
margin-bottom: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.login-title {
|
||||||
|
font-size: 28px;
|
||||||
|
color: #1890ff;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.login-form {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-item {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.login-input {
|
||||||
|
width: 100%;
|
||||||
|
height: 40px;
|
||||||
|
border: 1px solid #dcdfe6;
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 0 15px;
|
||||||
|
font-size: 14px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-tip {
|
||||||
|
font-size: 12px;
|
||||||
|
color: #909399;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.login-btn {
|
||||||
|
width: 120px;
|
||||||
|
height: 40px;
|
||||||
|
line-height: 40px;
|
||||||
|
background-color: #1890ff;
|
||||||
|
color: #fff;
|
||||||
|
font-size: 14px;
|
||||||
|
align-self: center;
|
||||||
|
border-radius: 4px;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.login-footer {
|
||||||
|
margin-top: 50px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer-links {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 20px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer-link {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #606266;
|
||||||
|
}
|
||||||
|
|
||||||
|
.copyright {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #909399;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|||||||
146
pages/mall/admin/maintain/lang/config.uvue
Normal file
146
pages/mall/admin/maintain/lang/config.uvue
Normal file
@@ -0,0 +1,146 @@
|
|||||||
|
<template>
|
||||||
|
<view class="admin-page">
|
||||||
|
<view class="admin-sections">
|
||||||
|
<!-- 页面标题 -->
|
||||||
|
<view class="page-header admin-card">
|
||||||
|
<text class="title">翻译配置</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 配置表单 -->
|
||||||
|
<view class="admin-card content-card form-container">
|
||||||
|
<view class="form-item">
|
||||||
|
<view class="form-label">
|
||||||
|
<text class="required">*</text>
|
||||||
|
<text>AccessKey:</text>
|
||||||
|
</view>
|
||||||
|
<view class="form-content">
|
||||||
|
<input class="form-input" v-model="config.accessKey" placeholder="请输入 AccessKey" />
|
||||||
|
<text class="form-tip">机器翻译仅支持火山翻译,注册地址 https://console.volcengine.com,在访问控制里面新建 api 密钥</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="form-item mt-24">
|
||||||
|
<view class="form-label">
|
||||||
|
<text class="required">*</text>
|
||||||
|
<text>SecretKey:</text>
|
||||||
|
</view>
|
||||||
|
<view class="form-content">
|
||||||
|
<input class="form-input" v-model="config.secretKey" placeholder="请输入 SecretKey" type="password" />
|
||||||
|
<text class="form-tip">机器翻译仅支持火山翻译,注册地址 https://console.volcengine.com,在访问控制里面新建 api 密钥</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="form-actions mt-32">
|
||||||
|
<button class="btn primary submit-btn" @click="onSubmit">提交</button>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="uts">
|
||||||
|
import { ref } from 'vue'
|
||||||
|
|
||||||
|
const config = ref({
|
||||||
|
accessKey: 'AKLTMzkzZTEzNjg3OTg2NDVlMzlwnmFIYzhmNzkzMmE4MmI4YmI',
|
||||||
|
secretKey: 'TVRneU16STFOVFV4WVRWVE5EERTJaV0pqWm1aa1U1UagINVFpPWld'
|
||||||
|
})
|
||||||
|
|
||||||
|
function onSubmit() {
|
||||||
|
uni.showLoading({ title: '提交中...' })
|
||||||
|
setTimeout(() => {
|
||||||
|
uni.hideLoading()
|
||||||
|
uni.showToast({ title: '保存成功' })
|
||||||
|
}, 1000)
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.admin-page {
|
||||||
|
padding: 24px;
|
||||||
|
background-color: #f5f7f9;
|
||||||
|
min-height: 100vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-card {
|
||||||
|
background-color: #fff;
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 20px 24px;
|
||||||
|
margin-bottom: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title {
|
||||||
|
font-size: 18px;
|
||||||
|
font-weight: 500;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-item {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: flex-start;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-label {
|
||||||
|
width: 120px;
|
||||||
|
padding-top: 8px;
|
||||||
|
text-align: right;
|
||||||
|
margin-right: 16px;
|
||||||
|
font-size: 14px;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.required {
|
||||||
|
color: #ff4d4f;
|
||||||
|
margin-right: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-content {
|
||||||
|
flex: 1;
|
||||||
|
max-width: 600px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-input {
|
||||||
|
width: 100%;
|
||||||
|
height: 38px;
|
||||||
|
border: 1px solid #d9d9d9;
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 0 12px;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-tip {
|
||||||
|
display: block;
|
||||||
|
margin-top: 8px;
|
||||||
|
font-size: 12px;
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mt-24 { margin-top: 24px; }
|
||||||
|
.mt-32 { margin-top: 32px; }
|
||||||
|
|
||||||
|
.form-actions {
|
||||||
|
padding-left: 136px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn {
|
||||||
|
height: 38px;
|
||||||
|
padding: 0 24px;
|
||||||
|
border-radius: 4px;
|
||||||
|
font-size: 14px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
cursor: pointer;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn.primary {
|
||||||
|
background-color: #1890ff;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.submit-btn {
|
||||||
|
width: 80px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
274
pages/mall/admin/maintain/lang/detail.uvue
Normal file
274
pages/mall/admin/maintain/lang/detail.uvue
Normal file
@@ -0,0 +1,274 @@
|
|||||||
|
<template>
|
||||||
|
<view class="admin-page">
|
||||||
|
<view class="admin-sections">
|
||||||
|
<!-- 搜索栏 -->
|
||||||
|
<view class="admin-card filter-card">
|
||||||
|
<view class="filter-row">
|
||||||
|
<view class="filter-item">
|
||||||
|
<text class="label">语言分类:</text>
|
||||||
|
<view class="filter-select">
|
||||||
|
<text class="select-text">页面语言</text>
|
||||||
|
<text class="arrow">▼</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="filter-item">
|
||||||
|
<text class="label">语言类型:</text>
|
||||||
|
<view class="filter-select select-md">
|
||||||
|
<text class="select-text">中文(zh-CN)</text>
|
||||||
|
<text class="arrow">▼</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="filter-item">
|
||||||
|
<text class="label">搜索:</text>
|
||||||
|
<input class="filter-input" placeholder="请输入语言备注" />
|
||||||
|
</view>
|
||||||
|
<button class="btn primary" @click="onSearch">搜索</button>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 提示栏 -->
|
||||||
|
<view class="alert-info">
|
||||||
|
<view class="info-block">
|
||||||
|
<text class="info-title">页面语言</text>
|
||||||
|
<text class="info-content">添加页面语言,添加完成之后状态码为中文文字,移动端面使用 $t('xxxx'),js文件中使用 this.$t('xxxx') 或者使用 that.$t('xxxx') 实现语言的切换</text>
|
||||||
|
</view>
|
||||||
|
<view class="info-block mt-12">
|
||||||
|
<text class="info-title">接口语言</text>
|
||||||
|
<text class="info-content">添加接口语言,添加完成之后状态码为6位数字,接口返回提示信息时,直接返回对应的错误码即可实现语言的切换</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 操作栏 -->
|
||||||
|
<view class="action-bar header-actions">
|
||||||
|
<button class="btn primary" @click="addWord">添加语句</button>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 表格内容 -->
|
||||||
|
<view class="admin-card content-card">
|
||||||
|
<view class="table-container list-table">
|
||||||
|
<view class="table-header">
|
||||||
|
<view class="col col-id"><text>编号</text></view>
|
||||||
|
<view class="col col-origin"><text>原语句</text></view>
|
||||||
|
<view class="col col-translation"><text>对应语言翻译</text></view>
|
||||||
|
<view class="col col-code"><text>状态码/文字(接口/页面调用参考)</text></view>
|
||||||
|
<view class="col col-type"><text>语言类型</text></view>
|
||||||
|
<view class="col col-action"><text>操作</text></view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="table-body">
|
||||||
|
<view v-for="item in dataList" :key="item.id" class="table-row">
|
||||||
|
<view class="col col-id"><text>{{ item.id }}</text></view>
|
||||||
|
<view class="col col-origin"><text>{{ item.origin }}</text></view>
|
||||||
|
<view class="col col-translation"><text>{{ item.translation }}</text></view>
|
||||||
|
<view class="col col-code"><text>{{ item.code }}</text></view>
|
||||||
|
<view class="col col-type"><text>{{ item.type }}</text></view>
|
||||||
|
<view class="col col-action">
|
||||||
|
<text class="action-btn" @click="editWord(item)">编辑</text>
|
||||||
|
<text class="action-btn divider">|</text>
|
||||||
|
<text class="action-btn danger" @click="deleteWord(item)">删除</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="uts">
|
||||||
|
import { ref } from 'vue'
|
||||||
|
|
||||||
|
const dataList = ref([
|
||||||
|
{ id: 55493, origin: '秒杀活动', translation: '秒杀活动', code: '秒杀活动', type: '中文(zh-CN)' },
|
||||||
|
{ id: 55483, origin: '哥哥我', translation: '', code: '哥哥我', type: '中文(zh-CN)' },
|
||||||
|
{ id: 25221, origin: '提交订单', translation: '提交订单', code: '提交订单', type: '中文(zh-CN)' },
|
||||||
|
{ id: 25211, origin: '用户等级优惠', translation: '用户等级优惠', code: '用户等级优惠', type: '中文(zh-CN)' },
|
||||||
|
{ id: 25201, origin: '暂不支付', translation: '暂不支付', code: '暂不支付', type: '中文(zh-CN)' },
|
||||||
|
{ id: 25191, origin: '确认支付', translation: '确认支付', code: '确认支付', type: '中文(zh-CN)' },
|
||||||
|
{ id: 25181, origin: '支付剩余时间', translation: '支付剩余时间', code: '支付剩余时间', type: '中文(zh-CN)' },
|
||||||
|
{ id: 24711, origin: '全部已读', translation: '全部已读', code: '全部已读', type: '中文(zh-CN)' },
|
||||||
|
{ id: 24701, origin: '获得拼团团长佣金', translation: '获得拼团团长佣金', code: '获得拼团团长佣金', type: '中文(zh-CN)' },
|
||||||
|
{ id: 24691, origin: '获得事业部推广订单佣金', translation: '获得事业部推广订单佣金', code: '获得事业部推广订单佣金', type: '中文(zh-CN)' }
|
||||||
|
])
|
||||||
|
|
||||||
|
function onSearch() {
|
||||||
|
uni.showToast({ title: '搜索中...', icon: 'none' })
|
||||||
|
}
|
||||||
|
|
||||||
|
function addWord() {
|
||||||
|
uni.showToast({ title: '添加语句', icon: 'none' })
|
||||||
|
}
|
||||||
|
|
||||||
|
function editWord(item: any) {
|
||||||
|
uni.showToast({ title: '编辑: ' + item.origin, icon: 'none' })
|
||||||
|
}
|
||||||
|
|
||||||
|
function deleteWord(item: any) {
|
||||||
|
uni.showModal({
|
||||||
|
title: '提示',
|
||||||
|
content: '确定要删除此翻译语句吗?',
|
||||||
|
success: (res) => {
|
||||||
|
if (res.confirm) {
|
||||||
|
uni.showToast({ title: '删除成功' })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.admin-page {
|
||||||
|
padding: 24px;
|
||||||
|
background-color: #f5f7f9;
|
||||||
|
min-height: 100vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
.filter-row {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
gap: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.filter-item {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.label {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #333;
|
||||||
|
margin-right: 8px;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.filter-select {
|
||||||
|
width: 150px;
|
||||||
|
height: 32px;
|
||||||
|
border: 1px solid #d9d9d9;
|
||||||
|
border-radius: 4px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: 0 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.select-md {
|
||||||
|
width: 200px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.filter-input {
|
||||||
|
width: 200px;
|
||||||
|
height: 32px;
|
||||||
|
border: 1px solid #d9d9d9;
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 0 10px;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.alert-info {
|
||||||
|
background-color: #fff7e6;
|
||||||
|
border: 1px solid #ffe7ba;
|
||||||
|
padding: 20px;
|
||||||
|
border-radius: 4px;
|
||||||
|
margin: 24px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-block {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mt-12 {
|
||||||
|
margin-top: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-title {
|
||||||
|
color: #fa8c16;
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: bold;
|
||||||
|
margin-bottom: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-content {
|
||||||
|
color: #fa8c16;
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 1.6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-bar {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-card {
|
||||||
|
background-color: #fff;
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn {
|
||||||
|
height: 32px;
|
||||||
|
padding: 0 16px;
|
||||||
|
border-radius: 4px;
|
||||||
|
font-size: 14px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
cursor: pointer;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn.primary {
|
||||||
|
background-color: #1890ff;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-container {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-header {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
background-color: #fafafa;
|
||||||
|
border-bottom: 1px solid #f0f0f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-row {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
border-bottom: 1px solid #f0f0f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.col {
|
||||||
|
padding: 16px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
font-size: 14px;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.col-id { width: 80px; }
|
||||||
|
.col-origin { flex: 2; }
|
||||||
|
.col-translation { flex: 2; }
|
||||||
|
.col-code { flex: 2; }
|
||||||
|
.col-type { width: 150px; }
|
||||||
|
.col-action { width: 150px; justify-content: flex-end; }
|
||||||
|
|
||||||
|
.action-btn {
|
||||||
|
color: #1890ff;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-btn.danger {
|
||||||
|
color: #ff4d4f;
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-btn.divider {
|
||||||
|
margin: 0 8px;
|
||||||
|
color: #e8e8e8;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
226
pages/mall/admin/maintain/lang/list.uvue
Normal file
226
pages/mall/admin/maintain/lang/list.uvue
Normal file
@@ -0,0 +1,226 @@
|
|||||||
|
<template>
|
||||||
|
<view class="admin-page">
|
||||||
|
<view class="admin-sections">
|
||||||
|
<!-- 操作栏 -->
|
||||||
|
<view class="action-bar header-actions">
|
||||||
|
<button class="btn primary" @click="addLanguage">添加语言</button>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 表格内容 -->
|
||||||
|
<view class="admin-card content-card">
|
||||||
|
<view class="table-container list-table">
|
||||||
|
<view class="table-header">
|
||||||
|
<view class="col col-id"><text>ID</text></view>
|
||||||
|
<view class="col col-name"><text>语言名称</text></view>
|
||||||
|
<view class="col col-code"><text>浏览器语言识别码</text></view>
|
||||||
|
<view class="col col-status"><text>状态</text></view>
|
||||||
|
<view class="col col-action"><text>操作</text></view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="table-body">
|
||||||
|
<view v-for="item in dataList" :key="item.id" class="table-row">
|
||||||
|
<view class="col col-id"><text>{{ item.id }}</text></view>
|
||||||
|
<view class="col col-name">
|
||||||
|
<text>{{ item.name }}</text>
|
||||||
|
<text v-if="item.isDefault" class="default-badge">默认</text>
|
||||||
|
</view>
|
||||||
|
<view class="col col-code"><text>{{ item.code }}</text></view>
|
||||||
|
<view class="col col-status">
|
||||||
|
<view :class="['status-tag', item.status ? 'active' : 'inactive']" @click="toggleStatus(item)">
|
||||||
|
<text class="tag-text">{{ item.status ? '开启' : '关闭' }}</text>
|
||||||
|
<view class="tag-dot"></view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="col col-action">
|
||||||
|
<text class="action-btn" @click="editItem(item)">编辑</text>
|
||||||
|
<text class="action-btn divider">|</text>
|
||||||
|
<text class="action-btn danger" @click="deleteItem(item)">删除</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 分页 -->
|
||||||
|
<view class="pagination">
|
||||||
|
<text class="page-info">共 10 条 15条/页</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="uts">
|
||||||
|
import { ref } from 'vue'
|
||||||
|
|
||||||
|
const dataList = ref([
|
||||||
|
{ id: 1, name: '中文', code: 'zh-CN', status: true, isDefault: true },
|
||||||
|
{ id: 2, name: 'English', code: 'en-US', status: true, isDefault: false },
|
||||||
|
{ id: 3, name: '繁體中文', code: 'zh-Hant', status: true, isDefault: false },
|
||||||
|
{ id: 4, name: 'Français', code: 'fr-FR', status: true, isDefault: false },
|
||||||
|
{ id: 5, name: 'Italiano', code: 'it-IT', status: true, isDefault: false },
|
||||||
|
{ id: 6, name: '日本語', code: 'ja-JP', status: true, isDefault: false },
|
||||||
|
{ id: 7, name: '한국어', code: 'ko-KR', status: true, isDefault: false },
|
||||||
|
{ id: 8, name: 'Монгол', code: 'mn-MN', status: true, isDefault: false },
|
||||||
|
{ id: 9, name: 'ภาษาไทย', code: 'th-TH', status: true, isDefault: false },
|
||||||
|
{ id: 10, name: 'ViệtName', code: 'vi-VN', status: true, isDefault: false }
|
||||||
|
])
|
||||||
|
|
||||||
|
function addLanguage() {
|
||||||
|
uni.showToast({ title: '添加语言', icon: 'none' })
|
||||||
|
}
|
||||||
|
|
||||||
|
function toggleStatus(item: any) {
|
||||||
|
item.status = !item.status
|
||||||
|
}
|
||||||
|
|
||||||
|
function editItem(item: any) {
|
||||||
|
uni.showToast({ title: '编辑: ' + item.name, icon: 'none' })
|
||||||
|
}
|
||||||
|
|
||||||
|
function deleteItem(item: any) {
|
||||||
|
uni.showModal({
|
||||||
|
title: '提示',
|
||||||
|
content: '确定要删除此语言吗?',
|
||||||
|
success: (res) => {
|
||||||
|
if (res.confirm) {
|
||||||
|
uni.showToast({ title: '删除成功' })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.admin-page {
|
||||||
|
padding: 24px;
|
||||||
|
background-color: #f5f7f9;
|
||||||
|
min-height: 100vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-bar {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-card {
|
||||||
|
background-color: #fff;
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn {
|
||||||
|
height: 32px;
|
||||||
|
padding: 0 16px;
|
||||||
|
border-radius: 4px;
|
||||||
|
font-size: 14px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
cursor: pointer;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn.primary {
|
||||||
|
background-color: #1890ff;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-container {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-header {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
background-color: #fafafa;
|
||||||
|
border-bottom: 1px solid #f0f0f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-row {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
border-bottom: 1px solid #f0f0f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.col {
|
||||||
|
padding: 16px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
font-size: 14px;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.col-id { width: 80px; }
|
||||||
|
.col-name { flex: 1; position: relative; }
|
||||||
|
.col-code { flex: 1; }
|
||||||
|
.col-status { width: 120px; justify-content: center; }
|
||||||
|
.col-action { width: 150px; justify-content: flex-end; }
|
||||||
|
|
||||||
|
.default-badge {
|
||||||
|
background-color: #e6f7ff;
|
||||||
|
color: #1890ff;
|
||||||
|
font-size: 12px;
|
||||||
|
padding: 2px 8px;
|
||||||
|
border-radius: 4px;
|
||||||
|
margin-left: 8px;
|
||||||
|
border: 1px solid #91d5ff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.status-tag {
|
||||||
|
width: 60px;
|
||||||
|
height: 24px;
|
||||||
|
border-radius: 12px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: 0 8px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.status-tag.active {
|
||||||
|
background-color: #1890ff;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.status-tag.inactive {
|
||||||
|
background-color: #d9d9d9;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tag-text {
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tag-dot {
|
||||||
|
width: 8px;
|
||||||
|
height: 8px;
|
||||||
|
background-color: #fff;
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-btn {
|
||||||
|
color: #1890ff;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-btn.danger {
|
||||||
|
color: #ff4d4f;
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-btn.divider {
|
||||||
|
margin: 0 8px;
|
||||||
|
color: #e8e8e8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pagination {
|
||||||
|
padding: 16px 24px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-info {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
191
pages/mall/admin/maintain/lang/region.uvue
Normal file
191
pages/mall/admin/maintain/lang/region.uvue
Normal file
@@ -0,0 +1,191 @@
|
|||||||
|
<template>
|
||||||
|
<view class="admin-page">
|
||||||
|
<view class="admin-sections">
|
||||||
|
<!-- 搜索栏 -->
|
||||||
|
<view class="admin-card filter-card">
|
||||||
|
<view class="filter-row">
|
||||||
|
<view class="filter-item">
|
||||||
|
<text class="label">搜索:</text>
|
||||||
|
<input class="filter-input" placeholder="请输入语言Code" />
|
||||||
|
</view>
|
||||||
|
<button class="btn primary" @click="onSearch">搜索</button>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 操作栏 -->
|
||||||
|
<view class="action-bar header-actions">
|
||||||
|
<button class="btn primary" @click="addRegion">添加语言地区</button>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 表格内容 -->
|
||||||
|
<view class="admin-card content-card">
|
||||||
|
<view class="table-container list-table">
|
||||||
|
<view class="table-header">
|
||||||
|
<view class="col col-id"><text>编号</text></view>
|
||||||
|
<view class="col col-code"><text>浏览器语言识别码</text></view>
|
||||||
|
<view class="col col-desc"><text>语言说明</text></view>
|
||||||
|
<view class="col col-lang"><text>关联语言</text></view>
|
||||||
|
<view class="col col-action"><text>操作</text></view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="table-body">
|
||||||
|
<view v-for="item in dataList" :key="item.id" class="table-row">
|
||||||
|
<view class="col col-id"><text>{{ item.id }}</text></view>
|
||||||
|
<view class="col col-code"><text>{{ item.code }}</text></view>
|
||||||
|
<view class="col col-desc"><text>{{ item.desc }}</text></view>
|
||||||
|
<view class="col col-lang"><text>{{ item.lang || '暂无' }}</text></view>
|
||||||
|
<view class="col col-action">
|
||||||
|
<text class="action-btn" @click="editItem(item)">编辑</text>
|
||||||
|
<text class="action-btn divider">|</text>
|
||||||
|
<text class="action-btn danger" @click="deleteItem(item)">删除</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="uts">
|
||||||
|
import { ref } from 'vue'
|
||||||
|
|
||||||
|
const dataList = ref([
|
||||||
|
{ id: 346, code: 'zh-HK', desc: '中文(繁体, 香港特别行政区)', lang: '' },
|
||||||
|
{ id: 344, code: 'zh-MO', desc: '中文(繁体, 澳门特别行政区)', lang: '' },
|
||||||
|
{ id: 343, code: 'zh-Hant', desc: '中文(繁体)', lang: '繁体中文(zh-Hant)' },
|
||||||
|
{ id: 342, code: 'zh', desc: '中文', lang: '' },
|
||||||
|
{ id: 340, code: 'vi', desc: '越南语', lang: '' },
|
||||||
|
{ id: 339, code: 'yo-NG', desc: '约鲁巴语(尼日利亚)', lang: '' },
|
||||||
|
{ id: 337, code: 'en-GB', desc: '英语(英国)', lang: '' },
|
||||||
|
{ id: 336, code: 'en-IN', desc: '英语(印度)', lang: '' },
|
||||||
|
{ id: 335, code: 'en-JM', desc: '英语(牙买加)', lang: '' },
|
||||||
|
{ id: 334, code: 'en-NZ', desc: '英语(新西兰)', lang: '' }
|
||||||
|
])
|
||||||
|
|
||||||
|
function onSearch() {
|
||||||
|
uni.showToast({ title: '搜索中...', icon: 'none' })
|
||||||
|
}
|
||||||
|
|
||||||
|
function addRegion() {
|
||||||
|
uni.showToast({ title: '添加语言地区', icon: 'none' })
|
||||||
|
}
|
||||||
|
|
||||||
|
function editItem(item: any) {
|
||||||
|
uni.showToast({ title: '编辑: ' + item.code, icon: 'none' })
|
||||||
|
}
|
||||||
|
|
||||||
|
function deleteItem(item: any) {
|
||||||
|
uni.showModal({
|
||||||
|
title: '提示',
|
||||||
|
content: '确定要删除此地区配置吗?',
|
||||||
|
success: (res) => {
|
||||||
|
if (res.confirm) {
|
||||||
|
uni.showToast({ title: '删除成功' })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.admin-page {
|
||||||
|
padding: 24px;
|
||||||
|
background-color: #f5f7f9;
|
||||||
|
min-height: 100vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
.filter-row {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
gap: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.label {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.filter-input {
|
||||||
|
width: 200px;
|
||||||
|
height: 32px;
|
||||||
|
border: 1px solid #d9d9d9;
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 0 10px;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn {
|
||||||
|
height: 32px;
|
||||||
|
padding: 0 16px;
|
||||||
|
border-radius: 4px;
|
||||||
|
font-size: 14px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
cursor: pointer;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn.primary {
|
||||||
|
background-color: #1890ff;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-bar {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-card {
|
||||||
|
background-color: #fff;
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-container {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-header {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
background-color: #fafafa;
|
||||||
|
border-bottom: 1px solid #f0f0f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-row {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
border-bottom: 1px solid #f0f0f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.col {
|
||||||
|
padding: 16px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
font-size: 14px;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.col-id { width: 100px; }
|
||||||
|
.col-code { flex: 1; }
|
||||||
|
.col-desc { flex: 2; }
|
||||||
|
.col-lang { flex: 1; }
|
||||||
|
.col-action { width: 150px; justify-content: flex-end; }
|
||||||
|
|
||||||
|
.action-btn {
|
||||||
|
color: #1890ff;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-btn.danger {
|
||||||
|
color: #ff4d4f;
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-btn.divider {
|
||||||
|
margin: 0 8px;
|
||||||
|
color: #e8e8e8;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -1,12 +1,236 @@
|
|||||||
<template>
|
<template>
|
||||||
<AdminLayout currentPage="security-online-upgrade">
|
<view class="admin-page">
|
||||||
<view class="page">
|
<view class="admin-sections">
|
||||||
<view class="header">
|
<!-- 提示栏 -->
|
||||||
<text class="title">在线升级</text>
|
<view class="alert-info">
|
||||||
</view>
|
<text class="alert-text">温馨提示:检查更新需要授权码,请先授权后再检查更新!</text>
|
||||||
<view class="content">
|
</view>
|
||||||
<text class="tip">TODO: 在线升级</text>
|
|
||||||
</view>
|
<!-- 选项卡 -->
|
||||||
</view>
|
<view class="admin-tabs">
|
||||||
</AdminLayout>
|
<view
|
||||||
|
v-for="tab in tabs"
|
||||||
|
:key="tab.value"
|
||||||
|
:class="['tab-item', activeTab === tab.value ? 'active' : '']"
|
||||||
|
@click="activeTab = tab.value"
|
||||||
|
>
|
||||||
|
<text class="tab-label">{{ tab.label }}</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 升级内容 -->
|
||||||
|
<view v-if="activeTab === 'upgrade'" class="admin-card">
|
||||||
|
<view class="upgrade-status">
|
||||||
|
<view class="status-item">
|
||||||
|
<text class="label">当前版本:</text>
|
||||||
|
<text class="value version-tag">v3.1.2</text>
|
||||||
|
</view>
|
||||||
|
<view class="status-item">
|
||||||
|
<text class="label">授权状态:</text>
|
||||||
|
<text class="value unauthorized">未授权</text>
|
||||||
|
</view>
|
||||||
|
<view class="status-item">
|
||||||
|
<button class="btn primary" @click="checkUpdates">检查更新</button>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 升级日志内容 -->
|
||||||
|
<view v-if="activeTab === 'log'" class="admin-card">
|
||||||
|
<view class="table-container list-table">
|
||||||
|
<view class="table-header">
|
||||||
|
<view class="col col-id"><text>ID</text></view>
|
||||||
|
<view class="col col-version"><text>版本号</text></view>
|
||||||
|
<view class="col col-content"><text>更新内容</text></view>
|
||||||
|
<view class="col col-time"><text>升级时间</text></view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="table-body">
|
||||||
|
<view v-for="item in logList" :key="item.id" class="table-row">
|
||||||
|
<view class="col col-id"><text>{{ item.id }}</text></view>
|
||||||
|
<view class="col col-version"><text>{{ item.version }}</text></view>
|
||||||
|
<view class="col col-content"><text>{{ item.content }}</text></view>
|
||||||
|
<view class="col col-time"><text>{{ item.time }}</text></view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="uts">
|
||||||
|
import { ref } from 'vue'
|
||||||
|
|
||||||
|
const activeTab = ref('upgrade')
|
||||||
|
const tabs = [
|
||||||
|
{ label: '系统升级', value: 'upgrade' },
|
||||||
|
{ label: '升级日志', value: 'log' }
|
||||||
|
]
|
||||||
|
|
||||||
|
const logList = ref([
|
||||||
|
{ id: 1, version: 'v3.1.2', content: '优化核心库性能,修复已知Bug', time: '2026-02-10 10:00' },
|
||||||
|
{ id: 2, version: 'v3.1.1', content: '修复支付接口异常,增加权限校验', time: '2026-01-25 15:30' },
|
||||||
|
{ id: 3, version: 'v3.1.0', content: '大版本发布,优化UI界面,支持多级路由', time: '2026-01-10 09:20' }
|
||||||
|
])
|
||||||
|
|
||||||
|
function checkUpdates() {
|
||||||
|
uni.showLoading({ title: '检查中...' })
|
||||||
|
setTimeout(() => {
|
||||||
|
uni.hideLoading()
|
||||||
|
uni.showToast({ title: '您已是最新版本', icon: 'success' })
|
||||||
|
}, 1500)
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.admin-page {
|
||||||
|
padding: 20px;
|
||||||
|
background-color: #f5f7f9;
|
||||||
|
min-height: 100vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
.alert-info {
|
||||||
|
background-color: #fffbe6;
|
||||||
|
border: 1px solid #ffe58f;
|
||||||
|
padding: 12px 16px;
|
||||||
|
border-radius: 4px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.alert-text {
|
||||||
|
color: #856404;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-tabs {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
border-bottom: 1px solid #e8e8e8;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-item {
|
||||||
|
padding: 12px 24px;
|
||||||
|
cursor: pointer;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-item.active {
|
||||||
|
background-color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-item.active::after {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
bottom: -1px;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
height: 2px;
|
||||||
|
background-color: #1890ff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-label {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-item.active .tab-label {
|
||||||
|
color: #1890ff;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-card {
|
||||||
|
background-color: #fff;
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.upgrade-status {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.status-item {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.label {
|
||||||
|
font-size: 16px;
|
||||||
|
color: #666;
|
||||||
|
width: 100px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.value {
|
||||||
|
font-size: 16px;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.version-tag {
|
||||||
|
background-color: #e6f7ff;
|
||||||
|
color: #1890ff;
|
||||||
|
padding: 2px 8px;
|
||||||
|
border-radius: 4px;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.unauthorized {
|
||||||
|
color: #ff4d4f;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn {
|
||||||
|
height: 38px;
|
||||||
|
padding: 0 30px;
|
||||||
|
border-radius: 4px;
|
||||||
|
font-size: 14px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
cursor: pointer;
|
||||||
|
border: 1px solid #d9d9d9;
|
||||||
|
background-color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn.primary {
|
||||||
|
background-color: #1890ff;
|
||||||
|
border-color: #1890ff;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-container {
|
||||||
|
width: 100%;
|
||||||
|
border: 1px solid #f0f0f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-header {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
background-color: #fafafa;
|
||||||
|
border-bottom: 1px solid #f0f0f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-row {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
border-bottom: 1px solid #f0f0f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.col {
|
||||||
|
padding: 12px 16px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
font-size: 14px;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.col-id { width: 80px; }
|
||||||
|
.col-version { width: 150px; }
|
||||||
|
.col-content { flex: 1; }
|
||||||
|
.col-time { width: 200px; }
|
||||||
|
</style>
|
||||||
|
|
||||||
|
|||||||
@@ -1,12 +1,116 @@
|
|||||||
<template>
|
<template>
|
||||||
<AdminLayout currentPage="security-refresh-cache">
|
<view class="admin-page">
|
||||||
<view class="page">
|
<view class="admin-sections">
|
||||||
<view class="header">
|
<view class="admin-grid-2">
|
||||||
<text class="title">刷新缓存</text>
|
<!-- 清除缓存 -->
|
||||||
</view>
|
<view class="admin-card cache-card">
|
||||||
<view class="content">
|
<view class="cache-header">
|
||||||
<text class="tip">TODO: 刷新缓存</text>
|
<text class="cache-title">清除缓存</text>
|
||||||
</view>
|
<text class="cache-desc">清除系统的所有缓存</text>
|
||||||
</view>
|
</view>
|
||||||
</AdminLayout>
|
<button class="btn primary full" @click="onClearCache">立即清除</button>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 清除日志 -->
|
||||||
|
<view class="admin-card cache-card">
|
||||||
|
<view class="cache-header">
|
||||||
|
<text class="cache-title">清除日志</text>
|
||||||
|
<text class="cache-desc">清除系统的所有日志文件</text>
|
||||||
|
</view>
|
||||||
|
<button class="btn primary full" @click="onClearLog">立即清除</button>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="uts">
|
||||||
|
function onClearCache() {
|
||||||
|
uni.showModal({
|
||||||
|
title: '提示',
|
||||||
|
content: '确定要清除所有缓存吗?',
|
||||||
|
success: (res) => {
|
||||||
|
if (res.confirm) {
|
||||||
|
uni.showToast({ title: '缓存已清除', icon: 'none' })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function onClearLog() {
|
||||||
|
uni.showModal({
|
||||||
|
title: '提示',
|
||||||
|
content: '确定要清除所有日志吗?',
|
||||||
|
success: (res) => {
|
||||||
|
if (res.confirm) {
|
||||||
|
uni.showToast({ title: '日志已清除', icon: 'none' })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.admin-page {
|
||||||
|
padding: 20px;
|
||||||
|
background-color: #f5f7f9;
|
||||||
|
min-height: 100vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-grid-2 {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
gap: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-card {
|
||||||
|
background-color: #fff;
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 40px;
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cache-header {
|
||||||
|
margin-bottom: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cache-title {
|
||||||
|
font-size: 18px;
|
||||||
|
color: #333;
|
||||||
|
font-weight: bold;
|
||||||
|
display: block;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cache-desc {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn {
|
||||||
|
height: 32px;
|
||||||
|
padding: 0 20px;
|
||||||
|
border-radius: 2px;
|
||||||
|
font-size: 14px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn.primary {
|
||||||
|
background-color: #1890ff;
|
||||||
|
color: #fff;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn.full {
|
||||||
|
width: 120px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
|||||||
@@ -1,12 +1,242 @@
|
|||||||
<template>
|
<template>
|
||||||
<AdminLayout currentPage="security-system-log">
|
<view class="admin-page">
|
||||||
<view class="page">
|
<view class="admin-sections">
|
||||||
<view class="header">
|
<!-- 搜索栏 -->
|
||||||
<text class="title">系统日志</text>
|
<view class="admin-card filter-card">
|
||||||
</view>
|
<view class="filter-row">
|
||||||
<view class="content">
|
<view class="filter-item">
|
||||||
<text class="tip">TODO: 系统日志</text>
|
<text class="label">选择时间:</text>
|
||||||
</view>
|
<view class="filter-date-range">
|
||||||
</view>
|
<input class="filter-input date-input" placeholder="开始日期" />
|
||||||
</AdminLayout>
|
<text class="date-sep">-</text>
|
||||||
|
<input class="filter-input date-input" placeholder="结束日期" />
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="filter-item">
|
||||||
|
<text class="label">名称:</text>
|
||||||
|
<view class="filter-select">
|
||||||
|
<text class="select-placeholder">请选择</text>
|
||||||
|
<text class="arrow">▼</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="filter-item">
|
||||||
|
<text class="label">链接:</text>
|
||||||
|
<input class="filter-input" placeholder="请输入链接" />
|
||||||
|
</view>
|
||||||
|
<view class="filter-item">
|
||||||
|
<text class="label">IP:</text>
|
||||||
|
<input class="filter-input" placeholder="请输入IP" />
|
||||||
|
</view>
|
||||||
|
<button class="btn primary" @click="onSearch">搜索</button>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 内容区 -->
|
||||||
|
<view class="admin-card content-card">
|
||||||
|
<!-- 表格 -->
|
||||||
|
<view class="table-container list-table">
|
||||||
|
<view class="table-header">
|
||||||
|
<view class="col col-id"><text>ID</text></view>
|
||||||
|
<view class="col col-user"><text>ID/名称</text></view>
|
||||||
|
<view class="col col-action"><text>操作</text></view>
|
||||||
|
<view class="col col-link"><text>链接</text></view>
|
||||||
|
<view class="col col-ip"><text>操作IP</text></view>
|
||||||
|
<view class="col col-type"><text>类型</text></view>
|
||||||
|
<view class="col col-time"><text>操作时间</text></view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="table-body">
|
||||||
|
<view v-for="item in dataList" :key="item.id" class="table-row">
|
||||||
|
<view class="col col-id"><text>{{ item.id }}</text></view>
|
||||||
|
<view class="col col-user"><text>{{ item.user }}</text></view>
|
||||||
|
<view class="col col-action"><text>{{ item.action }}</text></view>
|
||||||
|
<view class="col col-link"><text>{{ item.link }}</text></view>
|
||||||
|
<view class="col col-ip"><text>{{ item.ip }}</text></view>
|
||||||
|
<view class="col col-type"><text>{{ item.type }}</text></view>
|
||||||
|
<view class="col col-time"><text>{{ item.time }}</text></view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 分页 -->
|
||||||
|
<view class="pagination">
|
||||||
|
<text class="page-info">共 583387 条 15条/页</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="uts">
|
||||||
|
import { ref } from 'vue'
|
||||||
|
|
||||||
|
const dataList = ref([
|
||||||
|
{ id: 585387, user: '5 / demo', action: '系统日志', link: 'system/log', ip: '223.104.72.77', type: 'system', time: '2026-02-11 18:49' },
|
||||||
|
{ id: 585386, user: '5 / demo', action: '系统日志管理员搜索条件', link: 'system/log/search_admin', ip: '223.104.72.77', type: 'system', time: '2026-02-11 18:49' },
|
||||||
|
{ id: 585385, user: '5 / demo', action: '自定义事件类型', link: 'system/event/mark', ip: '223.104.72.77', type: 'system', time: '2026-02-11 18:49' },
|
||||||
|
{ id: 585384, user: '5 / demo', action: '自定义事件列表', link: 'system/event/list', ip: '223.104.72.77', type: 'system', time: '2026-02-11 18:49' },
|
||||||
|
{ id: 585383, user: '5 / demo', action: '积分配置编辑表单', link: 'marketing/integral_config/edit_basics', ip: '223.104.72.77', type: 'system', time: '2026-02-11 18:48' },
|
||||||
|
{ id: 585382, user: '5 / demo', action: '基本配置编辑头部数据', link: 'setting/config/header_basics', ip: '223.104.72.77', type: 'system', time: '2026-02-11 18:48' },
|
||||||
|
{ id: 585381, user: '5 / demo', action: '保存权限菜单', link: 'setting/menus', ip: '223.104.72.77', type: 'system', time: '2026-02-11 18:48' },
|
||||||
|
{ id: 585380, user: '5 / demo', action: '定时任务类型', link: 'system/crontab/mark', ip: '223.104.72.77', type: 'system', time: '2026-02-11 18:47' },
|
||||||
|
{ id: 585379, user: '5 / demo', action: '定时任务列表', link: 'system/crontab/list', ip: '223.104.72.77', type: 'system', time: '2026-02-11 18:47' },
|
||||||
|
{ id: 585378, user: '5 / demo', action: '保存组合数据', link: 'setting/group', ip: '223.104.72.77', type: 'system', time: '2026-02-11 18:47' },
|
||||||
|
{ id: 585377, user: '5 / demo', action: '保存系统配置分类', link: 'setting/config_class', ip: '223.104.72.77', type: 'system', time: '2026-02-11 18:47' }
|
||||||
|
])
|
||||||
|
|
||||||
|
function onSearch() {
|
||||||
|
uni.showToast({ title: '搜索中...', icon: 'none' })
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.admin-page {
|
||||||
|
padding: 20px;
|
||||||
|
background-color: #f5f7f9;
|
||||||
|
min-height: 100vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-card {
|
||||||
|
background-color: #fff;
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 20px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.filter-row {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
align-items: center;
|
||||||
|
gap: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.filter-item {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.label {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #333;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.filter-date-range {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
border: 1px solid #d9d9d9;
|
||||||
|
border-radius: 2px;
|
||||||
|
padding: 0 10px;
|
||||||
|
height: 32px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.date-input {
|
||||||
|
width: 100px;
|
||||||
|
border: none;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.date-sep {
|
||||||
|
margin: 0 8px;
|
||||||
|
color: #bfbfbf;
|
||||||
|
}
|
||||||
|
|
||||||
|
.filter-select {
|
||||||
|
width: 120px;
|
||||||
|
height: 32px;
|
||||||
|
border: 1px solid #d9d9d9;
|
||||||
|
border-radius: 2px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: 0 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.select-placeholder {
|
||||||
|
color: #bfbfbf;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.arrow {
|
||||||
|
font-size: 10px;
|
||||||
|
color: #bfbfbf;
|
||||||
|
}
|
||||||
|
|
||||||
|
.filter-input {
|
||||||
|
width: 150px;
|
||||||
|
height: 32px;
|
||||||
|
border: 1px solid #d9d9d9;
|
||||||
|
border-radius: 2px;
|
||||||
|
padding: 0 10px;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn {
|
||||||
|
height: 32px;
|
||||||
|
padding: 0 20px;
|
||||||
|
border-radius: 2px;
|
||||||
|
font-size: 14px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
cursor: pointer;
|
||||||
|
border: 1px solid #d9d9d9;
|
||||||
|
background-color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn.primary {
|
||||||
|
background-color: #1890ff;
|
||||||
|
border-color: #1890ff;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-container {
|
||||||
|
width: 100%;
|
||||||
|
border: 1px solid #f0f0f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-header {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
background-color: #fafafa;
|
||||||
|
border-bottom: 1px solid #f0f0f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-row {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
border-bottom: 1px solid #f0f0f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.col {
|
||||||
|
padding: 12px 16px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
font-size: 14px;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.col-id { width: 80px; }
|
||||||
|
.col-user { width: 120px; }
|
||||||
|
.col-action { flex: 2; }
|
||||||
|
.col-link { flex: 2; }
|
||||||
|
.col-ip { width: 150px; }
|
||||||
|
.col-type { width: 100px; }
|
||||||
|
.col-time { width: 180px; }
|
||||||
|
|
||||||
|
.pagination {
|
||||||
|
margin-top: 20px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-info {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
|||||||
178
pages/mall/admin/maintain/sys/info.uvue
Normal file
178
pages/mall/admin/maintain/sys/info.uvue
Normal file
@@ -0,0 +1,178 @@
|
|||||||
|
<template>
|
||||||
|
<view class="admin-page">
|
||||||
|
<view class="admin-sections">
|
||||||
|
<!-- 商业授权 -->
|
||||||
|
<view class="admin-card info-section">
|
||||||
|
<view class="section-header">
|
||||||
|
<text class="section-title">商业授权</text>
|
||||||
|
</view>
|
||||||
|
<view class="table-container header-table">
|
||||||
|
<view class="table-header">
|
||||||
|
<view class="col col-title"><text>产品证书编号</text></view>
|
||||||
|
<view class="col col-action"><text>操作</text></view>
|
||||||
|
</view>
|
||||||
|
<view class="table-body">
|
||||||
|
<view class="table-row">
|
||||||
|
<view class="col col-title"><text>ZC2884891</text></view>
|
||||||
|
<view class="col col-action">
|
||||||
|
<text class="action-btn" @click="gotoOfficial">进入官网</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 自定义版权信息 -->
|
||||||
|
<view class="admin-card info-section mt-24">
|
||||||
|
<view class="section-header">
|
||||||
|
<text class="section-title">自定义版权信息</text>
|
||||||
|
</view>
|
||||||
|
<view class="table-container header-table">
|
||||||
|
<view class="table-header">
|
||||||
|
<view class="col col-text"><text>文字版权信息</text></view>
|
||||||
|
<view class="col col-image"><text>底部版权图片</text></view>
|
||||||
|
<view class="col col-action"><text>操作</text></view>
|
||||||
|
</view>
|
||||||
|
<view class="table-body">
|
||||||
|
<view class="table-row">
|
||||||
|
<view class="col col-text"><text></text></view>
|
||||||
|
<view class="col col-image"><text></text></view>
|
||||||
|
<view class="col col-action">
|
||||||
|
<text class="action-btn" @click="editCopyright">编辑</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 服务器信息 -->
|
||||||
|
<view class="admin-card info-section mt-24">
|
||||||
|
<view class="section-header">
|
||||||
|
<text class="section-title">服务器信息</text>
|
||||||
|
</view>
|
||||||
|
<view class="table-container header-table">
|
||||||
|
<view class="table-header">
|
||||||
|
<view class="col col-env"><text>环境</text></view>
|
||||||
|
<view class="col col-req"><text>要求</text></view>
|
||||||
|
<view class="col col-status"><text>状态</text></view>
|
||||||
|
</view>
|
||||||
|
<view class="table-body">
|
||||||
|
<view class="table-row">
|
||||||
|
<view class="col col-env"><text>服务器系统</text></view>
|
||||||
|
<view class="col col-req"><text>类UNIX</text></view>
|
||||||
|
<view class="col col-status"><text>Linux</text></view>
|
||||||
|
</view>
|
||||||
|
<view class="table-row">
|
||||||
|
<view class="col col-env"><text>WEB环境</text></view>
|
||||||
|
<view class="col col-req"><text>Apache/Nginx/IIS</text></view>
|
||||||
|
<view class="col col-status"><text>nginx/1.24.0</text></view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 系统环境要求 -->
|
||||||
|
<view class="admin-card info-section mt-24">
|
||||||
|
<view class="section-header">
|
||||||
|
<text class="section-title">系统环境要求</text>
|
||||||
|
</view>
|
||||||
|
<view class="table-container header-table">
|
||||||
|
<view class="table-header">
|
||||||
|
<view class="col col-env"><text>环境</text></view>
|
||||||
|
<view class="col col-req"><text>要求</text></view>
|
||||||
|
<view class="col col-status"><text>状态</text></view>
|
||||||
|
</view>
|
||||||
|
<view class="table-body">
|
||||||
|
<view class="table-row">
|
||||||
|
<view class="col col-env"><text>PHP版本</text></view>
|
||||||
|
<view class="col col-req"><text>7.1-7.4</text></view>
|
||||||
|
<view class="col col-status"><text>7.4.33</text></view>
|
||||||
|
</view>
|
||||||
|
<view class="table-row">
|
||||||
|
<view class="col col-env"><text>MySQL版本</text></view>
|
||||||
|
<view class="col col-req"><text>5.6-8.0</text></view>
|
||||||
|
<view class="col col-status"><text>8.0.35</text></view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="uts">
|
||||||
|
function gotoOfficial() {
|
||||||
|
uni.showToast({ title: '正在打开官网...', icon: 'none' })
|
||||||
|
}
|
||||||
|
|
||||||
|
function editCopyright() {
|
||||||
|
uni.showToast({ title: '编辑版权信息', icon: 'none' })
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.admin-page {
|
||||||
|
padding: 24px;
|
||||||
|
background-color: #f5f7f9;
|
||||||
|
min-height: 100vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-card {
|
||||||
|
background-color: #fff;
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.section-header {
|
||||||
|
margin-bottom: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.section-title {
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-container {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-header {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
background-color: #e6f7ff;
|
||||||
|
border-bottom: 1px solid #f0f0f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-row {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
border-bottom: 1px solid #f0f0f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.col {
|
||||||
|
padding: 16px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
font-size: 14px;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 各表格占位列宽 */
|
||||||
|
.col-title { flex: 1; }
|
||||||
|
.col-text { flex: 1; }
|
||||||
|
.col-image { flex: 1; }
|
||||||
|
.col-env { flex: 1; }
|
||||||
|
.col-req { flex: 1; }
|
||||||
|
.col-status { flex: 1; }
|
||||||
|
.col-action { width: 150px; justify-content: flex-end; }
|
||||||
|
|
||||||
|
.action-btn {
|
||||||
|
color: #1890ff;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mt-24 {
|
||||||
|
margin-top: 24px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -1,23 +1,225 @@
|
|||||||
<template>
|
<template>
|
||||||
<view class="admin-page-container">
|
<view class="admin-page agreement-settings">
|
||||||
<view class="page-card">
|
<view class="admin-sections">
|
||||||
<view class="page-header">
|
<view class="admin-card">
|
||||||
<text class="page-title">协议管理</text>
|
<!-- 协议类型标签页 -->
|
||||||
</view>
|
<scroll-view class="tabs-scroll" scroll-x="true" show-scrollbar="false">
|
||||||
<view class="page-content">
|
<view class="tabs-bar">
|
||||||
<text class="placeholder-text">协议管理 页面开发中...</text>
|
<view
|
||||||
</view>
|
v-for="(tab, index) in agreementTabs"
|
||||||
</view>
|
:key="index"
|
||||||
</view>
|
class="tab-item"
|
||||||
</template>
|
:class="{ active: currentTab === index }"
|
||||||
|
@click="currentTab = index"
|
||||||
|
>
|
||||||
|
<text class="tab-text">{{ tab }}</text>
|
||||||
|
<view class="tab-line" v-if="currentTab === index"></view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</scroll-view>
|
||||||
|
|
||||||
|
<view class="editor-layout">
|
||||||
|
<!-- 左侧编辑器区域 -->
|
||||||
|
<view class="editor-main">
|
||||||
|
<view class="editor-toolbar">
|
||||||
|
<!-- 模拟富文本工具栏 -->
|
||||||
|
<view class="toolbar-icon">H</view>
|
||||||
|
<view class="toolbar-icon">B</view>
|
||||||
|
<view class="toolbar-icon">I</view>
|
||||||
|
<view class="toolbar-icon">U</view>
|
||||||
|
<view class="toolbar-icon">S</view>
|
||||||
|
<view class="toolbar-icon">🔗</view>
|
||||||
|
<view class="toolbar-icon">🖼️</view>
|
||||||
|
</view>
|
||||||
|
<textarea
|
||||||
|
class="rich-textarea"
|
||||||
|
v-model="agreementContent"
|
||||||
|
placeholder="请输入协议内容..."
|
||||||
|
></textarea>
|
||||||
|
<view class="editor-footer">
|
||||||
|
<button class="btn btn-primary" @click="handleSave">保存</button>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 右侧手机预览 -->
|
||||||
|
<view class="preview-area">
|
||||||
|
<view class="phone-frame">
|
||||||
|
<view class="phone-header">
|
||||||
|
<text class="phone-title">{{ agreementTabs[currentTab] }}</text>
|
||||||
|
</view>
|
||||||
|
<scroll-view class="phone-content" scroll-y="true">
|
||||||
|
<rich-text :nodes="agreementContent"></rich-text>
|
||||||
|
</scroll-view>
|
||||||
|
</view>
|
||||||
|
<text class="preview-tip">协议预览</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view></template>
|
||||||
<script setup lang="uts">
|
<script setup lang="uts">
|
||||||
|
import { ref, watch } from 'vue'
|
||||||
|
|
||||||
|
const currentTab = ref(0)
|
||||||
|
const agreementTabs = [
|
||||||
|
'付费会员协议', '代理商协议', '隐私协议', '用户协议', '注销协议', '积分协议', '分销协议'
|
||||||
|
]
|
||||||
|
|
||||||
|
const agreementContent = ref(`
|
||||||
|
<h2 style="text-align: center;">第1条 相关定义</h2>
|
||||||
|
<p>1.1 SVIP会员:SVIP会员是为商城客户打造的高级会员服务,通过提供高品质的客户服务,让网购变的更加方便,省钱和放心。</p>
|
||||||
|
<p>1.5 实名信息:用户开通SVIP11会员需保证商城用户信息真实,同一自然人如有多个商城账号,可同时开通对应的多个会员。</p>
|
||||||
|
<h2 style="text-align: center;">第2条 本站服务条款的确认和接纳</h2>
|
||||||
|
<p>2.1 本站所提供的SVIP会员试用期及正式期活动的所有权和运作权归本公司所有。</p>
|
||||||
|
<p>2.2 用户支付会员成功,即视为用户确认自己同意接受SVIP会员相关服务的条款,且同意按本协议内容履行,如产生用户相关责任的,同意承担相应法律责任。</p>
|
||||||
|
`)
|
||||||
|
|
||||||
|
const handleSave = () => {
|
||||||
|
uni.showToast({ title: '保存成功', icon: 'success' })
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.admin-page-container { padding: 20px; background-color: #f5f7f9; min-height: 100vh; }
|
.agreement-settings {
|
||||||
.page-card { background-color: #fff; border-radius: 4px; padding: 20px; box-shadow: 0 1px 4px rgba(0,21,41,0.08); }
|
padding: 20px;
|
||||||
.page-header { margin-bottom: 20px; border-bottom: 1px solid #f0f0f0; padding-bottom: 15px; }
|
background-color: #f5f7f9;
|
||||||
.page-title { font-size: 16px; font-weight: bold; color: #303133; }
|
}
|
||||||
.placeholder-text { font-size: 14px; color: #909399; }
|
|
||||||
|
.admin-card {
|
||||||
|
background-color: #fff;
|
||||||
|
padding: 24px;
|
||||||
|
border-radius: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tabs-scroll {
|
||||||
|
border-bottom: 1px solid #f0f0f0;
|
||||||
|
margin-bottom: 25px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tabs-bar {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-item {
|
||||||
|
padding: 12px 25px;
|
||||||
|
position: relative;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-item.active {
|
||||||
|
color: #1890ff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-text {
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-line {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
height: 2px;
|
||||||
|
background-color: #1890ff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.editor-layout {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
gap: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.editor-main {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
border: 1px solid #dcdfe6;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.editor-toolbar {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
padding: 10px;
|
||||||
|
background-color: #f8f8f9;
|
||||||
|
border-bottom: 1px solid #dcdfe6;
|
||||||
|
gap: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toolbar-icon {
|
||||||
|
font-size: 16px;
|
||||||
|
color: #666;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rich-textarea {
|
||||||
|
width: 100%;
|
||||||
|
height: 500px;
|
||||||
|
padding: 20px;
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 1.6;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
.editor-footer {
|
||||||
|
padding: 20px;
|
||||||
|
border-top: 1px solid #f0f0f0;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.preview-area {
|
||||||
|
width: 320px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.phone-frame {
|
||||||
|
width: 300px;
|
||||||
|
height: 600px;
|
||||||
|
border: 12px solid #333;
|
||||||
|
border-radius: 36px;
|
||||||
|
overflow: hidden;
|
||||||
|
background-color: #fff;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.phone-header {
|
||||||
|
height: 44px;
|
||||||
|
background-color: #f8f8f8;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
border-bottom: 1px solid #eeeeee;
|
||||||
|
}
|
||||||
|
|
||||||
|
.phone-title {
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.phone-content {
|
||||||
|
flex: 1;
|
||||||
|
padding: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.preview-tip {
|
||||||
|
margin-top: 15px;
|
||||||
|
font-size: 14px;
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-primary {
|
||||||
|
background-color: #1890ff;
|
||||||
|
color: #fff;
|
||||||
|
border: none;
|
||||||
|
padding: 0 30px;
|
||||||
|
height: 40px;
|
||||||
|
line-height: 40px;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
|||||||
@@ -1,23 +1,177 @@
|
|||||||
<template>
|
<template>
|
||||||
<view class="admin-page-container">
|
<view class="admin-page-container">
|
||||||
<view class="page-card">
|
<view class="page-card">
|
||||||
<view class="page-header">
|
<!-- 搜索栏 -->
|
||||||
<text class="page-title">管理员列表</text>
|
<view class="search-wrap">
|
||||||
|
<view class="search-item">
|
||||||
|
<text class="label">状态:</text>
|
||||||
|
<picker mode="selector" :range="statusRange" @change="onStatusChange">
|
||||||
|
<view class="picker-input">{{ statusText }}</view>
|
||||||
|
</picker>
|
||||||
|
</view>
|
||||||
|
<view class="search-item">
|
||||||
|
<text class="label">搜索:</text>
|
||||||
|
<input class="input" placeholder="请输入姓名或者账号" v-model="searchKey" />
|
||||||
|
</view>
|
||||||
|
<button class="btn btn-primary" @click="onSearch">查询</button>
|
||||||
</view>
|
</view>
|
||||||
<view class="page-content">
|
|
||||||
<text class="placeholder-text">管理员列表 页面开发中...</text>
|
<view class="action-wrap">
|
||||||
|
<button class="btn btn-primary" @click="onAdd">添加管理员</button>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 表格区域 -->
|
||||||
|
<view class="table-wrap">
|
||||||
|
<view class="table-header">
|
||||||
|
<view class="th" style="flex: 2;">姓名</view>
|
||||||
|
<view class="th" style="flex: 2;">账号</view>
|
||||||
|
<view class="th" style="flex: 2;">身份</view>
|
||||||
|
<view class="th" style="flex: 3;">最后一次登录时间</view>
|
||||||
|
<view class="th" style="flex: 3;">最后一次登录ip</view>
|
||||||
|
<view class="th" style="flex: 1;">开启</view>
|
||||||
|
<view class="th" style="flex: 2;">操作</view>
|
||||||
|
</view>
|
||||||
|
<view class="table-body">
|
||||||
|
<view class="no-data">
|
||||||
|
<text class="no-data-text">暂无数据</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="uts">
|
<script setup lang="uts">
|
||||||
|
import { ref } from 'vue'
|
||||||
|
|
||||||
|
const searchKey = ref('')
|
||||||
|
const statusRange = ['所有', '启用', '禁用']
|
||||||
|
const statusIndex = ref(0)
|
||||||
|
const statusText = ref('请选择')
|
||||||
|
|
||||||
|
function onStatusChange(e: any) {
|
||||||
|
statusIndex.value = parseInt(e.detail.value.toString())
|
||||||
|
statusText.value = statusRange[statusIndex.value]
|
||||||
|
}
|
||||||
|
|
||||||
|
function onSearch() {
|
||||||
|
console.log('Search:', searchKey.value, statusText.value)
|
||||||
|
}
|
||||||
|
|
||||||
|
function onAdd() {
|
||||||
|
console.log('Add admin')
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.admin-page-container { padding: 20px; background-color: #f5f7f9; min-height: 100vh; }
|
.admin-page-container {
|
||||||
.page-card { background-color: #fff; border-radius: 4px; padding: 20px; box-shadow: 0 1px 4px rgba(0,21,41,0.08); }
|
padding: 15px;
|
||||||
.page-header { margin-bottom: 20px; border-bottom: 1px solid #f0f0f0; padding-bottom: 15px; }
|
background-color: #f5f7f9;
|
||||||
.page-title { font-size: 16px; font-weight: bold; color: #303133; }
|
min-height: 100vh;
|
||||||
.placeholder-text { font-size: 14px; color: #909399; }
|
}
|
||||||
|
|
||||||
|
.page-card {
|
||||||
|
background-color: #fff;
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-wrap {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
padding-bottom: 20px;
|
||||||
|
border-bottom: 1px solid #f0f0f0;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-item {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
margin-right: 20px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.label {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #606266;
|
||||||
|
margin-right: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.picker-input {
|
||||||
|
width: 150px;
|
||||||
|
height: 32px;
|
||||||
|
line-height: 32px;
|
||||||
|
padding: 0 10px;
|
||||||
|
border: 1px solid #dcdfe6;
|
||||||
|
border-radius: 4px;
|
||||||
|
font-size: 14px;
|
||||||
|
color: #606266;
|
||||||
|
background-color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input {
|
||||||
|
width: 220px;
|
||||||
|
height: 32px;
|
||||||
|
padding: 0 10px;
|
||||||
|
border: 1px solid #dcdfe6;
|
||||||
|
border-radius: 4px;
|
||||||
|
font-size: 14px;
|
||||||
|
color: #606266;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn {
|
||||||
|
height: 32px;
|
||||||
|
line-height: 30px;
|
||||||
|
padding: 0 15px;
|
||||||
|
font-size: 14px;
|
||||||
|
border-radius: 4px;
|
||||||
|
border: none;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-primary {
|
||||||
|
background-color: #1890ff;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-wrap {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-wrap {
|
||||||
|
width: 100%;
|
||||||
|
border: 1px solid #f0f0f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-header {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
background-color: #f8f8f9;
|
||||||
|
}
|
||||||
|
|
||||||
|
.th {
|
||||||
|
padding: 12px 10px;
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #515a6e;
|
||||||
|
border-bottom: 1px solid #f0f0f0;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-body {
|
||||||
|
min-height: 100px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.no-data {
|
||||||
|
padding: 40px 0;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.no-data-text {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #c5c8ce;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -1,23 +1,188 @@
|
|||||||
<template>
|
<template>
|
||||||
<view class="admin-page-container">
|
<view class="admin-page-container">
|
||||||
<view class="page-card">
|
<view class="page-card">
|
||||||
<view class="page-header">
|
<!-- 搜索栏 -->
|
||||||
<text class="page-title">权限设置</text>
|
<view class="search-wrap">
|
||||||
|
<view class="search-item">
|
||||||
|
<text class="label">按钮名称:</text>
|
||||||
|
<input class="input" placeholder="请输入按钮名称" v-model="searchKey" />
|
||||||
|
</view>
|
||||||
|
<button class="btn btn-primary" @click="onSearch">查询</button>
|
||||||
</view>
|
</view>
|
||||||
<view class="page-content">
|
|
||||||
<text class="placeholder-text">权限设置 页面开发中...</text>
|
<!-- 表格区域 -->
|
||||||
|
<view class="table-wrap">
|
||||||
|
<view class="table-header">
|
||||||
|
<view class="th" style="flex: 4; text-align: left; padding-left: 20px;">按钮名称</view>
|
||||||
|
<view class="th" style="flex: 3;">类型</view>
|
||||||
|
<view class="th" style="flex: 2;">排序</view>
|
||||||
|
<view class="th" style="flex: 2;">是否显示</view>
|
||||||
|
<view class="th" style="flex: 2;">操作</view>
|
||||||
|
</view>
|
||||||
|
<view class="table-body">
|
||||||
|
<view v-for="item in permissionList" :key="item.id" class="tr">
|
||||||
|
<view class="td" style="flex: 4; text-align: left; padding-left: 20px;">
|
||||||
|
<text v-if="item.hasChildren" class="expand-icon">▶</text>
|
||||||
|
<text class="menu-name">{{ item.name }}</text>
|
||||||
|
</view>
|
||||||
|
<view class="td" style="flex: 3;">{{ item.type }}</view>
|
||||||
|
<view class="td" style="flex: 2;">{{ item.sort }}</view>
|
||||||
|
<view class="td" style="flex: 2;">
|
||||||
|
<switch :checked="item.isshow" color="#1890ff" @change="onToggleShow(item)" />
|
||||||
|
</view>
|
||||||
|
<view class="td" style="flex: 2;">
|
||||||
|
<text class="action-btn" @click="onEdit(item)">编辑</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="uts">
|
<script setup lang="uts">
|
||||||
|
import { ref, reactive } from 'vue'
|
||||||
|
|
||||||
|
const searchKey = ref('')
|
||||||
|
|
||||||
|
type PermissionItem = {
|
||||||
|
id: number
|
||||||
|
name: string
|
||||||
|
type: string
|
||||||
|
sort: number
|
||||||
|
isshow: boolean
|
||||||
|
hasChildren: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
const permissionList = reactive<PermissionItem[]>([
|
||||||
|
{ id: 1, name: '主页', type: '菜单:/admin/index', sort: 127, isshow: true, hasChildren: false },
|
||||||
|
{ id: 2, name: '用户', type: '菜单:/admin/user', sort: 125, isshow: true, hasChildren: true },
|
||||||
|
{ id: 3, name: '订单', type: '菜单:/admin/order', sort: 120, isshow: true, hasChildren: true },
|
||||||
|
{ id: 4, name: '商品', type: '菜单:/admin/product', sort: 115, isshow: true, hasChildren: true },
|
||||||
|
{ id: 5, name: '营销', type: '菜单:/admin/marketing', sort: 110, isshow: true, hasChildren: true }
|
||||||
|
])
|
||||||
|
|
||||||
|
function onSearch() {
|
||||||
|
console.log('Search:', searchKey.value)
|
||||||
|
}
|
||||||
|
|
||||||
|
function onToggleShow(item: PermissionItem) {
|
||||||
|
item.isshow = !item.isshow
|
||||||
|
}
|
||||||
|
|
||||||
|
function onEdit(item: PermissionItem) {
|
||||||
|
console.log('Edit:', item.name)
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.admin-page-container { padding: 20px; background-color: #f5f7f9; min-height: 100vh; }
|
.admin-page-container {
|
||||||
.page-card { background-color: #fff; border-radius: 4px; padding: 20px; box-shadow: 0 1px 4px rgba(0,21,41,0.08); }
|
padding: 15px;
|
||||||
.page-header { margin-bottom: 20px; border-bottom: 1px solid #f0f0f0; padding-bottom: 15px; }
|
background-color: #f5f7f9;
|
||||||
.page-title { font-size: 16px; font-weight: bold; color: #303133; }
|
min-height: 100vh;
|
||||||
.placeholder-text { font-size: 14px; color: #909399; }
|
}
|
||||||
|
|
||||||
|
.page-card {
|
||||||
|
background-color: #fff;
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-wrap {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
padding-bottom: 20px;
|
||||||
|
border-bottom: 1px solid #f0f0f0;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-item {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
margin-right: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.label {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #606266;
|
||||||
|
margin-right: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input {
|
||||||
|
width: 200px;
|
||||||
|
height: 32px;
|
||||||
|
padding: 0 10px;
|
||||||
|
border: 1px solid #dcdfe6;
|
||||||
|
border-radius: 4px;
|
||||||
|
font-size: 14px;
|
||||||
|
color: #606266;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn {
|
||||||
|
height: 32px;
|
||||||
|
line-height: 30px;
|
||||||
|
padding: 0 15px;
|
||||||
|
font-size: 14px;
|
||||||
|
border-radius: 4px;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-primary {
|
||||||
|
background-color: #1890ff;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-wrap {
|
||||||
|
width: 100%;
|
||||||
|
border: 1px solid #f0f0f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-header {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
background-color: #f8f8f9;
|
||||||
|
}
|
||||||
|
|
||||||
|
.th {
|
||||||
|
padding: 12px 10px;
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #515a6e;
|
||||||
|
border-bottom: 1px solid #f0f0f0;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tr {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
border-bottom: 1px solid #f0f0f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.td {
|
||||||
|
padding: 12px 10px;
|
||||||
|
font-size: 14px;
|
||||||
|
color: #515a6e;
|
||||||
|
text-align: center;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.expand-icon {
|
||||||
|
font-size: 12px;
|
||||||
|
color: #999;
|
||||||
|
margin-right: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.menu-name {
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-btn {
|
||||||
|
color: #1890ff;
|
||||||
|
font-size: 13px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -1,23 +1,174 @@
|
|||||||
<template>
|
<template>
|
||||||
<view class="admin-page-container">
|
<view class="admin-page-container">
|
||||||
<view class="page-card">
|
<view class="page-card">
|
||||||
<view class="page-header">
|
<!-- 搜索栏 -->
|
||||||
<text class="page-title">角色管理</text>
|
<view class="search-wrap">
|
||||||
|
<view class="search-item">
|
||||||
|
<text class="label">状态:</text>
|
||||||
|
<picker mode="selector" :range="statusRange" @change="onStatusChange">
|
||||||
|
<view class="picker-input">{{ statusText }}</view>
|
||||||
|
</picker>
|
||||||
|
</view>
|
||||||
|
<view class="search-item">
|
||||||
|
<text class="label">身份昵称:</text>
|
||||||
|
<input class="input" placeholder="请输入身份昵称" v-model="searchKey" />
|
||||||
|
</view>
|
||||||
|
<button class="btn btn-primary" @click="onSearch">查询</button>
|
||||||
</view>
|
</view>
|
||||||
<view class="page-content">
|
|
||||||
<text class="placeholder-text">角色管理 页面开发中...</text>
|
<view class="action-wrap">
|
||||||
|
<button class="btn btn-primary" @click="onAdd">添加身份</button>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 表格区域 -->
|
||||||
|
<view class="table-wrap">
|
||||||
|
<view class="table-header">
|
||||||
|
<view class="th" style="flex: 1;">ID</view>
|
||||||
|
<view class="th" style="flex: 3;">身份昵称</view>
|
||||||
|
<view class="th" style="flex: 2;">状态</view>
|
||||||
|
<view class="th" style="flex: 2;">操作</view>
|
||||||
|
</view>
|
||||||
|
<view class="table-body">
|
||||||
|
<view class="no-data">
|
||||||
|
<text class="no-data-text">暂无数据</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="uts">
|
<script setup lang="uts">
|
||||||
|
import { ref } from 'vue'
|
||||||
|
|
||||||
|
const searchKey = ref('')
|
||||||
|
const statusRange = ['所有', '启用', '禁用']
|
||||||
|
const statusIndex = ref(0)
|
||||||
|
const statusText = ref('请选择')
|
||||||
|
|
||||||
|
function onStatusChange(e: any) {
|
||||||
|
statusIndex.value = parseInt(e.detail.value.toString())
|
||||||
|
statusText.value = statusRange[statusIndex.value]
|
||||||
|
}
|
||||||
|
|
||||||
|
function onSearch() {
|
||||||
|
console.log('Search:', searchKey.value, statusText.value)
|
||||||
|
}
|
||||||
|
|
||||||
|
function onAdd() {
|
||||||
|
console.log('Add role')
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.admin-page-container { padding: 20px; background-color: #f5f7f9; min-height: 100vh; }
|
.admin-page-container {
|
||||||
.page-card { background-color: #fff; border-radius: 4px; padding: 20px; box-shadow: 0 1px 4px rgba(0,21,41,0.08); }
|
padding: 15px;
|
||||||
.page-header { margin-bottom: 20px; border-bottom: 1px solid #f0f0f0; padding-bottom: 15px; }
|
background-color: #f5f7f9;
|
||||||
.page-title { font-size: 16px; font-weight: bold; color: #303133; }
|
min-height: 100vh;
|
||||||
.placeholder-text { font-size: 14px; color: #909399; }
|
}
|
||||||
|
|
||||||
|
.page-card {
|
||||||
|
background-color: #fff;
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-wrap {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
padding-bottom: 20px;
|
||||||
|
border-bottom: 1px solid #f0f0f0;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-item {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
margin-right: 20px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.label {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #606266;
|
||||||
|
margin-right: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.picker-input {
|
||||||
|
width: 150px;
|
||||||
|
height: 32px;
|
||||||
|
line-height: 32px;
|
||||||
|
padding: 0 10px;
|
||||||
|
border: 1px solid #dcdfe6;
|
||||||
|
border-radius: 4px;
|
||||||
|
font-size: 14px;
|
||||||
|
color: #606266;
|
||||||
|
background-color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input {
|
||||||
|
width: 180px;
|
||||||
|
height: 32px;
|
||||||
|
padding: 0 10px;
|
||||||
|
border: 1px solid #dcdfe6;
|
||||||
|
border-radius: 4px;
|
||||||
|
font-size: 14px;
|
||||||
|
color: #606266;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn {
|
||||||
|
height: 32px;
|
||||||
|
line-height: 30px;
|
||||||
|
padding: 0 15px;
|
||||||
|
font-size: 14px;
|
||||||
|
border-radius: 4px;
|
||||||
|
border: none;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-primary {
|
||||||
|
background-color: #1890ff;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-wrap {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-wrap {
|
||||||
|
width: 100%;
|
||||||
|
border: 1px solid #f0f0f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-header {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
background-color: #f8f8f9;
|
||||||
|
}
|
||||||
|
|
||||||
|
.th {
|
||||||
|
padding: 12px 10px;
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #515a6e;
|
||||||
|
border-bottom: 1px solid #f0f0f0;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-body {
|
||||||
|
min-height: 100px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.no-data {
|
||||||
|
padding: 40px 0;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.no-data-text {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #c5c8ce;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -1,23 +1,162 @@
|
|||||||
<template>
|
<template>
|
||||||
<view class="admin-page-container">
|
<view class="admin-page-container">
|
||||||
<view class="page-card">
|
<view class="page-card">
|
||||||
<view class="page-header">
|
<view class="action-wrap">
|
||||||
<text class="page-title">配送员管理</text>
|
<button class="btn btn-primary" @click="onAdd">添加配送员</button>
|
||||||
</view>
|
</view>
|
||||||
<view class="page-content">
|
|
||||||
<text class="placeholder-text">配送员管理 页面开发中...</text>
|
<!-- 表格区域 -->
|
||||||
|
<view class="table-wrap">
|
||||||
|
<view class="table-header">
|
||||||
|
<view class="th" style="flex: 1;">ID</view>
|
||||||
|
<view class="th" style="flex: 1.5;">头像</view>
|
||||||
|
<view class="th" style="flex: 2;">名称</view>
|
||||||
|
<view class="th" style="flex: 2.5;">手机号码</view>
|
||||||
|
<view class="th" style="flex: 1.5;">是否显示</view>
|
||||||
|
<view class="th" style="flex: 3;">添加时间</view>
|
||||||
|
<view class="th" style="flex: 2;">操作</view>
|
||||||
|
</view>
|
||||||
|
<view class="table-body">
|
||||||
|
<view v-for="item in courierList" :key="item.id" class="tr">
|
||||||
|
<view class="td" style="flex: 1;">{{ item.id }}</view>
|
||||||
|
<view class="td" style="flex: 1.5;">
|
||||||
|
<image class="avatar" :src="item.avatar" mode="aspectFill" />
|
||||||
|
</view>
|
||||||
|
<view class="td" style="flex: 2;">{{ item.name }}</view>
|
||||||
|
<view class="td" style="flex: 2.5;">{{ item.phone }}</view>
|
||||||
|
<view class="td" style="flex: 1.5;">
|
||||||
|
<switch :checked="item.isshow" color="#1890ff" @change="onToggleShow(item)" />
|
||||||
|
</view>
|
||||||
|
<view class="td" style="flex: 3;">{{ item.addTime }}</view>
|
||||||
|
<view class="td" style="flex: 2;">
|
||||||
|
<text class="action-btn" @click="onEdit(item)">编辑</text>
|
||||||
|
<text class="action-btn-del" @click="onDel(item)">删除</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="uts">
|
<script setup lang="uts">
|
||||||
|
import { ref, reactive } from 'vue'
|
||||||
|
|
||||||
|
type CourierItem = {
|
||||||
|
id: number
|
||||||
|
avatar: string
|
||||||
|
name: string
|
||||||
|
phone: string
|
||||||
|
isshow: boolean
|
||||||
|
addTime: string
|
||||||
|
}
|
||||||
|
|
||||||
|
const courierList = reactive<CourierItem[]>([
|
||||||
|
{ id: 106, avatar: '/static/logo.png', name: 'cheshi', phone: '18943652356', isshow: true, addTime: '2025-06-29 21:45:19' },
|
||||||
|
{ id: 105, avatar: '/static/logo.png', name: 'dl', phone: '15648569914', isshow: true, addTime: '2025-06-28 18:40:26' },
|
||||||
|
{ id: 102, avatar: '/static/logo.png', name: '小牛马', phone: '13548652258', isshow: true, addTime: '2025-06-26 15:14:40' }
|
||||||
|
])
|
||||||
|
|
||||||
|
function onAdd() {
|
||||||
|
console.log('Add courier')
|
||||||
|
}
|
||||||
|
|
||||||
|
function onToggleShow(item: CourierItem) {
|
||||||
|
item.isshow = !item.isshow
|
||||||
|
}
|
||||||
|
|
||||||
|
function onEdit(item: CourierItem) {
|
||||||
|
console.log('Edit:', item.name)
|
||||||
|
}
|
||||||
|
|
||||||
|
function onDel(item: CourierItem) {
|
||||||
|
console.log('Delete:', item.id)
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.admin-page-container { padding: 20px; background-color: #f5f7f9; min-height: 100vh; }
|
.admin-page-container {
|
||||||
.page-card { background-color: #fff; border-radius: 4px; padding: 20px; box-shadow: 0 1px 4px rgba(0,21,41,0.08); }
|
padding: 15px;
|
||||||
.page-header { margin-bottom: 20px; border-bottom: 1px solid #f0f0f0; padding-bottom: 15px; }
|
background-color: #f5f7f9;
|
||||||
.page-title { font-size: 16px; font-weight: bold; color: #303133; }
|
min-height: 100vh;
|
||||||
.placeholder-text { font-size: 14px; color: #909399; }
|
}
|
||||||
|
|
||||||
|
.page-card {
|
||||||
|
background-color: #fff;
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-wrap {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn {
|
||||||
|
height: 32px;
|
||||||
|
line-height: 30px;
|
||||||
|
padding: 0 15px;
|
||||||
|
font-size: 14px;
|
||||||
|
border-radius: 4px;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-primary {
|
||||||
|
background-color: #1890ff;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-wrap {
|
||||||
|
width: 100%;
|
||||||
|
border: 1px solid #f0f0f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-header {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
background-color: #f8f8f9;
|
||||||
|
}
|
||||||
|
|
||||||
|
.th {
|
||||||
|
padding: 12px 10px;
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #515a6e;
|
||||||
|
border-bottom: 1px solid #f0f0f0;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tr {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
border-bottom: 1px solid #f0f0f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.td {
|
||||||
|
padding: 12px 10px;
|
||||||
|
font-size: 14px;
|
||||||
|
color: #515a6e;
|
||||||
|
text-align: center;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.avatar {
|
||||||
|
width: 40px;
|
||||||
|
height: 40px;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-btn {
|
||||||
|
color: #1890ff;
|
||||||
|
font-size: 13px;
|
||||||
|
margin-right: 10px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-btn-del {
|
||||||
|
color: #ed4014;
|
||||||
|
font-size: 13px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -1,23 +1,230 @@
|
|||||||
<template>
|
<template>
|
||||||
<view class="admin-page-container">
|
<view class="admin-page-container">
|
||||||
<view class="page-card">
|
<view class="page-card">
|
||||||
<view class="page-header">
|
<!-- 搜索栏 -->
|
||||||
<text class="page-title">提货点设置</text>
|
<view class="search-wrap">
|
||||||
|
<view class="search-item">
|
||||||
|
<text class="label">提货点搜索:</text>
|
||||||
|
<input class="input" placeholder="请输入提货点名称,电话" v-model="searchKey" />
|
||||||
|
</view>
|
||||||
|
<button class="btn btn-primary" @click="onSearch">查询</button>
|
||||||
</view>
|
</view>
|
||||||
<view class="page-content">
|
|
||||||
<text class="placeholder-text">提货点设置 页面开发中...</text>
|
<!-- 状态 Tabs -->
|
||||||
|
<view class="tabs-wrap">
|
||||||
|
<view class="tab-item active"><text class="tab-text">显示中的提货点(2)</text></view>
|
||||||
|
<view class="tab-item"><text class="tab-text">隐藏中的提货点(0)</text></view>
|
||||||
|
<view class="tab-item"><text class="tab-text">回收站中的提货点(9)</text></view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="action-wrap">
|
||||||
|
<button class="btn btn-primary" @click="onAdd">添加提货点</button>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 表格区域 -->
|
||||||
|
<view class="table-wrap">
|
||||||
|
<view class="table-header">
|
||||||
|
<view class="th" style="flex: 1;">ID</view>
|
||||||
|
<view class="th" style="flex: 2;">提货点图片</view>
|
||||||
|
<view class="th" style="flex: 2;">提货点名称</view>
|
||||||
|
<view class="th" style="flex: 2;">提货点电话</view>
|
||||||
|
<view class="th" style="flex: 3;">地址</view>
|
||||||
|
<view class="th" style="flex: 3;">营业时间</view>
|
||||||
|
<view class="th" style="flex: 1.5;">是否显示</view>
|
||||||
|
<view class="th" style="flex: 2;">操作</view>
|
||||||
|
</view>
|
||||||
|
<view class="table-body">
|
||||||
|
<view v-for="item in stationList" :key="item.id" class="tr">
|
||||||
|
<view class="td" style="flex: 1;">{{ item.id }}</view>
|
||||||
|
<view class="td" style="flex: 2;">
|
||||||
|
<image class="station-img" :src="item.image" mode="aspectFill" />
|
||||||
|
</view>
|
||||||
|
<view class="td" style="flex: 2;">{{ item.name }}</view>
|
||||||
|
<view class="td" style="flex: 2;">{{ item.phone }}</view>
|
||||||
|
<view class="td" style="flex: 3;">{{ item.address }}</view>
|
||||||
|
<view class="td" style="flex: 3;">{{ item.hours }}</view>
|
||||||
|
<view class="td" style="flex: 1.5;">
|
||||||
|
<switch :checked="item.isshow" color="#1890ff" />
|
||||||
|
</view>
|
||||||
|
<view class="td" style="flex: 2;">
|
||||||
|
<text class="action-btn" @click="onEdit(item)">编辑</text>
|
||||||
|
<text class="action-btn-del" @click="onDel(item)">删除</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="uts">
|
<script setup lang="uts">
|
||||||
|
import { ref, reactive } from 'vue'
|
||||||
|
|
||||||
|
const searchKey = ref('')
|
||||||
|
|
||||||
|
type StationItem = {
|
||||||
|
id: number
|
||||||
|
image: string
|
||||||
|
name: string
|
||||||
|
phone: string
|
||||||
|
address: string
|
||||||
|
hours: string
|
||||||
|
isshow: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
const stationList = reactive<StationItem[]>([
|
||||||
|
{ id: 46, image: '/static/logo.png', name: '提货点222', phone: '13769102384', address: '能看见你的困难', hours: '00:00:00 - 23:00:00', isshow: true },
|
||||||
|
{ id: 44, image: '/static/logo.png', name: '美东科技', phone: '15912341234', address: '襄阳火车站', hours: '08:00:00 - 22:00:00', isshow: true }
|
||||||
|
])
|
||||||
|
|
||||||
|
function onSearch() {
|
||||||
|
console.log('Search:', searchKey.value)
|
||||||
|
}
|
||||||
|
|
||||||
|
function onAdd() {
|
||||||
|
console.log('Add station')
|
||||||
|
}
|
||||||
|
|
||||||
|
function onEdit(item: StationItem) {
|
||||||
|
console.log('Edit:', item.name)
|
||||||
|
}
|
||||||
|
|
||||||
|
function onDel(item: StationItem) {
|
||||||
|
console.log('Delete:', item.id)
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.admin-page-container { padding: 20px; background-color: #f5f7f9; min-height: 100vh; }
|
.admin-page-container {
|
||||||
.page-card { background-color: #fff; border-radius: 4px; padding: 20px; box-shadow: 0 1px 4px rgba(0,21,41,0.08); }
|
padding: 15px;
|
||||||
.page-header { margin-bottom: 20px; border-bottom: 1px solid #f0f0f0; padding-bottom: 15px; }
|
background-color: #f5f7f9;
|
||||||
.page-title { font-size: 16px; font-weight: bold; color: #303133; }
|
min-height: 100vh;
|
||||||
.placeholder-text { font-size: 14px; color: #909399; }
|
}
|
||||||
|
|
||||||
|
.page-card {
|
||||||
|
background-color: #fff;
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-wrap {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
padding-bottom: 20px;
|
||||||
|
border-bottom: 1px solid #f0f0f0;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.label {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #606266;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input {
|
||||||
|
width: 250px;
|
||||||
|
height: 32px;
|
||||||
|
padding: 0 10px;
|
||||||
|
border: 1px solid #dcdfe6;
|
||||||
|
border-radius: 4px;
|
||||||
|
font-size: 14px;
|
||||||
|
color: #606266;
|
||||||
|
margin-right: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tabs-wrap {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
border-bottom: 1px solid #f0f2f5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-item {
|
||||||
|
padding: 10px 15px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-item.active {
|
||||||
|
border-bottom: 2px solid #1890ff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-item.active .tab-text {
|
||||||
|
color: #1890ff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-text {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #515a6e;
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-wrap {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn {
|
||||||
|
height: 32px;
|
||||||
|
line-height: 30px;
|
||||||
|
padding: 0 15px;
|
||||||
|
font-size: 14px;
|
||||||
|
border-radius: 4px;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-primary {
|
||||||
|
background-color: #1890ff;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-wrap {
|
||||||
|
width: 100%;
|
||||||
|
border: 1px solid #f0f0f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-header {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
background-color: #f8f8f9;
|
||||||
|
}
|
||||||
|
|
||||||
|
.th {
|
||||||
|
padding: 12px 10px;
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #515a6e;
|
||||||
|
border-bottom: 1px solid #f0f0f0;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tr {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
border-bottom: 1px solid #f0f0f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.td {
|
||||||
|
padding: 12px 10px;
|
||||||
|
font-size: 14px;
|
||||||
|
color: #515a6e;
|
||||||
|
text-align: center;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.station-img {
|
||||||
|
width: 40px;
|
||||||
|
height: 40px;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-btn {
|
||||||
|
color: #1890ff;
|
||||||
|
font-size: 13px;
|
||||||
|
margin-right: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-btn-del {
|
||||||
|
color: #ed4014;
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -1,23 +1,187 @@
|
|||||||
<template>
|
<template>
|
||||||
<view class="admin-page-container">
|
<view class="admin-page-container">
|
||||||
<view class="page-card">
|
<view class="page-card">
|
||||||
<view class="page-header">
|
<!-- 搜索栏 -->
|
||||||
<text class="page-title">运费模板</text>
|
<view class="search-wrap">
|
||||||
|
<view class="search-item">
|
||||||
|
<text class="label">搜索:</text>
|
||||||
|
<input class="input" placeholder="请输入模板名称" v-model="searchKey" />
|
||||||
|
</view>
|
||||||
|
<button class="btn btn-primary" @click="onSearch">查询</button>
|
||||||
</view>
|
</view>
|
||||||
<view class="page-content">
|
|
||||||
<text class="placeholder-text">运费模板 页面开发中...</text>
|
<view class="action-wrap">
|
||||||
|
<button class="btn btn-primary" @click="onAdd">添加运费模板</button>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 表格区域 -->
|
||||||
|
<view class="table-wrap">
|
||||||
|
<view class="table-header">
|
||||||
|
<view class="th" style="flex: 1;">ID</view>
|
||||||
|
<view class="th" style="flex: 2;">模板名称</view>
|
||||||
|
<view class="th" style="flex: 2;">计费方式</view>
|
||||||
|
<view class="th" style="flex: 2;">指定包邮</view>
|
||||||
|
<view class="th" style="flex: 1;">排序</view>
|
||||||
|
<view class="th" style="flex: 3;">添加时间</view>
|
||||||
|
<view class="th" style="flex: 2;">操作</view>
|
||||||
|
</view>
|
||||||
|
<view class="table-body">
|
||||||
|
<view v-for="item in freightList" :key="item.id" class="tr">
|
||||||
|
<view class="td" style="flex: 1;">{{ item.id }}</view>
|
||||||
|
<view class="td" style="flex: 2;">{{ item.name }}</view>
|
||||||
|
<view class="td" style="flex: 2;">{{ item.method }}</view>
|
||||||
|
<view class="td" style="flex: 2;">{{ item.freeShipping ? '开启' : '关闭' }}</view>
|
||||||
|
<view class="td" style="flex: 1;">{{ item.sort }}</view>
|
||||||
|
<view class="td" style="flex: 3;">{{ item.addTime }}</view>
|
||||||
|
<view class="td" style="flex: 2;">
|
||||||
|
<text class="action-btn" @click="onEdit(item)">修改</text>
|
||||||
|
<text class="action-btn-del" @click="onDel(item)">删除</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="uts">
|
<script setup lang="uts">
|
||||||
|
import { ref, reactive } from 'vue'
|
||||||
|
|
||||||
|
const searchKey = ref('')
|
||||||
|
|
||||||
|
type FreightItem = {
|
||||||
|
id: number
|
||||||
|
name: string
|
||||||
|
method: string
|
||||||
|
freeShipping: boolean
|
||||||
|
sort: number
|
||||||
|
addTime: string
|
||||||
|
}
|
||||||
|
|
||||||
|
const freightList = reactive<FreightItem[]>([
|
||||||
|
{ id: 5, name: '测试', method: '按件数', freeShipping: false, sort: 0, addTime: '2025-05-18 09:44:14' },
|
||||||
|
{ id: 4, name: '模板3', method: '按体积', freeShipping: false, sort: 0, addTime: '2023-12-20 09:53:23' },
|
||||||
|
{ id: 3, name: '运费2', method: '按重量', freeShipping: false, sort: 0, addTime: '2023-12-20 09:53:02' },
|
||||||
|
{ id: 2, name: '模板1', method: '按件数', freeShipping: true, sort: 0, addTime: '2023-12-20 09:29:05' }
|
||||||
|
])
|
||||||
|
|
||||||
|
function onSearch() {
|
||||||
|
console.log('Search:', searchKey.value)
|
||||||
|
}
|
||||||
|
|
||||||
|
function onAdd() {
|
||||||
|
console.log('Add freight template')
|
||||||
|
}
|
||||||
|
|
||||||
|
function onEdit(item: FreightItem) {
|
||||||
|
console.log('Edit:', item.name)
|
||||||
|
}
|
||||||
|
|
||||||
|
function onDel(item: FreightItem) {
|
||||||
|
console.log('Delete:', item.id)
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.admin-page-container { padding: 20px; background-color: #f5f7f9; min-height: 100vh; }
|
.admin-page-container {
|
||||||
.page-card { background-color: #fff; border-radius: 4px; padding: 20px; box-shadow: 0 1px 4px rgba(0,21,41,0.08); }
|
padding: 15px;
|
||||||
.page-header { margin-bottom: 20px; border-bottom: 1px solid #f0f0f0; padding-bottom: 15px; }
|
background-color: #f5f7f9;
|
||||||
.page-title { font-size: 16px; font-weight: bold; color: #303133; }
|
min-height: 100vh;
|
||||||
.placeholder-text { font-size: 14px; color: #909399; }
|
}
|
||||||
|
|
||||||
|
.page-card {
|
||||||
|
background-color: #fff;
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-wrap {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
padding-bottom: 20px;
|
||||||
|
border-bottom: 1px solid #f0f0f0;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.label {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #606266;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input {
|
||||||
|
width: 200px;
|
||||||
|
height: 32px;
|
||||||
|
padding: 0 10px;
|
||||||
|
border: 1px solid #dcdfe6;
|
||||||
|
border-radius: 4px;
|
||||||
|
font-size: 14px;
|
||||||
|
color: #606266;
|
||||||
|
margin-right: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-wrap {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn {
|
||||||
|
height: 32px;
|
||||||
|
line-height: 30px;
|
||||||
|
padding: 0 15px;
|
||||||
|
font-size: 14px;
|
||||||
|
border-radius: 4px;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-primary {
|
||||||
|
background-color: #1890ff;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-wrap {
|
||||||
|
width: 100%;
|
||||||
|
border: 1px solid #f0f0f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-header {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
background-color: #f8f8f9;
|
||||||
|
}
|
||||||
|
|
||||||
|
.th {
|
||||||
|
padding: 12px 10px;
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #515a6e;
|
||||||
|
border-bottom: 1px solid #f0f0f0;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tr {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
border-bottom: 1px solid #f0f0f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.td {
|
||||||
|
padding: 12px 10px;
|
||||||
|
font-size: 14px;
|
||||||
|
color: #515a6e;
|
||||||
|
text-align: center;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-btn {
|
||||||
|
color: #1890ff;
|
||||||
|
font-size: 13px;
|
||||||
|
margin-right: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-btn-del {
|
||||||
|
color: #ed4014;
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
207
pages/mall/admin/setting/delivery/verifier.uvue
Normal file
207
pages/mall/admin/setting/delivery/verifier.uvue
Normal file
@@ -0,0 +1,207 @@
|
|||||||
|
<template>
|
||||||
|
<view class="admin-page-container">
|
||||||
|
<view class="page-card">
|
||||||
|
<!-- 搜索栏 -->
|
||||||
|
<view class="search-wrap">
|
||||||
|
<view class="search-item">
|
||||||
|
<text class="label">提货点名称:</text>
|
||||||
|
<picker mode="selector" :range="stationRange" @change="onStationChange">
|
||||||
|
<view class="picker-input">{{ stationText }}</view>
|
||||||
|
</picker>
|
||||||
|
</view>
|
||||||
|
<button class="btn btn-primary" @click="onSearch">查询</button>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="action-wrap">
|
||||||
|
<button class="btn btn-primary" @click="onAdd">添加核销员</button>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 表格区域 -->
|
||||||
|
<view class="table-wrap">
|
||||||
|
<view class="table-header">
|
||||||
|
<view class="th" style="flex: 1;">ID</view>
|
||||||
|
<view class="th" style="flex: 1.5;">头像</view>
|
||||||
|
<view class="th" style="flex: 2;">微信名称</view>
|
||||||
|
<view class="th" style="flex: 2;">核销员名称</view>
|
||||||
|
<view class="th" style="flex: 2;">所属提货点</view>
|
||||||
|
<view class="th" style="flex: 3;">添加时间</view>
|
||||||
|
<view class="th" style="flex: 1.5;">状态</view>
|
||||||
|
<view class="th" style="flex: 2;">操作</view>
|
||||||
|
</view>
|
||||||
|
<view class="table-body">
|
||||||
|
<view v-for="item in verifierList" :key="item.id" class="tr">
|
||||||
|
<view class="td" style="flex: 1;">{{ item.id }}</view>
|
||||||
|
<view class="td" style="flex: 1.5;">
|
||||||
|
<image class="avatar" :src="item.avatar" mode="aspectFill" />
|
||||||
|
</view>
|
||||||
|
<view class="td" style="flex: 2;">{{ item.wechatName }}</view>
|
||||||
|
<view class="td" style="flex: 2;">{{ item.name }}</view>
|
||||||
|
<view class="td" style="flex: 2;">{{ item.station }}</view>
|
||||||
|
<view class="td" style="flex: 3;">{{ item.addTime }}</view>
|
||||||
|
<view class="td" style="flex: 1.5;">
|
||||||
|
<switch :checked="item.status" color="#1890ff" />
|
||||||
|
</view>
|
||||||
|
<view class="td" style="flex: 2;">
|
||||||
|
<text class="action-btn" @click="onEdit(item)">编辑</text>
|
||||||
|
<text class="action-btn-del" @click="onDel(item)">删除</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="uts">
|
||||||
|
import { ref, reactive } from 'vue'
|
||||||
|
|
||||||
|
const stationRange = ['所有', '提货点222', '美东科技']
|
||||||
|
const stationText = ref('请选择')
|
||||||
|
|
||||||
|
type VerifierItem = {
|
||||||
|
id: number
|
||||||
|
avatar: string
|
||||||
|
wechatName: string
|
||||||
|
name: string
|
||||||
|
station: string
|
||||||
|
addTime: string
|
||||||
|
status: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
const verifierList = reactive<VerifierItem[]>([
|
||||||
|
{ id: 94, avatar: '/static/logo.png', wechatName: '地球人', name: '15920014197', station: '美东科技', addTime: '2025-10-22 10:33:07', status: true }
|
||||||
|
])
|
||||||
|
|
||||||
|
function onStationChange(e: any) {
|
||||||
|
const index = parseInt(e.detail.value.toString())
|
||||||
|
stationText.value = stationRange[index]
|
||||||
|
}
|
||||||
|
|
||||||
|
function onSearch() {
|
||||||
|
console.log('Search:', stationText.value)
|
||||||
|
}
|
||||||
|
|
||||||
|
function onAdd() {
|
||||||
|
console.log('Add verifier')
|
||||||
|
}
|
||||||
|
|
||||||
|
function onEdit(item: VerifierItem) {
|
||||||
|
console.log('Edit:', item.name)
|
||||||
|
}
|
||||||
|
|
||||||
|
function onDel(item: VerifierItem) {
|
||||||
|
console.log('Delete:', item.id)
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.admin-page-container {
|
||||||
|
padding: 15px;
|
||||||
|
background-color: #f5f7f9;
|
||||||
|
min-height: 100vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-card {
|
||||||
|
background-color: #fff;
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-wrap {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
padding-bottom: 20px;
|
||||||
|
border-bottom: 1px solid #f0f0f0;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.label {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #606266;
|
||||||
|
}
|
||||||
|
|
||||||
|
.picker-input {
|
||||||
|
width: 200px;
|
||||||
|
height: 32px;
|
||||||
|
line-height: 32px;
|
||||||
|
padding: 0 10px;
|
||||||
|
border: 1px solid #dcdfe6;
|
||||||
|
border-radius: 4px;
|
||||||
|
font-size: 14px;
|
||||||
|
color: #606266;
|
||||||
|
background-color: #fff;
|
||||||
|
margin-right: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-wrap {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn {
|
||||||
|
height: 32px;
|
||||||
|
line-height: 30px;
|
||||||
|
padding: 0 15px;
|
||||||
|
font-size: 14px;
|
||||||
|
border-radius: 4px;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-primary {
|
||||||
|
background-color: #1890ff;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-wrap {
|
||||||
|
width: 100%;
|
||||||
|
border: 1px solid #f0f0f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-header {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
background-color: #f8f8f9;
|
||||||
|
}
|
||||||
|
|
||||||
|
.th {
|
||||||
|
padding: 12px 10px;
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #515a6e;
|
||||||
|
border-bottom: 1px solid #f0f0f0;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tr {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
border-bottom: 1px solid #f0f0f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.td {
|
||||||
|
padding: 12px 10px;
|
||||||
|
font-size: 14px;
|
||||||
|
color: #515a6e;
|
||||||
|
text-align: center;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.avatar {
|
||||||
|
width: 36px;
|
||||||
|
height: 36px;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-btn {
|
||||||
|
color: #1890ff;
|
||||||
|
font-size: 13px;
|
||||||
|
margin-right: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-btn-del {
|
||||||
|
color: #ed4014;
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -1,23 +1,215 @@
|
|||||||
<template>
|
<template>
|
||||||
<view class="admin-page-container">
|
<view class="admin-page-container">
|
||||||
<view class="page-card">
|
<view class="page-header">
|
||||||
<view class="page-header">
|
<view class="breadcrumb">
|
||||||
<text class="page-title">商品采集配置</text>
|
<text class="bc-item">设置</text>
|
||||||
|
<text class="bc-sep">/</text>
|
||||||
|
<text class="bc-item">接口配置</text>
|
||||||
|
<text class="bc-sep">/</text>
|
||||||
|
<text class="bc-item active">商品采集配置</text>
|
||||||
</view>
|
</view>
|
||||||
<view class="page-content">
|
</view>
|
||||||
<text class="placeholder-text">商品采集配置 页面开发中...</text>
|
<view class="content-card">
|
||||||
|
<view class="tabs-header">
|
||||||
|
<view :class="['tab-item', activeTab == 0 ? 'active' : '']" @click="activeTab = 0">
|
||||||
|
<text class="tab-text">基础配置</text>
|
||||||
|
</view>
|
||||||
|
<view :class="['tab-item', activeTab == 1 ? 'active' : '']" @click="activeTab = 1">
|
||||||
|
<text class="tab-text">99api配置</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 基础配置 -->
|
||||||
|
<view class="form-section" v-if="activeTab == 0">
|
||||||
|
<view class="form-content">
|
||||||
|
<view class="form-row">
|
||||||
|
<view class="form-label">接口选择:</view>
|
||||||
|
<view class="form-input-box">
|
||||||
|
<radio-group class="form-radio-group" @change="onBaseChange('type', $event)">
|
||||||
|
<label class="radio-label">
|
||||||
|
<radio value="onepass" :checked="form.base.type == 'onepass'" color="#2d8cf0" />
|
||||||
|
<text class="radio-text">一号通</text>
|
||||||
|
</label>
|
||||||
|
<label class="radio-label">
|
||||||
|
<radio value="99api" :checked="form.base.type == '99api'" color="#2d8cf0" />
|
||||||
|
<text class="radio-text">99Api</text>
|
||||||
|
</label>
|
||||||
|
</radio-group>
|
||||||
|
<text class="form-tips highlight">采集商品接口选择,一号通快速注册开通使用不用配置apikey,或者去99api网址:https://www.99api.com/注册账号。推荐一号通方便快捷</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="form-actions" style="margin-top: 20px;">
|
||||||
|
<button class="submit-btn" type="primary" @click="handleSave">提交</button>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 99api配置 -->
|
||||||
|
<view class="form-section" v-if="activeTab == 1">
|
||||||
|
<view class="form-content">
|
||||||
|
<view class="form-row">
|
||||||
|
<view class="form-label">99Api apiKey:</view>
|
||||||
|
<view class="form-input-box">
|
||||||
|
<input class="form-input max-width-input" v-model="form.api99.apiKey" placeholder="请输入99Api apiKey" />
|
||||||
|
<text class="form-tips highlight">注册99api采集接口在个人中心复制key</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="form-actions" style="margin-top: 20px;">
|
||||||
|
<button class="submit-btn" type="primary" @click="handleSave">提交</button>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="uts">
|
<script setup lang="uts">
|
||||||
|
import { ref, reactive } from 'vue'
|
||||||
|
|
||||||
|
const activeTab = ref(0)
|
||||||
|
const form = reactive({
|
||||||
|
base: {
|
||||||
|
type: 'onepass'
|
||||||
|
},
|
||||||
|
api99: {
|
||||||
|
apiKey: ''
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const onBaseChange = (key : string, e : any) => {
|
||||||
|
form.base[key] = e.detail.value
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleSave = () => {
|
||||||
|
uni.showToast({
|
||||||
|
title: '提交成功',
|
||||||
|
icon: 'success'
|
||||||
|
})
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.admin-page-container { padding: 20px; background-color: #f5f7f9; min-height: 100vh; }
|
.admin-page-container {
|
||||||
.page-card { background-color: #fff; border-radius: 4px; padding: 20px; box-shadow: 0 1px 4px rgba(0,21,41,0.08); }
|
min-height: 100vh;
|
||||||
.page-header { margin-bottom: 20px; border-bottom: 1px solid #f0f0f0; padding-bottom: 15px; }
|
background-color: #f5f7f9;
|
||||||
.page-title { font-size: 16px; font-weight: bold; color: #303133; }
|
padding: 20px;
|
||||||
.placeholder-text { font-size: 14px; color: #909399; }
|
}
|
||||||
|
.breadcrumb {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
.bc-item {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
.bc-item.active {
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
.bc-sep {
|
||||||
|
margin: 0 8px;
|
||||||
|
color: #ccc;
|
||||||
|
}
|
||||||
|
.content-card {
|
||||||
|
background-color: #fff;
|
||||||
|
border-radius: 4px;
|
||||||
|
box-shadow: 0 1px 4px rgba(0,21,41,.08);
|
||||||
|
}
|
||||||
|
.tabs-header {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
border-bottom: 1px solid #f0f0f0;
|
||||||
|
padding: 0 30px;
|
||||||
|
}
|
||||||
|
.tab-item {
|
||||||
|
padding: 16px 20px;
|
||||||
|
margin-right: 32px;
|
||||||
|
cursor: pointer;
|
||||||
|
border-bottom: 2px solid transparent;
|
||||||
|
}
|
||||||
|
.tab-text {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
.tab-item.active {
|
||||||
|
border-bottom-color: #2d8cf0;
|
||||||
|
}
|
||||||
|
.tab-item.active .tab-text {
|
||||||
|
color: #2d8cf0;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
.form-section {
|
||||||
|
padding: 30px;
|
||||||
|
}
|
||||||
|
.form-content {
|
||||||
|
max-width: 900px;
|
||||||
|
}
|
||||||
|
.form-row {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
margin-bottom: 24px;
|
||||||
|
}
|
||||||
|
.form-label {
|
||||||
|
width: 140px;
|
||||||
|
font-size: 14px;
|
||||||
|
color: #333;
|
||||||
|
text-align: right;
|
||||||
|
margin-right: 24px;
|
||||||
|
padding-top: 8px;
|
||||||
|
}
|
||||||
|
.form-input-box {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
.form-input {
|
||||||
|
width: 100%;
|
||||||
|
border: 1px solid #dcdfe6;
|
||||||
|
border-radius: 4px;
|
||||||
|
height: 34px;
|
||||||
|
padding: 0 12px;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
.max-width-input {
|
||||||
|
max-width: 450px;
|
||||||
|
}
|
||||||
|
.form-tips {
|
||||||
|
display: block;
|
||||||
|
font-size: 12px;
|
||||||
|
color: #999;
|
||||||
|
margin-top: 10px;
|
||||||
|
line-height: 1.6;
|
||||||
|
}
|
||||||
|
.highlight {
|
||||||
|
color: #c0c4cc;
|
||||||
|
}
|
||||||
|
.form-radio-group {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
height: 34px;
|
||||||
|
}
|
||||||
|
.radio-label {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
margin-right: 24px;
|
||||||
|
}
|
||||||
|
.radio-text {
|
||||||
|
font-size: 14px;
|
||||||
|
margin-left: 6px;
|
||||||
|
color: #606266;
|
||||||
|
}
|
||||||
|
.form-actions {
|
||||||
|
padding-left: 164px;
|
||||||
|
}
|
||||||
|
.submit-btn {
|
||||||
|
width: 65px;
|
||||||
|
height: 32px;
|
||||||
|
background-color: #2d8cf0;
|
||||||
|
color: #fff;
|
||||||
|
border-radius: 4px;
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 32px;
|
||||||
|
text-align: center;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -1,23 +1,240 @@
|
|||||||
<template>
|
<template>
|
||||||
<view class="admin-page-container">
|
<view class="admin-page-container">
|
||||||
<view class="page-card">
|
<view class="page-header">
|
||||||
<view class="page-header">
|
<view class="breadcrumb">
|
||||||
<text class="page-title">电子面单配置</text>
|
<text class="bc-item">设置</text>
|
||||||
|
<text class="bc-sep">/</text>
|
||||||
|
<text class="bc-item">接口配置</text>
|
||||||
|
<text class="bc-sep">/</text>
|
||||||
|
<text class="bc-item active">电子面单配置</text>
|
||||||
</view>
|
</view>
|
||||||
<view class="page-content">
|
</view>
|
||||||
<text class="placeholder-text">电子面单配置 页面开发中...</text>
|
<view class="content-card">
|
||||||
|
<view class="tabs-header">
|
||||||
|
<view :class="['tab-item', activeTab == 0 ? 'active' : '']" @click="activeTab = 0">
|
||||||
|
<text class="tab-text">基础配置</text>
|
||||||
|
</view>
|
||||||
|
<view :class="['tab-item', activeTab == 1 ? 'active' : '']" @click="activeTab = 1">
|
||||||
|
<text class="tab-text">一号通配置</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 基础配置 -->
|
||||||
|
<view class="form-section" v-if="activeTab == 0">
|
||||||
|
<view class="form-content">
|
||||||
|
<view class="form-row">
|
||||||
|
<view class="form-label">开启电子面单:</view>
|
||||||
|
<view class="form-input-box">
|
||||||
|
<radio-group class="form-radio-group" @change="onBaseChange('enabled', $event)">
|
||||||
|
<label class="radio-label"><radio value="1" :checked="form.base.enabled == '1'" color="#2d8cf0" /><text class="radio-text">开启</text></label>
|
||||||
|
<label class="radio-label"><radio value="0" :checked="form.base.enabled == '0'" color="#2d8cf0" /><text class="radio-text">关闭</text></label>
|
||||||
|
</radio-group>
|
||||||
|
<text class="form-tips">电子面单是否开启</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="form-row">
|
||||||
|
<view class="form-label">电子面单类型:</view>
|
||||||
|
<view class="form-input-box">
|
||||||
|
<radio-group class="form-radio-group" @change="onBaseChange('type', $event)">
|
||||||
|
<label class="radio-label"><radio value="onepass" :checked="form.base.type == 'onepass'" color="#2d8cf0" /><text class="radio-text">一号通</text></label>
|
||||||
|
</radio-group>
|
||||||
|
<text class="form-tips">电子面单类型</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="form-actions" style="margin-top: 20px;">
|
||||||
|
<button class="submit-btn" type="primary" @click="handleSave">提交</button>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 一号通配置 -->
|
||||||
|
<view class="form-section" v-if="activeTab == 1">
|
||||||
|
<view class="form-content">
|
||||||
|
<view class="form-row">
|
||||||
|
<view class="form-label">发货人姓名:</view>
|
||||||
|
<view class="form-input-box">
|
||||||
|
<input class="form-input max-width-input" v-model="form.onepass.senderName" placeholder="王二麻子" />
|
||||||
|
<text class="form-tips">快递面单发货人姓名</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="form-row">
|
||||||
|
<view class="form-label">发货人电话:</view>
|
||||||
|
<view class="form-input-box">
|
||||||
|
<input class="form-input max-width-input" v-model="form.onepass.senderPhone" placeholder="13020202020" />
|
||||||
|
<text class="form-tips">快递面单发货人电话</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="form-row">
|
||||||
|
<view class="form-label">发货人详细地址:</view>
|
||||||
|
<view class="form-input-box">
|
||||||
|
<input class="form-input max-width-input" v-model="form.onepass.senderAddress" placeholder="山西省长治市钢铁去送货单" />
|
||||||
|
<text class="form-tips">快递面单发货人详细地址</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="form-row">
|
||||||
|
<view class="form-label">打印机编号:</view>
|
||||||
|
<view class="form-input-box">
|
||||||
|
<input class="form-input max-width-input" v-model="form.onepass.printerId" placeholder="请输入打印机编号" />
|
||||||
|
<text class="form-tips">请购买快速100二代云打印机(KX100L3)</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="form-actions" style="margin-top: 20px;">
|
||||||
|
<button class="submit-btn" type="primary" @click="handleSave">提交</button>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="uts">
|
<script setup lang="uts">
|
||||||
|
import { ref, reactive } from 'vue'
|
||||||
|
|
||||||
|
const activeTab = ref(0)
|
||||||
|
const form = reactive({
|
||||||
|
base: {
|
||||||
|
enabled: '1',
|
||||||
|
type: 'onepass'
|
||||||
|
},
|
||||||
|
onepass: {
|
||||||
|
senderName: '王二麻子',
|
||||||
|
senderPhone: '13020202020',
|
||||||
|
senderAddress: '山西省长治市钢铁去送货单',
|
||||||
|
printerId: ''
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const onBaseChange = (key : string, e : any) => {
|
||||||
|
form.base[key] = e.detail.value
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleSave = () => {
|
||||||
|
uni.showToast({
|
||||||
|
title: '提交成功',
|
||||||
|
icon: 'success'
|
||||||
|
})
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.admin-page-container { padding: 20px; background-color: #f5f7f9; min-height: 100vh; }
|
.admin-page-container {
|
||||||
.page-card { background-color: #fff; border-radius: 4px; padding: 20px; box-shadow: 0 1px 4px rgba(0,21,41,0.08); }
|
min-height: 100vh;
|
||||||
.page-header { margin-bottom: 20px; border-bottom: 1px solid #f0f0f0; padding-bottom: 15px; }
|
background-color: #f5f7f9;
|
||||||
.page-title { font-size: 16px; font-weight: bold; color: #303133; }
|
padding: 20px;
|
||||||
.placeholder-text { font-size: 14px; color: #909399; }
|
}
|
||||||
|
.breadcrumb {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
.bc-item {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
.bc-item.active {
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
.bc-sep {
|
||||||
|
margin: 0 8px;
|
||||||
|
color: #ccc;
|
||||||
|
}
|
||||||
|
.content-card {
|
||||||
|
background-color: #fff;
|
||||||
|
border-radius: 4px;
|
||||||
|
box-shadow: 0 1px 4px rgba(0,21,41,.08);
|
||||||
|
}
|
||||||
|
.tabs-header {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
border-bottom: 1px solid #f0f0f0;
|
||||||
|
padding: 0 30px;
|
||||||
|
}
|
||||||
|
.tab-item {
|
||||||
|
padding: 16px 20px;
|
||||||
|
margin-right: 32px;
|
||||||
|
cursor: pointer;
|
||||||
|
border-bottom: 2px solid transparent;
|
||||||
|
}
|
||||||
|
.tab-text {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
.tab-item.active {
|
||||||
|
border-bottom-color: #2d8cf0;
|
||||||
|
}
|
||||||
|
.tab-item.active .tab-text {
|
||||||
|
color: #2d8cf0;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
.form-section {
|
||||||
|
padding: 30px;
|
||||||
|
}
|
||||||
|
.form-content {
|
||||||
|
max-width: 900px;
|
||||||
|
}
|
||||||
|
.form-row {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
margin-bottom: 24px;
|
||||||
|
}
|
||||||
|
.form-label {
|
||||||
|
width: 140px;
|
||||||
|
font-size: 14px;
|
||||||
|
color: #333;
|
||||||
|
text-align: right;
|
||||||
|
margin-right: 24px;
|
||||||
|
padding-top: 8px;
|
||||||
|
}
|
||||||
|
.form-input-box {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
.form-input {
|
||||||
|
width: 100%;
|
||||||
|
border: 1px solid #dcdfe6;
|
||||||
|
border-radius: 4px;
|
||||||
|
height: 34px;
|
||||||
|
padding: 0 12px;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
.max-width-input {
|
||||||
|
max-width: 450px;
|
||||||
|
}
|
||||||
|
.form-tips {
|
||||||
|
display: block;
|
||||||
|
font-size: 12px;
|
||||||
|
color: #999;
|
||||||
|
margin-top: 10px;
|
||||||
|
line-height: 1.6;
|
||||||
|
}
|
||||||
|
.form-radio-group {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
height: 34px;
|
||||||
|
}
|
||||||
|
.radio-label {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
margin-right: 24px;
|
||||||
|
}
|
||||||
|
.radio-text {
|
||||||
|
font-size: 14px;
|
||||||
|
margin-left: 6px;
|
||||||
|
color: #606266;
|
||||||
|
}
|
||||||
|
.form-actions {
|
||||||
|
padding-left: 164px;
|
||||||
|
}
|
||||||
|
.submit-btn {
|
||||||
|
width: 65px;
|
||||||
|
height: 32px;
|
||||||
|
background-color: #2d8cf0;
|
||||||
|
color: #fff;
|
||||||
|
border-radius: 4px;
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 32px;
|
||||||
|
text-align: center;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -1,23 +1,209 @@
|
|||||||
<template>
|
<template>
|
||||||
<view class="admin-page-container">
|
<view class="admin-page-container">
|
||||||
<view class="page-card">
|
<view class="page-header">
|
||||||
<view class="page-header">
|
<view class="breadcrumb">
|
||||||
<text class="page-title">物流查询配置</text>
|
<text class="bc-item">设置</text>
|
||||||
|
<text class="bc-sep">/</text>
|
||||||
|
<text class="bc-item">接口配置</text>
|
||||||
|
<text class="bc-sep">/</text>
|
||||||
|
<text class="bc-item active">物流查询配置</text>
|
||||||
</view>
|
</view>
|
||||||
<view class="page-content">
|
</view>
|
||||||
<text class="placeholder-text">物流查询配置 页面开发中...</text>
|
<view class="content-card">
|
||||||
|
<view class="tabs-header">
|
||||||
|
<view :class="['tab-item', activeTab == 0 ? 'active' : '']" @click="activeTab = 0">
|
||||||
|
<text class="tab-text">基础配置</text>
|
||||||
|
</view>
|
||||||
|
<view :class="['tab-item', activeTab == 1 ? 'active' : '']" @click="activeTab = 1">
|
||||||
|
<text class="tab-text">阿里云配置</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 基础配置 -->
|
||||||
|
<view class="form-section" v-if="activeTab == 0">
|
||||||
|
<view class="form-content">
|
||||||
|
<view class="form-row">
|
||||||
|
<view class="form-label">接口选择:</view>
|
||||||
|
<view class="form-input-box">
|
||||||
|
<radio-group class="form-radio-group" @change="onBaseChange('type', $event)">
|
||||||
|
<label class="radio-label"><radio value="onepass" :checked="form.base.type == 'onepass'" color="#2d8cf0" /><text class="radio-text">一号通</text></label>
|
||||||
|
<label class="radio-label"><radio value="aliyun" :checked="form.base.type == 'aliyun'" color="#2d8cf0" /><text class="radio-text">阿里云物流查询</text></label>
|
||||||
|
</radio-group>
|
||||||
|
<text class="form-tips highlight">建议使用一号通更方便不用配置密钥,阿里云云市场购买链接:https://0x9.me/w9vnq</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="form-actions" style="margin-top: 20px;">
|
||||||
|
<button class="submit-btn" type="primary" @click="handleSave">提交</button>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 阿里云配置 -->
|
||||||
|
<view class="form-section" v-if="activeTab == 1">
|
||||||
|
<view class="form-content">
|
||||||
|
<view class="form-row">
|
||||||
|
<view class="form-label">快递查询密钥:</view>
|
||||||
|
<view class="form-input-box">
|
||||||
|
<input class="form-input max-width-input" v-model="form.ali.appCode" placeholder="请输入快递查询密钥" />
|
||||||
|
<text class="form-tips highlight">阿里云云市场快递查询接口密钥购买地址:https://market.aliyun.com/products/57126001/cmapi021863.html?spm=5176.2020520132.101.4.42a672183nvgfH#sku=yuncode1586300000</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="form-actions" style="margin-top: 20px;">
|
||||||
|
<button class="submit-btn" type="primary" @click="handleSave">提交</button>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="uts">
|
<script setup lang="uts">
|
||||||
|
import { ref, reactive } from 'vue'
|
||||||
|
|
||||||
|
const activeTab = ref(0)
|
||||||
|
const form = reactive({
|
||||||
|
base: {
|
||||||
|
type: 'onepass'
|
||||||
|
},
|
||||||
|
ali: {
|
||||||
|
appCode: ''
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const onBaseChange = (key : string, e : any) => {
|
||||||
|
form.base[key] = e.detail.value
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleSave = () => {
|
||||||
|
uni.showToast({
|
||||||
|
title: '提交成功',
|
||||||
|
icon: 'success'
|
||||||
|
})
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.admin-page-container { padding: 20px; background-color: #f5f7f9; min-height: 100vh; }
|
.admin-page-container {
|
||||||
.page-card { background-color: #fff; border-radius: 4px; padding: 20px; box-shadow: 0 1px 4px rgba(0,21,41,0.08); }
|
min-height: 100vh;
|
||||||
.page-header { margin-bottom: 20px; border-bottom: 1px solid #f0f0f0; padding-bottom: 15px; }
|
background-color: #f5f7f9;
|
||||||
.page-title { font-size: 16px; font-weight: bold; color: #303133; }
|
padding: 20px;
|
||||||
.placeholder-text { font-size: 14px; color: #909399; }
|
}
|
||||||
|
.breadcrumb {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
.bc-item {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
.bc-item.active {
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
.bc-sep {
|
||||||
|
margin: 0 8px;
|
||||||
|
color: #ccc;
|
||||||
|
}
|
||||||
|
.content-card {
|
||||||
|
background-color: #fff;
|
||||||
|
border-radius: 4px;
|
||||||
|
box-shadow: 0 1px 4px rgba(0,21,41,.08);
|
||||||
|
}
|
||||||
|
.tabs-header {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
border-bottom: 1px solid #f0f0f0;
|
||||||
|
padding: 0 30px;
|
||||||
|
}
|
||||||
|
.tab-item {
|
||||||
|
padding: 16px 20px;
|
||||||
|
margin-right: 32px;
|
||||||
|
cursor: pointer;
|
||||||
|
border-bottom: 2px solid transparent;
|
||||||
|
}
|
||||||
|
.tab-text {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
.tab-item.active {
|
||||||
|
border-bottom-color: #2d8cf0;
|
||||||
|
}
|
||||||
|
.tab-item.active .tab-text {
|
||||||
|
color: #2d8cf0;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
.form-section {
|
||||||
|
padding: 30px;
|
||||||
|
}
|
||||||
|
.form-content {
|
||||||
|
max-width: 900px;
|
||||||
|
}
|
||||||
|
.form-row {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
margin-bottom: 24px;
|
||||||
|
}
|
||||||
|
.form-label {
|
||||||
|
width: 140px;
|
||||||
|
font-size: 14px;
|
||||||
|
color: #333;
|
||||||
|
text-align: right;
|
||||||
|
margin-right: 24px;
|
||||||
|
padding-top: 8px;
|
||||||
|
}
|
||||||
|
.form-input-box {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
.form-input {
|
||||||
|
width: 100%;
|
||||||
|
border: 1px solid #dcdfe6;
|
||||||
|
border-radius: 4px;
|
||||||
|
height: 34px;
|
||||||
|
padding: 0 12px;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
.max-width-input {
|
||||||
|
max-width: 450px;
|
||||||
|
}
|
||||||
|
.form-tips {
|
||||||
|
display: block;
|
||||||
|
font-size: 12px;
|
||||||
|
color: #999;
|
||||||
|
margin-top: 10px;
|
||||||
|
line-height: 1.6;
|
||||||
|
}
|
||||||
|
.highlight {
|
||||||
|
color: #c0c4cc;
|
||||||
|
}
|
||||||
|
.form-radio-group {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
height: 34px;
|
||||||
|
}
|
||||||
|
.radio-label {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
margin-right: 24px;
|
||||||
|
}
|
||||||
|
.radio-text {
|
||||||
|
font-size: 14px;
|
||||||
|
margin-left: 6px;
|
||||||
|
color: #606266;
|
||||||
|
}
|
||||||
|
.form-actions {
|
||||||
|
padding-left: 164px;
|
||||||
|
}
|
||||||
|
.submit-btn {
|
||||||
|
width: 65px;
|
||||||
|
height: 32px;
|
||||||
|
background-color: #2d8cf0;
|
||||||
|
color: #fff;
|
||||||
|
border-radius: 4px;
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 32px;
|
||||||
|
text-align: center;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -1,23 +1,90 @@
|
|||||||
<template>
|
<template>
|
||||||
<view class="admin-page-container">
|
<view class="admin-page-container">
|
||||||
<view class="page-card">
|
<view class="page-header">
|
||||||
<view class="page-header">
|
<view class="breadcrumb">
|
||||||
<text class="page-title">一号通配置</text>
|
<text class="bc-item">设置</text>
|
||||||
|
<text class="bc-sep">/</text>
|
||||||
|
<text class="bc-item">接口配置</text>
|
||||||
|
<text class="bc-sep">/</text>
|
||||||
|
<text class="bc-item">一号通</text>
|
||||||
|
<text class="bc-sep">/</text>
|
||||||
|
<text class="bc-item active">一号通配置</text>
|
||||||
</view>
|
</view>
|
||||||
<view class="page-content">
|
</view>
|
||||||
<text class="placeholder-text">一号通配置 页面开发中...</text>
|
<view class="content-card">
|
||||||
|
<view class="tabs-header">
|
||||||
|
<view class="tab-item" @click="navigateTo('/pages/mall/admin/setting/interface/onepass/index')">
|
||||||
|
<text class="tab-text">一号通账户</text>
|
||||||
|
</view>
|
||||||
|
<view class="tab-item active">
|
||||||
|
<text class="tab-text">一号通配置</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="form-section">
|
||||||
|
<view class="section-title">一号通配置</view>
|
||||||
|
<view class="form-content">
|
||||||
|
<view class="form-row">
|
||||||
|
<view class="form-label"><text class="star">*</text>AppId:</view>
|
||||||
|
<view class="form-input-box">
|
||||||
|
<input class="form-input" v-model="form.appId" placeholder="一号通账号内创建应用的AppId" />
|
||||||
|
<text class="form-tips">一号通账号内创建应用的AppId</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="form-row">
|
||||||
|
<view class="form-label"><text class="star">*</text>AppSecret:</view>
|
||||||
|
<view class="form-input-box">
|
||||||
|
<input class="form-input" v-model="form.appSecret" type="password" placeholder="一号通账号内创建应用的AppSecret" />
|
||||||
|
<text class="form-tips">一号通账号内创建应用的AppSecret</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="form-row">
|
||||||
|
<view class="form-label">电子发票状态:</view>
|
||||||
|
<view class="form-input-box">
|
||||||
|
<radio-group class="form-radio-group" @change="onInvoiceStatusChange">
|
||||||
|
<label class="radio-label"><radio value="1" :checked="form.invoiceStatus == '1'" color="#2d8cf0" /><text class="radio-text">开启</text></label>
|
||||||
|
<label class="radio-label"><radio value="0" :checked="form.invoiceStatus == '0'" color="#2d8cf0" /><text class="radio-text">关闭</text></label>
|
||||||
|
</radio-group>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="form-actions">
|
||||||
|
<button class="submit-btn" type="primary" @click="handleSubmit">提交</button>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="uts">
|
<script setup lang="uts">
|
||||||
|
import { ref, reactive } from 'vue'
|
||||||
|
const form = reactive({ appId: 'Aiok6xUdyOmpgXNd8Syf', appSecret: 'IO30qpzHFLf2CPIPjcwTWTPVID1jeX9uTVDz', invoiceStatus: '0' })
|
||||||
|
const onInvoiceStatusChange = (e : any) => { form.invoiceStatus = e.detail.value }
|
||||||
|
const handleSubmit = () => { uni.showToast({ title: '提交成功' }) }
|
||||||
|
const navigateTo = (url : string) => { uni.navigateTo({ url }) }
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.admin-page-container { padding: 20px; background-color: #f5f7f9; min-height: 100vh; }
|
.admin-page-container { min-height: 100vh; background-color: #f5f7f9; padding: 20px; }
|
||||||
.page-card { background-color: #fff; border-radius: 4px; padding: 20px; box-shadow: 0 1px 4px rgba(0,21,41,0.08); }
|
.breadcrumb { display: flex; flex-direction: row; align-items: center; margin-bottom: 20px; }
|
||||||
.page-header { margin-bottom: 20px; border-bottom: 1px solid #f0f0f0; padding-bottom: 15px; }
|
.bc-item { font-size: 14px; color: #999; }
|
||||||
.page-title { font-size: 16px; font-weight: bold; color: #303133; }
|
.bc-item.active { color: #333; }
|
||||||
.placeholder-text { font-size: 14px; color: #909399; }
|
.bc-sep { margin: 0 8px; color: #ccc; }
|
||||||
|
.content-card { background-color: #fff; border-radius: 4px; overflow: hidden; }
|
||||||
|
.tabs-header { display: flex; flex-direction: row; border-bottom: 1px solid #f0f0f0; padding: 0 20px; }
|
||||||
|
.tab-item { padding: 15px 20px; cursor: pointer; }
|
||||||
|
.tab-text { font-size: 14px; color: #666; }
|
||||||
|
.tab-item.active { border-bottom: 2px solid #2d8cf0; }
|
||||||
|
.tab-item.active .tab-text { color: #2d8cf0; font-weight: bold; }
|
||||||
|
.form-section { padding: 20px; }
|
||||||
|
.section-title { font-size: 16px; font-weight: bold; color: #333; margin-bottom: 40px; padding-bottom: 15px; border-bottom: 1px solid #f0f0f0; }
|
||||||
|
.form-content { max-width: 800px; padding-left: 40px; }
|
||||||
|
.form-row { display: flex; flex-direction: row; margin-bottom: 24px; }
|
||||||
|
.form-label { width: 120px; font-size: 14px; color: #606266; text-align: right; padding-top: 8px; margin-right: 20px; }
|
||||||
|
.star { color: #ff4d4f; margin-right: 4px; }
|
||||||
|
.form-input-box { flex: 1; }
|
||||||
|
.form-input { width: 100%; max-width: 400px; border: 1px solid #dcdfe6; border-radius: 4px; height: 36px; padding: 0 12px; font-size: 14px; }
|
||||||
|
.form-tips { display: block; font-size: 12px; color: #999; margin-top: 8px; }
|
||||||
|
.form-radio-group { display: flex; flex-direction: row; align-items: center; height: 36px; }
|
||||||
|
.radio-label { display: flex; flex-direction: row; align-items: center; margin-right: 20px; }
|
||||||
|
.radio-text { font-size: 14px; margin-left: 8px; }
|
||||||
|
.form-actions { margin-top: 40px; padding-left: 140px; }
|
||||||
|
.submit-btn { width: 80px; height: 36px; background-color: #2d8cf0; color: #fff; border-radius: 4px; font-size: 14px; line-height: 36px; text-align: center; }
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -1,23 +1,149 @@
|
|||||||
<template>
|
<template>
|
||||||
<view class="admin-page-container">
|
<view class="admin-page-container">
|
||||||
<view class="page-card">
|
<view class="login-wrapper">
|
||||||
<view class="page-header">
|
<view class="login-card">
|
||||||
<text class="page-title">一号通页面</text>
|
<view class="login-aside">
|
||||||
|
<view class="aside-content">
|
||||||
|
<text class="aside-title">商家寄件</text>
|
||||||
|
<text class="aside-desc">中小商家可灵活选择多家快递品牌</text>
|
||||||
|
<view class="aside-illustration">
|
||||||
|
<view class="illu-box">
|
||||||
|
<view class="illu-icon"></view>
|
||||||
|
<view class="illu-card">
|
||||||
|
<view class="illu-avatar"></view>
|
||||||
|
<view class="illu-line"></view>
|
||||||
|
<view class="illu-line short"></view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="login-main">
|
||||||
|
<view class="login-tabs">
|
||||||
|
<view class="tab-item" :class="{ active: activeTab == 'account' }" @click="activeTab = 'account'">
|
||||||
|
<text class="tab-text">账号登录</text>
|
||||||
|
</view>
|
||||||
|
<view class="tab-item" :class="{ active: activeTab == 'sms' }" @click="activeTab = 'sms'">
|
||||||
|
<text class="tab-text">短信登录/注册</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="login-form">
|
||||||
|
<template v-if="activeTab == 'account'">
|
||||||
|
<view class="form-item">
|
||||||
|
<input class="form-input" placeholder="请输入手机号/账号" v-model="account" />
|
||||||
|
</view>
|
||||||
|
<view class="form-item password-item">
|
||||||
|
<input class="form-input" type="password" placeholder="请输入密码" v-model="password" />
|
||||||
|
<text class="forget-password">忘记密码</text>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
<template v-else>
|
||||||
|
<view class="form-item">
|
||||||
|
<input class="form-input" placeholder="请输入手机号" v-model="phone" />
|
||||||
|
</view>
|
||||||
|
<view class="form-item sms-item">
|
||||||
|
<input class="form-input" placeholder="请输入验证码" v-model="verifyCode" />
|
||||||
|
<text class="get-code">获取验证码</text>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
<view class="form-agreement">
|
||||||
|
<checkbox-group @change="onAgreementChange">
|
||||||
|
<label class="agreement-label">
|
||||||
|
<checkbox class="agreement-cb" value="agreed" color="#2d8cf0" :checked="isAgreed" />
|
||||||
|
<text class="agreement-text">仔细阅读并同意</text>
|
||||||
|
<text class="agreement-link">《用户协议》</text>
|
||||||
|
</label>
|
||||||
|
</checkbox-group>
|
||||||
|
</view>
|
||||||
|
<button class="login-btn" type="primary" @click="handleLogin" :disabled="!isAgreed">登录</button>
|
||||||
|
<view class="contact-box">
|
||||||
|
<text class="contact-text">咨询客服</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
</view>
|
</view>
|
||||||
<view class="page-content">
|
<view class="float-tabs">
|
||||||
<text class="placeholder-text">一号通页面 页面开发中...</text>
|
<view class="float-tab active">
|
||||||
|
<text class="float-icon">U</text>
|
||||||
|
<text class="float-text">账号登录</text>
|
||||||
|
</view>
|
||||||
|
<view class="float-tab">
|
||||||
|
<text class="float-icon gray">C</text>
|
||||||
|
<text class="float-text gray">扫码登录</text>
|
||||||
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
<view class="page-footer">
|
||||||
|
<view class="footer-links">
|
||||||
|
<text class="footer-link">官网</text>
|
||||||
|
<text class="footer-link">社区</text>
|
||||||
|
<text class="footer-link">文档</text>
|
||||||
|
</view>
|
||||||
|
<text class="footer-copy">Copyright (c) 2014-2025 CRMEB-BZ v5.6.4</text>
|
||||||
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="uts">
|
<script setup lang="uts">
|
||||||
|
import { ref } from 'vue'
|
||||||
|
const activeTab = ref('account')
|
||||||
|
const account = ref('')
|
||||||
|
const password = ref('')
|
||||||
|
const phone = ref('')
|
||||||
|
const verifyCode = ref('')
|
||||||
|
const isAgreed = ref(false)
|
||||||
|
const onAgreementChange = (e : any) => {
|
||||||
|
const values = e.detail.value as string[]
|
||||||
|
isAgreed.value = values.includes('agreed')
|
||||||
|
}
|
||||||
|
const handleLogin = () => {
|
||||||
|
if (!isAgreed.value) {
|
||||||
|
uni.showToast({ title: '请先同意用户协议', icon: 'none' })
|
||||||
|
return
|
||||||
|
}
|
||||||
|
uni.showToast({ title: '登录中...', icon: 'loading' })
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.admin-page-container { padding: 20px; background-color: #f5f7f9; min-height: 100vh; }
|
.admin-page-container { display: flex; flex-direction: column; justify-content: center; align-items: center; min-height: 100vh; background-color: #f5f7f9; padding: 40px 20px; }
|
||||||
.page-card { background-color: #fff; border-radius: 4px; padding: 20px; box-shadow: 0 1px 4px rgba(0,21,41,0.08); }
|
.login-wrapper { position: relative; display: flex; flex-direction: row; margin-bottom: 60px; }
|
||||||
.page-header { margin-bottom: 20px; border-bottom: 1px solid #f0f0f0; padding-bottom: 15px; }
|
.login-card { display: flex; flex-direction: row; width: 800px; height: 480px; background-color: #fff; border-radius: 8px; overflow: hidden; box-shadow: 0 4px 24px rgba(0,0,0,0.1); }
|
||||||
.page-title { font-size: 16px; font-weight: bold; color: #303133; }
|
.login-aside { width: 320px; background: linear-gradient(135deg, #3a7bd5 0%, #00d2ff 100%); padding: 40px; color: #fff; }
|
||||||
.placeholder-text { font-size: 14px; color: #909399; }
|
.aside-title { font-size: 28px; font-weight: bold; margin-bottom: 12px; display: block; }
|
||||||
|
.aside-desc { font-size: 14px; opacity: 0.9; line-height: 1.6; }
|
||||||
|
.aside-illustration { margin-top: 60px; display: flex; justify-content: center; }
|
||||||
|
.illu-box { width: 160px; height: 160px; background-color: rgba(255,255,255,0.2); border-radius: 12px; position: relative; display: flex; flex-direction: column; align-items: center; justify-content: center; }
|
||||||
|
.illu-card { width: 80px; height: 100px; background-color: #fff; border-radius: 4px; padding: 10px; box-shadow: 0 4px 12px rgba(0,0,0,0.1); }
|
||||||
|
.illu-avatar { width: 30px; height: 30px; background-color: #e6f7ff; border-radius: 50%; margin: 0 auto 10px; }
|
||||||
|
.illu-line { height: 4px; background-color: #f0f0f0; border-radius: 2px; margin-bottom: 8px; }
|
||||||
|
.illu-line.short { width: 60%; }
|
||||||
|
.login-main { flex: 1; padding: 40px 60px; display: flex; flex-direction: column; }
|
||||||
|
.login-tabs { display: flex; flex-direction: row; margin-bottom: 40px; border-bottom: 1px solid #f0f0f0; }
|
||||||
|
.tab-item { margin-right: 32px; padding: 0 0 12px 0; cursor: pointer; position: relative; }
|
||||||
|
.tab-text { font-size: 18px; color: #909399; }
|
||||||
|
.tab-item.active .tab-text { color: #303133; font-weight: bold; }
|
||||||
|
.tab-item.active::after { content: ''; position: absolute; bottom: -1px; left: 0; right: 0; height: 2px; background-color: #2d8cf0; }
|
||||||
|
.login-form { display: flex; flex-direction: column; }
|
||||||
|
.form-item { margin-bottom: 24px; border-bottom: 1px solid #dcdfe6; padding-bottom: 8px; display: flex; flex-direction: row; align-items: center; }
|
||||||
|
.form-input { flex: 1; height: 36px; font-size: 14px; }
|
||||||
|
.forget-password { font-size: 14px; color: #2d8cf0; cursor: pointer; }
|
||||||
|
.sms-item .get-code { font-size: 14px; color: #2d8cf0; cursor: pointer; }
|
||||||
|
.form-agreement { margin-bottom: 30px; }
|
||||||
|
.agreement-label { display: flex; flex-direction: row; align-items: center; }
|
||||||
|
.agreement-cb { transform: scale(0.7); margin-right: 4px; }
|
||||||
|
.agreement-text { font-size: 12px; color: #909399; }
|
||||||
|
.agreement-link { font-size: 12px; color: #2d8cf0; cursor: pointer; }
|
||||||
|
.login-btn { width: 100%; height: 44px; background-color: #2d8cf0; color: #fff; border-radius: 4px; font-size: 16px; margin-bottom: 20px; }
|
||||||
|
.contact-box { display: flex; justify-content: center; }
|
||||||
|
.contact-text { font-size: 14px; color: #909399; cursor: pointer; }
|
||||||
|
.float-tabs { display: flex; flex-direction: column; margin-left: 1px; }
|
||||||
|
.float-tab { width: 44px; height: 90px; background-color: #f0f2f5; display: flex; flex-direction: column; align-items: center; justify-content: center; border-radius: 0 4px 4px 0; margin-bottom: 1px; cursor: pointer; }
|
||||||
|
.float-tab.active { background-color: #2d8cf0; }
|
||||||
|
.float-icon { font-size: 20px; color: #fff; margin-bottom: 8px; }
|
||||||
|
.float-icon.gray { color: #909399; }
|
||||||
|
.float-text { font-size: 12px; color: #fff; writing-mode: vertical-lr; letter-spacing: 2px; }
|
||||||
|
.float-text.gray { color: #909399; writing-mode: vertical-lr; }
|
||||||
|
.page-footer { display: flex; flex-direction: column; align-items: center; }
|
||||||
|
.footer-links { display: flex; flex-direction: row; margin-bottom: 12px; }
|
||||||
|
.footer-link { font-size: 14px; color: #909399; margin: 0 12px; }
|
||||||
|
.footer-copy { font-size: 12px; color: #c0c4cc; }
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -1,23 +1,145 @@
|
|||||||
<template>
|
<template>
|
||||||
<view class="admin-page-container">
|
<view class="admin-page-container">
|
||||||
<view class="page-card">
|
<view class="page-header">
|
||||||
<view class="page-header">
|
<view class="breadcrumb">
|
||||||
<text class="page-title">商城支付配置</text>
|
<text class="bc-item">设置</text>
|
||||||
|
<text class="bc-sep">/</text>
|
||||||
|
<text class="bc-item">接口配置</text>
|
||||||
|
<text class="bc-sep">/</text>
|
||||||
|
<text class="bc-item active">商城支付配置</text>
|
||||||
</view>
|
</view>
|
||||||
<view class="page-content">
|
</view>
|
||||||
<text class="placeholder-text">商城支付配置 页面开发中...</text>
|
<view class="content-card">
|
||||||
|
<view class="tabs-header">
|
||||||
|
<view :class="['tab-item', activeTab == 0 ? 'active' : '']" @click="activeTab = 0">
|
||||||
|
<text class="tab-text">基础配置</text>
|
||||||
|
</view>
|
||||||
|
<view :class="['tab-item', activeTab == 1 ? 'active' : '']" @click="activeTab = 1">
|
||||||
|
<text class="tab-text">微信支付配置</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 基础配置内容 -->
|
||||||
|
<view class="form-section" v-if="activeTab == 0">
|
||||||
|
<view class="form-content">
|
||||||
|
<view class="form-row">
|
||||||
|
<view class="form-label">余额支付:</view>
|
||||||
|
<view class="form-input-box">
|
||||||
|
<radio-group class="form-radio-group" @change="onBaseChange('balancePay', $event)">
|
||||||
|
<label class="radio-label"><radio value="1" :checked="form.base.balancePay == '1'" color="#2d8cf0" /><text class="radio-text">开启</text></label>
|
||||||
|
<label class="radio-label"><radio value="0" :checked="form.base.balancePay == '0'" color="#2d8cf0" /><text class="radio-text">关闭</text></label>
|
||||||
|
</radio-group>
|
||||||
|
<text class="form-tips">余额支付请选择开启或关闭</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="form-row">
|
||||||
|
<view class="form-label">好友代付:</view>
|
||||||
|
<view class="form-input-box">
|
||||||
|
<radio-group class="form-radio-group" @change="onBaseChange('friendPay', $event)">
|
||||||
|
<label class="radio-label"><radio value="1" :checked="form.base.friendPay == '1'" color="#2d8cf0" /><text class="radio-text">开启</text></label>
|
||||||
|
<label class="radio-label"><radio value="0" :checked="form.base.friendPay == '0'" color="#2d8cf0" /><text class="radio-text">关闭</text></label>
|
||||||
|
</radio-group>
|
||||||
|
<text class="form-tips">好友代付开关,关闭后付款类型不显示好友代付</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="form-actions" style="margin-top: 20px;">
|
||||||
|
<button class="submit-btn" type="primary" @click="handleSave">提交</button>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 微信支付配置内容 (保持之前版本) -->
|
||||||
|
<view class="form-section" v-if="activeTab == 1">
|
||||||
|
<view class="form-content extra-wide">
|
||||||
|
<view class="form-row">
|
||||||
|
<view class="form-label">支付接口类型:</view>
|
||||||
|
<view class="form-input-box">
|
||||||
|
<radio-group class="form-radio-group" @change="onWxRadioChange('vVersion', $event)">
|
||||||
|
<label class="radio-label"><radio value="v2" :checked="form.wx.vVersion == 'v2'" color="#2d8cf0" /><text class="radio-text">v2 (支持企业付款到零钱)</text></label>
|
||||||
|
<label class="radio-label"><radio value="v3" :checked="form.wx.vVersion == 'v3'" color="#2d8cf0" /><text class="radio-text">v3 (支持商户转账到零钱)</text></label>
|
||||||
|
</radio-group>
|
||||||
|
<text class="form-tips highlight">支付接口类型v2对应微信支付旧版v2支付。v3对应微信支付v3支付接口。支付证书可以通用一个,支付秘钥和v2旧版支付有区别</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="form-row">
|
||||||
|
<view class="form-label">证书序列号:</view>
|
||||||
|
<view class="form-input-box">
|
||||||
|
<input class="form-input max-width-input" v-model="form.wx.serialNo" placeholder="请输入证书序列号" />
|
||||||
|
<text class="form-tips">「商户API证书」的「证书序列号」,可以在证书管理里面查看</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="form-row">
|
||||||
|
<view class="form-label">微信自动提现场景值:</view>
|
||||||
|
<view class="form-input-box">
|
||||||
|
<input class="form-input max-width-input" v-model="form.wx.sceneValue" placeholder="1000" />
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="form-row">
|
||||||
|
<view class="form-label">v3支付Key:</view>
|
||||||
|
<view class="form-input-box">
|
||||||
|
<input class="form-input max-width-input" v-model="form.wx.v3Key" placeholder="V3支付秘钥" />
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="form-row">
|
||||||
|
<view class="form-label">Mchid:</view>
|
||||||
|
<view class="form-input-box">
|
||||||
|
<input class="form-input max-width-input" v-model="form.wx.mchid" placeholder="微信商户号" />
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="form-actions" style="margin-top: 20px;">
|
||||||
|
<button class="submit-btn" type="primary" @click="handleSave">提交</button>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="uts">
|
<script setup lang="uts">
|
||||||
|
import { ref, reactive } from 'vue'
|
||||||
|
const activeTab = ref(0)
|
||||||
|
const form = reactive({
|
||||||
|
base: {
|
||||||
|
balancePay: '1',
|
||||||
|
friendPay: '1'
|
||||||
|
},
|
||||||
|
wx: {
|
||||||
|
vVersion: 'v3',
|
||||||
|
serialNo: '2C79D0EF62EC9229C93D1017222EF7ED6CB4B88A',
|
||||||
|
sceneValue: '1000',
|
||||||
|
v3Key: 'wXID8YARmzbF126iBkpdCyLVz0o3GH95',
|
||||||
|
mchid: '1481090182'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
const onBaseChange = (key : string, e : any) => { form.base[key] = e.detail.value }
|
||||||
|
const onWxRadioChange = (key : string, e : any) => { form.wx[key] = e.detail.value }
|
||||||
|
const handleSave = () => { uni.showToast({ title: '提交成功' }) }
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.admin-page-container { padding: 20px; background-color: #f5f7f9; min-height: 100vh; }
|
.admin-page-container { min-height: 100vh; background-color: #f5f7f9; padding: 20px; }
|
||||||
.page-card { background-color: #fff; border-radius: 4px; padding: 20px; box-shadow: 0 1px 4px rgba(0,21,41,0.08); }
|
.breadcrumb { display: flex; flex-direction: row; margin-bottom: 20px; }
|
||||||
.page-header { margin-bottom: 20px; border-bottom: 1px solid #f0f0f0; padding-bottom: 15px; }
|
.bc-item { font-size: 14px; color: #999; }
|
||||||
.page-title { font-size: 16px; font-weight: bold; color: #303133; }
|
.bc-item.active { color: #333; }
|
||||||
.placeholder-text { font-size: 14px; color: #909399; }
|
.bc-sep { margin: 0 8px; color: #ccc; }
|
||||||
|
.content-card { background-color: #fff; border-radius: 4px; }
|
||||||
|
.tabs-header { display: flex; flex-direction: row; border-bottom: 1px solid #f0f0f0; padding: 0 30px; }
|
||||||
|
.tab-item { padding: 16px 20px; margin-right: 32px; border-bottom: 2px solid transparent; }
|
||||||
|
.tab-text { font-size: 14px; color: #666; }
|
||||||
|
.tab-item.active { border-bottom-color: #2d8cf0; }
|
||||||
|
.tab-item.active .tab-text { color: #2d8cf0; font-weight: bold; }
|
||||||
|
.form-section { padding: 30px; }
|
||||||
|
.form-content { max-width: 900px; }
|
||||||
|
.form-row { display: flex; flex-direction: row; margin-bottom: 24px; }
|
||||||
|
.form-label { width: 160px; font-size: 14px; color: #333; text-align: right; margin-right: 24px; padding-top: 8px; }
|
||||||
|
.form-input-box { flex: 1; }
|
||||||
|
.form-input { width: 100%; border: 1px solid #dcdfe6; border-radius: 4px; height: 34px; padding: 0 12px; font-size: 14px; }
|
||||||
|
.max-width-input { max-width: 450px; }
|
||||||
|
.form-tips { display: block; font-size: 12px; color: #999; margin-top: 10px; }
|
||||||
|
.highlight { color: #c0c4cc; }
|
||||||
|
.form-radio-group { display: flex; flex-direction: row; align-items: center; height: 34px; }
|
||||||
|
.radio-label { display: flex; flex-direction: row; align-items: center; margin-right: 24px; }
|
||||||
|
.radio-text { font-size: 14px; margin-left: 6px; }
|
||||||
|
.form-actions { padding-left: 184px; }
|
||||||
|
.submit-btn { width: 65px; height: 32px; background-color: #2d8cf0; color: #fff; border-radius: 4px; font-size: 14px; line-height: 32px; text-align: center; border: none; }
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -1,23 +1,277 @@
|
|||||||
<template>
|
<template>
|
||||||
<view class="admin-page-container">
|
<view class="admin-page-container">
|
||||||
<view class="page-card">
|
<view class="page-header">
|
||||||
<view class="page-header">
|
<view class="breadcrumb">
|
||||||
<text class="page-title">短信接口配置</text>
|
<text class="bc-item">设置</text>
|
||||||
|
<text class="bc-sep">/</text>
|
||||||
|
<text class="bc-item">接口配置</text>
|
||||||
|
<text class="bc-sep">/</text>
|
||||||
|
<text class="bc-item active">短信接口配置</text>
|
||||||
</view>
|
</view>
|
||||||
<view class="page-content">
|
</view>
|
||||||
<text class="placeholder-text">短信接口配置 页面开发中...</text>
|
<view class="content-card">
|
||||||
|
<view class="tabs-header">
|
||||||
|
<view :class="['tab-item', activeTab == 0 ? 'active' : '']" @click="activeTab = 0">
|
||||||
|
<text class="tab-text">基础配置</text>
|
||||||
|
</view>
|
||||||
|
<view :class="['tab-item', activeTab == 1 ? 'active' : '']" @click="activeTab = 1">
|
||||||
|
<text class="tab-text">阿里云配置</text>
|
||||||
|
</view>
|
||||||
|
<view :class="['tab-item', activeTab == 2 ? 'active' : '']" @click="activeTab = 2">
|
||||||
|
<text class="tab-text">腾讯云配置</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 基础配置 -->
|
||||||
|
<view class="form-section" v-if="activeTab == 0">
|
||||||
|
<view class="form-content">
|
||||||
|
<view class="form-row">
|
||||||
|
<view class="form-label">短信类型:</view>
|
||||||
|
<view class="form-input-box">
|
||||||
|
<radio-group class="form-radio-group" @change="onBaseChange('smsType', $event)">
|
||||||
|
<label class="radio-label"><radio value="onepass" :checked="form.base.smsType == 'onepass'" color="#2d8cf0" /><text class="radio-text">一号通</text></label>
|
||||||
|
<label class="radio-label"><radio value="aliyun" :checked="form.base.smsType == 'aliyun'" color="#2d8cf0" /><text class="radio-text">阿里云</text></label>
|
||||||
|
<label class="radio-label"><radio value="tencent" :checked="form.base.smsType == 'tencent'" color="#2d8cf0" /><text class="radio-text">腾讯云</text></label>
|
||||||
|
</radio-group>
|
||||||
|
<text class="form-tips">短信类型,选择发送的短信类型</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="form-actions" style="margin-top: 20px;">
|
||||||
|
<button class="submit-btn" type="primary" @click="handleSave">提交</button>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 阿里云配置 -->
|
||||||
|
<view class="form-section" v-if="activeTab == 1">
|
||||||
|
<view class="form-content">
|
||||||
|
<view class="form-row">
|
||||||
|
<view class="form-label">AccessKeyId:</view>
|
||||||
|
<view class="form-input-box">
|
||||||
|
<input class="form-input max-width-input" v-model="form.ali.ak" placeholder="请输入AccessKeyId" />
|
||||||
|
<text class="form-tips">阿里云AccessKeyId</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="form-row">
|
||||||
|
<view class="form-label">AccessKeySecret:</view>
|
||||||
|
<view class="form-input-box">
|
||||||
|
<input class="form-input max-width-input" v-model="form.ali.sk" placeholder="请输入AccessKeySecret" />
|
||||||
|
<text class="form-tips">阿里云AccessKeySecret</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="form-row">
|
||||||
|
<view class="form-label">短信签名:</view>
|
||||||
|
<view class="form-input-box">
|
||||||
|
<input class="form-input max-width-input" v-model="form.ali.sign" placeholder="请输入短信签名" />
|
||||||
|
<text class="form-tips">短信签名</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="form-actions" style="margin-top: 20px;">
|
||||||
|
<button class="submit-btn" type="primary" @click="handleSave">提交</button>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 腾讯云配置 -->
|
||||||
|
<view class="form-section" v-if="activeTab == 2">
|
||||||
|
<view class="form-content">
|
||||||
|
<view class="form-row">
|
||||||
|
<view class="form-label">SKD AppID:</view>
|
||||||
|
<view class="form-input-box">
|
||||||
|
<input class="form-input max-width-input" v-model="form.tencent.appId" placeholder="请输入SKD AppID" />
|
||||||
|
<text class="form-tips">腾讯云短信应用SKD APPID</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="form-row">
|
||||||
|
<view class="form-label">AccessKeyId:</view>
|
||||||
|
<view class="form-input-box">
|
||||||
|
<input class="form-input max-width-input" v-model="form.tencent.ak" placeholder="请输入AccessKeyId" />
|
||||||
|
<text class="form-tips">腾讯云AccessKeyId</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="form-row">
|
||||||
|
<view class="form-label">AccessKeySecret:</view>
|
||||||
|
<view class="form-input-box">
|
||||||
|
<input class="form-input max-width-input" v-model="form.tencent.sk" placeholder="请输入AccessKeySecret" />
|
||||||
|
<text class="form-tips">腾讯云AccessKeySecret</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="form-row">
|
||||||
|
<view class="form-label">腾讯云短信签名:</view>
|
||||||
|
<view class="form-input-box">
|
||||||
|
<input class="form-input max-width-input" v-model="form.tencent.sign" placeholder="请输入腾讯云短信签名" />
|
||||||
|
<text class="form-tips">腾讯云短信签名</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="form-row">
|
||||||
|
<view class="form-label">短信区域:</view>
|
||||||
|
<view class="form-input-box">
|
||||||
|
<input class="form-input max-width-input" v-model="form.tencent.region" placeholder="请输入短信区域" />
|
||||||
|
<text class="form-tips">短信区域ap-beijing、ap-guangzhou、ap-nanjing任选其一填写</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="form-actions" style="margin-top: 20px;">
|
||||||
|
<button class="submit-btn" type="primary" @click="handleSave">提交</button>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="uts">
|
<script setup lang="uts">
|
||||||
|
import { ref, reactive } from 'vue'
|
||||||
|
|
||||||
|
const activeTab = ref(0)
|
||||||
|
const form = reactive({
|
||||||
|
base: {
|
||||||
|
smsType: 'onepass'
|
||||||
|
},
|
||||||
|
ali: {
|
||||||
|
ak: '',
|
||||||
|
sk: '',
|
||||||
|
sign: ''
|
||||||
|
},
|
||||||
|
tencent: {
|
||||||
|
appId: '',
|
||||||
|
ak: '',
|
||||||
|
sk: '',
|
||||||
|
sign: '',
|
||||||
|
region: ''
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const onBaseChange = (key : string, e : any) => {
|
||||||
|
form.base[key] = e.detail.value
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleSave = () => {
|
||||||
|
uni.showToast({
|
||||||
|
title: '提交成功',
|
||||||
|
icon: 'success'
|
||||||
|
})
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.admin-page-container { padding: 20px; background-color: #f5f7f9; min-height: 100vh; }
|
.admin-page-container {
|
||||||
.page-card { background-color: #fff; border-radius: 4px; padding: 20px; box-shadow: 0 1px 4px rgba(0,21,41,0.08); }
|
min-height: 100vh;
|
||||||
.page-header { margin-bottom: 20px; border-bottom: 1px solid #f0f0f0; padding-bottom: 15px; }
|
background-color: #f5f7f9;
|
||||||
.page-title { font-size: 16px; font-weight: bold; color: #303133; }
|
padding: 20px;
|
||||||
.placeholder-text { font-size: 14px; color: #909399; }
|
}
|
||||||
|
.breadcrumb {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
.bc-item {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
.bc-item.active {
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
.bc-sep {
|
||||||
|
margin: 0 8px;
|
||||||
|
color: #ccc;
|
||||||
|
}
|
||||||
|
.content-card {
|
||||||
|
background-color: #fff;
|
||||||
|
border-radius: 4px;
|
||||||
|
box-shadow: 0 1px 4px rgba(0,21,41,.08);
|
||||||
|
}
|
||||||
|
.tabs-header {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
border-bottom: 1px solid #f0f0f0;
|
||||||
|
padding: 0 30px;
|
||||||
|
}
|
||||||
|
.tab-item {
|
||||||
|
padding: 16px 20px;
|
||||||
|
margin-right: 32px;
|
||||||
|
cursor: pointer;
|
||||||
|
border-bottom: 2px solid transparent;
|
||||||
|
}
|
||||||
|
.tab-text {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
.tab-item.active {
|
||||||
|
border-bottom-color: #2d8cf0;
|
||||||
|
}
|
||||||
|
.tab-item.active .tab-text {
|
||||||
|
color: #2d8cf0;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
.form-section {
|
||||||
|
padding: 30px;
|
||||||
|
}
|
||||||
|
.form-content {
|
||||||
|
max-width: 900px;
|
||||||
|
}
|
||||||
|
.form-row {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
margin-bottom: 24px;
|
||||||
|
}
|
||||||
|
.form-label {
|
||||||
|
width: 140px;
|
||||||
|
font-size: 14px;
|
||||||
|
color: #333;
|
||||||
|
text-align: right;
|
||||||
|
margin-right: 24px;
|
||||||
|
padding-top: 8px;
|
||||||
|
}
|
||||||
|
.form-input-box {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
.form-input {
|
||||||
|
width: 100%;
|
||||||
|
border: 1px solid #dcdfe6;
|
||||||
|
border-radius: 4px;
|
||||||
|
height: 34px;
|
||||||
|
padding: 0 12px;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
.max-width-input {
|
||||||
|
max-width: 450px;
|
||||||
|
}
|
||||||
|
.form-tips {
|
||||||
|
display: block;
|
||||||
|
font-size: 12px;
|
||||||
|
color: #999;
|
||||||
|
margin-top: 10px;
|
||||||
|
line-height: 1.6;
|
||||||
|
}
|
||||||
|
.form-radio-group {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
height: 34px;
|
||||||
|
}
|
||||||
|
.radio-label {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
margin-right: 24px;
|
||||||
|
}
|
||||||
|
.radio-text {
|
||||||
|
font-size: 14px;
|
||||||
|
margin-left: 6px;
|
||||||
|
color: #606266;
|
||||||
|
}
|
||||||
|
.form-actions {
|
||||||
|
padding-left: 164px;
|
||||||
|
}
|
||||||
|
.submit-btn {
|
||||||
|
width: 65px;
|
||||||
|
height: 32px;
|
||||||
|
background-color: #2d8cf0;
|
||||||
|
color: #fff;
|
||||||
|
border-radius: 4px;
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 32px;
|
||||||
|
text-align: center;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -1,23 +1,481 @@
|
|||||||
<template>
|
<template>
|
||||||
<view class="admin-page-container">
|
<view class="admin-page">
|
||||||
<view class="page-card">
|
<view class="page-header">
|
||||||
<view class="page-header">
|
<view class="breadcrumb">
|
||||||
<text class="page-title">系统存储配置</text>
|
<text class="bc-item">设置</text>
|
||||||
|
<text class="bc-sep">/</text>
|
||||||
|
<text class="bc-item">接口配置</text>
|
||||||
|
<text class="bc-sep">/</text>
|
||||||
|
<text class="bc-item active">系统存储配置</text>
|
||||||
</view>
|
</view>
|
||||||
<view class="page-content">
|
</view>
|
||||||
<text class="placeholder-text">系统存储配置 页面开发中...</text>
|
|
||||||
|
<view class="content-card">
|
||||||
|
<view class="tabs-header">
|
||||||
|
<scroll-view class="tabs-scroll" scroll-x="true" show-scrollbar="false">
|
||||||
|
<view class="tabs-list">
|
||||||
|
<view
|
||||||
|
v-for="(item, index) in tabs"
|
||||||
|
:key="index"
|
||||||
|
class="tab-item"
|
||||||
|
:class="{ active: activeTab === index }"
|
||||||
|
@click="activeTab = index"
|
||||||
|
>
|
||||||
|
<text class="tab-text">{{ item }}</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</scroll-view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="tab-body">
|
||||||
|
<!-- Tab 0: 储存配置 -->
|
||||||
|
<view v-if="activeTab === 0" class="config-view">
|
||||||
|
<view class="notice-box">
|
||||||
|
<view class="notice-content">
|
||||||
|
<text class="notice-line">上传图片时会生成缩略图</text>
|
||||||
|
<text class="notice-line">未设置按照系统默认生成,系统默认:大图800*800,中图300*300,小图150*150</text>
|
||||||
|
<text class="notice-line">水印只在上传图片时生成,原图,大中小缩略图都会按照比例存在。</text>
|
||||||
|
<text class="notice-line">若上传图片时未开启水印,则该图在开启水印之后依旧无水印效果。</text>
|
||||||
|
</view>
|
||||||
|
<text class="notice-close">×</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="form-body">
|
||||||
|
<view class="form-row">
|
||||||
|
<text class="form-label">存储方式:</text>
|
||||||
|
<view class="form-control">
|
||||||
|
<radio-group class="storage-radio-group" @change="onStorageTypeChange">
|
||||||
|
<label class="radio-label" v-for="st in storageOptions" :key="st.value">
|
||||||
|
<radio :value="st.value" :checked="form.storageType === st.value" color="#2d8cf0" style="transform:scale(0.8)" />
|
||||||
|
<text class="radio-text">{{ st.label }}</text>
|
||||||
|
</label>
|
||||||
|
</radio-group>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="form-row mt-30">
|
||||||
|
<text class="form-label">是否开启缩略图:</text>
|
||||||
|
<view class="form-control">
|
||||||
|
<switch :checked="form.enableThumb" @change="onToggleThumb" color="#2d8cf0" style="transform:scale(0.8)" />
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="form-row mt-30">
|
||||||
|
<text class="form-label">是否开启水印:</text>
|
||||||
|
<view class="form-control">
|
||||||
|
<switch :checked="form.enableWatermark" @change="onToggleWatermark" color="#2d8cf0" style="transform:scale(0.8)" />
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="form-footer mt-40">
|
||||||
|
<button class="save-btn" type="primary" @click="handleSave">保存</button>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- Tab 1-6: Cloud Storage -->
|
||||||
|
<view v-else class="cloud-view">
|
||||||
|
<view class="cloud-notice">
|
||||||
|
<view class="notice-title">
|
||||||
|
<text class="blue-title">{{ tabs[activeTab] }}开通方法:</text>
|
||||||
|
<text class="link-text">点击查看</text>
|
||||||
|
</view>
|
||||||
|
<text class="notice-step">第一步:添加【存储空间】(空间名称不能重复)</text>
|
||||||
|
<text class="notice-step">第二步:开启【使用状态】</text>
|
||||||
|
<text class="notice-step">第三步(可选):选择云存储空间列表上的修改【空间域名操作】</text>
|
||||||
|
<text class="notice-step">第四步(可选):选择云存储空间列表上的修改【CNAME配置】,打开后复制记录值到对应的平台解析</text>
|
||||||
|
<text class="notice-close">×</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="action-bar mt-20">
|
||||||
|
<view class="left-actions">
|
||||||
|
<button class="action-btn primary-btn">添加存储空间</button>
|
||||||
|
<button class="action-btn success-btn ml-10">同步存储空间</button>
|
||||||
|
</view>
|
||||||
|
<button class="action-btn outline-btn">修改配置信息</button>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="table-container mt-20">
|
||||||
|
<view class="table-header">
|
||||||
|
<text class="th flex-2">储存空间名称</text>
|
||||||
|
<text class="th flex-1">区域</text>
|
||||||
|
<text class="th flex-3">空间域名</text>
|
||||||
|
<text class="th flex-1">使用状态</text>
|
||||||
|
<text class="th flex-2">创建时间</text>
|
||||||
|
<text class="th flex-2">更新时间</text>
|
||||||
|
<text class="th flex-2 center">操作</text>
|
||||||
|
</view>
|
||||||
|
<view class="table-body">
|
||||||
|
<view v-if="getCloudData().length > 0">
|
||||||
|
<view
|
||||||
|
class="table-row"
|
||||||
|
v-for="(row, rIndex) in getCloudData()"
|
||||||
|
:key="rIndex"
|
||||||
|
>
|
||||||
|
<text class="td flex-2">{{ row.name }}</text>
|
||||||
|
<text class="td flex-1">{{ row.region }}</text>
|
||||||
|
<text class="td flex-3 link">{{ row.domain }}</text>
|
||||||
|
<view class="td flex-1">
|
||||||
|
<switch :checked="row.status" scale="0.6" color="#2d8cf0" />
|
||||||
|
</view>
|
||||||
|
<text class="td flex-2 small-text muted">{{ row.createTime }}</text>
|
||||||
|
<text class="td flex-2 small-text muted">{{ row.updateTime }}</text>
|
||||||
|
<view class="td flex-2 center-row">
|
||||||
|
<text class="op-link">CNAME配置</text>
|
||||||
|
<text class="op-link ml-10">修改空间域名</text>
|
||||||
|
<text class="op-link danger ml-10">删除</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view v-else class="empty-state">
|
||||||
|
<text class="empty-text">暂无数据</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="uts">
|
<script setup lang="uts">
|
||||||
|
import { ref, reactive } from 'vue'
|
||||||
|
|
||||||
|
const tabs = ['储存配置', '七牛云储存', '阿里云储存', '腾讯云储存', '京东云储存', '华为云储存', '天翼云储存']
|
||||||
|
const activeTab = ref(0)
|
||||||
|
|
||||||
|
const storageOptions = [
|
||||||
|
{ label: '本地存储', value: 'local' },
|
||||||
|
{ label: '七牛云存储', value: 'qiniu' },
|
||||||
|
{ label: '阿里云存储', value: 'aliyun' },
|
||||||
|
{ label: '腾讯云存储', value: 'tencent' },
|
||||||
|
{ label: '京东云存储', value: 'jd' },
|
||||||
|
{ label: '华为云存储', value: 'huawei' },
|
||||||
|
{ label: '天翼云存储', value: 'tianyi' }
|
||||||
|
]
|
||||||
|
|
||||||
|
const form = reactive({
|
||||||
|
storageType: 'local',
|
||||||
|
enableThumb: false,
|
||||||
|
enableWatermark: false
|
||||||
|
})
|
||||||
|
|
||||||
|
const onStorageTypeChange = (e : any) => {
|
||||||
|
form.storageType = e.detail.value as string
|
||||||
|
}
|
||||||
|
|
||||||
|
const onToggleThumb = (e : any) => {
|
||||||
|
form.enableThumb = e.detail.value as boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
const onToggleWatermark = (e : any) => {
|
||||||
|
form.enableWatermark = e.detail.value as boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleSave = () => {
|
||||||
|
uni.showToast({
|
||||||
|
title: '保存成功',
|
||||||
|
icon: 'success'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Simulated data for Aliyun Storage (based on screenshot)
|
||||||
|
const aliyunData = [
|
||||||
|
{ name: 'crmebdoc', region: '华北2 (北京)', domain: 'https://crmebdoc.oss-cn-beijing.aliyuncs.com', status: false, createTime: '2024-07-30 12:10:42', updateTime: '2025-01-22 10:58:20' },
|
||||||
|
{ name: 'crmebjavasingle', region: '华北2 (北京)', domain: 'https://crmebjavasingl...oss-cn-beijing.aliyunc...s.com', status: false, createTime: '2024-07-29 17:22:24', updateTime: '2025-01-22 10:58:20' },
|
||||||
|
{ name: 'crmebjavamer', region: '华北2 (北京)', domain: 'https://crmebjavamer.o...ss-cn-beijing.aliyuncs.c...om', status: false, createTime: '2024-07-22 14:43:42', updateTime: '2025-01-22 10:58:20' },
|
||||||
|
{ name: 'crmebmer', region: '华北2 (北京)', domain: 'https://crmebmer.oss-c...n-beijing.aliyuncs.com', status: false, createTime: '2024-07-22 14:42:53', updateTime: '2025-01-22 10:58:20' },
|
||||||
|
{ name: 'crmebmulti', region: '华北2 (北京)', domain: 'https://crmebmulti.oss-...cn-beijing.aliyuncs.com', status: false, createTime: '2024-07-22 14:42:08', updateTime: '2025-01-22 10:58:20' },
|
||||||
|
{ name: 'crmebpros', region: '华北2 (北京)', domain: 'https://crmebpros.oss-c...n-beijing.aliyuncs.com', status: false, createTime: '2024-07-22 14:41:17', updateTime: '2025-01-22 10:58:20' },
|
||||||
|
{ name: 'crmebbz', region: '华东1 (杭州)', domain: 'https://crmebbz.oss-cn-...hangzhou.aliyuncs.com', status: true, createTime: '2022-08-18 17:30:33', updateTime: '2025-01-22 10:58:20' }
|
||||||
|
]
|
||||||
|
|
||||||
|
const getCloudData = () : any[] => {
|
||||||
|
if (activeTab.value === 2) { // 阿里云
|
||||||
|
return aliyunData
|
||||||
|
}
|
||||||
|
return [] as any[]
|
||||||
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.admin-page-container { padding: 20px; background-color: #f5f7f9; min-height: 100vh; }
|
.admin-page {
|
||||||
.page-card { background-color: #fff; border-radius: 4px; padding: 20px; box-shadow: 0 1px 4px rgba(0,21,41,0.08); }
|
min-height: 100vh;
|
||||||
.page-header { margin-bottom: 20px; border-bottom: 1px solid #f0f0f0; padding-bottom: 15px; }
|
background-color: #f5f7f9;
|
||||||
.page-title { font-size: 16px; font-weight: bold; color: #303133; }
|
padding: 20px;
|
||||||
.placeholder-text { font-size: 14px; color: #909399; }
|
}
|
||||||
|
|
||||||
|
.breadcrumb {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bc-item {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bc-item.active {
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bc-sep {
|
||||||
|
margin: 0 8px;
|
||||||
|
color: #ccc;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content-card {
|
||||||
|
background-color: #ffffff;
|
||||||
|
border-radius: 4px;
|
||||||
|
box-shadow: 0 1px 4px rgba(0,21,41,.08);
|
||||||
|
}
|
||||||
|
|
||||||
|
.tabs-header {
|
||||||
|
border-bottom: 1px solid #f0f0f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tabs-scroll {
|
||||||
|
white-space: nowrap;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tabs-list {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
padding: 0 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-item {
|
||||||
|
padding: 15px 15px;
|
||||||
|
cursor: pointer;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-text {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-item.active .tab-text {
|
||||||
|
color: #2d8cf0;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-item.active::after {
|
||||||
|
content: "";
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0;
|
||||||
|
left: 15px;
|
||||||
|
right: 15px;
|
||||||
|
height: 2px;
|
||||||
|
background-color: #2d8cf0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-body {
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Notice Box Styles */
|
||||||
|
.notice-box {
|
||||||
|
background-color: #fffaf3;
|
||||||
|
border: 1px solid #ffebcc;
|
||||||
|
padding: 15px 20px;
|
||||||
|
border-radius: 4px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: space-between;
|
||||||
|
margin-bottom: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.notice-line {
|
||||||
|
font-size: 13px;
|
||||||
|
color: #666;
|
||||||
|
line-height: 1.8;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.notice-close {
|
||||||
|
color: #ccc;
|
||||||
|
font-size: 18px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Form Styles */
|
||||||
|
.form-body {
|
||||||
|
max-width: 800px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-row {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-label {
|
||||||
|
width: 140px;
|
||||||
|
font-size: 13px;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.storage-radio-group {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.radio-label {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
margin-right: 20px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.radio-text {
|
||||||
|
font-size: 13px;
|
||||||
|
margin-left: 4px;
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
|
||||||
|
.save-btn {
|
||||||
|
width: 80px;
|
||||||
|
height: 32px;
|
||||||
|
line-height: 32px;
|
||||||
|
background-color: #2d8cf0;
|
||||||
|
color: white;
|
||||||
|
font-size: 13px;
|
||||||
|
padding: 0;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mt-20 { margin-top: 20px; }
|
||||||
|
.mt-30 { margin-top: 30px; }
|
||||||
|
.mt-40 { margin-top: 40px; }
|
||||||
|
.ml-10 { margin-left: 10px; }
|
||||||
|
|
||||||
|
/* Cloud View Styles */
|
||||||
|
.cloud-notice {
|
||||||
|
background-color: #f0faff;
|
||||||
|
border: 1px solid #d5e8fc;
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 15px 20px;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.blue-title {
|
||||||
|
color: #2db7f5;
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.link-text {
|
||||||
|
color: #2d8cf0;
|
||||||
|
font-size: 14px;
|
||||||
|
margin-left: 10px;
|
||||||
|
cursor: pointer;
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
.notice-step {
|
||||||
|
display: block;
|
||||||
|
font-size: 13px;
|
||||||
|
color: #666;
|
||||||
|
line-height: 1.8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-bar {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
|
||||||
|
.left-actions {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-btn {
|
||||||
|
font-size: 12px;
|
||||||
|
height: 30px;
|
||||||
|
line-height: 30px;
|
||||||
|
padding: 0 12px;
|
||||||
|
border-radius: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.primary-btn { background-color: #2d8cf0; color: white; border: none; }
|
||||||
|
.success-btn { background-color: #19be6b; color: white; border: none; }
|
||||||
|
.outline-btn { background-color: white; color: #666; border: 1px solid #dcdee2; }
|
||||||
|
|
||||||
|
/* Table Styles */
|
||||||
|
.table-container {
|
||||||
|
border: 1px solid #f0f0f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-header {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
background-color: #f8f8f9;
|
||||||
|
border-bottom: 1px solid #f0f0f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.th {
|
||||||
|
padding: 12px 10px;
|
||||||
|
font-size: 13px;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-row {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
border-bottom: 1px solid #f0f0f0;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.td {
|
||||||
|
padding: 12px 10px;
|
||||||
|
font-size: 13px;
|
||||||
|
color: #666;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.flex-1 { flex: 1; }
|
||||||
|
.flex-2 { flex: 2; }
|
||||||
|
.flex-3 { flex: 3; }
|
||||||
|
.center { justify-content: center; }
|
||||||
|
.center-row { justify-content: center; }
|
||||||
|
|
||||||
|
.link {
|
||||||
|
color: #2d8cf0;
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
.small-text { font-size: 11px; }
|
||||||
|
.muted { color: #999; }
|
||||||
|
|
||||||
|
.op-link {
|
||||||
|
color: #2d8cf0;
|
||||||
|
font-size: 12px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.op-link.danger {
|
||||||
|
color: #ed4014;
|
||||||
|
}
|
||||||
|
|
||||||
|
.empty-state {
|
||||||
|
padding: 40px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.empty-text {
|
||||||
|
color: #ccc;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
|||||||
@@ -1,23 +1,238 @@
|
|||||||
<template>
|
<template>
|
||||||
<view class="admin-page-container">
|
<view class="admin-page message-management">
|
||||||
<view class="page-card">
|
<view class="admin-sections">
|
||||||
<view class="page-header">
|
<view class="admin-card">
|
||||||
<text class="page-title">消息管理</text>
|
<!-- 标签页 -->
|
||||||
</view>
|
<view class="tabs-container">
|
||||||
<view class="page-content">
|
<view class="tabs-bar">
|
||||||
<text class="placeholder-text">消息管理 页面开发中...</text>
|
<view
|
||||||
</view>
|
class="tab-item"
|
||||||
</view>
|
:class="{ active: currentTab === 0 }"
|
||||||
</view>
|
@click="currentTab = 0"
|
||||||
</template>
|
>
|
||||||
|
<text class="tab-text">会员通知</text>
|
||||||
|
<view class="tab-line" v-if="currentTab === 0"></view>
|
||||||
|
</view>
|
||||||
|
<view
|
||||||
|
class="tab-item"
|
||||||
|
:class="{ active: currentTab === 1 }"
|
||||||
|
@click="currentTab = 1"
|
||||||
|
>
|
||||||
|
<text class="tab-text">平台通知</text>
|
||||||
|
<view class="tab-line" v-if="currentTab === 1"></view>
|
||||||
|
</view>
|
||||||
|
<view
|
||||||
|
class="tab-item"
|
||||||
|
:class="{ active: currentTab === 2 }"
|
||||||
|
@click="currentTab = 2"
|
||||||
|
>
|
||||||
|
<text class="tab-text">自定义通知</text>
|
||||||
|
<view class="tab-line" v-if="currentTab === 2"></view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 顶部操作 -->
|
||||||
|
<view class="top-actions">
|
||||||
|
<button class="btn btn-primary" @click="syncMiniProgram">同步小程序订阅消息</button>
|
||||||
|
<button class="btn btn-primary ml-10" @click="syncWechat">同步微信模板消息</button>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 提示信息 -->
|
||||||
|
<view class="alert-info">
|
||||||
|
<text class="alert-title">小程序订阅消息</text>
|
||||||
|
<text class="alert-desc">登录微信小程序后台,基本设置,服务类目增加《生活服务 > 百货/超市/便利店》(否则同步小程序订阅消息会报错)</text>
|
||||||
|
<text class="alert-desc">同步小程序订阅消息,是在小程序后台未添加订阅消息模板的前提下使用的,会新增一个模板消息并把信息同步过来,并非本项目数据库。</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 数据表格 -->
|
||||||
|
<view class="table-container">
|
||||||
|
<view class="table-header">
|
||||||
|
<view class="table-cell" style="flex: 0 0 60px;">ID</view>
|
||||||
|
<view class="table-cell" style="flex: 2;">通知类型</view>
|
||||||
|
<view class="table-cell" style="flex: 3;">通知场景说明</view>
|
||||||
|
<view class="table-cell" style="flex: 1;">站内信</view>
|
||||||
|
<view class="table-cell" style="flex: 1.5;">公众号模板</view>
|
||||||
|
<view class="table-cell" style="flex: 1;">发送短信</view>
|
||||||
|
<view class="table-cell" style="flex: 1.5;">小程序订阅</view>
|
||||||
|
<view class="table-cell action-cell" style="flex: 1;">操作</view>
|
||||||
|
</view>
|
||||||
|
<view class="table-body">
|
||||||
|
<view class="table-row" v-for="(item, index) in messageList" :key="index">
|
||||||
|
<view class="table-cell" style="flex: 0 0 60px;">{{ item.id }}</view>
|
||||||
|
<view class="table-cell" style="flex: 2;">{{ item.type }}</view>
|
||||||
|
<view class="table-cell" style="flex: 3;">{{ item.desc }}</view>
|
||||||
|
<view class="table-cell" style="flex: 1;">
|
||||||
|
<switch color="#1890ff" :checked="item.is_msg" style="transform: scale(0.7);" />
|
||||||
|
</view>
|
||||||
|
<view class="table-cell" style="flex: 1.5;">
|
||||||
|
<switch color="#1890ff" :checked="item.is_wechat" style="transform: scale(0.7);" />
|
||||||
|
</view>
|
||||||
|
<view class="table-cell" style="flex: 1;">
|
||||||
|
<switch color="#1890ff" :checked="item.is_sms" style="transform: scale(0.7);" />
|
||||||
|
</view>
|
||||||
|
<view class="table-cell" style="flex: 1.5;">
|
||||||
|
<switch color="#1890ff" :checked="item.is_mini" style="transform: scale(0.7);" />
|
||||||
|
</view>
|
||||||
|
<view class="table-cell action-cell" style="flex: 1;">
|
||||||
|
<text class="action-link" @click="handleSet(item)">设置</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view></template>
|
||||||
<script setup lang="uts">
|
<script setup lang="uts">
|
||||||
|
import { ref } from 'vue'
|
||||||
|
|
||||||
|
const currentTab = ref(0)
|
||||||
|
const messageList = ref([
|
||||||
|
{ id: 1, type: '短信验证码', desc: '短信验证码', is_msg: false, is_wechat: false, is_sms: true, is_mini: false },
|
||||||
|
{ id: 2, type: '绑定推广关系消息', desc: '绑定推广关系消息', is_msg: true, is_wechat: false, is_sms: false, is_mini: false },
|
||||||
|
{ id: 3, type: '支付成功提醒消息', desc: '支付成功提醒消息', is_msg: true, is_wechat: true, is_sms: true, is_mini: true },
|
||||||
|
{ id: 4, type: '发货提醒消息', desc: '发货提醒消息', is_msg: true, is_wechat: true, is_sms: true, is_mini: true },
|
||||||
|
{ id: 5, type: '送货提醒消息', desc: '送货提醒消息', is_msg: true, is_wechat: true, is_sms: false, is_mini: true },
|
||||||
|
{ id: 6, type: '确认收货提醒消息', desc: '确认收货提醒消息', is_msg: true, is_wechat: true, is_sms: false, is_mini: true },
|
||||||
|
{ id: 7, type: '退款成功提醒消息', desc: '退款成功提醒消息', is_msg: true, is_wechat: true, is_sms: false, is_mini: true },
|
||||||
|
{ id: 8, type: '退款失败提醒消息', desc: '退款失败提醒消息', is_msg: true, is_wechat: true, is_sms: false, is_mini: true },
|
||||||
|
{ id: 9, type: '改价提醒消息', desc: '改价提醒消息', is_msg: true, is_wechat: true, is_sms: false, is_mini: true },
|
||||||
|
{ id: 10, type: '未付款提醒消息', desc: '未付款提醒消息', is_msg: true, is_wechat: true, is_sms: false, is_mini: true }
|
||||||
|
])
|
||||||
|
|
||||||
|
function syncMiniProgram() {
|
||||||
|
uni.showToast({ title: '同步小程序订阅消息', icon: 'none' })
|
||||||
|
}
|
||||||
|
|
||||||
|
function syncWechat() {
|
||||||
|
uni.showToast({ title: '同步微信模板消息', icon: 'none' })
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleSet(item: any) {
|
||||||
|
uni.showToast({ title: '设置: ' + item.type, icon: 'none' })
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.admin-page-container { padding: 20px; background-color: #f5f7f9; min-height: 100vh; }
|
.message-management {
|
||||||
.page-card { background-color: #fff; border-radius: 4px; padding: 20px; box-shadow: 0 1px 4px rgba(0,21,41,0.08); }
|
padding: 20px;
|
||||||
.page-header { margin-bottom: 20px; border-bottom: 1px solid #f0f0f0; padding-bottom: 15px; }
|
background-color: #f5f7f9;
|
||||||
.page-title { font-size: 16px; font-weight: bold; color: #303133; }
|
}
|
||||||
.placeholder-text { font-size: 14px; color: #909399; }
|
|
||||||
|
.admin-card {
|
||||||
|
background-color: #fff;
|
||||||
|
padding: 24px;
|
||||||
|
border-radius: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tabs-container {
|
||||||
|
border-bottom: 1px solid #f0f0f0;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tabs-bar {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-item {
|
||||||
|
padding: 12px 20px;
|
||||||
|
position: relative;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-item.active {
|
||||||
|
color: #1890ff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-text {
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-line {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
height: 2px;
|
||||||
|
background-color: #1890ff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.top-actions {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn {
|
||||||
|
height: 32px;
|
||||||
|
line-height: 32px;
|
||||||
|
font-size: 14px;
|
||||||
|
padding: 0 15px;
|
||||||
|
border-radius: 4px;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-primary {
|
||||||
|
background-color: #1890ff;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.alert-info {
|
||||||
|
background-color: #fff7e6;
|
||||||
|
border: 1px solid #ffd591;
|
||||||
|
padding: 15px;
|
||||||
|
border-radius: 4px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.alert-title {
|
||||||
|
color: #fa8c16;
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 14px;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.alert-desc {
|
||||||
|
color: #666;
|
||||||
|
font-size: 13px;
|
||||||
|
line-height: 1.6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-container {
|
||||||
|
border: 1px solid #f0f0f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-header {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
background-color: #f8f8f9;
|
||||||
|
border-bottom: 1px solid #f0f0f0;
|
||||||
|
padding: 12px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-row {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
border-bottom: 1px solid #f0f0f0;
|
||||||
|
padding: 12px 0;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-cell {
|
||||||
|
font-size: 13px;
|
||||||
|
color: #666;
|
||||||
|
padding: 0 10px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-link {
|
||||||
|
color: #1890ff;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ml-10 {
|
||||||
|
margin-left: 10px;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
|||||||
@@ -1,23 +1,256 @@
|
|||||||
<template>
|
<template>
|
||||||
<view class="admin-page-container">
|
<view class="admin-page ticket-config">
|
||||||
<view class="page-card">
|
<view class="admin-sections">
|
||||||
<view class="page-header">
|
<view class="admin-card">
|
||||||
<text class="page-title">客服设置</text>
|
<!-- 搜索和添加 -->
|
||||||
</view>
|
<view class="header-tools">
|
||||||
<view class="page-content">
|
<view class="search-form">
|
||||||
<text class="placeholder-text">客服设置 页面开发中...</text>
|
<view class="form-item">
|
||||||
</view>
|
<text class="label">打印机名称:</text>
|
||||||
</view>
|
<input class="search-input" v-model="searchQuery.name" placeholder="请输入打印机名称" />
|
||||||
</view>
|
</view>
|
||||||
</template>
|
<view class="form-item ml-20">
|
||||||
|
<text class="label">平台选择:</text>
|
||||||
|
<picker :range="platforms" @change="onPlatformChange">
|
||||||
|
<view class="picker-view">{{ platforms[selectedPlatform] }}</view>
|
||||||
|
</picker>
|
||||||
|
</view>
|
||||||
|
<button class="btn-search ml-20" @click="handleSearch">查询</button>
|
||||||
|
</view>
|
||||||
|
<button class="btn-primary" @click="handleAdd">添加打印机</button>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 数据表格 -->
|
||||||
|
<view class="table-container">
|
||||||
|
<view class="table-header">
|
||||||
|
<view class="table-cell" style="flex: 0 0 60px;">ID</view>
|
||||||
|
<view class="table-cell" style="flex: 2;">打印机名称</view>
|
||||||
|
<view class="table-cell" style="flex: 1.5;">平台</view>
|
||||||
|
<view class="table-cell" style="flex: 1.5;">应用账号</view>
|
||||||
|
<view class="table-cell" style="flex: 1;">打印联数</view>
|
||||||
|
<view class="table-cell" style="flex: 2;">创建时间</view>
|
||||||
|
<view class="table-cell" style="flex: 1;">打印开关</view>
|
||||||
|
<view class="table-cell action-cell" style="flex: 2;">操作</view>
|
||||||
|
</view>
|
||||||
|
<view class="table-body">
|
||||||
|
<view class="table-row" v-for="(item, index) in printerList" :key="index">
|
||||||
|
<view class="table-cell" style="flex: 0 0 60px;">{{ item.id }}</view>
|
||||||
|
<view class="table-cell" style="flex: 2;">{{ item.name }}</view>
|
||||||
|
<view class="table-cell" style="flex: 1.5;">{{ item.platform }}</view>
|
||||||
|
<view class="table-cell" style="flex: 1.5;">{{ item.account }}</view>
|
||||||
|
<view class="table-cell" style="flex: 1;">{{ item.copies }}</view>
|
||||||
|
<view class="table-cell" style="flex: 2;">{{ item.add_time }}</view>
|
||||||
|
<view class="table-cell" style="flex: 1;">
|
||||||
|
<switch color="#1890ff" :checked="item.status" style="transform: scale(0.7);" />
|
||||||
|
</view>
|
||||||
|
<view class="table-cell action-cell" style="flex: 2;">
|
||||||
|
<text class="action-link" @click="handleDesign(item)">设计</text>
|
||||||
|
<text class="action-link ml-10" @click="handleEdit(item)">编辑</text>
|
||||||
|
<text class="action-link link-danger ml-10" @click="handleDelete(item)">删除</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 分页 (模拟) -->
|
||||||
|
<view class="pagination">
|
||||||
|
<text class="total">共 1 条</text>
|
||||||
|
<picker :range="['15条/页', '30条/页']">
|
||||||
|
<view class="page-size">15条/页</view>
|
||||||
|
</picker>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view></template>
|
||||||
<script setup lang="uts">
|
<script setup lang="uts">
|
||||||
|
import { ref } from 'vue'
|
||||||
|
|
||||||
|
const searchQuery = ref({ name: '' })
|
||||||
|
const platforms = ['全部', '易联云', '飞鹅打印机']
|
||||||
|
const selectedPlatform = ref(0)
|
||||||
|
|
||||||
|
const printerList = ref([
|
||||||
|
{ id: 1, name: '一号打印', platform: '易联云', account: '222', copies: 1, add_time: '2024-12-11 15:12:58', status: true }
|
||||||
|
])
|
||||||
|
|
||||||
|
function onPlatformChange(e: any) {
|
||||||
|
selectedPlatform.value = e.detail.value
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleSearch() {
|
||||||
|
uni.showToast({ title: '查询中...', icon: 'none' })
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleAdd() {
|
||||||
|
uni.showToast({ title: '添加打印机', icon: 'none' })
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleDesign(item: any) {
|
||||||
|
uni.showToast({ title: '打印设计: ' + item.name, icon: 'none' })
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleEdit(item: any) {
|
||||||
|
uni.showToast({ title: '编辑打印机: ' + item.name, icon: 'none' })
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleDelete(item: any) {
|
||||||
|
uni.showModal({
|
||||||
|
title: '提示',
|
||||||
|
content: '确定删除该打印机吗?',
|
||||||
|
success: (res) => {
|
||||||
|
if (res.confirm) {
|
||||||
|
uni.showToast({ title: '已删除', icon: 'success' })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.admin-page-container { padding: 20px; background-color: #f5f7f9; min-height: 100vh; }
|
.ticket-config {
|
||||||
.page-card { background-color: #fff; border-radius: 4px; padding: 20px; box-shadow: 0 1px 4px rgba(0,21,41,0.08); }
|
padding: 20px;
|
||||||
.page-header { margin-bottom: 20px; border-bottom: 1px solid #f0f0f0; padding-bottom: 15px; }
|
background-color: #f5f7f9;
|
||||||
.page-title { font-size: 16px; font-weight: bold; color: #303133; }
|
}
|
||||||
.placeholder-text { font-size: 14px; color: #909399; }
|
|
||||||
|
.admin-card {
|
||||||
|
background-color: #fff;
|
||||||
|
padding: 24px;
|
||||||
|
border-radius: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header-tools {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-form {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-item {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.label {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-input {
|
||||||
|
width: 180px;
|
||||||
|
height: 32px;
|
||||||
|
border: 1px solid #d9d9d9;
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 0 12px;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.picker-view {
|
||||||
|
width: 120px;
|
||||||
|
height: 32px;
|
||||||
|
line-height: 32px;
|
||||||
|
border: 1px solid #d9d9d9;
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 0 12px;
|
||||||
|
font-size: 14px;
|
||||||
|
background-color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-search {
|
||||||
|
background-color: #1890ff;
|
||||||
|
color: #fff;
|
||||||
|
height: 32px;
|
||||||
|
line-height: 32px;
|
||||||
|
padding: 0 15px;
|
||||||
|
font-size: 14px;
|
||||||
|
border: none;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-primary {
|
||||||
|
background-color: #1890ff;
|
||||||
|
color: #fff;
|
||||||
|
height: 32px;
|
||||||
|
line-height: 32px;
|
||||||
|
padding: 0 15px;
|
||||||
|
font-size: 14px;
|
||||||
|
border: none;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-container {
|
||||||
|
border: 1px solid #f0f0f0;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-header {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
background-color: #f8f8f9;
|
||||||
|
border-bottom: 1px solid #f0f0f0;
|
||||||
|
padding: 12px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-row {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
border-bottom: 1px solid #f0f0f0;
|
||||||
|
padding: 12px 0;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-cell {
|
||||||
|
font-size: 13px;
|
||||||
|
color: #666;
|
||||||
|
padding: 0 10px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-link {
|
||||||
|
color: #1890ff;
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.link-danger {
|
||||||
|
color: #ff4d4f;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pagination {
|
||||||
|
margin-top: 20px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: flex-end;
|
||||||
|
align-items: center;
|
||||||
|
gap: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.total {
|
||||||
|
font-size: 13px;
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-size {
|
||||||
|
font-size: 13px;
|
||||||
|
color: #666;
|
||||||
|
border: 1px solid #d9d9d9;
|
||||||
|
padding: 2px 10px;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ml-20 {
|
||||||
|
margin-left: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ml-10 {
|
||||||
|
margin-left: 10px;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
|||||||
641
pages/mall/admin/错误信息.txt
Normal file
641
pages/mall/admin/错误信息.txt
Normal file
@@ -0,0 +1,641 @@
|
|||||||
|
adminComponentMap.uts:194 GET http://localhost:5173/pages/mall/admin/maintain/dev-tools/file.uvue?t=1770810007330&import net::ERR_ABORTED 500 (Internal Server Error)
|
||||||
|
(anonymous) @ adminComponentMap.uts:194
|
||||||
|
load @ vue.runtime.esm.js:3681
|
||||||
|
setup @ vue.runtime.esm.js:3760
|
||||||
|
callWithErrorHandling @ vue.runtime.esm.js:1381
|
||||||
|
setupStatefulComponent @ vue.runtime.esm.js:8985
|
||||||
|
setupComponent @ vue.runtime.esm.js:8946
|
||||||
|
mountComponent @ vue.runtime.esm.js:7262
|
||||||
|
processComponent @ vue.runtime.esm.js:7228
|
||||||
|
patch @ vue.runtime.esm.js:6694
|
||||||
|
patchKeyedChildren @ vue.runtime.esm.js:7783
|
||||||
|
patchChildren @ vue.runtime.esm.js:7564
|
||||||
|
processFragment @ vue.runtime.esm.js:7202
|
||||||
|
patch @ vue.runtime.esm.js:6668
|
||||||
|
patchKeyedChildren @ vue.runtime.esm.js:7650
|
||||||
|
patchChildren @ vue.runtime.esm.js:7564
|
||||||
|
patchElement @ vue.runtime.esm.js:6989
|
||||||
|
processElement @ vue.runtime.esm.js:6825
|
||||||
|
patch @ vue.runtime.esm.js:6682
|
||||||
|
componentUpdateFn @ vue.runtime.esm.js:7453
|
||||||
|
run @ vue.runtime.esm.js:153
|
||||||
|
instance.update @ vue.runtime.esm.js:7497
|
||||||
|
callWithErrorHandling @ vue.runtime.esm.js:1381
|
||||||
|
flushJobs @ vue.runtime.esm.js:1585
|
||||||
|
Promise.then
|
||||||
|
queueFlush @ vue.runtime.esm.js:1494
|
||||||
|
queueJob @ vue.runtime.esm.js:1488
|
||||||
|
(anonymous) @ vue.runtime.esm.js:7491
|
||||||
|
resetScheduling @ vue.runtime.esm.js:236
|
||||||
|
triggerEffects @ vue.runtime.esm.js:280
|
||||||
|
triggerRefValue @ vue.runtime.esm.js:1033
|
||||||
|
set value @ vue.runtime.esm.js:1078
|
||||||
|
(anonymous) @ AdminLayout.uvue:263
|
||||||
|
setTimeout
|
||||||
|
watch.immediate @ AdminLayout.uvue:262
|
||||||
|
callWithErrorHandling @ vue.runtime.esm.js:1381
|
||||||
|
callWithAsyncErrorHandling @ vue.runtime.esm.js:1388
|
||||||
|
job @ vue.runtime.esm.js:3157
|
||||||
|
callWithErrorHandling @ vue.runtime.esm.js:1381
|
||||||
|
flushJobs @ vue.runtime.esm.js:1585
|
||||||
|
Promise.then
|
||||||
|
queueFlush @ vue.runtime.esm.js:1494
|
||||||
|
queueJob @ vue.runtime.esm.js:1488
|
||||||
|
scheduler @ vue.runtime.esm.js:3179
|
||||||
|
resetScheduling @ vue.runtime.esm.js:236
|
||||||
|
triggerEffects @ vue.runtime.esm.js:280
|
||||||
|
triggerRefValue @ vue.runtime.esm.js:1033
|
||||||
|
set value @ vue.runtime.esm.js:1078
|
||||||
|
openRoute @ adminNavStore.uts:87
|
||||||
|
onSubClick @ AdminLayout.uvue:318
|
||||||
|
callWithErrorHandling @ vue.runtime.esm.js:1381
|
||||||
|
callWithAsyncErrorHandling @ vue.runtime.esm.js:1388
|
||||||
|
emit @ vue.runtime.esm.js:1907
|
||||||
|
(anonymous) @ vue.runtime.esm.js:9176
|
||||||
|
handleNodeClick @ AdminSubSider.uvue:116
|
||||||
|
onClick @ AdminSubSider.uvue?import:112
|
||||||
|
callWithErrorHandling @ vue.runtime.esm.js:1381
|
||||||
|
callWithAsyncErrorHandling @ vue.runtime.esm.js:1388
|
||||||
|
invoker @ vue.runtime.esm.js:10253
|
||||||
|
AdminLayout.uvue:263 [Vue warn]: Unhandled error during execution of async component loader
|
||||||
|
at <AsyncComponentWrapper>
|
||||||
|
at <View>
|
||||||
|
at <View>
|
||||||
|
at <View>
|
||||||
|
at <View>
|
||||||
|
at <AdminLayout>
|
||||||
|
at <View>
|
||||||
|
at <Index>
|
||||||
|
at <AsyncComponentWrapper>
|
||||||
|
at <PageBody>
|
||||||
|
at <Page>
|
||||||
|
at <Anonymous>
|
||||||
|
at <KeepAlive>
|
||||||
|
at <RouterView>
|
||||||
|
at <Layout>
|
||||||
|
at <App>
|
||||||
|
warnHandler @ uni-h5.es.js:19975
|
||||||
|
callWithErrorHandling @ vue.runtime.esm.js:1381
|
||||||
|
warn$1 @ vue.runtime.esm.js:1207
|
||||||
|
logError @ vue.runtime.esm.js:1438
|
||||||
|
errorHandler @ uni-h5.es.js:19600
|
||||||
|
callWithErrorHandling @ vue.runtime.esm.js:1381
|
||||||
|
handleError @ vue.runtime.esm.js:1421
|
||||||
|
onError @ vue.runtime.esm.js:3724
|
||||||
|
(anonymous) @ vue.runtime.esm.js:3767
|
||||||
|
Promise.catch
|
||||||
|
setup @ vue.runtime.esm.js:3766
|
||||||
|
callWithErrorHandling @ vue.runtime.esm.js:1381
|
||||||
|
setupStatefulComponent @ vue.runtime.esm.js:8985
|
||||||
|
setupComponent @ vue.runtime.esm.js:8946
|
||||||
|
mountComponent @ vue.runtime.esm.js:7262
|
||||||
|
processComponent @ vue.runtime.esm.js:7228
|
||||||
|
patch @ vue.runtime.esm.js:6694
|
||||||
|
patchKeyedChildren @ vue.runtime.esm.js:7783
|
||||||
|
patchChildren @ vue.runtime.esm.js:7564
|
||||||
|
processFragment @ vue.runtime.esm.js:7202
|
||||||
|
patch @ vue.runtime.esm.js:6668
|
||||||
|
patchKeyedChildren @ vue.runtime.esm.js:7650
|
||||||
|
patchChildren @ vue.runtime.esm.js:7564
|
||||||
|
patchElement @ vue.runtime.esm.js:6989
|
||||||
|
processElement @ vue.runtime.esm.js:6825
|
||||||
|
patch @ vue.runtime.esm.js:6682
|
||||||
|
componentUpdateFn @ vue.runtime.esm.js:7453
|
||||||
|
run @ vue.runtime.esm.js:153
|
||||||
|
instance.update @ vue.runtime.esm.js:7497
|
||||||
|
callWithErrorHandling @ vue.runtime.esm.js:1381
|
||||||
|
flushJobs @ vue.runtime.esm.js:1585
|
||||||
|
Promise.then
|
||||||
|
queueFlush @ vue.runtime.esm.js:1494
|
||||||
|
queueJob @ vue.runtime.esm.js:1488
|
||||||
|
(anonymous) @ vue.runtime.esm.js:7491
|
||||||
|
resetScheduling @ vue.runtime.esm.js:236
|
||||||
|
triggerEffects @ vue.runtime.esm.js:280
|
||||||
|
triggerRefValue @ vue.runtime.esm.js:1033
|
||||||
|
set value @ vue.runtime.esm.js:1078
|
||||||
|
(anonymous) @ AdminLayout.uvue:263
|
||||||
|
setTimeout
|
||||||
|
watch.immediate @ AdminLayout.uvue:262
|
||||||
|
callWithErrorHandling @ vue.runtime.esm.js:1381
|
||||||
|
callWithAsyncErrorHandling @ vue.runtime.esm.js:1388
|
||||||
|
job @ vue.runtime.esm.js:3157
|
||||||
|
callWithErrorHandling @ vue.runtime.esm.js:1381
|
||||||
|
flushJobs @ vue.runtime.esm.js:1585
|
||||||
|
Promise.then
|
||||||
|
queueFlush @ vue.runtime.esm.js:1494
|
||||||
|
queueJob @ vue.runtime.esm.js:1488
|
||||||
|
scheduler @ vue.runtime.esm.js:3179
|
||||||
|
resetScheduling @ vue.runtime.esm.js:236
|
||||||
|
triggerEffects @ vue.runtime.esm.js:280
|
||||||
|
triggerRefValue @ vue.runtime.esm.js:1033
|
||||||
|
set value @ vue.runtime.esm.js:1078
|
||||||
|
openRoute @ adminNavStore.uts:87
|
||||||
|
onSubClick @ AdminLayout.uvue:318
|
||||||
|
callWithErrorHandling @ vue.runtime.esm.js:1381
|
||||||
|
callWithAsyncErrorHandling @ vue.runtime.esm.js:1388
|
||||||
|
emit @ vue.runtime.esm.js:1907
|
||||||
|
(anonymous) @ vue.runtime.esm.js:9176
|
||||||
|
handleNodeClick @ AdminSubSider.uvue:116
|
||||||
|
onClick @ AdminSubSider.uvue?import:112
|
||||||
|
callWithErrorHandling @ vue.runtime.esm.js:1381
|
||||||
|
callWithAsyncErrorHandling @ vue.runtime.esm.js:1388
|
||||||
|
invoker @ vue.runtime.esm.js:10253
|
||||||
|
AdminLayout.uvue:263 TypeError: Failed to fetch dynamically imported module: http://localhost:5173/pages/mall/admin/maintain/dev-tools/file.uvue?t=1770810007330&import
|
||||||
|
logError @ vue.runtime.esm.js:1443
|
||||||
|
errorHandler @ uni-h5.es.js:19600
|
||||||
|
callWithErrorHandling @ vue.runtime.esm.js:1381
|
||||||
|
handleError @ vue.runtime.esm.js:1421
|
||||||
|
onError @ vue.runtime.esm.js:3724
|
||||||
|
(anonymous) @ vue.runtime.esm.js:3767
|
||||||
|
Promise.catch
|
||||||
|
setup @ vue.runtime.esm.js:3766
|
||||||
|
callWithErrorHandling @ vue.runtime.esm.js:1381
|
||||||
|
setupStatefulComponent @ vue.runtime.esm.js:8985
|
||||||
|
setupComponent @ vue.runtime.esm.js:8946
|
||||||
|
mountComponent @ vue.runtime.esm.js:7262
|
||||||
|
processComponent @ vue.runtime.esm.js:7228
|
||||||
|
patch @ vue.runtime.esm.js:6694
|
||||||
|
patchKeyedChildren @ vue.runtime.esm.js:7783
|
||||||
|
patchChildren @ vue.runtime.esm.js:7564
|
||||||
|
processFragment @ vue.runtime.esm.js:7202
|
||||||
|
patch @ vue.runtime.esm.js:6668
|
||||||
|
patchKeyedChildren @ vue.runtime.esm.js:7650
|
||||||
|
patchChildren @ vue.runtime.esm.js:7564
|
||||||
|
patchElement @ vue.runtime.esm.js:6989
|
||||||
|
processElement @ vue.runtime.esm.js:6825
|
||||||
|
patch @ vue.runtime.esm.js:6682
|
||||||
|
componentUpdateFn @ vue.runtime.esm.js:7453
|
||||||
|
run @ vue.runtime.esm.js:153
|
||||||
|
instance.update @ vue.runtime.esm.js:7497
|
||||||
|
callWithErrorHandling @ vue.runtime.esm.js:1381
|
||||||
|
flushJobs @ vue.runtime.esm.js:1585
|
||||||
|
Promise.then
|
||||||
|
queueFlush @ vue.runtime.esm.js:1494
|
||||||
|
queueJob @ vue.runtime.esm.js:1488
|
||||||
|
(anonymous) @ vue.runtime.esm.js:7491
|
||||||
|
resetScheduling @ vue.runtime.esm.js:236
|
||||||
|
triggerEffects @ vue.runtime.esm.js:280
|
||||||
|
triggerRefValue @ vue.runtime.esm.js:1033
|
||||||
|
set value @ vue.runtime.esm.js:1078
|
||||||
|
(anonymous) @ AdminLayout.uvue:263
|
||||||
|
setTimeout
|
||||||
|
watch.immediate @ AdminLayout.uvue:262
|
||||||
|
callWithErrorHandling @ vue.runtime.esm.js:1381
|
||||||
|
callWithAsyncErrorHandling @ vue.runtime.esm.js:1388
|
||||||
|
job @ vue.runtime.esm.js:3157
|
||||||
|
callWithErrorHandling @ vue.runtime.esm.js:1381
|
||||||
|
flushJobs @ vue.runtime.esm.js:1585
|
||||||
|
Promise.then
|
||||||
|
queueFlush @ vue.runtime.esm.js:1494
|
||||||
|
queueJob @ vue.runtime.esm.js:1488
|
||||||
|
scheduler @ vue.runtime.esm.js:3179
|
||||||
|
resetScheduling @ vue.runtime.esm.js:236
|
||||||
|
triggerEffects @ vue.runtime.esm.js:280
|
||||||
|
triggerRefValue @ vue.runtime.esm.js:1033
|
||||||
|
set value @ vue.runtime.esm.js:1078
|
||||||
|
openRoute @ adminNavStore.uts:87
|
||||||
|
onSubClick @ AdminLayout.uvue:318
|
||||||
|
callWithErrorHandling @ vue.runtime.esm.js:1381
|
||||||
|
callWithAsyncErrorHandling @ vue.runtime.esm.js:1388
|
||||||
|
emit @ vue.runtime.esm.js:1907
|
||||||
|
(anonymous) @ vue.runtime.esm.js:9176
|
||||||
|
handleNodeClick @ AdminSubSider.uvue:116
|
||||||
|
onClick @ AdminSubSider.uvue?import:112
|
||||||
|
callWithErrorHandling @ vue.runtime.esm.js:1381
|
||||||
|
callWithAsyncErrorHandling @ vue.runtime.esm.js:1388
|
||||||
|
invoker @ vue.runtime.esm.js:10253
|
||||||
|
adminComponentMap.uts:195 GET http://localhost:5173/pages/mall/admin/maintain/dev-tools/api.uvue?t=1770809996535&import net::ERR_ABORTED 500 (Internal Server Error)
|
||||||
|
(anonymous) @ adminComponentMap.uts:195
|
||||||
|
load @ vue.runtime.esm.js:3681
|
||||||
|
setup @ vue.runtime.esm.js:3760
|
||||||
|
callWithErrorHandling @ vue.runtime.esm.js:1381
|
||||||
|
setupStatefulComponent @ vue.runtime.esm.js:8985
|
||||||
|
setupComponent @ vue.runtime.esm.js:8946
|
||||||
|
mountComponent @ vue.runtime.esm.js:7262
|
||||||
|
processComponent @ vue.runtime.esm.js:7228
|
||||||
|
patch @ vue.runtime.esm.js:6694
|
||||||
|
patchKeyedChildren @ vue.runtime.esm.js:7783
|
||||||
|
patchChildren @ vue.runtime.esm.js:7564
|
||||||
|
processFragment @ vue.runtime.esm.js:7202
|
||||||
|
patch @ vue.runtime.esm.js:6668
|
||||||
|
patchKeyedChildren @ vue.runtime.esm.js:7650
|
||||||
|
patchChildren @ vue.runtime.esm.js:7564
|
||||||
|
patchElement @ vue.runtime.esm.js:6989
|
||||||
|
processElement @ vue.runtime.esm.js:6825
|
||||||
|
patch @ vue.runtime.esm.js:6682
|
||||||
|
componentUpdateFn @ vue.runtime.esm.js:7453
|
||||||
|
run @ vue.runtime.esm.js:153
|
||||||
|
instance.update @ vue.runtime.esm.js:7497
|
||||||
|
callWithErrorHandling @ vue.runtime.esm.js:1381
|
||||||
|
flushJobs @ vue.runtime.esm.js:1585
|
||||||
|
Promise.then
|
||||||
|
queueFlush @ vue.runtime.esm.js:1494
|
||||||
|
queueJob @ vue.runtime.esm.js:1488
|
||||||
|
(anonymous) @ vue.runtime.esm.js:7491
|
||||||
|
resetScheduling @ vue.runtime.esm.js:236
|
||||||
|
triggerEffects @ vue.runtime.esm.js:280
|
||||||
|
triggerRefValue @ vue.runtime.esm.js:1033
|
||||||
|
set value @ vue.runtime.esm.js:1078
|
||||||
|
(anonymous) @ AdminLayout.uvue:263
|
||||||
|
setTimeout
|
||||||
|
watch.immediate @ AdminLayout.uvue:262
|
||||||
|
callWithErrorHandling @ vue.runtime.esm.js:1381
|
||||||
|
callWithAsyncErrorHandling @ vue.runtime.esm.js:1388
|
||||||
|
job @ vue.runtime.esm.js:3157
|
||||||
|
callWithErrorHandling @ vue.runtime.esm.js:1381
|
||||||
|
flushJobs @ vue.runtime.esm.js:1585
|
||||||
|
Promise.then
|
||||||
|
queueFlush @ vue.runtime.esm.js:1494
|
||||||
|
queueJob @ vue.runtime.esm.js:1488
|
||||||
|
scheduler @ vue.runtime.esm.js:3179
|
||||||
|
resetScheduling @ vue.runtime.esm.js:236
|
||||||
|
triggerEffects @ vue.runtime.esm.js:280
|
||||||
|
triggerRefValue @ vue.runtime.esm.js:1033
|
||||||
|
set value @ vue.runtime.esm.js:1078
|
||||||
|
openRoute @ adminNavStore.uts:87
|
||||||
|
onSubClick @ AdminLayout.uvue:318
|
||||||
|
callWithErrorHandling @ vue.runtime.esm.js:1381
|
||||||
|
callWithAsyncErrorHandling @ vue.runtime.esm.js:1388
|
||||||
|
emit @ vue.runtime.esm.js:1907
|
||||||
|
(anonymous) @ vue.runtime.esm.js:9176
|
||||||
|
handleNodeClick @ AdminSubSider.uvue:116
|
||||||
|
onClick @ AdminSubSider.uvue?import:112
|
||||||
|
callWithErrorHandling @ vue.runtime.esm.js:1381
|
||||||
|
callWithAsyncErrorHandling @ vue.runtime.esm.js:1388
|
||||||
|
invoker @ vue.runtime.esm.js:10253
|
||||||
|
AdminLayout.uvue:263 [Vue warn]: Unhandled error during execution of async component loader
|
||||||
|
at <AsyncComponentWrapper>
|
||||||
|
at <View>
|
||||||
|
at <View>
|
||||||
|
at <View>
|
||||||
|
at <View>
|
||||||
|
at <AdminLayout>
|
||||||
|
at <View>
|
||||||
|
at <Index>
|
||||||
|
at <AsyncComponentWrapper>
|
||||||
|
at <PageBody>
|
||||||
|
at <Page>
|
||||||
|
at <Anonymous>
|
||||||
|
at <KeepAlive>
|
||||||
|
at <RouterView>
|
||||||
|
at <Layout>
|
||||||
|
at <App>
|
||||||
|
warnHandler @ uni-h5.es.js:19975
|
||||||
|
callWithErrorHandling @ vue.runtime.esm.js:1381
|
||||||
|
warn$1 @ vue.runtime.esm.js:1207
|
||||||
|
logError @ vue.runtime.esm.js:1438
|
||||||
|
errorHandler @ uni-h5.es.js:19600
|
||||||
|
callWithErrorHandling @ vue.runtime.esm.js:1381
|
||||||
|
handleError @ vue.runtime.esm.js:1421
|
||||||
|
onError @ vue.runtime.esm.js:3724
|
||||||
|
(anonymous) @ vue.runtime.esm.js:3767
|
||||||
|
Promise.catch
|
||||||
|
setup @ vue.runtime.esm.js:3766
|
||||||
|
callWithErrorHandling @ vue.runtime.esm.js:1381
|
||||||
|
setupStatefulComponent @ vue.runtime.esm.js:8985
|
||||||
|
setupComponent @ vue.runtime.esm.js:8946
|
||||||
|
mountComponent @ vue.runtime.esm.js:7262
|
||||||
|
processComponent @ vue.runtime.esm.js:7228
|
||||||
|
patch @ vue.runtime.esm.js:6694
|
||||||
|
patchKeyedChildren @ vue.runtime.esm.js:7783
|
||||||
|
patchChildren @ vue.runtime.esm.js:7564
|
||||||
|
processFragment @ vue.runtime.esm.js:7202
|
||||||
|
patch @ vue.runtime.esm.js:6668
|
||||||
|
patchKeyedChildren @ vue.runtime.esm.js:7650
|
||||||
|
patchChildren @ vue.runtime.esm.js:7564
|
||||||
|
patchElement @ vue.runtime.esm.js:6989
|
||||||
|
processElement @ vue.runtime.esm.js:6825
|
||||||
|
patch @ vue.runtime.esm.js:6682
|
||||||
|
componentUpdateFn @ vue.runtime.esm.js:7453
|
||||||
|
run @ vue.runtime.esm.js:153
|
||||||
|
instance.update @ vue.runtime.esm.js:7497
|
||||||
|
callWithErrorHandling @ vue.runtime.esm.js:1381
|
||||||
|
flushJobs @ vue.runtime.esm.js:1585
|
||||||
|
Promise.then
|
||||||
|
queueFlush @ vue.runtime.esm.js:1494
|
||||||
|
queueJob @ vue.runtime.esm.js:1488
|
||||||
|
(anonymous) @ vue.runtime.esm.js:7491
|
||||||
|
resetScheduling @ vue.runtime.esm.js:236
|
||||||
|
triggerEffects @ vue.runtime.esm.js:280
|
||||||
|
triggerRefValue @ vue.runtime.esm.js:1033
|
||||||
|
set value @ vue.runtime.esm.js:1078
|
||||||
|
(anonymous) @ AdminLayout.uvue:263
|
||||||
|
setTimeout
|
||||||
|
watch.immediate @ AdminLayout.uvue:262
|
||||||
|
callWithErrorHandling @ vue.runtime.esm.js:1381
|
||||||
|
callWithAsyncErrorHandling @ vue.runtime.esm.js:1388
|
||||||
|
job @ vue.runtime.esm.js:3157
|
||||||
|
callWithErrorHandling @ vue.runtime.esm.js:1381
|
||||||
|
flushJobs @ vue.runtime.esm.js:1585
|
||||||
|
Promise.then
|
||||||
|
queueFlush @ vue.runtime.esm.js:1494
|
||||||
|
queueJob @ vue.runtime.esm.js:1488
|
||||||
|
scheduler @ vue.runtime.esm.js:3179
|
||||||
|
resetScheduling @ vue.runtime.esm.js:236
|
||||||
|
triggerEffects @ vue.runtime.esm.js:280
|
||||||
|
triggerRefValue @ vue.runtime.esm.js:1033
|
||||||
|
set value @ vue.runtime.esm.js:1078
|
||||||
|
openRoute @ adminNavStore.uts:87
|
||||||
|
onSubClick @ AdminLayout.uvue:318
|
||||||
|
callWithErrorHandling @ vue.runtime.esm.js:1381
|
||||||
|
callWithAsyncErrorHandling @ vue.runtime.esm.js:1388
|
||||||
|
emit @ vue.runtime.esm.js:1907
|
||||||
|
(anonymous) @ vue.runtime.esm.js:9176
|
||||||
|
handleNodeClick @ AdminSubSider.uvue:116
|
||||||
|
onClick @ AdminSubSider.uvue?import:112
|
||||||
|
callWithErrorHandling @ vue.runtime.esm.js:1381
|
||||||
|
callWithAsyncErrorHandling @ vue.runtime.esm.js:1388
|
||||||
|
invoker @ vue.runtime.esm.js:10253
|
||||||
|
AdminLayout.uvue:263 TypeError: Failed to fetch dynamically imported module: http://localhost:5173/pages/mall/admin/maintain/dev-tools/api.uvue?t=1770809996535&import
|
||||||
|
logError @ vue.runtime.esm.js:1443
|
||||||
|
errorHandler @ uni-h5.es.js:19600
|
||||||
|
callWithErrorHandling @ vue.runtime.esm.js:1381
|
||||||
|
handleError @ vue.runtime.esm.js:1421
|
||||||
|
onError @ vue.runtime.esm.js:3724
|
||||||
|
(anonymous) @ vue.runtime.esm.js:3767
|
||||||
|
Promise.catch
|
||||||
|
setup @ vue.runtime.esm.js:3766
|
||||||
|
callWithErrorHandling @ vue.runtime.esm.js:1381
|
||||||
|
setupStatefulComponent @ vue.runtime.esm.js:8985
|
||||||
|
setupComponent @ vue.runtime.esm.js:8946
|
||||||
|
mountComponent @ vue.runtime.esm.js:7262
|
||||||
|
processComponent @ vue.runtime.esm.js:7228
|
||||||
|
patch @ vue.runtime.esm.js:6694
|
||||||
|
patchKeyedChildren @ vue.runtime.esm.js:7783
|
||||||
|
patchChildren @ vue.runtime.esm.js:7564
|
||||||
|
processFragment @ vue.runtime.esm.js:7202
|
||||||
|
patch @ vue.runtime.esm.js:6668
|
||||||
|
patchKeyedChildren @ vue.runtime.esm.js:7650
|
||||||
|
patchChildren @ vue.runtime.esm.js:7564
|
||||||
|
patchElement @ vue.runtime.esm.js:6989
|
||||||
|
processElement @ vue.runtime.esm.js:6825
|
||||||
|
patch @ vue.runtime.esm.js:6682
|
||||||
|
componentUpdateFn @ vue.runtime.esm.js:7453
|
||||||
|
run @ vue.runtime.esm.js:153
|
||||||
|
instance.update @ vue.runtime.esm.js:7497
|
||||||
|
callWithErrorHandling @ vue.runtime.esm.js:1381
|
||||||
|
flushJobs @ vue.runtime.esm.js:1585
|
||||||
|
Promise.then
|
||||||
|
queueFlush @ vue.runtime.esm.js:1494
|
||||||
|
queueJob @ vue.runtime.esm.js:1488
|
||||||
|
(anonymous) @ vue.runtime.esm.js:7491
|
||||||
|
resetScheduling @ vue.runtime.esm.js:236
|
||||||
|
triggerEffects @ vue.runtime.esm.js:280
|
||||||
|
triggerRefValue @ vue.runtime.esm.js:1033
|
||||||
|
set value @ vue.runtime.esm.js:1078
|
||||||
|
(anonymous) @ AdminLayout.uvue:263
|
||||||
|
setTimeout
|
||||||
|
watch.immediate @ AdminLayout.uvue:262
|
||||||
|
callWithErrorHandling @ vue.runtime.esm.js:1381
|
||||||
|
callWithAsyncErrorHandling @ vue.runtime.esm.js:1388
|
||||||
|
job @ vue.runtime.esm.js:3157
|
||||||
|
callWithErrorHandling @ vue.runtime.esm.js:1381
|
||||||
|
flushJobs @ vue.runtime.esm.js:1585
|
||||||
|
Promise.then
|
||||||
|
queueFlush @ vue.runtime.esm.js:1494
|
||||||
|
queueJob @ vue.runtime.esm.js:1488
|
||||||
|
scheduler @ vue.runtime.esm.js:3179
|
||||||
|
resetScheduling @ vue.runtime.esm.js:236
|
||||||
|
triggerEffects @ vue.runtime.esm.js:280
|
||||||
|
triggerRefValue @ vue.runtime.esm.js:1033
|
||||||
|
set value @ vue.runtime.esm.js:1078
|
||||||
|
openRoute @ adminNavStore.uts:87
|
||||||
|
onSubClick @ AdminLayout.uvue:318
|
||||||
|
callWithErrorHandling @ vue.runtime.esm.js:1381
|
||||||
|
callWithAsyncErrorHandling @ vue.runtime.esm.js:1388
|
||||||
|
emit @ vue.runtime.esm.js:1907
|
||||||
|
(anonymous) @ vue.runtime.esm.js:9176
|
||||||
|
handleNodeClick @ AdminSubSider.uvue:116
|
||||||
|
onClick @ AdminSubSider.uvue?import:112
|
||||||
|
callWithErrorHandling @ vue.runtime.esm.js:1381
|
||||||
|
callWithAsyncErrorHandling @ vue.runtime.esm.js:1388
|
||||||
|
invoker @ vue.runtime.esm.js:10253
|
||||||
|
adminComponentMap.uts:196 GET http://localhost:5173/pages/mall/admin/maintain/dev-tools/data-dict.uvue?t=1770810020653&import net::ERR_ABORTED 500 (Internal Server Error)
|
||||||
|
(anonymous) @ adminComponentMap.uts:196
|
||||||
|
load @ vue.runtime.esm.js:3681
|
||||||
|
setup @ vue.runtime.esm.js:3760
|
||||||
|
callWithErrorHandling @ vue.runtime.esm.js:1381
|
||||||
|
setupStatefulComponent @ vue.runtime.esm.js:8985
|
||||||
|
setupComponent @ vue.runtime.esm.js:8946
|
||||||
|
mountComponent @ vue.runtime.esm.js:7262
|
||||||
|
processComponent @ vue.runtime.esm.js:7228
|
||||||
|
patch @ vue.runtime.esm.js:6694
|
||||||
|
patchKeyedChildren @ vue.runtime.esm.js:7783
|
||||||
|
patchChildren @ vue.runtime.esm.js:7564
|
||||||
|
processFragment @ vue.runtime.esm.js:7202
|
||||||
|
patch @ vue.runtime.esm.js:6668
|
||||||
|
patchKeyedChildren @ vue.runtime.esm.js:7650
|
||||||
|
patchChildren @ vue.runtime.esm.js:7564
|
||||||
|
patchElement @ vue.runtime.esm.js:6989
|
||||||
|
processElement @ vue.runtime.esm.js:6825
|
||||||
|
patch @ vue.runtime.esm.js:6682
|
||||||
|
componentUpdateFn @ vue.runtime.esm.js:7453
|
||||||
|
run @ vue.runtime.esm.js:153
|
||||||
|
instance.update @ vue.runtime.esm.js:7497
|
||||||
|
callWithErrorHandling @ vue.runtime.esm.js:1381
|
||||||
|
flushJobs @ vue.runtime.esm.js:1585
|
||||||
|
Promise.then
|
||||||
|
queueFlush @ vue.runtime.esm.js:1494
|
||||||
|
queueJob @ vue.runtime.esm.js:1488
|
||||||
|
(anonymous) @ vue.runtime.esm.js:7491
|
||||||
|
resetScheduling @ vue.runtime.esm.js:236
|
||||||
|
triggerEffects @ vue.runtime.esm.js:280
|
||||||
|
triggerRefValue @ vue.runtime.esm.js:1033
|
||||||
|
set value @ vue.runtime.esm.js:1078
|
||||||
|
(anonymous) @ AdminLayout.uvue:263
|
||||||
|
setTimeout
|
||||||
|
watch.immediate @ AdminLayout.uvue:262
|
||||||
|
callWithErrorHandling @ vue.runtime.esm.js:1381
|
||||||
|
callWithAsyncErrorHandling @ vue.runtime.esm.js:1388
|
||||||
|
job @ vue.runtime.esm.js:3157
|
||||||
|
callWithErrorHandling @ vue.runtime.esm.js:1381
|
||||||
|
flushJobs @ vue.runtime.esm.js:1585
|
||||||
|
Promise.then
|
||||||
|
queueFlush @ vue.runtime.esm.js:1494
|
||||||
|
queueJob @ vue.runtime.esm.js:1488
|
||||||
|
scheduler @ vue.runtime.esm.js:3179
|
||||||
|
resetScheduling @ vue.runtime.esm.js:236
|
||||||
|
triggerEffects @ vue.runtime.esm.js:280
|
||||||
|
triggerRefValue @ vue.runtime.esm.js:1033
|
||||||
|
set value @ vue.runtime.esm.js:1078
|
||||||
|
openRoute @ adminNavStore.uts:87
|
||||||
|
onSubClick @ AdminLayout.uvue:318
|
||||||
|
callWithErrorHandling @ vue.runtime.esm.js:1381
|
||||||
|
callWithAsyncErrorHandling @ vue.runtime.esm.js:1388
|
||||||
|
emit @ vue.runtime.esm.js:1907
|
||||||
|
(anonymous) @ vue.runtime.esm.js:9176
|
||||||
|
handleNodeClick @ AdminSubSider.uvue:116
|
||||||
|
onClick @ AdminSubSider.uvue?import:112
|
||||||
|
callWithErrorHandling @ vue.runtime.esm.js:1381
|
||||||
|
callWithAsyncErrorHandling @ vue.runtime.esm.js:1388
|
||||||
|
invoker @ vue.runtime.esm.js:10253
|
||||||
|
AdminLayout.uvue:263 [Vue warn]: Unhandled error during execution of async component loader
|
||||||
|
at <AsyncComponentWrapper>
|
||||||
|
at <View>
|
||||||
|
at <View>
|
||||||
|
at <View>
|
||||||
|
at <View>
|
||||||
|
at <AdminLayout>
|
||||||
|
at <View>
|
||||||
|
at <Index>
|
||||||
|
at <AsyncComponentWrapper>
|
||||||
|
at <PageBody>
|
||||||
|
at <Page>
|
||||||
|
at <Anonymous>
|
||||||
|
at <KeepAlive>
|
||||||
|
at <RouterView>
|
||||||
|
at <Layout>
|
||||||
|
at <App>
|
||||||
|
warnHandler @ uni-h5.es.js:19975
|
||||||
|
callWithErrorHandling @ vue.runtime.esm.js:1381
|
||||||
|
warn$1 @ vue.runtime.esm.js:1207
|
||||||
|
logError @ vue.runtime.esm.js:1438
|
||||||
|
errorHandler @ uni-h5.es.js:19600
|
||||||
|
callWithErrorHandling @ vue.runtime.esm.js:1381
|
||||||
|
handleError @ vue.runtime.esm.js:1421
|
||||||
|
onError @ vue.runtime.esm.js:3724
|
||||||
|
(anonymous) @ vue.runtime.esm.js:3767
|
||||||
|
Promise.catch
|
||||||
|
setup @ vue.runtime.esm.js:3766
|
||||||
|
callWithErrorHandling @ vue.runtime.esm.js:1381
|
||||||
|
setupStatefulComponent @ vue.runtime.esm.js:8985
|
||||||
|
setupComponent @ vue.runtime.esm.js:8946
|
||||||
|
mountComponent @ vue.runtime.esm.js:7262
|
||||||
|
processComponent @ vue.runtime.esm.js:7228
|
||||||
|
patch @ vue.runtime.esm.js:6694
|
||||||
|
patchKeyedChildren @ vue.runtime.esm.js:7783
|
||||||
|
patchChildren @ vue.runtime.esm.js:7564
|
||||||
|
processFragment @ vue.runtime.esm.js:7202
|
||||||
|
patch @ vue.runtime.esm.js:6668
|
||||||
|
patchKeyedChildren @ vue.runtime.esm.js:7650
|
||||||
|
patchChildren @ vue.runtime.esm.js:7564
|
||||||
|
patchElement @ vue.runtime.esm.js:6989
|
||||||
|
processElement @ vue.runtime.esm.js:6825
|
||||||
|
patch @ vue.runtime.esm.js:6682
|
||||||
|
componentUpdateFn @ vue.runtime.esm.js:7453
|
||||||
|
run @ vue.runtime.esm.js:153
|
||||||
|
instance.update @ vue.runtime.esm.js:7497
|
||||||
|
callWithErrorHandling @ vue.runtime.esm.js:1381
|
||||||
|
flushJobs @ vue.runtime.esm.js:1585
|
||||||
|
Promise.then
|
||||||
|
queueFlush @ vue.runtime.esm.js:1494
|
||||||
|
queueJob @ vue.runtime.esm.js:1488
|
||||||
|
(anonymous) @ vue.runtime.esm.js:7491
|
||||||
|
resetScheduling @ vue.runtime.esm.js:236
|
||||||
|
triggerEffects @ vue.runtime.esm.js:280
|
||||||
|
triggerRefValue @ vue.runtime.esm.js:1033
|
||||||
|
set value @ vue.runtime.esm.js:1078
|
||||||
|
(anonymous) @ AdminLayout.uvue:263
|
||||||
|
setTimeout
|
||||||
|
watch.immediate @ AdminLayout.uvue:262
|
||||||
|
callWithErrorHandling @ vue.runtime.esm.js:1381
|
||||||
|
callWithAsyncErrorHandling @ vue.runtime.esm.js:1388
|
||||||
|
job @ vue.runtime.esm.js:3157
|
||||||
|
callWithErrorHandling @ vue.runtime.esm.js:1381
|
||||||
|
flushJobs @ vue.runtime.esm.js:1585
|
||||||
|
Promise.then
|
||||||
|
queueFlush @ vue.runtime.esm.js:1494
|
||||||
|
queueJob @ vue.runtime.esm.js:1488
|
||||||
|
scheduler @ vue.runtime.esm.js:3179
|
||||||
|
resetScheduling @ vue.runtime.esm.js:236
|
||||||
|
triggerEffects @ vue.runtime.esm.js:280
|
||||||
|
triggerRefValue @ vue.runtime.esm.js:1033
|
||||||
|
set value @ vue.runtime.esm.js:1078
|
||||||
|
openRoute @ adminNavStore.uts:87
|
||||||
|
onSubClick @ AdminLayout.uvue:318
|
||||||
|
callWithErrorHandling @ vue.runtime.esm.js:1381
|
||||||
|
callWithAsyncErrorHandling @ vue.runtime.esm.js:1388
|
||||||
|
emit @ vue.runtime.esm.js:1907
|
||||||
|
(anonymous) @ vue.runtime.esm.js:9176
|
||||||
|
handleNodeClick @ AdminSubSider.uvue:116
|
||||||
|
onClick @ AdminSubSider.uvue?import:112
|
||||||
|
callWithErrorHandling @ vue.runtime.esm.js:1381
|
||||||
|
callWithAsyncErrorHandling @ vue.runtime.esm.js:1388
|
||||||
|
invoker @ vue.runtime.esm.js:10253
|
||||||
|
AdminLayout.uvue:263 TypeError: Failed to fetch dynamically imported module: http://localhost:5173/pages/mall/admin/maintain/dev-tools/data-dict.uvue?t=1770810020653&import
|
||||||
|
logError @ vue.runtime.esm.js:1443
|
||||||
|
errorHandler @ uni-h5.es.js:19600
|
||||||
|
callWithErrorHandling @ vue.runtime.esm.js:1381
|
||||||
|
handleError @ vue.runtime.esm.js:1421
|
||||||
|
onError @ vue.runtime.esm.js:3724
|
||||||
|
(anonymous) @ vue.runtime.esm.js:3767
|
||||||
|
Promise.catch
|
||||||
|
setup @ vue.runtime.esm.js:3766
|
||||||
|
callWithErrorHandling @ vue.runtime.esm.js:1381
|
||||||
|
setupStatefulComponent @ vue.runtime.esm.js:8985
|
||||||
|
setupComponent @ vue.runtime.esm.js:8946
|
||||||
|
mountComponent @ vue.runtime.esm.js:7262
|
||||||
|
processComponent @ vue.runtime.esm.js:7228
|
||||||
|
patch @ vue.runtime.esm.js:6694
|
||||||
|
patchKeyedChildren @ vue.runtime.esm.js:7783
|
||||||
|
patchChildren @ vue.runtime.esm.js:7564
|
||||||
|
processFragment @ vue.runtime.esm.js:7202
|
||||||
|
patch @ vue.runtime.esm.js:6668
|
||||||
|
patchKeyedChildren @ vue.runtime.esm.js:7650
|
||||||
|
patchChildren @ vue.runtime.esm.js:7564
|
||||||
|
patchElement @ vue.runtime.esm.js:6989
|
||||||
|
processElement @ vue.runtime.esm.js:6825
|
||||||
|
patch @ vue.runtime.esm.js:6682
|
||||||
|
componentUpdateFn @ vue.runtime.esm.js:7453
|
||||||
|
run @ vue.runtime.esm.js:153
|
||||||
|
instance.update @ vue.runtime.esm.js:7497
|
||||||
|
callWithErrorHandling @ vue.runtime.esm.js:1381
|
||||||
|
flushJobs @ vue.runtime.esm.js:1585
|
||||||
|
Promise.then
|
||||||
|
queueFlush @ vue.runtime.esm.js:1494
|
||||||
|
queueJob @ vue.runtime.esm.js:1488
|
||||||
|
(anonymous) @ vue.runtime.esm.js:7491
|
||||||
|
resetScheduling @ vue.runtime.esm.js:236
|
||||||
|
triggerEffects @ vue.runtime.esm.js:280
|
||||||
|
triggerRefValue @ vue.runtime.esm.js:1033
|
||||||
|
set value @ vue.runtime.esm.js:1078
|
||||||
|
(anonymous) @ AdminLayout.uvue:263
|
||||||
|
setTimeout
|
||||||
|
watch.immediate @ AdminLayout.uvue:262
|
||||||
|
callWithErrorHandling @ vue.runtime.esm.js:1381
|
||||||
|
callWithAsyncErrorHandling @ vue.runtime.esm.js:1388
|
||||||
|
job @ vue.runtime.esm.js:3157
|
||||||
|
callWithErrorHandling @ vue.runtime.esm.js:1381
|
||||||
|
flushJobs @ vue.runtime.esm.js:1585
|
||||||
|
Promise.then
|
||||||
|
queueFlush @ vue.runtime.esm.js:1494
|
||||||
|
queueJob @ vue.runtime.esm.js:1488
|
||||||
|
scheduler @ vue.runtime.esm.js:3179
|
||||||
|
resetScheduling @ vue.runtime.esm.js:236
|
||||||
|
triggerEffects @ vue.runtime.esm.js:280
|
||||||
|
triggerRefValue @ vue.runtime.esm.js:1033
|
||||||
|
set value @ vue.runtime.esm.js:1078
|
||||||
|
openRoute @ adminNavStore.uts:87
|
||||||
|
onSubClick @ AdminLayout.uvue:318
|
||||||
|
callWithErrorHandling @ vue.runtime.esm.js:1381
|
||||||
|
callWithAsyncErrorHandling @ vue.runtime.esm.js:1388
|
||||||
|
emit @ vue.runtime.esm.js:1907
|
||||||
|
(anonymous) @ vue.runtime.esm.js:9176
|
||||||
|
handleNodeClick @ AdminSubSider.uvue:116
|
||||||
|
onClick @ AdminSubSider.uvue?import:112
|
||||||
|
callWithErrorHandling @ vue.runtime.esm.js:1381
|
||||||
|
callWithAsyncErrorHandling @ vue.runtime.esm.js:1388
|
||||||
|
invoker @ vue.runtime.esm.js:10253
|
||||||
|
pages-json-js?t=1770810049956:278 GET http://localhost:5173/pages/mall/admin/setting/message.uvue?t=1770810030507&import net::ERR_ABORTED 500 (Internal Server Error)
|
||||||
|
PagesMallAdminSettingMessageLoader @ pages-json-js?t=1770810049956:278
|
||||||
|
(anonymous) @ uni-h5.es.js:24748
|
||||||
|
(anonymous) @ uni-h5.es.js:4125
|
||||||
|
invokeApi @ uni-h5.es.js:3971
|
||||||
|
(anonymous) @ uni-h5.es.js:3989
|
||||||
|
(anonymous) @ uni-h5.es.js:24765
|
||||||
|
(anonymous) @ uni-h5.es.js:24764
|
||||||
|
Promise.then
|
||||||
|
(anonymous) @ uni-h5.es.js:24763
|
||||||
|
(anonymous) @ uni-h5.es.js:24762
|
||||||
|
pages-json-js?t=1770810049956:280 GET http://localhost:5173/pages/mall/admin/setting/agreement.uvue?t=1770810040122&import net::ERR_ABORTED 500 (Internal Server Error)
|
||||||
|
PagesMallAdminSettingAgreementLoader @ pages-json-js?t=1770810049956:280
|
||||||
|
(anonymous) @ uni-h5.es.js:24748
|
||||||
|
(anonymous) @ uni-h5.es.js:4125
|
||||||
|
invokeApi @ uni-h5.es.js:3971
|
||||||
|
(anonymous) @ uni-h5.es.js:3989
|
||||||
|
(anonymous) @ uni-h5.es.js:24765
|
||||||
|
(anonymous) @ uni-h5.es.js:24764
|
||||||
|
Promise.then
|
||||||
|
(anonymous) @ uni-h5.es.js:24763
|
||||||
|
(anonymous) @ uni-h5.es.js:24762
|
||||||
|
pages-json-js?t=1770810049956:282 GET http://localhost:5173/pages/mall/admin/setting/ticket.uvue?t=1770810049956&import net::ERR_ABORTED 500 (Internal Server Error).
|
||||||
Reference in New Issue
Block a user