From c288c15f6be22feb5426c03dfaeff9c9badfbb49 Mon Sep 17 00:00:00 2001 From: lihui Date: Tue, 11 Nov 2025 14:27:48 +0800 Subject: [PATCH 1/2] =?UTF-8?q?=E6=8F=90=E4=BA=A4=E4=BF=A1=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/__tests__/environment.test.ts | 41 ++ src/views/bankPaymentPage.vue | 127 ++++++ src/views/workspace/index_.vue | 911 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 1079 insertions(+) create mode 100644 src/__tests__/environment.test.ts create mode 100644 src/views/bankPaymentPage.vue create mode 100644 src/views/workspace/index_.vue diff --git a/src/__tests__/environment.test.ts b/src/__tests__/environment.test.ts new file mode 100644 index 0000000..d61e6ea --- /dev/null +++ b/src/__tests__/environment.test.ts @@ -0,0 +1,41 @@ +import { describe, it, expect, beforeEach, afterEach } from 'vitest'; + +describe('Environment Variables', () => { + const originalEnv = process.env; + + beforeEach(() => { + // 保存原始环境变量 + vi.resetModules(); + }); + + afterEach(() => { + // 恢复原始环境变量 + process.env = { ...originalEnv }; + }); + + it('should load development environment variables', async () => { + // 在实际项目中,您可能需要根据具体框架加载环境变量 + const env = import.meta.env; + + // 验证环境变量是否存在 + expect(env).toBeDefined(); + + // 注意:由于 .env.development 是空的,这里不会有很多变量可以测试 + // 但在实际项目中,您可以添加类似这样的测试: + // expect(env.VITE_API_BASE).toBe('expected_development_api_url'); + }); + + it('should have required environment variables', () => { + // 检查生产环境中必需的变量是否已定义 + const requiredVars = [ + // 'VITE_API_BASE', + // 'VITE_UPLOAD_URL' + ]; + + requiredVars.forEach((varName) => { + // 由于 .env.development 是空的,这些测试会失败 + // 请根据实际情况取消注释并修改 + // expect(import.meta.env[varName]).toBeDefined(); + }); + }); +}); \ No newline at end of file diff --git a/src/views/bankPaymentPage.vue b/src/views/bankPaymentPage.vue new file mode 100644 index 0000000..44f81ca --- /dev/null +++ b/src/views/bankPaymentPage.vue @@ -0,0 +1,127 @@ + + + + + diff --git a/src/views/workspace/index_.vue b/src/views/workspace/index_.vue new file mode 100644 index 0000000..190e23c --- /dev/null +++ b/src/views/workspace/index_.vue @@ -0,0 +1,911 @@ + + + + + \ No newline at end of file From d49019cb5035579f501846fbfe2141dcec1fcd95 Mon Sep 17 00:00:00 2001 From: lihui Date: Sat, 15 Nov 2025 16:11:22 +0800 Subject: [PATCH 2/2] =?UTF-8?q?add=EF=BC=9A=E6=9A=82=E6=97=B6=E9=9A=90?= =?UTF-8?q?=E8=97=8F=E6=95=B0=E6=8D=AE=E5=88=B7=E6=96=B0=20add:=E6=B6=88?= =?UTF-8?q?=E6=81=AF=E6=8E=A8=E9=80=81=E6=8E=A5=E5=8F=A3=E5=AF=B9=E6=8E=A5?= =?UTF-8?q?=20add:=E9=A2=91=E9=81=93=E6=A0=A1=E9=AA=8C=E6=9A=82=E6=97=B6?= =?UTF-8?q?=E5=85=B3=E9=97=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main.ts | 5 +- src/router/index.js | 141 +++++++++------- src/store/index.js | 33 ++++ src/utils/getMessage.js | 71 ++++++++ src/utils/goToCheck.js | 36 ++++ src/views/home.vue | 279 ++++++++++++++----------------- src/views/permissions/rolePermission.vue | 132 ++++++++------- 7 files changed, 413 insertions(+), 284 deletions(-) create mode 100644 src/utils/getMessage.js create mode 100644 src/utils/goToCheck.js diff --git a/src/main.ts b/src/main.ts index c5cca9e..830388d 100644 --- a/src/main.ts +++ b/src/main.ts @@ -17,6 +17,7 @@ import {useAdminStore} from './store' import request from "@/util/request"; import "./global.css"; import '@/assets/css/btn.css'; +import {useMessageStore} from "@/store"; const app = createApp(App) @@ -43,4 +44,6 @@ app.use(ElementPlus, { // 在 app 挂载之后再使用 store const adminStore = useAdminStore() -adminStore.initFromLocalStorage() \ No newline at end of file +const messageStore = useMessageStore() +adminStore.initFromLocalStorage() +messageStore.initFromLocalStorage() \ No newline at end of file diff --git a/src/router/index.js b/src/router/index.js index 00130fb..b636ed3 100644 --- a/src/router/index.js +++ b/src/router/index.js @@ -1,7 +1,7 @@ -import { createRouter, createWebHashHistory } from 'vue-router'; -import axios from "axios"; -import { storeToRefs } from "pinia"; -import { useAdminStore } from "@/store/index.js"; +import {createRouter, createWebHashHistory} from 'vue-router'; +import {storeToRefs} from "pinia"; +import {useAdminStore, useMessageStore} from "@/store/index.js"; +import API from '@/util/http.js'; // 路由定义(包含权限映射 meta.permissionId) @@ -16,7 +16,7 @@ const routes = [ component: () => import("../views/login.vue"), }, { - meta: { requireAuth: true }, + meta: {requireAuth: true}, path: '/', component: () => import("../views/home.vue"), children: [ @@ -25,48 +25,48 @@ const routes = [ path: 'workbench', name: "workbench", component: () => import("../views/workspace/index.vue"), - meta: { permissionId: 2 } + meta: {permissionId: 2} }, //金币管理 { path: '/goldManage', name: 'goldManage', - meta: { permissionId: 3 }, + meta: {permissionId: 3}, children: [ // 审核 { path: '/audit', name: "audit", component: () => import("../views/audit/gold/audit.vue"), - meta: { permissionId: 4 }, + meta: {permissionId: 4}, children: [ // 充值审核 { path: 'rechargeAudit', name: "rechargeAudit", component: () => import("../views/audit/gold/rechargeAudit.vue"), - meta: { permissionId: [6, 7, 8, 9, 10, 11, 12] } + meta: {permissionId: [6, 7, 8, 9, 10, 11, 12]} }, // 退款审核 { path: 'refundAudit', name: "refundAudit", component: () => import("../views/audit/gold/refundAudit.vue"), - meta: { permissionId: [13, 14, 15, 16, 17, 18, 19] } + meta: {permissionId: [13, 14, 15, 16, 17, 18, 19]} }, ] }, { path: '/beanAudit', name: "beanAudit", component: () => import("../views/audit/bean/beanAudit.vue"), - meta: { permissionId: 20 }, + meta: {permissionId: 20}, children: [ // 充值审核 { path: 'addbeanAudit', name: "addbeanAudit", component: () => import("../views/audit/bean/beanAudit.vue"), - meta: { permissionId: [21, 22, 23, 24, 25, 26] } + meta: {permissionId: [21, 22, 23, 24, 25, 26]} }, ] }, @@ -77,21 +77,21 @@ const routes = [ path: '/coinConsume', name: "coinConsume", component: () => import("../views/consume/gold/coinConsume.vue"), - meta: { permissionId: 39 }, + meta: {permissionId: 39}, children: [ // 金币新增消耗 { path: 'add', name: "addCoinConsume", component: () => import("../views/consume/gold/addCoinConsume.vue"), - meta: { permissionId: 41 } + meta: {permissionId: 41} }, // 金币消耗明细详情 { path: 'detail', name: "coinConsumeDetail", component: () => import("../views/consume/gold/coinConsumeDetail.vue"), - meta: { permissionId: 40 } + meta: {permissionId: 40} } ] }, @@ -100,35 +100,35 @@ const routes = [ path: '/beanConsume', name: "beanConsume", component: () => import("../views/consume/bean/beanConsume.vue"), - meta: { permissionId: 42 }, + meta: {permissionId: 42}, children: [ // 金豆新增消耗 { path: 'add', name: "addBeanConsume", component: () => import("../views/consume/bean/addBeanConsume.vue"), - meta: { permissionId: 46 } + meta: {permissionId: 46} }, // 直播 { path: 'live', name: "liveStream", component: () => import("../views/consume/bean/liveStream.vue"), - meta: { permissionId: 43 } + meta: {permissionId: 43} }, // 铁粉 { path: 'fan', name: "dieHardFan", component: () => import("../views/consume/bean/dieHardFan.vue"), - meta: { permissionId: 44 } + meta: {permissionId: 44} }, // 文章视频 { path: 'article', name: "articleVideo", component: () => import("../views/consume/bean/articleVideo.vue"), - meta: { permissionId: 45 } + meta: {permissionId: 45} } ] @@ -139,7 +139,7 @@ const routes = [ path: '/rate', name: "rate", component: () => import("../views/managerecharge/rate.vue"), - meta: { permissionId: [27, 28, 29] } + meta: {permissionId: [27, 28, 29]} }, // 金币充值 @@ -147,21 +147,21 @@ const routes = [ path: '/coinRecharge', name: "coinRecharge", component: () => import("../views/recharge/gold/coinRecharge.vue"), - meta: { permissionId: 31 }, + meta: {permissionId: 31}, children: [ // 金币新增充值 { path: 'add', name: "addCoinRecharge", component: () => import("../views/recharge/gold/addCoinRecharge.vue"), - meta: { permissionId: 33 } + meta: {permissionId: 33} }, // 金币充值明细 { path: 'detail', name: "coinRechargeDetail", component: () => import("../views/recharge/gold/coinRechargeDetail.vue"), - meta: { permissionId: 32 } + meta: {permissionId: 32} } ] }, @@ -171,28 +171,28 @@ const routes = [ path: '/beanRecharge', name: "beanRecharge", component: () => import("../views/recharge/bean/beanRecharge.vue"), - meta: { permissionId: 34 }, + meta: {permissionId: 34}, children: [ // 金豆新增充值 { path: 'add', name: "addBeanRecharge", component: () => import("../views/recharge/bean/addBeanRecharge.vue"), - meta: { permissionId: 37 } + meta: {permissionId: 37} }, // 金豆系统充值 { path: 'system', name: "beanSystemRecharge", component: () => import("../views/recharge/bean/beanSystemRecharge.vue"), - meta: { permissionId: 35 } + meta: {permissionId: 35} }, // 金豆线上充值 { path: 'online', name: "beanOnlineRecharge", component: () => import("../views/recharge/bean/beanOnlineRecharge.vue"), - meta: { permissionId: 36 } + meta: {permissionId: 36} } ] }, @@ -202,21 +202,21 @@ const routes = [ path: '/coinRefund', name: "coinRefund", component: () => import("../views/refund/gold/coinRefund.vue"), - meta: { permissionId: 47 }, + meta: {permissionId: 47}, children: [ // 金币新增退款 { path: 'add', name: "addCoinRefund", component: () => import("../views/refund/gold/addCoinRefund.vue"), - meta: { permissionId: 48 } + meta: {permissionId: 48} }, // 金币退款明细详情 { path: 'detail', name: "coinRefundDetail", component: () => import("../views/refund/gold/coinRefundDetail.vue"), - meta: { permissionId: 49 } + meta: {permissionId: 49} } ] }, @@ -226,21 +226,21 @@ const routes = [ path: '/usergold', name: "usergold", component: () => import("../views/usergold/gold/clientCount.vue"), - meta: { permissionId: 51 }, + meta: {permissionId: 51}, children: [ // 金币明细 { path: 'detail', name: "clientCountDetail", component: () => import("../views/usergold/gold/clientCountDetail.vue"), - meta: { permissionId: 52 } + meta: {permissionId: 52} }, // 金币余额 { path: 'balance', name: "clientCountBalance", component: () => import("../views/usergold/gold/clientCountBalance.vue"), - meta: { permissionId: 53 } + meta: {permissionId: 53} }, ] }, @@ -248,25 +248,25 @@ const routes = [ path: '/userbean', name: "userbean", component: () => import("../views/usergold/bean/userbean.vue"), - meta: { permissionId: 54 } + meta: {permissionId: 54} }, { path: '/history', name: "history", component: () => import("../views/history/history.vue"), - meta: { permissionId: 55 }, + meta: {permissionId: 55}, children: [ { path: 'newHistory', name: "newHistory", component: () => import("../views/history/newHistory.vue"), - meta: { permissionId: 56 } + meta: {permissionId: 56} }, { path: 'oldHistory', name: "oldHistory", component: () => import("../views/history/oldHistory.vue"), - meta: { permissionId: 57 } + meta: {permissionId: 57} } ] }, @@ -276,21 +276,21 @@ const routes = [ path: '/permissions', name: "permissions", component: () => import("../views/permissions/permissions.vue"), - meta: { permissionId: 128 }, + meta: {permissionId: 128}, children: [ // 用户权限 { path: 'userPermission', name: "userPermission", component: () => import("../views/permissions/userPermission.vue"), - meta: { permissionId: 129 } + meta: {permissionId: 129} }, // 角色权限 { path: 'rolePermission', name: "rolePermission", component: () => import("../views/permissions/rolePermission.vue"), - meta: { permissionId: 130 } + meta: {permissionId: 130} } ] } @@ -300,40 +300,40 @@ const routes = [ { path: '/moneyManage', name: 'moneyManage', - meta: { permissionId: 58 }, + meta: {permissionId: 58}, children: [ // 收款明细 { path: 'receiveDetail', name: "receiveDetail", - meta: { permissionId: 74 }, + meta: {permissionId: 74}, children: [ // 客服页面 { path: 'receiveService', name: "receiveService", component: () => import("../views/moneyManage/receiveDetail/receiveService.vue"), - meta: { permissionId: 60 } + meta: {permissionId: 60} }, // 地区负责人页面 { path: 'receiveManager', name: "receiveManager", component: () => import("../views/moneyManage/receiveDetail/receiveManage.vue"), - meta: { permissionId: [67, 79] } + meta: {permissionId: [67, 79]} }, {//地区财务 path: 'receiveFinance', name: "receiveFinance", component: () => import("../views/moneyManage/receiveDetail/receiveFinance.vue"), - meta: { permissionId: [67, 79] } + meta: {permissionId: [67, 79]} }, //总部管理员及财务 { path: 'receiveHeader', name: "receiveHeader", component: () => import("../views/moneyManage/receiveDetail/receiveHead.vue"), - meta: { permissionId: 91 } + meta: {permissionId: 91} }, ] }, @@ -342,35 +342,35 @@ const routes = [ path: 'refundDetail', name: "refundDetail", component: () => import("../views/moneyManage/refundDetail/refundDetail.vue"), - meta: { permissionId: 98 }, + meta: {permissionId: 98}, children: [ // 客服页面 { path: 'refundService', name: "refundService", component: () => import("../views/moneyManage/refundDetail/refundService.vue"), - meta: { permissionId: 99 } + meta: {permissionId: 99} }, // 地区财务页面 { path: 'refundFinance', name: "refundFinance", component: () => import("../views/moneyManage/refundDetail/refundFinance.vue"), - meta: { permissionId: 103 } + meta: {permissionId: 103} }, // 地区负责人页面 { path: 'refundCharge', name: "refundCharge", component: () => import("../views/moneyManage/refundDetail/refundCharge.vue"), - meta: { permissionId: 107 } + meta: {permissionId: 107} }, //总部管理员及财务 { path: 'refundHeader', name: "refundHeader", component: () => import("../views/moneyManage/refundDetail/refundHeader.vue"), - meta: { permissionId: 111 } + meta: {permissionId: 111} }, ] }, @@ -379,7 +379,7 @@ const routes = [ path: 'executor', name: "executor", component: () => import("../views/moneyManage/executor/executor.vue"), - meta: { permissionId: 115 } + meta: {permissionId: 115} }, ] }, @@ -387,29 +387,29 @@ const routes = [ { path: 'channelManage', name: 'channelManage', - meta: { permissionId: 124 }, + meta: {permissionId: 124}, children: [ // 打赏 { path: 'reward', name: "reward", component: () => import("../views/channelManage/reward/reward.vue"), - meta: { permissionId: 125 } + meta: {permissionId: 125} }, // 铁粉 { path: 'fans', name: "fans", component: () => import("../views/channelManage/fans/fans.vue"), - meta: { permissionId: 126 } + meta: {permissionId: 126} }, // 购物车 { path: 'cart', name: "cart", component: () => import("../views/noPermissionPage.vue"), - meta: { permissionId: 127 } - } + meta: {permissionId: 127} + } ] }, // 活动管理 @@ -417,7 +417,7 @@ const routes = [ path: 'activityManage', name: "activityManage", component: () => import("../views/activityManage/activity.vue"), - meta: { permissionId: 119 } + meta: {permissionId: 119} }, // 没有权限 { @@ -457,12 +457,11 @@ const getAllPermissionIds = (menuTree) => { return permissionIds; }; - // 全局路由守卫 router.beforeEach(async (to, from, next) => { const adminStore = useAdminStore() - const { adminData, menuTree } = storeToRefs(adminStore) + const {adminData, menuTree} = storeToRefs(adminStore) const token = localStorage.getItem("token"); const machineId = localStorage.getItem("machineId"); @@ -520,4 +519,24 @@ router.beforeEach(async (to, from, next) => { next(); }); +// 全局后置守卫:每次路由切换后执行 +router.afterEach(async () => { + try { + // 执行/getMessage请求 + const newMessageRes = await API({ + url: '/getMessage', + method: 'POST', + data: {} + }); + console.log('newMessageRes=======================:', newMessageRes.data) + // 存入全局状态,供所有页面访问 + const messageStore = useMessageStore(); + // 过滤 flag=1的消息 + newMessageRes.data = newMessageRes.data.filter(item => item.flag !== 1); + + messageStore.setMessages(newMessageRes.data); + } catch (error) { + console.error('获取消息失败:', error); + } +}); export default router; \ No newline at end of file diff --git a/src/store/index.js b/src/store/index.js index cab0bfe..bdd210c 100644 --- a/src/store/index.js +++ b/src/store/index.js @@ -1,4 +1,6 @@ // src/store/index.js +// useMessageStore +// 引入Pinia的defineStore import {defineStore} from 'pinia' export const useAdminStore = defineStore('admin', { @@ -68,4 +70,35 @@ export const useAdminStore = defineStore('admin', { // localStorage.removeItem('token') } } +}) + +// 最基础的messageStore +// 模仿adminStore风格的messageStore +export const useMessageStore = defineStore('messages', { + state: () => ({ + messages: [], // 消息列表数据 + }), + actions: { + // 设置消息列表并同步到localStorage + setMessages(data) { + this.messages = data + localStorage.setItem('messages', JSON.stringify(data)) + }, + + // 从localStorage初始化消息相关数据 + initFromLocalStorage() { + const messages = localStorage.getItem('messages') + if (messages) { + this.messages = JSON.parse(messages) + } + }, + + // 清空消息状态并移除localStorage数据 + clearMessages() { + this.messages = [] + localStorage.removeItem('messages') + + }, + + } }) \ No newline at end of file diff --git a/src/utils/getMessage.js b/src/utils/getMessage.js new file mode 100644 index 0000000..cc70410 --- /dev/null +++ b/src/utils/getMessage.js @@ -0,0 +1,71 @@ +// 所有导入放在顶部 +import API from '@/util/http.js'; +import {ref} from "vue"; + +// 声明变量 +const messageList1 = ref() + +/** + * 格式化时间为相对时间 + * @param {String} timeStr - 原始时间字符串 + * @returns {String} 格式化后的时间 + */ +function formatTime(timeStr) { + // 函数逻辑不变... + const now = new Date(); + const msgTime = new Date(timeStr); + const diffMs = now - msgTime; + const diffMins = Math.floor(diffMs / (1000 * 60)); + const diffHours = Math.floor(diffMins / 60); + const diffDays = Math.floor(diffHours / 24); + + if (diffHours < 1) { + return `${diffMins}分钟前`; + } else if (diffDays < 1) { + return `${diffHours}小时前`; + } else if (diffDays === 1) { + return '昨天'; + } else { + return `${msgTime.getFullYear()}-${String(msgTime.getMonth() + 1).padStart(2, '0')}-${String(msgTime.getDate()).padStart(2, '0')}`; + } +} + + +/** + * 按日期分组消息(返回扁平化列表,每条消息包含group字段) + * @param {Array} messages - 原始消息列表 + * @returns {Array} 带分组信息的消息列表 + */ +export function groupMessages(messages) { + const today = new Date(); + today.setHours(0, 0, 0, 0); + const yesterday = new Date(today); + yesterday.setDate(yesterday.getDate() - 1); + + // 直接返回处理后的消息数组(每条消息带group字段) + return messages + .filter(msg => msg.flag !== 1) + .map(msg => { + + const msgTime = new Date(msg.czTime); + const formattedTime = formatTime(msg.czTime); + let group; + + if (msgTime >= today) { + group = '今天'; + } else if (msgTime >= yesterday) { + group = '昨天'; + } else { + group = '更早'; + } + + return {...msg, czTime: formattedTime, group}; + }); +} + +// // 异步获取消息 +// export const newMessageRes = await API({ +// url: '/getMessage', +// method: 'POST', +// data: {} +// }); diff --git a/src/utils/goToCheck.js b/src/utils/goToCheck.js new file mode 100644 index 0000000..c9d40b6 --- /dev/null +++ b/src/utils/goToCheck.js @@ -0,0 +1,36 @@ +export function getOrderPage(status) { + // 收款相关状态(0-5) + const receiveStatusMap = { + 0: '/moneyManage/receiveDetail/receiveFinance', // 线下财务待审核 + 1: '/moneyManage/receiveDetail/receiveService', // 线下财务审核通过待填手续费 + 2: '/moneyManage/receiveDetail/receiveService', // 线下财务审核驳回 + 3: '/moneyManage/receiveDetail/receiveService', // link线上财务复核待填手续费 + // 4: '/moneyManage/receiveDetail', // 收款流程全部结束 + 5: '/moneyManage/receiveDetail/receiveService' // 手动撤回待编辑提交 + }; + + // 退款相关状态(6及10-41中退款流程状态) + const refundStatusMap = { + 6: '/moneyManage/refundDetail', // 退款 + 10: '/moneyManage/refundDetail/refundFinance', // 地区财务待审核 + 11: '/moneyManage/refundDetail/refundFinance', // 地区财务手动撤回待编辑提交 + 12: '/moneyManage/refundDetail/refundFinance', // 地区财务驳回 + 20: '/moneyManage/refundDetail/refundCharge', // 地区负责人待审核 + 22: '/moneyManage/refundDetail/refundCharge', // 地区负责人驳回 + 30: '/moneyManage/refundDetail/refundHeader', // 总部财务待审核 + 32: '/moneyManage/refundDetail/refundHeader', // 总部财务驳回 + 40: '/moneyManage/refundDetail/refundService', // 执行人待处理 + 41: '/moneyManage/refundDetail/refundService' // 执行人已处理,退款结束 + }; + + // 优先匹配退款状态(包含6和10-41区间) + if (refundStatusMap.hasOwnProperty(status)) { + return refundStatusMap[status]; + } + // 匹配收款状态(0-5) + if (receiveStatusMap.hasOwnProperty(status)) { + return receiveStatusMap[status]; + } + // 未知状态返回工作台 + return '/workbench'; +} \ No newline at end of file diff --git a/src/views/home.vue b/src/views/home.vue index 363a155..be89c7f 100644 --- a/src/views/home.vue +++ b/src/views/home.vue @@ -1,19 +1,23 @@ -