From 2b920557a1b529ff9c73848ce2cc18a0a93c5063 Mon Sep 17 00:00:00 2001 From: LOG1997 <2694233102@qq.com> Date: Wed, 1 Oct 2025 11:02:33 +0800 Subject: [PATCH] =?UTF-8?q?refactor:=20=E4=BA=BA=E5=91=98=E5=88=97?= =?UTF-8?q?=E8=A1=A8=E4=BB=A3=E7=A0=81=E7=BB=93=E6=9E=84=E9=87=8D=E7=BB=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components.d.ts | 1 + src/components/Dialog/index.vue | 56 ++++ src/router/index.ts | 240 +++++++++--------- .../Person/PersonAll/importExcel.worker.ts | 32 +++ src/views/Config/Person/PersonAll/index.vue | 73 ++++++ .../Config/Person/PersonAll/useViewModel.ts | 153 +++++++++++ 6 files changed, 435 insertions(+), 120 deletions(-) create mode 100644 src/components/Dialog/index.vue create mode 100644 src/views/Config/Person/PersonAll/importExcel.worker.ts create mode 100644 src/views/Config/Person/PersonAll/index.vue create mode 100644 src/views/Config/Person/PersonAll/useViewModel.ts diff --git a/src/components.d.ts b/src/components.d.ts index 04d884e..7b0c306 100644 --- a/src/components.d.ts +++ b/src/components.d.ts @@ -9,6 +9,7 @@ export {} declare module 'vue' { export interface GlobalComponents { DaiysuiTable: typeof import('./components/DaiysuiTable/index.vue')['default'] + Dialog: typeof import('./components/Dialog/index.vue')['default'] EditSeparateDialog: typeof import('./components/NumberSeparate/EditSeparateDialog.vue')['default'] HelloWorld: typeof import('./components/HelloWorld.vue')['default'] ImageSync: typeof import('./components/ImageSync/index.vue')['default'] diff --git a/src/components/Dialog/index.vue b/src/components/Dialog/index.vue new file mode 100644 index 0000000..a004158 --- /dev/null +++ b/src/components/Dialog/index.vue @@ -0,0 +1,56 @@ + + + + + diff --git a/src/router/index.ts b/src/router/index.ts index 1a37f75..ef753a3 100644 --- a/src/router/index.ts +++ b/src/router/index.ts @@ -1,142 +1,142 @@ +import { createRouter, createWebHashHistory, createWebHistory } from 'vue-router' import Layout from '@/layout/index.vue' import i18n from '@/locales/i18n' import Home from '@/views/Home/index.vue' -import { createRouter, createWebHistory,createWebHashHistory } from 'vue-router' export const configRoutes = { - path: '/log-lottery/config', - name: 'Config', - component: () => import('@/views/Config/index.vue'), - children: [ - { - path: '', - redirect: '/log-lottery/config/person', - }, - { - path: '/log-lottery/config/person', - name: 'PersonConfig', - component: () => import('@/views/Config/Person/PersonConfig.vue'), - meta: { - title: i18n.global.t('sidebar.personConfiguration'), - icon: 'person', - }, - children: [ + path: '/log-lottery/config', + name: 'Config', + component: () => import('@/views/Config/index.vue'), + children: [ { - path: '', - redirect: '/log-lottery/config/person/all', + path: '', + redirect: '/log-lottery/config/person', }, { - path: '/log-lottery/config/person/all', - name: 'AllPersonConfig', - component: () => import('@/views/Config/Person/PersonAll.vue'), - meta: { - title: i18n.global.t('sidebar.personList'), - icon: 'all', - }, + path: '/log-lottery/config/person', + name: 'PersonConfig', + component: () => import('@/views/Config/Person/PersonConfig.vue'), + meta: { + title: i18n.global.t('sidebar.personConfiguration'), + icon: 'person', + }, + children: [ + { + path: '', + redirect: '/log-lottery/config/person/all', + }, + { + path: '/log-lottery/config/person/all', + name: 'AllPersonConfig', + component: () => import('@/views/Config/Person/PersonAll/index.vue'), + meta: { + title: i18n.global.t('sidebar.personList'), + icon: 'all', + }, + }, + { + path: '/log-lottery/config/person/already', + name: 'AlreadyPerson', + component: () => import('@/views/Config/Person/PersonAlready.vue'), + meta: { + title: i18n.global.t('sidebar.winnerList'), + icon: 'already', + }, + }, + // { + // path:'other', + // name:'OtherPersonConfig', + // component:()=>import('@/views/Config/Person/OtherPersonConfig.vue'), + // meta:{ + // title:'其他配置', + // icon:'other' + // } + // } + ], }, { - path: '/log-lottery/config/person/already', - name: 'AlreadyPerson', - component: () => import('@/views/Config/Person/PersonAlready.vue'), - meta: { - title: i18n.global.t('sidebar.winnerList'), - icon: 'already', - }, - }, - // { - // path:'other', - // name:'OtherPersonConfig', - // component:()=>import('@/views/Config/Person/OtherPersonConfig.vue'), - // meta:{ - // title:'其他配置', - // icon:'other' - // } - // } - ], - }, - { - path: '/log-lottery/config/prize', - name: 'PrizeConfig', - component: () => import('@/views/Config/Prize/PrizeConfig.vue'), - meta: { - title: i18n.global.t('sidebar.prizeConfiguration'), - icon: 'prize', - }, - }, - { - path: '/log-lottery/config/global', - name: 'GlobalConfig', - redirect: '/log-lottery/config/global/all', - meta: { - title: i18n.global.t('sidebar.globalSetting'), - icon: 'global', - }, - children: [ - { - path: '/log-lottery/config/global/face', - name: 'FaceConfig', - component: () => import('@/views/Config/Global/FaceConfig.vue'), - meta: { - title: i18n.global.t('sidebar.viewSetting'), - icon: 'face', - }, + path: '/log-lottery/config/prize', + name: 'PrizeConfig', + component: () => import('@/views/Config/Prize/PrizeConfig.vue'), + meta: { + title: i18n.global.t('sidebar.prizeConfiguration'), + icon: 'prize', + }, }, { - path: '/log-lottery/config/global/image', - name: 'ImageConfig', - component: () => import('@/views/Config/Global/ImageConfig.vue'), - meta: { - title: i18n.global.t('sidebar.imagesManagement'), - icon: 'image', - }, + path: '/log-lottery/config/global', + name: 'GlobalConfig', + redirect: '/log-lottery/config/global/all', + meta: { + title: i18n.global.t('sidebar.globalSetting'), + icon: 'global', + }, + children: [ + { + path: '/log-lottery/config/global/face', + name: 'FaceConfig', + component: () => import('@/views/Config/Global/FaceConfig.vue'), + meta: { + title: i18n.global.t('sidebar.viewSetting'), + icon: 'face', + }, + }, + { + path: '/log-lottery/config/global/image', + name: 'ImageConfig', + component: () => import('@/views/Config/Global/ImageConfig.vue'), + meta: { + title: i18n.global.t('sidebar.imagesManagement'), + icon: 'image', + }, + }, + { + path: '/log-lottery/config/global/music', + name: 'MusicConfig', + component: () => import('@/views/Config/Global/MusicConfig.vue'), + meta: { + title: i18n.global.t('sidebar.musicManagement'), + icon: 'music', + }, + }, + ], }, { - path: '/log-lottery/config/global/music', - name: 'MusicConfig', - component: () => import('@/views/Config/Global/MusicConfig.vue'), - meta: { - title: i18n.global.t('sidebar.musicManagement'), - icon: 'music', - }, + path: '/log-lottery/config/readme', + name: 'Readme', + component: () => import('@/views/Config/Readme/index.vue'), + meta: { + title: i18n.global.t('sidebar.operatingInstructions'), + icon: 'readme', + }, }, - ], - }, - { - path: '/log-lottery/config/readme', - name: 'Readme', - component: () => import('@/views/Config/Readme/index.vue'), - meta: { - title: i18n.global.t('sidebar.operatingInstructions'), - icon: 'readme', - }, - }, - ], + ], } const routes = [ - { - path: '/log-lottery', - component: Layout, - redirect: '/log-lottery/home', - children: [ - { - path: '/log-lottery/home', - name: 'Home', - component: Home, - }, - { - path: '/log-lottery/demo', - name: 'Demo', - component: () => import('@/views/Demo/index.vue'), - }, - configRoutes, - ], - }, -]; -const envMode=import.meta.env.MODE; + { + path: '/log-lottery', + component: Layout, + redirect: '/log-lottery/home', + children: [ + { + path: '/log-lottery/home', + name: 'Home', + component: Home, + }, + { + path: '/log-lottery/demo', + name: 'Demo', + component: () => import('@/views/Demo/index.vue'), + }, + configRoutes, + ], + }, +] +const envMode = import.meta.env.MODE const router = createRouter({ // 读取环境变量 - history: envMode==='file'?createWebHashHistory():createWebHistory(), - routes, + history: envMode === 'file' ? createWebHashHistory() : createWebHistory(), + routes, }) export default router diff --git a/src/views/Config/Person/PersonAll/importExcel.worker.ts b/src/views/Config/Person/PersonAll/importExcel.worker.ts new file mode 100644 index 0000000..6b9a39e --- /dev/null +++ b/src/views/Config/Person/PersonAll/importExcel.worker.ts @@ -0,0 +1,32 @@ +import * as XLSX from 'xlsx' +import { addOtherInfo } from '@/utils' +// 定义消息类型 +interface WorkerMessage { + type: 'start' | 'stop' | 'reset' + data: any +} + +let allData: any[] = [] + +// 接收主线程消息 +globalThis.onmessage = async (e: MessageEvent) => { + switch (e.data.type) { + case 'start': + { + const fileData = e.data.data + // const dataBinary = await readFileBinary(((fileEvent.target as HTMLInputElement).files as FileList)[0]!) + const workBook = XLSX.read(fileData, { type: 'binary', cellDates: true }) + const workSheet = workBook.Sheets[workBook.SheetNames[0]] + const excelData = XLSX.utils.sheet_to_json(workSheet) + allData = addOtherInfo(excelData) + globalThis.postMessage({ + type: 'done', + data: allData, + message: '读取完成', + }) + break + } + default: + break + } +} diff --git a/src/views/Config/Person/PersonAll/index.vue b/src/views/Config/Person/PersonAll/index.vue new file mode 100644 index 0000000..7d52530 --- /dev/null +++ b/src/views/Config/Person/PersonAll/index.vue @@ -0,0 +1,73 @@ + + + + + + diff --git a/src/views/Config/Person/PersonAll/useViewModel.ts b/src/views/Config/Person/PersonAll/useViewModel.ts new file mode 100644 index 0000000..3a1de31 --- /dev/null +++ b/src/views/Config/Person/PersonAll/useViewModel.ts @@ -0,0 +1,153 @@ +import type { IPersonConfig } from '@/types/storeType' +import { storeToRefs } from 'pinia' +import * as XLSX from 'xlsx' +import i18n from '@/locales/i18n' +import useStore from '@/store' +import { readFileBinary } from '@/utils/file' +import ImportExcelWorker from './importExcel.worker?worker' + +export function useViewModel() { + const worker: Worker | null = new ImportExcelWorker() + const personConfig = useStore().personConfig + const { getAllPersonList: allPersonList, getAlreadyPersonList: alreadyPersonList } = storeToRefs(personConfig) + const tableColumns = [ + { + label: i18n.global.t('data.number'), + props: 'uid', + }, + { + label: i18n.global.t('data.name'), + props: 'name', + }, + { + label: i18n.global.t('data.department'), + props: 'department', + }, + { + label: i18n.global.t('data.avatar'), + props: 'avatar', + formatValue(row: any) { + return row.avatar ? `avatar` : '-' + }, + }, + { + label: i18n.global.t('data.identity'), + props: 'identity', + }, + { + label: i18n.global.t('data.isWin'), + props: 'isWin', + formatValue(row: IPersonConfig) { + return row.isWin ? i18n.global.t('data.yes') : i18n.global.t('data.no') + }, + }, + { + label: i18n.global.t('data.operation'), + actions: [ + // { + // label: '编辑', + // type: 'btn-info', + // onClick: (row: any) => { + // delPersonItem(row) + // } + // }, + { + label: i18n.global.t('data.delete'), + type: 'btn-error', + onClick: (row: IPersonConfig) => { + delPersonItem(row) + }, + }, + + ], + }, + ] + /// 向worker发送消息 + function sendWorkerMessage(message: any) { + if (worker) { + worker.postMessage(message) + } + } + /// 开始导入 + function startWorker(data: Event) { + sendWorkerMessage({ type: 'start', data }) + } + /** + * 获取用户数据 + */ + async function handleFileChange(e: Event) { + // worker = new ImportExcelWorker() + if (worker) { + worker.onmessage = (e) => { + if (e.data.type === 'done') { + personConfig.resetPerson() + personConfig.addNotPersonList(e.data.data) + } + } + } + const dataBinary = await readFileBinary(((e.target as HTMLInputElement).files as FileList)[0]!) + startWorker(dataBinary) + } + /// 导出数据 + function exportData() { + let data = JSON.parse(JSON.stringify(allPersonList.value)) + // 排除一些字段 + for (let i = 0; i < data.length; i++) { + delete data[i].x + delete data[i].y + delete data[i].id + delete data[i].createTime + delete data[i].updateTime + delete data[i].prizeId + // 修改字段名称 + if (data[i].isWin) { + data[i].isWin = i18n.global.t('data.yes') + } + else { + data[i].isWin = i18n.global.t('data.no') + } + // 格式化数组为 + data[i].prizeTime = data[i].prizeTime.join(',') + data[i].prizeName = data[i].prizeName.join(',') + } + let dataString = JSON.stringify(data) + dataString = dataString + .replaceAll(/uid/g, i18n.global.t('data.number')) + .replaceAll(/isWin/g, i18n.global.t('data.isWin')) + .replaceAll(/department/g, i18n.global.t('data.department')) + .replaceAll(/name/g, i18n.global.t('data.name')) + .replaceAll(/identity/g, i18n.global.t('data.identity')) + .replaceAll(/prizeName/g, i18n.global.t('data.prizeName')) + .replaceAll(/prizeTime/g, i18n.global.t('data.prizeTime')) + + data = JSON.parse(dataString) + + if (data.length > 0) { + const dataBinary = XLSX.utils.json_to_sheet(data) + const dataBinaryBinary = XLSX.utils.book_new() + XLSX.utils.book_append_sheet(dataBinaryBinary, dataBinary, 'Sheet1') + XLSX.writeFile(dataBinaryBinary, 'data.xlsx') + } + } + + function resetData() { + personConfig.resetAlreadyPerson() + } + + function deleteAll() { + personConfig.deleteAllPerson() + } + + function delPersonItem(row: IPersonConfig) { + personConfig.deletePerson(row) + } + return { + resetData, + deleteAll, + handleFileChange, + exportData, + alreadyPersonList, + allPersonList, + tableColumns, + } +}