From f8098a9737ff477a7f0c6f613493e929a219d035 Mon Sep 17 00:00:00 2001 From: LOG1997 <2694233102@qq.com> Date: Mon, 22 Dec 2025 17:28:10 +0800 Subject: [PATCH] Confilct dev date 12 22 (#131) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix(home): 🐛 解决多次切换路由后页面卡顿的问题 #96 卸载路由时清除requestAnimationFrame * feat: ✨ 文件存储使用Blob格式 * style: 💄 修改部分类型any为具体类型 * feat: ✨ 界面设置中模块使用瀑布流布局 #96 * fix: 🐛 md文档更换文件夹解决控制台警告 * style: 💄 switch按钮改回使用daisyui组件 * refactor: ♻️ 所有人员列表提取tableColumn * style: 💄 奖项列表中的图片类型修复 * fix(globalConfig): 修复当前音乐项类型缺失问题 * feat: ✨ single person not done * feat: ✨ 可添加单人 #96 * build(.gitignore): 添加 auto-imports.d.ts 到忽略文件 * fix: 🐛 上传、下载excel文件时修复路径错误 打包成应用和网页端的baseUrl不一样,使用环境变量来表示 * fix: 🐛 导入人员列表时处理有值为空的情况 * style: 💄 改变toaster的组件 * fix: 🐛 上传文件、解析数据与存储/读取数据的处理 、 --- .gitignore | 1 + src/auto-imports.d.ts | 10 -- src/components.d.ts | 67 -------- src/components/DaiysuiTable/index.vue | 4 +- src/components/Drawer/index.vue | 38 +++++ src/components/FileUpload/index.vue | 1 - src/hooks/useElement.ts | 152 +++++++++--------- src/layout/index.vue | 3 - src/store/globalConfig.ts | 2 +- src/store/personConfig.ts | 23 ++- src/utils/dexie/index.ts | 8 +- src/utils/index.ts | 6 +- .../FaceConfig/components/UploadDialog.vue | 1 - .../PersonAll/components/SinglePerson.vue | 46 ++++++ .../Person/PersonAll/importExcel.worker.ts | 4 +- src/views/Config/Person/PersonAll/index.vue | 20 ++- .../Config/Person/PersonAll/useViewModel.ts | 44 ++++- src/views/Config/Prize/usePrizeConfig.ts | 3 +- 18 files changed, 254 insertions(+), 179 deletions(-) delete mode 100644 src/auto-imports.d.ts delete mode 100644 src/components.d.ts create mode 100644 src/components/Drawer/index.vue create mode 100644 src/views/Config/Person/PersonAll/components/SinglePerson.vue diff --git a/.gitignore b/.gitignore index 31afa73..d5d6507 100644 --- a/.gitignore +++ b/.gitignore @@ -82,6 +82,7 @@ web_modules/ .env.local **/components.d.ts +**/auto-imports.d.ts # parcel-bundler cache (https://parceljs.org/) .cache diff --git a/src/auto-imports.d.ts b/src/auto-imports.d.ts deleted file mode 100644 index 9d24007..0000000 --- a/src/auto-imports.d.ts +++ /dev/null @@ -1,10 +0,0 @@ -/* eslint-disable */ -/* prettier-ignore */ -// @ts-nocheck -// noinspection JSUnusedGlobalSymbols -// Generated by unplugin-auto-import -// biome-ignore lint: disable -export {} -declare global { - -} diff --git a/src/components.d.ts b/src/components.d.ts deleted file mode 100644 index d40878a..0000000 --- a/src/components.d.ts +++ /dev/null @@ -1,67 +0,0 @@ -/* eslint-disable */ -// @ts-nocheck -// biome-ignore lint: disable -// oxlint-disable -// ------ -// Generated by unplugin-vue-components -// Read more: https://github.com/vuejs/core/pull/3399 - -export {} - -/* prettier-ignore */ -declare module 'vue' { - export interface GlobalComponents { - Button: typeof import('./components/ui/button/Button.vue')['default'] - Command: typeof import('./components/ui/command/Command.vue')['default'] - CommandDialog: typeof import('./components/ui/command/CommandDialog.vue')['default'] - CommandEmpty: typeof import('./components/ui/command/CommandEmpty.vue')['default'] - CommandGroup: typeof import('./components/ui/command/CommandGroup.vue')['default'] - CommandInput: typeof import('./components/ui/command/CommandInput.vue')['default'] - CommandItem: typeof import('./components/ui/command/CommandItem.vue')['default'] - CommandList: typeof import('./components/ui/command/CommandList.vue')['default'] - CommandSeparator: typeof import('./components/ui/command/CommandSeparator.vue')['default'] - CommandShortcut: typeof import('./components/ui/command/CommandShortcut.vue')['default'] - DaiysuiTable: typeof import('./components/DaiysuiTable/index.vue')['default'] - Dialog: typeof import('./components/Dialog/index.vue')['default'] - DialogClose: typeof import('./components/ui/dialog/DialogClose.vue')['default'] - DialogContent: typeof import('./components/ui/dialog/DialogContent.vue')['default'] - DialogDescription: typeof import('./components/ui/dialog/DialogDescription.vue')['default'] - DialogFooter: typeof import('./components/ui/dialog/DialogFooter.vue')['default'] - DialogHeader: typeof import('./components/ui/dialog/DialogHeader.vue')['default'] - DialogOverlay: typeof import('./components/ui/dialog/DialogOverlay.vue')['default'] - DialogScrollContent: typeof import('./components/ui/dialog/DialogScrollContent.vue')['default'] - DialogTitle: typeof import('./components/ui/dialog/DialogTitle.vue')['default'] - DialogTrigger: typeof import('./components/ui/dialog/DialogTrigger.vue')['default'] - DropdownMenu: typeof import('./components/ui/dropdown-menu/DropdownMenu.vue')['default'] - DropdownMenuCheckboxItem: typeof import('./components/ui/dropdown-menu/DropdownMenuCheckboxItem.vue')['default'] - DropdownMenuContent: typeof import('./components/ui/dropdown-menu/DropdownMenuContent.vue')['default'] - DropdownMenuGroup: typeof import('./components/ui/dropdown-menu/DropdownMenuGroup.vue')['default'] - DropdownMenuItem: typeof import('./components/ui/dropdown-menu/DropdownMenuItem.vue')['default'] - DropdownMenuLabel: typeof import('./components/ui/dropdown-menu/DropdownMenuLabel.vue')['default'] - DropdownMenuRadioGroup: typeof import('./components/ui/dropdown-menu/DropdownMenuRadioGroup.vue')['default'] - DropdownMenuRadioItem: typeof import('./components/ui/dropdown-menu/DropdownMenuRadioItem.vue')['default'] - DropdownMenuSeparator: typeof import('./components/ui/dropdown-menu/DropdownMenuSeparator.vue')['default'] - DropdownMenuShortcut: typeof import('./components/ui/dropdown-menu/DropdownMenuShortcut.vue')['default'] - DropdownMenuSub: typeof import('./components/ui/dropdown-menu/DropdownMenuSub.vue')['default'] - DropdownMenuSubContent: typeof import('./components/ui/dropdown-menu/DropdownMenuSubContent.vue')['default'] - DropdownMenuSubTrigger: typeof import('./components/ui/dropdown-menu/DropdownMenuSubTrigger.vue')['default'] - DropdownMenuTrigger: typeof import('./components/ui/dropdown-menu/DropdownMenuTrigger.vue')['default'] - EditSeparateDialog: typeof import('./components/NumberSeparate/EditSeparateDialog.vue')['default'] - FileUpload: typeof import('./components/FileUpload/index.vue')['default'] - HelloWorld: typeof import('./components/HelloWorld.vue')['default'] - ImageSync: typeof import('./components/ImageSync/index.vue')['default'] - Loading: typeof import('./components/Loading/index.vue')['default'] - PageHeader: typeof import('./components/PageHeader/index.vue')['default'] - Popover: typeof import('./components/ui/popover/Popover.vue')['default'] - PopoverAnchor: typeof import('./components/ui/popover/PopoverAnchor.vue')['default'] - PopoverContent: typeof import('./components/ui/popover/PopoverContent.vue')['default'] - PopoverTrigger: typeof import('./components/ui/popover/PopoverTrigger.vue')['default'] - RouterLink: typeof import('vue-router')['RouterLink'] - RouterView: typeof import('vue-router')['RouterView'] - Sonner: typeof import('./components/ui/sonner/Sonner.vue')['default'] - SvgIcon: typeof import('./components/SvgIcon/index.vue')['default'] - Switch: typeof import('./components/ui/switch/Switch.vue')['default'] - ToTop: typeof import('./components/ToTop/index.vue')['default'] - Waterfall: typeof import('./components/Waterfall/index.vue')['default'] - } -} diff --git a/src/components/DaiysuiTable/index.vue b/src/components/DaiysuiTable/index.vue index 86d4f4d..40f13b3 100644 --- a/src/components/DaiysuiTable/index.vue +++ b/src/components/DaiysuiTable/index.vue @@ -47,9 +47,9 @@ const actionsColumns = computed(() => { - {{ item.id }} + - + {{ item[column.props] }} diff --git a/src/components/Drawer/index.vue b/src/components/Drawer/index.vue new file mode 100644 index 0000000..67eedb2 --- /dev/null +++ b/src/components/Drawer/index.vue @@ -0,0 +1,38 @@ + + + + + diff --git a/src/components/FileUpload/index.vue b/src/components/FileUpload/index.vue index 7628862..a391965 100644 --- a/src/components/FileUpload/index.vue +++ b/src/components/FileUpload/index.vue @@ -27,7 +27,6 @@ async function handleFileChange(e: Event) { return } const { data: blobData, fileName } = await readFileDataAsBlob(file) - console.log('datafile', blobData, fileName) fileData.value = { data: blobData, fileName, type } originFileName.value = fileName emits('uploadFile', fileData.value) diff --git a/src/hooks/useElement.ts b/src/hooks/useElement.ts index abacabc..e861d42 100644 --- a/src/hooks/useElement.ts +++ b/src/hooks/useElement.ts @@ -2,54 +2,56 @@ import type { IPersonConfig } from '@/types/storeType' import { rgba } from '@/utils/color' export function useElementStyle(element: any, person: IPersonConfig, index: number, patternList: number[], patternColor: string, cardColor: string, cardSize: { width: number, height: number }, textSize: number, mod: 'default' | 'lucky' | 'sphere' = 'default', type: 'add' | 'change' = 'add') { - if (patternList.includes(index + 1) && mod === 'default') { - element.style.backgroundColor = rgba(patternColor, Math.random() * 0.2 + 0.8) - } - else if (mod === 'sphere' || mod === 'default') { - element.style.backgroundColor = rgba(cardColor, Math.random() * 0.5 + 0.25) - } - else if (mod === 'lucky') { - element.style.backgroundColor = rgba(cardColor, 0.8) - } - element.style.border = `1px solid ${rgba(cardColor, 0.25)}` - element.style.boxShadow = `0 0 12px ${rgba(cardColor, 0.5)}` - element.style.width = `${cardSize.width}px` - element.style.height = `${cardSize.height}px` - if (mod === 'lucky') { - element.className = 'lucky-element-card' - } - else { - element.className = 'element-card' - } - if (type === 'add') { - element.addEventListener('mouseenter', (ev: MouseEvent) => { - const target = ev.target as HTMLElement - target.style.border = `1px solid ${rgba(cardColor, 0.75)}` - target.style.boxShadow = `0 0 12px ${rgba(cardColor, 0.75)}` - }) - element.addEventListener('mouseleave', (ev: MouseEvent) => { - const target = ev.target as HTMLElement - target.style.border = `1px solid ${rgba(cardColor, 0.25)}` - target.style.boxShadow = `0 0 12px ${rgba(cardColor, 0.5)}` - }) - } - element.children[0].style.fontSize = `${textSize * 0.5}px` - if (person.uid) { - element.children[0].textContent = person.uid - } + if (patternList.includes(index + 1) && mod === 'default') { + element.style.backgroundColor = rgba(patternColor, Math.random() * 0.2 + 0.8) + } + else if (mod === 'sphere' || mod === 'default') { + element.style.backgroundColor = rgba(cardColor, Math.random() * 0.5 + 0.25) + } + else if (mod === 'lucky') { + element.style.backgroundColor = rgba(cardColor, 0.8) + } + element.style.border = `1px solid ${rgba(cardColor, 0.25)}` + element.style.boxShadow = `0 0 12px ${rgba(cardColor, 0.5)}` + element.style.width = `${cardSize.width}px` + element.style.height = `${cardSize.height}px` + if (mod === 'lucky') { + element.className = 'lucky-element-card' + } + else { + element.className = 'element-card' + } + if (type === 'add') { + element.addEventListener('mouseenter', (ev: MouseEvent) => { + const target = ev.target as HTMLElement + target.style.border = `1px solid ${rgba(cardColor, 0.75)}` + target.style.boxShadow = `0 0 12px ${rgba(cardColor, 0.75)}` + }) + element.addEventListener('mouseleave', (ev: MouseEvent) => { + const target = ev.target as HTMLElement + target.style.border = `1px solid ${rgba(cardColor, 0.25)}` + target.style.boxShadow = `0 0 12px ${rgba(cardColor, 0.5)}` + }) + } + element.children[0].style.fontSize = `${textSize * 0.5}px` + if (person.uid) { + element.children[0].textContent = person.uid + } - element.children[1].style.fontSize = `${textSize}px` - element.children[1].style.lineHeight = `${textSize * 3}px` - element.children[1].style.textShadow = `0 0 12px ${rgba(cardColor, 0.95)}` - if (person.name) { - element.children[1].textContent = person.name - } - element.children[2].style.fontSize = `${textSize * 0.5}px` - if (person.department || person.identity) { - element.children[2].innerHTML = `${person.department ? person.department : ''}
${person.identity ? person.identity : ''}` - } + element.children[1].style.fontSize = `${textSize}px` + element.children[1].style.lineHeight = `${textSize * 3}px` + element.children[1].style.textShadow = `0 0 12px ${rgba(cardColor, 0.95)}` + if (person.name) { + element.children[1].textContent = person.name + } + // element.children[2].style.fontSize = `${textSize * 0.5}px` + // if (person.department || person.identity) { + // element.children[2].innerHTML = `${person.department ? person.department : ''}
${person.identity ? person.identity : ''}` + // } - element.children[2].style.fontSize = textSize * 0.5 + 'px' + element.children[2].style.fontSize = `${textSize * 0.5}px` + // 设置部门和身份的默认值 + element.children[2].innerHTML = '' if (person.department || person.identity) { element.children[2].innerHTML = `${person.department ? person.department : ''}
${person.identity ? person.identity : ''}` } @@ -63,36 +65,36 @@ export function useElementStyle(element: any, person: IPersonConfig, index: numb */ // TODO:不超过5个时:单行排列;超过5个时,6:上3下3;7:上3下4;8:上3下5;9:上4下5;10:上5下5 export function useElementPosition(element: any, count: number, totalCount: number, cardSize: { width: number, height: number }, windowSize: { width: number, height: number }, cardIndex: number) { - let xTable = 0 - let yTable = 0 - const centerPosition = { - x: 0, - y: windowSize.height / 2 - cardSize.height / 2, - } - // 有一行为偶数的特殊数量 - const specialPosition = [2, 4, 7, 9] - // 不包含特殊值的 和 分两行中第一行为奇数值的 - if (!specialPosition.includes(totalCount) || (totalCount > 5 && cardIndex < 5)) { - const index = cardIndex % 5 - if (index === 0) { - xTable = centerPosition.x - yTable = centerPosition.y - Math.floor(cardIndex / 5) * (cardSize.height + 60) + let xTable = 0 + let yTable = 0 + const centerPosition = { + x: 0, + y: windowSize.height / 2 - cardSize.height / 2, + } + // 有一行为偶数的特殊数量 + const specialPosition = [2, 4, 7, 9] + // 不包含特殊值的 和 分两行中第一行为奇数值的 + if (!specialPosition.includes(totalCount) || (totalCount > 5 && cardIndex < 5)) { + const index = cardIndex % 5 + if (index === 0) { + xTable = centerPosition.x + yTable = centerPosition.y - Math.floor(cardIndex / 5) * (cardSize.height + 60) + } + else { + xTable = index % 2 === 0 ? Math.ceil(index / 2) * (cardSize.width + 100) : -Math.ceil(index / 2) * (cardSize.width + 100) + yTable = centerPosition.y - Math.floor(cardIndex / 5) * (cardSize.height + 60) + } } else { - xTable = index % 2 === 0 ? Math.ceil(index / 2) * (cardSize.width + 100) : -Math.ceil(index / 2) * (cardSize.width + 100) - yTable = centerPosition.y - Math.floor(cardIndex / 5) * (cardSize.height + 60) + const index = cardIndex % 5 + if (index === 0) { + xTable = centerPosition.x + (cardSize.width + 100) / 2 + yTable = centerPosition.y - Math.floor(cardIndex / 5) * (cardSize.height + 60) + } + else { + xTable = index % 2 === 0 ? Math.ceil(index / 2) * (cardSize.width + 100) + (cardSize.width + 100) / 2 : -(Math.ceil(index / 2) * (cardSize.width + 100)) + (cardSize.width + 100) / 2 + yTable = centerPosition.y - Math.floor(cardIndex / 5) * (cardSize.height + 60) + } } - } - else { - const index = cardIndex % 5 - if (index === 0) { - xTable = centerPosition.x + (cardSize.width + 100) / 2 - yTable = centerPosition.y - Math.floor(cardIndex / 5) * (cardSize.height + 60) - } - else { - xTable = index % 2 === 0 ? Math.ceil(index / 2) * (cardSize.width + 100) + (cardSize.width + 100) / 2 : -(Math.ceil(index / 2) * (cardSize.width + 100)) + (cardSize.width + 100) / 2 - yTable = centerPosition.y - Math.floor(cardIndex / 5) * (cardSize.height + 60) - } - } - return { xTable, yTable } + return { xTable, yTable } } diff --git a/src/layout/index.vue b/src/layout/index.vue index 1025242..e24439f 100644 --- a/src/layout/index.vue +++ b/src/layout/index.vue @@ -5,10 +5,8 @@ import { useI18n } from 'vue-i18n' import CustomModal from '@/components/Dialog/index.vue' import { Loading } from '@/components/Loading' import ToTop from '@/components/ToTop/index.vue' -import { Toaster } from '@/components/ui/sonner' import RightButton from './RightButton/index.vue' import { useMounted } from './useMounted' -import 'vue-sonner/style.css' const tipDialog = ref() const { tipDesc } = useMounted(tipDialog) @@ -31,7 +29,6 @@ function scrollToTop() {
- diff --git a/src/store/globalConfig.ts b/src/store/globalConfig.ts index 3b423fa..ed5fe80 100644 --- a/src/store/globalConfig.ts +++ b/src/store/globalConfig.ts @@ -32,7 +32,7 @@ export const useGlobalConfig = defineStore('global', { imageList: defaultImageList as IImage[], }, currentMusic: { - item: defaultMusicList[0], + item: defaultMusicList[0] as IMusic, paused: true, }, } diff --git a/src/store/personConfig.ts b/src/store/personConfig.ts index 60365ba..215d2b9 100644 --- a/src/store/personConfig.ts +++ b/src/store/personConfig.ts @@ -2,7 +2,7 @@ import type { IPersonConfig, IPrizeConfig } from '@/types/storeType' import dayjs from 'dayjs' import { defineStore } from 'pinia' import { v4 as uuidv4 } from 'uuid' -import { computed, ref, toRaw, watch } from 'vue' +import { computed, ref, toRaw } from 'vue' import { IndexDb } from '@/utils/dexie' import { defaultPersonList } from './data' import { usePrizeConfig } from './prizeConfig' @@ -10,13 +10,13 @@ import { usePrizeConfig } from './prizeConfig' // 获取IPersonConfig的key组成数组 export const personListKey = Object.keys(defaultPersonList[0]) export const usePersonConfig = defineStore('person', () => { - const personDb = new IndexDb('person', ['allPersonList', 'alreadyPersonList'], 1, personListKey) + const personDb = new IndexDb('person', ['allPersonList', 'alreadyPersonList'], 1, ['createTime']) // NOTE: state const personConfig = ref({ allPersonList: [] as IPersonConfig[], alreadyPersonList: [] as IPersonConfig[], }) - personDb.getAllData('allPersonList').then((data) => { + personDb.getDataSortedByDateTime('allPersonList', 'createTime').then((data) => { personConfig.value.allPersonList = data }) personDb.getAllData('alreadyPersonList').then((data) => { @@ -51,7 +51,7 @@ export const usePersonConfig = defineStore('person', () => { return item.isWin === false })) // NOTE: action - // 添加未中奖人员 + // 添加全部未中奖人员 function addNotPersonList(personList: IPersonConfig[]) { if (personList.length <= 0) { return @@ -61,6 +61,20 @@ export const usePersonConfig = defineStore('person', () => { }) personDb.setAllData('allPersonList', personList) } + // 添加数据 + function addOnePerson(person: IPersonConfig[]) { + if (person.length <= 0) { + return + } + if (person.length > 1) { + console.warn('只支持添加单个用户') + return + } + person.forEach((item: IPersonConfig) => { + personConfig.value.allPersonList.push(item) + personDb.setData('allPersonList', item) + }) + } // 添加已中奖人员 function addAlreadyPersonList(personList: IPersonConfig[], prize: IPrizeConfig | null) { if (personList.length <= 0) { @@ -176,6 +190,7 @@ export const usePersonConfig = defineStore('person', () => { getAlreadyPersonDetail, getNotPersonList, addNotPersonList, + addOnePerson, addAlreadyPersonList, moveAlreadyToNot, deletePerson, diff --git a/src/utils/dexie/index.ts b/src/utils/dexie/index.ts index 704073b..28205f3 100644 --- a/src/utils/dexie/index.ts +++ b/src/utils/dexie/index.ts @@ -18,7 +18,7 @@ class IndexDb { // 获取存在的key const stores: Record = {} for (const tableName of tableNames) { - stores[tableName] = 'id,dateTime,type,uid' // 根据需要调整字段 + stores[tableName] = `id,dateTime,type,uid,${dbKeys.join(',')}` // 根据需要调整字段 } this.dbStore.version(this.version).stores(stores) } @@ -72,6 +72,12 @@ class IndexDb { return isAsc ? allData : allData.reverse() } + // 按 dateTime 排序获取所有数据 + async getDataSortedByDateTime(tableName: string, orderTimeName: string = 'dataTime') { + const allData = await this.dbStore[tableName].orderBy(orderTimeName).toArray() + return allData + } + // 分页获取数据 async getPageData(tableName: string, pageNum: number, pageSize: number, isAsc: boolean = true) { const allData = await this.dbStore[tableName].toArray() diff --git a/src/utils/index.ts b/src/utils/index.ts index 9138357..b863556 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -25,9 +25,9 @@ export function filterData(tableData: any[], localRowCount: number) { export function addOtherInfo(personList: any[]) { const len = personList.length for (let i = 0; i < len; i++) { - personList[i].id = i - personList[i].createTime = dayjs(new Date()).format('YYYY-MM-DD HH:mm:ss') - personList[i].updateTime = dayjs(new Date()).format('YYYY-MM-DD HH:mm:ss') + personList[i].id = uuidv4() + personList[i].createTime = dayjs(new Date()).format('YYYY-MM-DD HH:mm:ss:ms') + personList[i].updateTime = dayjs(new Date()).format('YYYY-MM-DD HH:mm:ss:ms') personList[i].prizeName = [] as string[] personList[i].prizeTime = [] as string[] personList[i].prizeId = [] diff --git a/src/views/Config/Global/FaceConfig/components/UploadDialog.vue b/src/views/Config/Global/FaceConfig/components/UploadDialog.vue index 64e7b65..918f0c5 100644 --- a/src/views/Config/Global/FaceConfig/components/UploadDialog.vue +++ b/src/views/Config/Global/FaceConfig/components/UploadDialog.vue @@ -43,7 +43,6 @@ function submitUpload() { if (jsonFileData.value) { // 把文件转化为json数据 const jsonData = jsonFileData.value.data - console.log('jsonData', jsonData) props.importAllConfigData(jsonData) } } diff --git a/src/views/Config/Person/PersonAll/components/SinglePerson.vue b/src/views/Config/Person/PersonAll/components/SinglePerson.vue new file mode 100644 index 0000000..ac87164 --- /dev/null +++ b/src/views/Config/Person/PersonAll/components/SinglePerson.vue @@ -0,0 +1,46 @@ + + + + + diff --git a/src/views/Config/Person/PersonAll/importExcel.worker.ts b/src/views/Config/Person/PersonAll/importExcel.worker.ts index c4f78c1..3df5cb4 100644 --- a/src/views/Config/Person/PersonAll/importExcel.worker.ts +++ b/src/views/Config/Person/PersonAll/importExcel.worker.ts @@ -10,8 +10,8 @@ interface WorkerMessage { let allData: any[] = [] function headersEqual(template: string[], actual: string[]): boolean { - return template.length === actual.length - && template.every((value, index) => value === actual[index]) + return template.length >= actual.length + && actual.some(item => template.includes(item)) } // 接收主线程消息 diff --git a/src/views/Config/Person/PersonAll/index.vue b/src/views/Config/Person/PersonAll/index.vue index 9367601..1600f98 100644 --- a/src/views/Config/Person/PersonAll/index.vue +++ b/src/views/Config/Person/PersonAll/index.vue @@ -4,13 +4,17 @@ import { ref } from 'vue' import { useI18n } from 'vue-i18n' import DaiysuiTable from '@/components/DaiysuiTable/index.vue' import CustomDialog from '@/components/Dialog/index.vue' +import CustomDrawer from '@/components/Drawer/index.vue' import PageHeader from '@/components/PageHeader/index.vue' +import SinglePersonContent from './components/SinglePerson.vue' import { useViewModel } from './useViewModel' const resetDataDialogRef = ref() const delAllDataDialogRef = ref() const exportInputFileRef = ref() -const { resetData, deleteAll, handleFileChange, exportData, alreadyPersonList, allPersonList, tableColumnList } = useViewModel({ exportInputFileRef }) +const addOnePersonDrawerRef = ref() +const baseUrl = import.meta.env.BASE_URL +const { resetData, deleteAll, handleFileChange, exportData, addOnePerson, singlePersonData, alreadyPersonList, allPersonList, tableColumnList } = useViewModel({ exportInputFileRef }) const { t } = useI18n() const limitType = '.xlsx,.xls' @@ -28,6 +32,15 @@ const limitType = '.xlsx,.xls' :desc="t('dialog.dialogDelAllPerson')" :submit-func="deleteAll" /> + + +
@@ -39,7 +52,7 @@ const limitType = '.xlsx,.xls'
@@ -60,6 +73,9 @@ const limitType = '.xlsx,.xls' +
{{ t('table.luckyPeopleNumber') }}: {{ alreadyPersonList.length }} diff --git a/src/views/Config/Person/PersonAll/useViewModel.ts b/src/views/Config/Person/PersonAll/useViewModel.ts index 7b28718..e071a08 100644 --- a/src/views/Config/Person/PersonAll/useViewModel.ts +++ b/src/views/Config/Person/PersonAll/useViewModel.ts @@ -1,30 +1,43 @@ import type { Ref } from 'vue' import type { IPersonConfig } from '@/types/storeType' import { storeToRefs } from 'pinia' -import { inject } from 'vue' -import { toast } from 'vue-sonner' +import { v4 as uuidv4 } from 'uuid' +import { inject, ref, toRaw } from 'vue' +import { useToast } from 'vue-toast-notification' import * as XLSX from 'xlsx' import { loadingKey } from '@/components/Loading' import i18n from '@/locales/i18n' import useStore from '@/store' +import { addOtherInfo } from '@/utils' import { readFileBinary, readLocalFileAsArraybuffer } from '@/utils/file' import { tableColumns } from './columns' import ImportExcelWorker from './importExcel.worker?worker' +type IBasePersonConfig = Pick + export function useViewModel({ exportInputFileRef }: { exportInputFileRef: Ref }) { + const toast = useToast() const worker: Worker | null = new ImportExcelWorker() const loading = inject(loadingKey) const personConfig = useStore().personConfig const { getAllPersonList: allPersonList, getAlreadyPersonList: alreadyPersonList } = storeToRefs(personConfig) const tableColumnList = tableColumns({ handleDeletePerson: delPersonItem }) + const addPersonModalVisible = ref(false) + const singlePersonData = ref({ + uid: '', + name: '', + department: '', + avatar: '', + identity: '', + }) async function getExcelTemplateContent() { const locale = i18n.global.locale.value if (locale === 'zhCn') { - const templateData = await readLocalFileAsArraybuffer('/log-lottery/人口登记表-zhCn.xlsx') + const templateData = await readLocalFileAsArraybuffer(`${import.meta.env.BASE_URL}人口登记表-zhCn.xlsx`) return templateData } else { - const templateData = await readLocalFileAsArraybuffer('/log-lottery/personListTemplate-en.xlsx') + const templateData = await readLocalFileAsArraybuffer(`${import.meta.env.BASE_URL}personListTemplate-en.xlsx`) return templateData } } @@ -53,7 +66,12 @@ export function useViewModel({ exportInputFileRef }: { exportInputFileRef: Ref