feat: 添加Loading效果
This commit is contained in:
@@ -1,11 +1,13 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { storeToRefs } from 'pinia'
|
import { storeToRefs } from 'pinia'
|
||||||
import { onMounted, ref } from 'vue'
|
import { onMounted, provide, ref } from 'vue'
|
||||||
import { useI18n } from 'vue-i18n'
|
import { useI18n } from 'vue-i18n'
|
||||||
|
import { loadingKey, loadingState } from '@/components/Loading'
|
||||||
import PlayMusic from '@/components/PlayMusic/index.vue'
|
import PlayMusic from '@/components/PlayMusic/index.vue'
|
||||||
import useStore from '@/store'
|
import useStore from '@/store'
|
||||||
import { themeChange } from '@/utils'
|
import { themeChange } from '@/utils'
|
||||||
|
|
||||||
|
provide(loadingKey, loadingState)
|
||||||
const { t } = useI18n()
|
const { t } = useI18n()
|
||||||
const globalConfig = useStore().globalConfig
|
const globalConfig = useStore().globalConfig
|
||||||
const prizeConfig = useStore().prizeConfig
|
const prizeConfig = useStore().prizeConfig
|
||||||
@@ -14,7 +16,6 @@ const { getTheme: localTheme } = storeToRefs(globalConfig)
|
|||||||
const { getPrizeConfig: prizeList } = storeToRefs(prizeConfig)
|
const { getPrizeConfig: prizeList } = storeToRefs(prizeConfig)
|
||||||
|
|
||||||
const tipDialog = ref()
|
const tipDialog = ref()
|
||||||
|
|
||||||
// 设置当前奖列表
|
// 设置当前奖列表
|
||||||
function setCurrentPrize() {
|
function setCurrentPrize() {
|
||||||
if (prizeList.value.length <= 0) {
|
if (prizeList.value.length <= 0) {
|
||||||
|
|||||||
1
src/components.d.ts
vendored
1
src/components.d.ts
vendored
@@ -13,6 +13,7 @@ declare module 'vue' {
|
|||||||
EditSeparateDialog: typeof import('./components/NumberSeparate/EditSeparateDialog.vue')['default']
|
EditSeparateDialog: typeof import('./components/NumberSeparate/EditSeparateDialog.vue')['default']
|
||||||
HelloWorld: typeof import('./components/HelloWorld.vue')['default']
|
HelloWorld: typeof import('./components/HelloWorld.vue')['default']
|
||||||
ImageSync: typeof import('./components/ImageSync/index.vue')['default']
|
ImageSync: typeof import('./components/ImageSync/index.vue')['default']
|
||||||
|
Loading: typeof import('./components/Loading/index.vue')['default']
|
||||||
PlayMusic: typeof import('./components/PlayMusic/index.vue')['default']
|
PlayMusic: typeof import('./components/PlayMusic/index.vue')['default']
|
||||||
RouterLink: typeof import('vue-router')['RouterLink']
|
RouterLink: typeof import('vue-router')['RouterLink']
|
||||||
RouterView: typeof import('vue-router')['RouterView']
|
RouterView: typeof import('vue-router')['RouterView']
|
||||||
|
|||||||
5
src/components/Loading/index.ts
Normal file
5
src/components/Loading/index.ts
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
import type { LoadingOptions } from './loading-context'
|
||||||
|
import Loading from './index.vue'
|
||||||
|
import { loadingKey, loadingState } from './loading-context'
|
||||||
|
|
||||||
|
export { Loading, loadingKey, LoadingOptions, loadingState }
|
||||||
22
src/components/Loading/index.vue
Normal file
22
src/components/Loading/index.vue
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
<script setup lang='ts'>
|
||||||
|
import type { LoadingOptions } from './loading-context'
|
||||||
|
import { inject } from 'vue'
|
||||||
|
import { loadingKey } from './loading-context'
|
||||||
|
|
||||||
|
// 注入全局状态
|
||||||
|
const loading = inject(loadingKey) as LoadingOptions
|
||||||
|
|
||||||
|
// 解构状态(响应式)
|
||||||
|
const { visible, text } = loading
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div v-if="visible" class="fixed top-0 left-0 w-screen h-screen bg-[rgba(0,0,0,0.5)] flex flex-col gap-6 justify-center items-center z-50">
|
||||||
|
<span v-if="visible" class="loading loading-spinner loading-xl" />
|
||||||
|
<span>{{ text ? text : '加载中' }}</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
</style>
|
||||||
61
src/components/Loading/loading-context.ts
Normal file
61
src/components/Loading/loading-context.ts
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
// src/contexts/loading-context.ts
|
||||||
|
import type { InjectionKey, Ref } from 'vue'
|
||||||
|
import { ref } from 'vue'
|
||||||
|
|
||||||
|
// 定义 Loading 配置类型
|
||||||
|
export interface LoadingOptions {
|
||||||
|
visible: Ref<boolean>
|
||||||
|
text: Ref<string>
|
||||||
|
fullscreen: Ref<boolean>
|
||||||
|
zIndex: Ref<number>
|
||||||
|
count: Ref<number>
|
||||||
|
show: (options?: Partial<{ text: string, fullscreen: boolean, zIndex: number }>) => void
|
||||||
|
hide: () => void
|
||||||
|
}
|
||||||
|
|
||||||
|
// 注入密钥(Symbol 确保唯一性)
|
||||||
|
export const loadingKey: InjectionKey<LoadingOptions> = Symbol('loading')
|
||||||
|
|
||||||
|
// 全局状态(单例)
|
||||||
|
const visible = ref(false)
|
||||||
|
const text = ref('')
|
||||||
|
const fullscreen = ref(true)
|
||||||
|
const zIndex = ref(9999)
|
||||||
|
const count = ref(0)
|
||||||
|
|
||||||
|
// 显示 Loading
|
||||||
|
function show(options?: Partial<{ text: string, fullscreen: boolean, zIndex: number }>) {
|
||||||
|
count.value++
|
||||||
|
if (count.value > 1)
|
||||||
|
return
|
||||||
|
visible.value = true
|
||||||
|
if (options) {
|
||||||
|
text.value = options.text || ''
|
||||||
|
fullscreen.value = options.fullscreen ?? true
|
||||||
|
zIndex.value = options.zIndex || 9999
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 隐藏 Loading
|
||||||
|
function hide() {
|
||||||
|
if (count.value <= 0)
|
||||||
|
return
|
||||||
|
count.value--
|
||||||
|
if (count.value === 0) {
|
||||||
|
visible.value = false
|
||||||
|
text.value = ''
|
||||||
|
fullscreen.value = true
|
||||||
|
zIndex.value = 9999
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 导出全局状态(供根组件提供)
|
||||||
|
export const loadingState: LoadingOptions = {
|
||||||
|
visible,
|
||||||
|
text,
|
||||||
|
fullscreen,
|
||||||
|
zIndex,
|
||||||
|
count,
|
||||||
|
show,
|
||||||
|
hide,
|
||||||
|
}
|
||||||
@@ -1,12 +1,12 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import ToTop from '@/components/ToTop/index.vue'
|
|
||||||
import { useScroll } from '@vueuse/core'
|
import { useScroll } from '@vueuse/core'
|
||||||
// import Header from './Header/index.vue';
|
// import Header from './Header/index.vue';
|
||||||
// import Footer from './Footer/index.vue';
|
// import Footer from './Footer/index.vue';
|
||||||
import { ref } from 'vue'
|
import { ref } from 'vue'
|
||||||
|
import { Loading } from '@/components/Loading'
|
||||||
|
import ToTop from '@/components/ToTop/index.vue'
|
||||||
|
|
||||||
const mainContainer = ref<HTMLElement | null>(null)
|
const mainContainer = ref<HTMLElement | null>(null)
|
||||||
|
|
||||||
const { y } = useScroll(mainContainer)
|
const { y } = useScroll(mainContainer)
|
||||||
|
|
||||||
function scrollToTop() {
|
function scrollToTop() {
|
||||||
@@ -19,6 +19,7 @@ function scrollToTop() {
|
|||||||
<!-- <header class="shadow-2xl head-container h-14">
|
<!-- <header class="shadow-2xl head-container h-14">
|
||||||
<Header></Header>
|
<Header></Header>
|
||||||
</header> -->
|
</header> -->
|
||||||
|
<Loading />
|
||||||
<ToTop v-if="y > 400" @click="scrollToTop" />
|
<ToTop v-if="y > 400" @click="scrollToTop" />
|
||||||
<main ref="mainContainer" class="box-content w-screen h-screen overflow-x-hidden overflow-y-auto main-container">
|
<main ref="mainContainer" class="box-content w-screen h-screen overflow-x-hidden overflow-y-auto main-container">
|
||||||
<router-view class="h-full main-container-content" />
|
<router-view class="h-full main-container-content" />
|
||||||
|
|||||||
16
src/main.ts
16
src/main.ts
@@ -1,20 +1,20 @@
|
|||||||
import svgIcon from '@/components/SvgIcon/index.vue'
|
// pinia
|
||||||
import i18n from '@/locales/i18n'
|
import { createPinia } from 'pinia'
|
||||||
|
// pinia持久化
|
||||||
|
import piniaPluginPersist from 'pinia-plugin-persist'
|
||||||
import * as THREE from 'three'
|
import * as THREE from 'three'
|
||||||
import { createApp } from 'vue'
|
import { createApp } from 'vue'
|
||||||
import VueDOMPurifyHTML from 'vue-dompurify-html'
|
import VueDOMPurifyHTML from 'vue-dompurify-html'
|
||||||
|
import svgIcon from '@/components/SvgIcon/index.vue'
|
||||||
|
import i18n from '@/locales/i18n'
|
||||||
|
// svg全局组件// 路由
|
||||||
|
import router from '@/router'
|
||||||
import App from './App.vue'
|
import App from './App.vue'
|
||||||
import './style.css'
|
import './style.css'
|
||||||
import './style/markdown.css'
|
import './style/markdown.css'
|
||||||
import './style/style.scss'
|
import './style/style.scss'
|
||||||
// 全局svg组件
|
// 全局svg组件
|
||||||
import 'virtual:svg-icons-register'
|
import 'virtual:svg-icons-register'
|
||||||
// svg全局组件// 路由
|
|
||||||
import router from '@/router'
|
|
||||||
// pinia
|
|
||||||
import { createPinia } from 'pinia'
|
|
||||||
// pinia持久化
|
|
||||||
import piniaPluginPersist from 'pinia-plugin-persist'
|
|
||||||
|
|
||||||
const app = createApp(App)
|
const app = createApp(App)
|
||||||
const pinia = createPinia()
|
const pinia = createPinia()
|
||||||
|
|||||||
@@ -27,6 +27,11 @@ globalThis.onmessage = async (e: MessageEvent<WorkerMessage>) => {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
globalThis.postMessage({
|
||||||
|
type: 'fail',
|
||||||
|
data: null,
|
||||||
|
message: '读取失败',
|
||||||
|
})
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,12 +6,12 @@ import DaiysuiTable from '@/components/DaiysuiTable/index.vue'
|
|||||||
import CustomDialog from '@/components/Dialog/index.vue'
|
import CustomDialog from '@/components/Dialog/index.vue'
|
||||||
import { useViewModel } from './useViewModel'
|
import { useViewModel } from './useViewModel'
|
||||||
|
|
||||||
const { resetData, deleteAll, handleFileChange, exportData, alreadyPersonList, allPersonList, tableColumns } = useViewModel()
|
|
||||||
const { t } = useI18n()
|
|
||||||
const limitType = '.xlsx,.xls'
|
|
||||||
|
|
||||||
const resetDataDialogRef = ref()
|
const resetDataDialogRef = ref()
|
||||||
const delAllDataDialogRef = ref()
|
const delAllDataDialogRef = ref()
|
||||||
|
const exportInputFileRef = ref()
|
||||||
|
const { resetData, deleteAll, handleFileChange, exportData, alreadyPersonList, allPersonList, tableColumns } = useViewModel({ exportInputFileRef })
|
||||||
|
const { t } = useI18n()
|
||||||
|
const limitType = '.xlsx,.xls'
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@@ -45,8 +45,8 @@ const delAllDataDialogRef = ref()
|
|||||||
|
|
||||||
<div class="tooltip tooltip-bottom" :data-tip="t('tooltip.uploadExcelTip')">
|
<div class="tooltip tooltip-bottom" :data-tip="t('tooltip.uploadExcelTip')">
|
||||||
<input
|
<input
|
||||||
id="explore" type="file" class="" style="display: none" :accept="limitType"
|
id="explore" ref="exportInputFileRef" type="file" class="" style="display: none"
|
||||||
@change="handleFileChange"
|
:accept="limitType" @change="handleFileChange"
|
||||||
>
|
>
|
||||||
|
|
||||||
<span class="btn btn-primary btn-sm">{{ t('button.importData') }}</span>
|
<span class="btn btn-primary btn-sm">{{ t('button.importData') }}</span>
|
||||||
|
|||||||
@@ -1,153 +1,167 @@
|
|||||||
|
import type { Ref } from 'vue'
|
||||||
import type { IPersonConfig } from '@/types/storeType'
|
import type { IPersonConfig } from '@/types/storeType'
|
||||||
import { storeToRefs } from 'pinia'
|
import { storeToRefs } from 'pinia'
|
||||||
|
import { inject } from 'vue'
|
||||||
import * as XLSX from 'xlsx'
|
import * as XLSX from 'xlsx'
|
||||||
|
import { loadingKey } from '@/components/Loading'
|
||||||
import i18n from '@/locales/i18n'
|
import i18n from '@/locales/i18n'
|
||||||
import useStore from '@/store'
|
import useStore from '@/store'
|
||||||
import { readFileBinary } from '@/utils/file'
|
import { readFileBinary } from '@/utils/file'
|
||||||
import ImportExcelWorker from './importExcel.worker?worker'
|
import ImportExcelWorker from './importExcel.worker?worker'
|
||||||
|
|
||||||
export function useViewModel() {
|
export function useViewModel({ exportInputFileRef }: { exportInputFileRef: Ref<HTMLInputElement> }) {
|
||||||
const worker: Worker | null = new ImportExcelWorker()
|
const worker: Worker | null = new ImportExcelWorker()
|
||||||
const personConfig = useStore().personConfig
|
const loading = inject(loadingKey)
|
||||||
const { getAllPersonList: allPersonList, getAlreadyPersonList: alreadyPersonList } = storeToRefs(personConfig)
|
const personConfig = useStore().personConfig
|
||||||
const tableColumns = [
|
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 ? `<img src="${row.avatar}" alt="avatar" style="width: 50px; height: 50px;"/>` : '-'
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
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'),
|
label: i18n.global.t('data.number'),
|
||||||
type: 'btn-error',
|
props: 'uid',
|
||||||
onClick: (row: IPersonConfig) => {
|
|
||||||
delPersonItem(row)
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
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 ? `<img src="${row.avatar}" alt="avatar" style="width: 50px; height: 50px;"/>` : '-'
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
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发送消息
|
/// 向worker发送消息
|
||||||
function sendWorkerMessage(message: any) {
|
function sendWorkerMessage(message: any) {
|
||||||
if (worker) {
|
if (worker) {
|
||||||
worker.postMessage(message)
|
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 startWorker(data: Event) {
|
||||||
}
|
loading?.show()
|
||||||
/// 导出数据
|
sendWorkerMessage({ type: 'start', data })
|
||||||
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'))
|
async function handleFileChange(e: Event) {
|
||||||
.replaceAll(/department/g, i18n.global.t('data.department'))
|
// worker = new ImportExcelWorker()
|
||||||
.replaceAll(/name/g, i18n.global.t('data.name'))
|
if (worker) {
|
||||||
.replaceAll(/identity/g, i18n.global.t('data.identity'))
|
worker.onmessage = (e) => {
|
||||||
.replaceAll(/prizeName/g, i18n.global.t('data.prizeName'))
|
if (e.data.type === 'done') {
|
||||||
.replaceAll(/prizeTime/g, i18n.global.t('data.prizeTime'))
|
personConfig.resetPerson()
|
||||||
|
personConfig.addNotPersonList(e.data.data)
|
||||||
data = JSON.parse(dataString)
|
// 导入成功后清空file input
|
||||||
|
clearFileInput()
|
||||||
if (data.length > 0) {
|
}
|
||||||
const dataBinary = XLSX.utils.json_to_sheet(data)
|
loading?.hide()
|
||||||
const dataBinaryBinary = XLSX.utils.book_new()
|
}
|
||||||
XLSX.utils.book_append_sheet(dataBinaryBinary, dataBinary, 'Sheet1')
|
}
|
||||||
XLSX.writeFile(dataBinaryBinary, 'data.xlsx')
|
const dataBinary = await readFileBinary(((e.target as HTMLInputElement).files as FileList)[0]!)
|
||||||
|
startWorker(dataBinary)
|
||||||
}
|
}
|
||||||
}
|
// 清空file input
|
||||||
|
function clearFileInput() {
|
||||||
|
if (exportInputFileRef.value) {
|
||||||
|
exportInputFileRef.value.value = ''
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// 导出数据
|
||||||
|
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'))
|
||||||
|
|
||||||
function resetData() {
|
data = JSON.parse(dataString)
|
||||||
personConfig.resetAlreadyPerson()
|
|
||||||
}
|
|
||||||
|
|
||||||
function deleteAll() {
|
if (data.length > 0) {
|
||||||
personConfig.deleteAllPerson()
|
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 delPersonItem(row: IPersonConfig) {
|
function resetData() {
|
||||||
personConfig.deletePerson(row)
|
personConfig.resetAlreadyPerson()
|
||||||
}
|
}
|
||||||
return {
|
|
||||||
resetData,
|
function deleteAll() {
|
||||||
deleteAll,
|
personConfig.deleteAllPerson()
|
||||||
handleFileChange,
|
}
|
||||||
exportData,
|
|
||||||
alreadyPersonList,
|
function delPersonItem(row: IPersonConfig) {
|
||||||
allPersonList,
|
personConfig.deletePerson(row)
|
||||||
tableColumns,
|
}
|
||||||
}
|
return {
|
||||||
|
resetData,
|
||||||
|
deleteAll,
|
||||||
|
handleFileChange,
|
||||||
|
exportData,
|
||||||
|
alreadyPersonList,
|
||||||
|
allPersonList,
|
||||||
|
tableColumns,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
7
src/vite-env.d.ts
vendored
7
src/vite-env.d.ts
vendored
@@ -1,11 +1,12 @@
|
|||||||
/// <reference types="vite/client" />
|
/// <reference types="vite/client" />
|
||||||
|
|
||||||
declare module '*.vue' {
|
declare module '*.vue' {
|
||||||
import type { DefineComponent } from 'vue'
|
import type { DefineComponent } from 'vue'
|
||||||
|
|
||||||
const component: DefineComponent<object, object, any>
|
const component: DefineComponent<object, object, any>
|
||||||
export default component
|
export default component
|
||||||
}
|
}
|
||||||
|
|
||||||
declare module 'sparticles'
|
declare module 'sparticles'
|
||||||
declare module 'three-trackballcontrols'
|
declare module 'three-trackballcontrols'
|
||||||
|
declare module 'virtual:svg-icons-register'
|
||||||
|
|||||||
Reference in New Issue
Block a user