feat: 国际化
This commit is contained in:
2
.github/workflows/node.js.yml
vendored
2
.github/workflows/node.js.yml
vendored
@@ -4,8 +4,6 @@
|
||||
name: Node.js CI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ "main" ]
|
||||
pull_request:
|
||||
branches: [ "main" ]
|
||||
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
"three-css3d": "^1.0.6",
|
||||
"vue": "^3.4.31",
|
||||
"vue-dompurify-html": "^5.1.0",
|
||||
"vue-i18n": "^10.0.4",
|
||||
"vue-router": "^4.4.0",
|
||||
"vue-toast-notification": "^3",
|
||||
"vue3-colorpicker": "^2.3.0",
|
||||
|
||||
56
pnpm-lock.yaml
generated
56
pnpm-lock.yaml
generated
@@ -56,6 +56,9 @@ importers:
|
||||
vue-dompurify-html:
|
||||
specifier: ^5.1.0
|
||||
version: 5.1.0(vue@3.4.31(typescript@5.5.3))
|
||||
vue-i18n:
|
||||
specifier: ^10.0.4
|
||||
version: 10.0.4(vue@3.4.31(typescript@5.5.3))
|
||||
vue-router:
|
||||
specifier: ^4.4.0
|
||||
version: 4.4.0(vue@3.4.31(typescript@5.5.3))
|
||||
@@ -565,6 +568,18 @@ packages:
|
||||
'@iconify/utils@2.1.25':
|
||||
resolution: {integrity: sha512-Y+iGko8uv/Fz5bQLLJyNSZGOdMW0G7cnlEX1CiNcKsRXX9cq/y/vwxrIAtLCZhKHr3m0VJmsjVPsvnM4uX8YLg==}
|
||||
|
||||
'@intlify/core-base@10.0.4':
|
||||
resolution: {integrity: sha512-GG428DkrrWCMhxRMRQZjuS7zmSUzarYcaHJqG9VB8dXAxw4iQDoKVQ7ChJRB6ZtsCsX3Jse1PEUlHrJiyQrOTg==}
|
||||
engines: {node: '>= 16'}
|
||||
|
||||
'@intlify/message-compiler@10.0.4':
|
||||
resolution: {integrity: sha512-AFbhEo10DP095/45EauinQJ5hJ3rJUmuuqltGguvc3WsvezZN+g8qNHLGWKu60FHQVizMrQY7VJ+zVlBXlQQkQ==}
|
||||
engines: {node: '>= 16'}
|
||||
|
||||
'@intlify/shared@10.0.4':
|
||||
resolution: {integrity: sha512-ukFn0I01HsSgr3VYhYcvkTCLS7rGa0gw4A4AMpcy/A9xx/zRJy7PS2BElMXLwUazVFMAr5zuiTk3MQeoeGXaJg==}
|
||||
engines: {node: '>= 16'}
|
||||
|
||||
'@isaacs/cliui@8.0.2':
|
||||
resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==}
|
||||
engines: {node: '>=12'}
|
||||
@@ -1034,6 +1049,7 @@ packages:
|
||||
|
||||
acorn-import-assertions@1.9.0:
|
||||
resolution: {integrity: sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA==}
|
||||
deprecated: package has been renamed to acorn-import-attributes
|
||||
peerDependencies:
|
||||
acorn: ^8
|
||||
|
||||
@@ -3230,11 +3246,6 @@ packages:
|
||||
uglify-js:
|
||||
optional: true
|
||||
|
||||
terser@5.24.0:
|
||||
resolution: {integrity: sha512-ZpGR4Hy3+wBEzVEnHvstMvqpD/nABNelQn/z2r0fjVWGQsN3bpOLzQlqDxmb4CDZnXq5lpjnQ+mHQLAOpfM5iw==}
|
||||
engines: {node: '>=10'}
|
||||
hasBin: true
|
||||
|
||||
terser@5.31.1:
|
||||
resolution: {integrity: sha512-37upzU1+viGvuFtBo9NPufCb9dwM0+l9hMxYyWfBA+fbwrPqNJAhbZ6W47bBFnZHKHTUBnMvi87434qq+qnxOg==}
|
||||
engines: {node: '>=10'}
|
||||
@@ -3590,6 +3601,12 @@ packages:
|
||||
peerDependencies:
|
||||
eslint: '>=6.0.0'
|
||||
|
||||
vue-i18n@10.0.4:
|
||||
resolution: {integrity: sha512-1xkzVxqBLk2ZFOmeI+B5r1J7aD/WtNJ4j9k2mcFcQo5BnOmHBmD7z4/oZohh96AAaRZ4Q7mNQvxc9h+aT+Md3w==}
|
||||
engines: {node: '>= 16'}
|
||||
peerDependencies:
|
||||
vue: ^3.0.0
|
||||
|
||||
vue-router@4.4.0:
|
||||
resolution: {integrity: sha512-HB+t2p611aIZraV2aPSRNXf0Z/oLZFrlygJm+sZbdJaW6lcFqEDQwnzUBXn+DApw+/QzDU/I9TeWx9izEjTmsA==}
|
||||
peerDependencies:
|
||||
@@ -4166,6 +4183,18 @@ snapshots:
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
'@intlify/core-base@10.0.4':
|
||||
dependencies:
|
||||
'@intlify/message-compiler': 10.0.4
|
||||
'@intlify/shared': 10.0.4
|
||||
|
||||
'@intlify/message-compiler@10.0.4':
|
||||
dependencies:
|
||||
'@intlify/shared': 10.0.4
|
||||
source-map-js: 1.2.0
|
||||
|
||||
'@intlify/shared@10.0.4': {}
|
||||
|
||||
'@isaacs/cliui@8.0.2':
|
||||
dependencies:
|
||||
string-width: 5.1.2
|
||||
@@ -7042,18 +7071,10 @@ snapshots:
|
||||
jest-worker: 27.5.1
|
||||
schema-utils: 3.3.0
|
||||
serialize-javascript: 6.0.1
|
||||
terser: 5.24.0
|
||||
terser: 5.31.1
|
||||
webpack: 5.89.0
|
||||
optional: true
|
||||
|
||||
terser@5.24.0:
|
||||
dependencies:
|
||||
'@jridgewell/source-map': 0.3.5
|
||||
acorn: 8.12.0
|
||||
commander: 2.20.3
|
||||
source-map-support: 0.5.21
|
||||
optional: true
|
||||
|
||||
terser@5.31.1:
|
||||
dependencies:
|
||||
'@jridgewell/source-map': 0.3.5
|
||||
@@ -7437,6 +7458,13 @@ snapshots:
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
vue-i18n@10.0.4(vue@3.4.31(typescript@5.5.3)):
|
||||
dependencies:
|
||||
'@intlify/core-base': 10.0.4
|
||||
'@intlify/shared': 10.0.4
|
||||
'@vue/devtools-api': 6.5.1
|
||||
vue: 3.4.31(typescript@5.5.3)
|
||||
|
||||
vue-router@4.4.0(vue@3.4.31(typescript@5.5.3)):
|
||||
dependencies:
|
||||
'@vue/devtools-api': 6.5.1
|
||||
|
||||
31
public/readme-en.md
Normal file
31
public/readme-en.md
Normal file
@@ -0,0 +1,31 @@
|
||||
# Operation Guide
|
||||
|
||||
## Steps
|
||||
|
||||
1. Upon first entry, no data will be displayed. You can choose to use default data to view the overall display effect. It is recommended to import your own data for operation. The steps are as follows:
|
||||
|
||||
a. Personnel Configuration - Personnel List - Download Template, download the data template and modify it with your data (please note that the header cannot be modified).
|
||||
|
||||
b. After modification, click 'Upload File' on the same page to upload the modified Excel table.
|
||||
|
||||
2. Enter the Prize Configuration to modify your prize information. Try to keep the name short for better display; "All Participants" indicates whether this award will be drawn from all participants (those who have already won can still participate); "Winners" refers to the number of people to be drawn for this award; "Already Won" cannot be edited; "Selected" means this award has been used, unselecting it will reset the award but not the winners; "Image" is the prize image displayed on the home page (you can upload images in the image list); "Left Icon" is used to adjust the order of prizes.
|
||||
|
||||
Completing the above two steps allows normal use.
|
||||
|
||||
## Function Description
|
||||
|
||||
1. Add Temporary Draw: There is a '+' button in the prize list on the draw page. Clicking it allows you to add a temporary draw. Note: Only one temporary draw can be added at a time. After adding successfully, the current prize will be set to the temporary prize, and after drawing, it will return to the normal prize list.
|
||||
2. Music and Image List: You can upload files yourself for use. After uploading images successfully, you can select them in the prize configuration for display. After uploading music successfully, it will be added to the play list.
|
||||
3. Music Playback: Left-click with the mouse to play/pause, right-click to play the next song.
|
||||
4. Interface Configuration - Pattern Settings: You can use the mouse to click and customize the highlighted patterns on the home page.
|
||||
5. If you do not want to display the prize list on the home page, uncheck 'Always Show Prize List' in the interface configuration.
|
||||
6. When clicking buttons on the home page, the button value will not update immediately but will only update after the animation ends. This is a normal phenomenon.
|
||||
|
||||
## Shortcuts
|
||||
|
||||
Shortcuts are set up on the draw page.
|
||||
|
||||
| Shortcut | Description |
|
||||
| --- | --- |
|
||||
| Space | Enter Draw / Start / Draw Lucky Winner / Continue |
|
||||
| Esc | Cancel |
|
||||
BIN
public/人口登记表-zhCn.xlsx
Normal file
BIN
public/人口登记表-zhCn.xlsx
Normal file
Binary file not shown.
@@ -66,13 +66,13 @@ onMounted(() => {
|
||||
<template>
|
||||
<dialog id="my_modal_1" ref="tipDialog" class="border-none modal">
|
||||
<div class="modal-box">
|
||||
<h3 class="text-lg font-bold">提示!</h3>
|
||||
<p class="py-4" v-if="judgeMobile()">请使用PC进行访问以获得最佳显示效果</p>
|
||||
<p class="py-4" v-if=" !judgeChromeOrEdge()">请使用最新版Chrome或者Edge浏览器</p>
|
||||
<h3 class="text-lg font-bold">{{ $t('dialog.titleTip') }}</h3>
|
||||
<p class="py-4" v-if="judgeMobile()">{{ $t('dialog.dialogPCWeb') }}</p>
|
||||
<p class="py-4" v-if=" !judgeChromeOrEdge()">{{ $t('dialog.dialogLatestBrowser') }}</p>
|
||||
<div class="modal-action">
|
||||
<form method="dialog" class="flex justify-start w-full gap-3">
|
||||
<!-- if there is a button in form, it will close the modal -->
|
||||
<button class="btn">确定</button>
|
||||
<button class="btn">{{ $t('button.confirm') }}</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -94,7 +94,7 @@ watch(currentMusic, (val: any) => {
|
||||
|
||||
<template>
|
||||
<div class="flex flex-col gap-3" ref="settingRef">
|
||||
<div v-if="route.path.includes('/config')" class="tooltip tooltip-left" data-tip="主页">
|
||||
<div v-if="route.path.includes('/config')" class="tooltip tooltip-left" :data-tip="$t('tooltip.toHome')">
|
||||
<div class="flex items-center justify-center w-10 h-10 p-0 m-0 cursor-pointer setting-container bg-slate-500/50 rounded-l-xl hover:bg-slate-500/80 hover:text-blue-400/90"
|
||||
@click="enterHome">
|
||||
<svg-icon name="home"></svg-icon>
|
||||
|
||||
111
src/locales/en.ts
Normal file
111
src/locales/en.ts
Normal file
@@ -0,0 +1,111 @@
|
||||
export default {
|
||||
button: {
|
||||
enterLottery: 'Enter Lottery',
|
||||
start:'Start',
|
||||
selectLucky:'Draw the Lucky',
|
||||
continue: 'Continue',
|
||||
confirm: 'Confirm',
|
||||
cancel: 'Cancel',
|
||||
setting: 'Setting',
|
||||
delete: 'Delete',
|
||||
allDelete: 'Delete All',
|
||||
downloadTemplate: 'Download Template',
|
||||
importData: 'Import Data',
|
||||
resetData: 'Reset Data',
|
||||
exportResult: 'Export Result',
|
||||
add: 'Add',
|
||||
resetDefault: 'Reset Default',
|
||||
resetAllData: 'Reset All Data',
|
||||
clearPattern: 'Clear Pattern',
|
||||
DefaultPattern: 'Default Pattern',
|
||||
upload: 'Upload',
|
||||
reset: 'Reset',
|
||||
play: 'Play',
|
||||
setLayout:'Set Layout',
|
||||
close:'Close'
|
||||
},
|
||||
sidebar:{
|
||||
personConfiguration:'Person Configuration',
|
||||
personList:'Person List',
|
||||
winnerList:'Winner List',
|
||||
prizeConfiguration:'Prize Configuration',
|
||||
globalSetting:'Global Configuration',
|
||||
viewSetting:'View Setting',
|
||||
imagesManagement:'Images Management',
|
||||
musicManagement:'Music Management',
|
||||
operatingInstructions:'Operating Instructions'
|
||||
},
|
||||
viewTitle:{
|
||||
personManagement:'Person Management',
|
||||
winnerManagement:'Winner Management',
|
||||
prizeManagement:'Prize Management',
|
||||
globalSetting:'Global Setting',
|
||||
operatingInstructions:'Operating Instructions'
|
||||
},
|
||||
table:{
|
||||
// person configuration
|
||||
number:'Number',
|
||||
name:'Name',
|
||||
prizeName:'Name',
|
||||
department:'Department',
|
||||
identity:'Identity',
|
||||
isLucky:'Is Lucky',
|
||||
operation:'Operation',
|
||||
luckyPeopleNumber:'Lucky People Number',
|
||||
|
||||
detail:'Detail',
|
||||
// prize configuration
|
||||
fullParticipation:'FullParticipation',
|
||||
numberParticipants:'NumberParticipants',
|
||||
isDone:'is Done',
|
||||
image:'Image',
|
||||
onceNumber:'Once Number',
|
||||
time:'Time',
|
||||
// view setting
|
||||
title:'Main Title',
|
||||
columnNumber:'Column Number',
|
||||
theme:'Theme',
|
||||
language:'Language',
|
||||
cardColor:'Card Color',
|
||||
winnerColor:'Winner Color',
|
||||
textColor:'Text Color',
|
||||
cardWidth:'Card Width',
|
||||
cardHeight:'Card Height',
|
||||
textSize:'Text Size',
|
||||
highlightColor:'HighLight Color',
|
||||
patternSetting:'Pattern Setting',
|
||||
alwaysDisplay:'Always Display Prize List',
|
||||
},
|
||||
dialog:{
|
||||
titleTip:'Tip!',
|
||||
titleTemporary:'Add Temporary Activity',
|
||||
dialogPCWeb:'Please use a PC browser to access for optimal display performance',
|
||||
dialogDelAllPerson:'This operation will delete all personnel list data. Do you want to continue?',
|
||||
dialogResetWinner:'This operation will clear the winning information of personnel. Do you want to continue?',
|
||||
dialogResetAllData:'This operation will reset all data. Do you want to continue?',
|
||||
dialogSingleDrawLimit:'Only 10 characters can be extracted in a single draw',
|
||||
dialogLatestBrowser:'Please use the latest version of Chrome or Edge browser',
|
||||
tipResetPrize:'Performing operations may reset data, please proceed with caution',
|
||||
},
|
||||
tooltip:{
|
||||
settingConfiguration:'Setting/Configuration',
|
||||
nextSong:'Right Click to Next Song',
|
||||
noSongPlay:'No Song to Play',
|
||||
prizeList:'Prize List',
|
||||
addActivity:'Add Activity',
|
||||
downloadTemplateTip:'After downloading the file, please fill in the data in Excel and save it in xlsx format',
|
||||
uploadExcelTip:'Upload the modified Excel file',
|
||||
leftClick:'Left Click to Slice',
|
||||
toHome:'to Home',
|
||||
resetLayout:'This item is time-consuming and performance intensive',
|
||||
defaultLayout:'The default pattern setting is valid for 17 columns, please set the number of other columns yourself',
|
||||
doneCount:'Number of winners',
|
||||
edit:'Edit',
|
||||
delete:'Delete'
|
||||
},
|
||||
|
||||
footer:{
|
||||
'self-reflection':'Turn inward and examine yourself when you encounter difficulties in life.',
|
||||
'thiefEasy':'Thief difficult mountain thief easily, breaking heart.'
|
||||
}
|
||||
}
|
||||
29
src/locales/i18n.ts
Normal file
29
src/locales/i18n.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
// i18n配置
|
||||
import { createI18n } from "vue-i18n";
|
||||
import zhCn from "./zhCn";
|
||||
import en from "./en";
|
||||
export type Language='en'|'zhCn'
|
||||
|
||||
export const languageList=[
|
||||
{
|
||||
key:'zhCn',
|
||||
name:'中文'
|
||||
},
|
||||
{
|
||||
key:'en',
|
||||
name:'English'
|
||||
}
|
||||
]
|
||||
// 创建i18n
|
||||
const i18n = createI18n({
|
||||
locale: JSON.parse(localStorage.getItem("globalConfig")?localStorage.getItem("globalConfig") as string:"{globalConfig:{language:'zhCn'}}").globalConfig.language || "zhCn", // 语言标识
|
||||
globalInjection: true, // 全局注入,可以直接使用$t
|
||||
// 处理报错: Uncaught (in promise) SyntaxError: Not available in legacy mode (at message-compiler.esm-bundler.js:54:19)
|
||||
legacy:false,
|
||||
messages: {
|
||||
zhCn,
|
||||
en
|
||||
}
|
||||
})
|
||||
|
||||
export default i18n;
|
||||
111
src/locales/zhCn.ts
Normal file
111
src/locales/zhCn.ts
Normal file
@@ -0,0 +1,111 @@
|
||||
export default {
|
||||
button: {
|
||||
enterLottery: '进入抽奖',
|
||||
start:'开始',
|
||||
selectLucky:'抽取幸运儿',
|
||||
continue: '继续',
|
||||
confirm: '确认',
|
||||
cancel: '取消',
|
||||
setting: '设置',
|
||||
delete: '删除',
|
||||
allDelete: '删除全部',
|
||||
downloadTemplate: '下载模板',
|
||||
importData: '导入数据',
|
||||
resetData: '重置数据',
|
||||
exportResult: '导出结果',
|
||||
add: '添加',
|
||||
resetDefault: '重置为默认',
|
||||
resetAllData: '重置所有数据',
|
||||
clearPattern: '清除图案',
|
||||
DefaultPattern: '默认图案',
|
||||
upload: '上传',
|
||||
reset: '重置',
|
||||
play: '播放',
|
||||
setLayout:'重设布局',
|
||||
close:'关闭'
|
||||
},
|
||||
sidebar:{
|
||||
personConfiguration:'人员配置',
|
||||
personList:'人员列表',
|
||||
winnerList:'中奖人员',
|
||||
prizeConfiguration:'奖品配置',
|
||||
globalSetting:'全局配置',
|
||||
viewSetting:'界面设置',
|
||||
imagesManagement:'图片管理',
|
||||
musicManagement:'音乐管理',
|
||||
operatingInstructions:'操作说明'
|
||||
},
|
||||
viewTitle:{
|
||||
personManagement:'人员管理',
|
||||
winnerManagement:'已中奖人员管理',
|
||||
prizeManagement:'奖项配置',
|
||||
globalSetting:'全局配置',
|
||||
operatingInstructions:'操作说明'
|
||||
},
|
||||
table:{
|
||||
// person configuration
|
||||
number:'编号',
|
||||
name:'姓名',
|
||||
prizeName:'名称',
|
||||
department:'部门',
|
||||
identity:'身份',
|
||||
isLucky:'是否中奖',
|
||||
operation:'操作',
|
||||
luckyPeopleNumber:'中奖人数',
|
||||
|
||||
detail:'详细信息',
|
||||
// prize configuration
|
||||
fullParticipation:'全员参加',
|
||||
numberParticipants:'抽奖人数',
|
||||
isDone:'已抽取',
|
||||
image:'图片',
|
||||
onceNumber:'单次抽取个数',
|
||||
time:'时间',
|
||||
// view setting
|
||||
title:'主标题',
|
||||
columnNumber:'列数',
|
||||
theme:'主题',
|
||||
language:'语言',
|
||||
cardColor:'卡片颜色',
|
||||
winnerColor:'中奖卡片颜色',
|
||||
textColor:'文字颜色',
|
||||
cardWidth:'卡片宽度',
|
||||
cardHeight:'卡片高度',
|
||||
textSize:'文字大小',
|
||||
highlightColor:'高亮颜色',
|
||||
patternSetting:'图案设置',
|
||||
alwaysDisplay:'常显奖项列表',
|
||||
},
|
||||
dialog:{
|
||||
titleTip:'提示!',
|
||||
titleTemporary:'增加临时抽奖',
|
||||
dialogPCWeb:'请使用PC进行访问以获得最佳显示效果',
|
||||
dialogDelAllPerson:'该操作会删除所有人员数据,是否继续?',
|
||||
dialogResetWinner:'该操作会清空人员中奖信息,是否继续?',
|
||||
dialogResetAllData:'该操作会重置所有数据,是否继续?',
|
||||
dialogSingleDrawLimit:'单次抽取只能抽取10位',
|
||||
dialogLatestBrowser:'请使用最新版Chrome或者Edge浏览器',
|
||||
tipResetPrize:'进行操作可能会重置数据,请谨慎操作',
|
||||
},
|
||||
tooltip:{
|
||||
settingConfiguration:'设置/配置',
|
||||
nextSong:'右键点击下一首',
|
||||
noSongPlay:'没有音乐可以播放',
|
||||
prizeList:'奖项列表',
|
||||
addActivity:'添加抽奖',
|
||||
downloadTemplateTip:'下载文件后,请在excel中填写数据,并保存为xlsx格式',
|
||||
uploadExcelTip:'上传修改好的excel文件',
|
||||
leftClick:'左键切割',
|
||||
toHome:'主页',
|
||||
resetLayout:'该项比较耗费时间和性能',
|
||||
defaultLayout:'默认图案设置针对17列时有效,其他列数请自行设置',
|
||||
doneCount:'已抽取',
|
||||
edit:'编辑',
|
||||
delete:'删除'
|
||||
},
|
||||
|
||||
footer:{
|
||||
'self-reflection':'行有不得,反求诸己',
|
||||
'thiefEasy':'破山中贼易,破心中贼难'
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,7 @@ import './style/style.scss'
|
||||
import * as THREE from 'three';
|
||||
import App from './App.vue';
|
||||
import VueDOMPurifyHTML from 'vue-dompurify-html'
|
||||
import i18n from '@/locales/i18n'
|
||||
|
||||
const app = createApp(App);
|
||||
// 全局svg组件
|
||||
@@ -21,4 +22,4 @@ pinia.use(piniaPluginPersist);
|
||||
|
||||
app.config.globalProperties.$THREE = THREE; //挂载到原型
|
||||
app.component('svg-icon', svgIcon);
|
||||
app.use(router).use(VueDOMPurifyHTML).use(pinia).mount('#app');
|
||||
app.use(router).use(VueDOMPurifyHTML).use(pinia).use(i18n).mount('#app');
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { createRouter, createWebHistory } from 'vue-router';
|
||||
import Layout from '@/layout/index.vue';
|
||||
import Home from '@/views/Home/index.vue';
|
||||
import i18n from '@/locales/i18n'
|
||||
export const configRoutes={
|
||||
path: '/log-lottery/config',
|
||||
name: 'Config',
|
||||
@@ -15,7 +16,7 @@ export const configRoutes={
|
||||
name: 'PersonConfig',
|
||||
component: () => import('@/views/Config/Person/PersonConfig.vue'),
|
||||
meta: {
|
||||
title: '人员配置',
|
||||
title: i18n.global.t('sidebar.personConfiguration'),
|
||||
icon: 'person',
|
||||
},
|
||||
children:[
|
||||
@@ -28,7 +29,7 @@ export const configRoutes={
|
||||
name:'AllPersonConfig',
|
||||
component:()=>import('@/views/Config/Person/PersonAll.vue'),
|
||||
meta:{
|
||||
title:'人员名单',
|
||||
title:i18n.global.t('sidebar.personList'),
|
||||
icon:'all'
|
||||
}
|
||||
},
|
||||
@@ -37,7 +38,7 @@ export const configRoutes={
|
||||
name:'AlreadyPerson',
|
||||
component:()=>import('@/views/Config/Person/PersonAlready.vue'),
|
||||
meta:{
|
||||
title:'中奖名单人员',
|
||||
title:i18n.global.t('sidebar.winnerList'),
|
||||
icon:'already'
|
||||
}
|
||||
},
|
||||
@@ -57,7 +58,7 @@ export const configRoutes={
|
||||
name: 'PrizeConfig',
|
||||
component: () => import('@/views/Config/Prize/PrizeConfig.vue'),
|
||||
meta:{
|
||||
title: '奖品配置',
|
||||
title: i18n.global.t('sidebar.prizeConfiguration'),
|
||||
icon: 'prize'
|
||||
}
|
||||
},
|
||||
@@ -66,7 +67,7 @@ export const configRoutes={
|
||||
name:'GlobalConfig',
|
||||
redirect: '/log-lottery/config/global/all',
|
||||
meta:{
|
||||
title:'全局配置',
|
||||
title:i18n.global.t('sidebar.globalSetting'),
|
||||
icon:'global'
|
||||
},
|
||||
children:[
|
||||
@@ -75,7 +76,7 @@ export const configRoutes={
|
||||
name:'FaceConfig',
|
||||
component:()=>import('@/views/Config/Global/FaceConfig.vue'),
|
||||
meta:{
|
||||
title:'界面配置',
|
||||
title:i18n.global.t('sidebar.viewSetting'),
|
||||
icon:'face'
|
||||
}
|
||||
},
|
||||
@@ -84,7 +85,7 @@ export const configRoutes={
|
||||
name:'ImageConfig',
|
||||
component:()=>import('@/views/Config/Global/ImageConfig.vue'),
|
||||
meta:{
|
||||
title:'图片列表',
|
||||
title:i18n.global.t('sidebar.imagesManagement'),
|
||||
icon:'image'
|
||||
}
|
||||
},
|
||||
@@ -93,7 +94,7 @@ export const configRoutes={
|
||||
name:'MusicConfig',
|
||||
component:()=>import('@/views/Config/Global/MusicConfig.vue'),
|
||||
meta:{
|
||||
title:'音乐列表',
|
||||
title:i18n.global.t('sidebar.musicManagement'),
|
||||
icon:'music'
|
||||
}
|
||||
}
|
||||
@@ -104,7 +105,7 @@ export const configRoutes={
|
||||
name: 'Readme',
|
||||
component: () => import('@/views/Config/Readme/index.vue'),
|
||||
meta:{
|
||||
title: '操作说明',
|
||||
title: i18n.global.t('sidebar.operatingInstructions') ,
|
||||
icon: 'readme'
|
||||
}
|
||||
},
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { defineStore } from 'pinia';
|
||||
import { defaultMusicList, defaultImageList, defaultPatternList } from './data'
|
||||
import { IMusic, IImage } from '@/types/storeType';
|
||||
import i18n,{Language} from '@/locales/i18n'
|
||||
// import { IPrizeConfig } from '@/types/storeType';
|
||||
export const useGlobalConfig = defineStore('global', {
|
||||
state() {
|
||||
@@ -9,6 +10,7 @@ export const useGlobalConfig = defineStore('global', {
|
||||
rowCount: 17,
|
||||
isSHowPrizeList: true,
|
||||
topTitle: '大明内阁六部御前奏对',
|
||||
language:'zhCn',
|
||||
theme: {
|
||||
name: 'dracula',
|
||||
detail: { primary: '#0f5fd3' },
|
||||
@@ -93,8 +95,11 @@ export const useGlobalConfig = defineStore('global', {
|
||||
// 获取是否显示奖品列表
|
||||
getIsShowPrizeList(state) {
|
||||
return state.globalConfig.isSHowPrizeList;
|
||||
},
|
||||
// 获取当前语言
|
||||
getLanguage(state) {
|
||||
return state.globalConfig.language;
|
||||
}
|
||||
|
||||
},
|
||||
actions: {
|
||||
// 设置rowCount
|
||||
@@ -208,12 +213,18 @@ export const useGlobalConfig = defineStore('global', {
|
||||
setIsShowPrizeList(isShowPrizeList: boolean) {
|
||||
this.globalConfig.isSHowPrizeList = isShowPrizeList;
|
||||
},
|
||||
// 设置
|
||||
setLanguage(language: string) {
|
||||
this.globalConfig.language = language;
|
||||
i18n.global.locale.value=language
|
||||
},
|
||||
// 重置所有配置
|
||||
reset() {
|
||||
this.globalConfig = {
|
||||
rowCount: 17,
|
||||
isSHowPrizeList: true,
|
||||
topTitle: '大明内阁六部御前奏对',
|
||||
language: 'zhCn',
|
||||
theme: {
|
||||
name: 'dracula',
|
||||
detail: { primary: '#0f5fd3' },
|
||||
|
||||
@@ -9,11 +9,12 @@ import { ColorPicker } from 'vue3-colorpicker';
|
||||
import 'vue3-colorpicker/style.css';
|
||||
import { isRgbOrRgba, isHex } from '@/utils/color'
|
||||
import PatternSetting from './components/PatternSetting.vue'
|
||||
|
||||
import {languageList} from '@/locales/i18n'
|
||||
import {Language} from '@/locales/i18n'
|
||||
const globalConfig = useStore().globalConfig
|
||||
const personConfig = useStore().personConfig
|
||||
const prizeConfig= useStore().prizeConfig
|
||||
const { getTopTitle: topTitle, getTheme: localTheme, getPatterColor: patternColor, getPatternList: patternList, getCardColor: cardColor, getLuckyColor: luckyCardColor, getTextColor: textColor, getCardSize: cardSize, getTextSize: textSize, getRowCount: rowCount, getIsShowPrizeList: isShowPrizeList } = storeToRefs(globalConfig)
|
||||
const { getTopTitle: topTitle, getTheme: localTheme, getPatterColor: patternColor, getPatternList: patternList, getCardColor: cardColor, getLuckyColor: luckyCardColor, getTextColor: textColor, getCardSize: cardSize, getTextSize: textSize, getRowCount: rowCount, getIsShowPrizeList: isShowPrizeList,getLanguage:userLanguage } = storeToRefs(globalConfig)
|
||||
const { getAlreadyPersonList: alreadyPersonList, getNotPersonList: notPersonList } = storeToRefs(personConfig)
|
||||
const colorPickerRef = ref()
|
||||
const resetDataDialogRef=ref()
|
||||
@@ -29,6 +30,7 @@ const textColorValue = ref(structuredClone(textColor.value))
|
||||
const cardSizeValue = ref(structuredClone(cardSize.value))
|
||||
const textSizeValue = ref(structuredClone(textSize.value))
|
||||
const rowCountValue = ref(structuredClone(rowCount.value))
|
||||
const languageValue=ref(structuredClone(userLanguage.value))
|
||||
const isShowPrizeListValue = ref(structuredClone(isShowPrizeList.value))
|
||||
const patternColorValue = ref(structuredClone(patternColor.value))
|
||||
const themeList = ref(Object.keys(daisyuiThemes))
|
||||
@@ -145,6 +147,9 @@ watch(cardSizeValue, (val: { width: number; height: number; }) => {
|
||||
watch(isShowPrizeListValue, () => {
|
||||
globalConfig.setIsShowPrizeList(isShowPrizeListValue.value)
|
||||
})
|
||||
watch(languageValue,(val:string)=>{
|
||||
globalConfig.setLanguage(val)
|
||||
})
|
||||
onMounted(() => {
|
||||
})
|
||||
</script>
|
||||
@@ -152,13 +157,13 @@ onMounted(() => {
|
||||
<template>
|
||||
<dialog id="my_modal_1" ref="resetDataDialogRef" class="border-none modal">
|
||||
<div class="modal-box">
|
||||
<h3 class="text-lg font-bold">提示!</h3>
|
||||
<p class="py-4">该操作会重置所有数据,是否继续?</p>
|
||||
<h3 class="text-lg font-bold">{{$t('dialog.titleTip')}}</h3>
|
||||
<p class="py-4">{{ $t('dialog.dialogResetAllData') }}</p>
|
||||
<div class="modal-action">
|
||||
<form method="dialog" class="flex gap-3">
|
||||
<!-- if there is a button in form, it will close the modal -->
|
||||
<button class="btn" @click="resetDataDialogRef.close()">取消</button>
|
||||
<button class="btn" @click="resetData">确定</button>
|
||||
<button class="btn" @click="resetDataDialogRef.close()">{{$t(`button.cancel`)}}</button>
|
||||
<button class="btn" @click="resetData">{{$t('button.confirm')}}</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
@@ -166,12 +171,12 @@ onMounted(() => {
|
||||
<div>
|
||||
<h2>全局配置</h2>
|
||||
<div class="mb-8">
|
||||
<button class="btn btn-sm btn-primary" @click="resetDataDialogRef.showModal()">重置所有数据</button>
|
||||
<button class="btn btn-sm btn-primary" @click="resetDataDialogRef.showModal()">{{$t('button.resetAllData')}}</button>
|
||||
</div>
|
||||
<label class="flex flex-row items-center w-full gap-24 mb-10 form-control">
|
||||
<div class="">
|
||||
<div class="label">
|
||||
<span class="label-text">标题</span>
|
||||
<span class="label-text">{{$t('table.title')}}</span>
|
||||
</div>
|
||||
<input type="text" v-model="topTitleValue" placeholder="输入标题"
|
||||
class="w-full max-w-xs input input-bordered" />
|
||||
@@ -180,7 +185,7 @@ onMounted(() => {
|
||||
<label class="flex flex-row items-center w-full gap-24 mb-10 form-control">
|
||||
<div class="">
|
||||
<div class="label">
|
||||
<span class="label-text">列数</span>
|
||||
<span class="label-text">{{$t('table.columnNumber')}}</span>
|
||||
</div>
|
||||
<input type="number" v-model="formData.rowCount" placeholder="Type here"
|
||||
class="w-full max-w-xs input input-bordered" />
|
||||
@@ -191,9 +196,9 @@ onMounted(() => {
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div class="tooltip" data-tip="该项比较耗费时间和性能">
|
||||
<div class="tooltip" :data-tip="$t('tooltip.resetLayout')">
|
||||
<button class="mt-5 btn btn-info btn-sm" :disabled="isRowCountChange != 1" @click="resetPersonLayout">
|
||||
<span>重设布局</span>
|
||||
<span>{{$t('button.setLayout')}}</span>
|
||||
<span class="loading loading-ring loading-md" v-show="isRowCountChange == 2"></span>
|
||||
</button>
|
||||
</div>
|
||||
@@ -201,22 +206,31 @@ onMounted(() => {
|
||||
</label>
|
||||
<label class="w-full max-w-xs form-control">
|
||||
<div class="label">
|
||||
<span class="label-text">选择主题</span>
|
||||
<span class="label-text">{{$t('table.language')}}</span>
|
||||
</div>
|
||||
<select data-choose-theme class="w-full max-w-xs border-solid select border-1" v-model="languageValue">
|
||||
<option disabled selected>{{$t('table.language')}}</option>
|
||||
<option v-for="item in languageList" :key="item.key" :value="item.key">{{ item.name }}</option>
|
||||
</select>
|
||||
</label>
|
||||
<label class="w-full max-w-xs form-control">
|
||||
<div class="label">
|
||||
<span class="label-text">{{$t('table.theme')}}</span>
|
||||
</div>
|
||||
<select data-choose-theme class="w-full max-w-xs border-solid select border-1" v-model="themeValue">
|
||||
<option disabled selected>选取主题</option>
|
||||
<option disabled selected>{{$t('table.theme')}}</option>
|
||||
<option v-for="(item, index) in themeList" :key="index" :value="item">{{ item }}</option>
|
||||
</select>
|
||||
</label>
|
||||
<label class="w-full max-w-xs form-control">
|
||||
<div class="label">
|
||||
<span class="label-text">卡片颜色</span>
|
||||
<span class="label-text">{{$t('table.cardColor')}}</span>
|
||||
</div>
|
||||
<ColorPicker ref="colorPickerRef" v-model="cardColorValue" v-model:pure-color="cardColorValue"></ColorPicker>
|
||||
</label>
|
||||
<label class="w-full max-w-xs form-control">
|
||||
<div class="label">
|
||||
<span class="label-text">中奖卡片颜色</span>
|
||||
<span class="label-text">{{$t('table.winnerColor')}}</span>
|
||||
</div>
|
||||
<ColorPicker ref="colorPickerRef" v-model="luckyCardColorValue" v-model:pure-color="luckyCardColorValue">
|
||||
</ColorPicker>
|
||||
@@ -224,21 +238,21 @@ onMounted(() => {
|
||||
|
||||
<label class="w-full max-w-xs form-control">
|
||||
<div class="label">
|
||||
<span class="label-text">文字颜色</span>
|
||||
<span class="label-text">{{$t('table.textColor')}}</span>
|
||||
</div>
|
||||
<ColorPicker ref="colorPickerRef" v-model="textColorValue" v-model:pure-color="textColorValue"></ColorPicker>
|
||||
</label>
|
||||
<label class="flex flex-row w-full max-w-xs gap-10 mb-10 form-control">
|
||||
<div>
|
||||
<div class="label">
|
||||
<span class="label-text">卡片宽度</span>
|
||||
<span class="label-text">{{$t('table.cardWidth')}}</span>
|
||||
</div>
|
||||
<input type="number" v-model="cardSizeValue.width" placeholder="Type here"
|
||||
class="w-full max-w-xs input input-bordered" />
|
||||
</div>
|
||||
<div>
|
||||
<div class="label">
|
||||
<span class="label-text">卡片高度</span>
|
||||
<span class="label-text">{{$t('table.cardHeight')}}</span>
|
||||
</div>
|
||||
<input type="number" v-model="cardSizeValue.height" placeholder="Type here"
|
||||
class="w-full max-w-xs input input-bordered" />
|
||||
@@ -246,14 +260,14 @@ onMounted(() => {
|
||||
</label>
|
||||
<label class="w-full max-w-xs mb-10 form-control">
|
||||
<div class="label">
|
||||
<span class="label-text">文字大小</span>
|
||||
<span class="label-text">{{$t('table.textSize')}}</span>
|
||||
</div>
|
||||
<input type="number" v-model="textSizeValue" placeholder="Type here"
|
||||
class="w-full max-w-xs input input-bordered" />
|
||||
</label>
|
||||
<label class="w-full max-w-xs form-control">
|
||||
<div class="label">
|
||||
<span class="label-text">高亮颜色</span>
|
||||
<span class="label-text">{{$t('table.highlightColor')}}</span>
|
||||
</div>
|
||||
<ColorPicker ref="colorPickerRef" v-model="patternColorValue" v-model:pure-color="patternColorValue">
|
||||
</ColorPicker>
|
||||
@@ -261,7 +275,7 @@ onMounted(() => {
|
||||
<label class="flex flex-row items-center w-full gap-24 mb-0 form-control">
|
||||
<div>
|
||||
<div class="label">
|
||||
<span class="label-text">图案设置</span>
|
||||
<span class="label-text">{{$t('table.patternSetting')}}</span>
|
||||
</div>
|
||||
<div class="h-auto">
|
||||
<PatternSetting :rowCount="rowCount" :cardColor="cardColor" :patternColor="patternColor"
|
||||
@@ -271,18 +285,18 @@ onMounted(() => {
|
||||
</label>
|
||||
<div class="flex w-full h-24 gap-3 m-0">
|
||||
<button class="mt-5 btn btn-info btn-sm" @click.stop="clearPattern">
|
||||
<span>清空图案设置</span>
|
||||
<span>{{ $t('button.clearPattern') }}</span>
|
||||
</button>
|
||||
<div class="tooltip" data-tip="默认图案设置针对17列时有效,其他列数请自行设置">
|
||||
<div class="tooltip" :data-tip="$t('tooltip.defaultLayout')">
|
||||
<button class="mt-5 btn btn-info btn-sm" @click="resetPattern">
|
||||
<span>默认图案设置</span>
|
||||
<span>{{ $t('button.DefaultPattern') }}</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<label class="w-full max-w-xs mb-10 form-control">
|
||||
<div class="label">
|
||||
<span class="label-text">是否常显奖品列表</span>
|
||||
<span class="label-text">{{$t('table.alwaysDisplay')}}</span>
|
||||
</div>
|
||||
<input type="checkbox" :checked="isShowPrizeListValue" @change="isShowPrizeListValue = !isShowPrizeListValue"
|
||||
class="mt-2 border-solid checkbox checkbox-secondary border-1" />
|
||||
|
||||
@@ -84,7 +84,7 @@ watch(() => imgUploadToast.value, (val) => {
|
||||
<label for="explore">
|
||||
<input type="file" class="" id="explore" style="display: none" @change="handleFileChange"
|
||||
:accept="limitType" />
|
||||
<span class="btn btn-primary btn-sm">上传图片</span>
|
||||
<span class="btn btn-primary btn-sm">{{ $t('button.upload') }}</span>
|
||||
</label>
|
||||
</div>
|
||||
<ul class="p-0">
|
||||
@@ -100,7 +100,7 @@ watch(() => imgUploadToast.value, (val) => {
|
||||
<div class="overflow-hidden font-bold whitespace-nowrap text-ellipsis">{{ item.name}}</div>
|
||||
</div>
|
||||
<div>
|
||||
<button class="btn btn-error btn-xs" @click="removeImage(item)">删除</button>
|
||||
<button class="btn btn-error btn-xs" @click="removeImage(item)">{{ $t('button.upload') }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
|
||||
@@ -74,13 +74,13 @@ onMounted(() => {
|
||||
<template>
|
||||
<div>
|
||||
<div class="flex gap-3">
|
||||
<button class="btn btn-primary btn-sm" @click="resetMusic">重置音乐列表</button>
|
||||
<button class="btn btn-primary btn-sm" @click="resetMusic">{{ $t('button.reset') }}</button>
|
||||
<label for="explore">
|
||||
<input type="file" class="" id="explore" style="display: none" @change="handleFileChange"
|
||||
:accept="limitType" />
|
||||
<span class="btn btn-primary btn-sm">上传音乐</span>
|
||||
<span class="btn btn-primary btn-sm">{{ $t('button.upload') }}</span>
|
||||
</label>
|
||||
<button class="btn btn-error btn-sm" @click="deleteAll">删除所有</button>
|
||||
<button class="btn btn-error btn-sm" @click="deleteAll">{{ $t('button.allDelete') }}</button>
|
||||
</div>
|
||||
<div>
|
||||
<ul class="p-0">
|
||||
@@ -90,8 +90,8 @@ onMounted(() => {
|
||||
{{ item.name }}</span>
|
||||
</div>
|
||||
<div class="flex gap-3">
|
||||
<button class="btn btn-primary btn-xs" @click="play(item)">播放</button>
|
||||
<button class="btn btn-error btn-xs" @click="deleteMusic(item)">删除</button>
|
||||
<button class="btn btn-primary btn-xs" @click="play(item)">{{ $t('button.play') }}</button>
|
||||
<button class="btn btn-error btn-xs" @click="deleteMusic(item)">{{ $t('button.delete') }}</button>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
@@ -130,26 +130,26 @@ onMounted(() => {
|
||||
<template>
|
||||
<dialog id="my_modal_1" ref="resetDataDialog" class="border-none modal">
|
||||
<div class="modal-box">
|
||||
<h3 class="text-lg font-bold">提示!</h3>
|
||||
<p class="py-4">该操作会清空人员中奖信息,是否继续?</p>
|
||||
<h3 class="text-lg font-bold">{{ $t('dialog.titleTip') }}</h3>
|
||||
<p class="py-4">{{ $t('dialog.dialogResetWinner') }}</p>
|
||||
<div class="modal-action">
|
||||
<form method="dialog" class="flex gap-3">
|
||||
<!-- if there is a button in form, it will close the modal -->
|
||||
<button class="btn" @click="resetDataDialog.close()">取消</button>
|
||||
<button class="btn" @click="resetData">确定</button>
|
||||
<button class="btn" @click="resetDataDialog.close()">{{ $t('button.cancel') }}</button>
|
||||
<button class="btn" @click="resetData">{{ $t('dialog.confirm') }}</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</dialog>
|
||||
<dialog id="my_modal_1" ref="delAllDataDialog" class="border-none modal">
|
||||
<div class="modal-box">
|
||||
<h3 class="text-lg font-bold">提示!</h3>
|
||||
<p class="py-4">该操作会删除所有人员数据,是否继续?</p>
|
||||
<h3 class="text-lg font-bold">{{ $t('dialog.titleTip') }}</h3>
|
||||
<p class="py-4">{{ $t('dialog.dialogDelAllPerson') }}</p>
|
||||
<div class="modal-action">
|
||||
<form method="dialog" class="flex gap-3">
|
||||
<!-- if there is a button in form, it will close the modal -->
|
||||
<button class="btn" @click="delAllDataDialog.close()">取消</button>
|
||||
<button class="btn" @click="deleteAll">确定</button>
|
||||
<button class="btn" @click="delAllDataDialog.close()">{{ $t('button.cancel') }}</button>
|
||||
<button class="btn" @click="deleteAll">{{ $t('button.confirm') }}</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
@@ -158,28 +158,28 @@ onMounted(() => {
|
||||
|
||||
<h2>人员管理</h2>
|
||||
<div class="flex gap-3">
|
||||
<button class="btn btn-error btn-sm" @click="delAllDataDialog.showModal()">全部删除</button>
|
||||
<div class="tooltip tooltip-bottom" data-tip="下载文件后,请在excel中填写数据,并保存为xlsx格式">
|
||||
<button class="btn btn-error btn-sm" @click="delAllDataDialog.showModal()">{{ $t('button.allDelete') }}</button>
|
||||
<div class="tooltip tooltip-bottom" :data-tip="$t('tooltip.downloadTemplateTip')">
|
||||
<a class="no-underline btn btn-secondary btn-sm" download="人口登记表.xlsx" target="_blank"
|
||||
href="/log-lottery/人口登记表.xlsx">下载模板</a>
|
||||
href="/log-lottery/人口登记表.xlsx">{{ $t('button.downloadTemplate') }}</a>
|
||||
</div>
|
||||
<div class="">
|
||||
<label for="explore">
|
||||
|
||||
<div class="tooltip tooltip-bottom" data-tip="上传修改好的excel文件">
|
||||
<div class="tooltip tooltip-bottom" :data-tip="$t('tooltip.uploadExcelTip')">
|
||||
<input type="file" class="" id="explore" style="display: none" @change="handleFileChange"
|
||||
:accept="limitType" />
|
||||
|
||||
<span class="btn btn-primary btn-sm">导入人员数据</span>
|
||||
<span class="btn btn-primary btn-sm">{{ $t('button.importData') }}</span>
|
||||
</div>
|
||||
</label>
|
||||
<!-- <button class="btn btn-primary btn-sm">上传excel</button> -->
|
||||
|
||||
</div>
|
||||
<button class="btn btn-error btn-sm" @click="resetDataDialog.showModal()">重置人员数据</button>
|
||||
<button class="btn btn-accent btn-sm" @click="exportData">导出结果</button>
|
||||
<button class="btn btn-error btn-sm" @click="resetDataDialog.showModal()">{{ $t('button.resetData') }}</button>
|
||||
<button class="btn btn-accent btn-sm" @click="exportData">{{ $t('button.exportResult') }}</button>
|
||||
<div>
|
||||
<span>中奖人数:</span>
|
||||
<span>{{$t('table.luckyPeopleNumber')}}:</span>
|
||||
<span>{{ alreadyPersonList.length }}</span>
|
||||
<span> / </span>
|
||||
<span>{{ allPersonList.length }}</span>
|
||||
|
||||
@@ -106,17 +106,17 @@ const tableColumnsDetail = [
|
||||
<template>
|
||||
<div class="overflow-y-auto">
|
||||
|
||||
<h2>已中奖人员管理</h2>
|
||||
<h2>{{ $t('viewTitle.winnerManagement') }}</h2>
|
||||
<div class="flex items-center justify-start gap-10">
|
||||
<!-- <button class="btn btn-error btn-sm" @click="deleteAll">全部删除</button> -->
|
||||
<div>
|
||||
<span>中奖人数:</span>
|
||||
<span>{{$t('table.luckyPeopleNumber')}}:</span>
|
||||
<span>{{ alreadyPersonList.length }}</span>
|
||||
</div>
|
||||
<div class="flex flex-col">
|
||||
<div class="form-control">
|
||||
<label class="cursor-pointer label">
|
||||
<span class="label-text">详细信息:</span>
|
||||
<span class="label-text">{{$t('table.detail')}}:</span>
|
||||
<input type="checkbox" class="border-solid toggle toggle-primary border-1" v-model="isDetail" />
|
||||
</label>
|
||||
</div>
|
||||
|
||||
@@ -147,11 +147,11 @@ watch(() => prizeList.value, (val: IPrizeConfig[]) => {
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<h2>奖项配置</h2>
|
||||
<h2>{{ $t('viewTitle.prizeManagement') }}</h2>
|
||||
<div class="flex w-full gap-3">
|
||||
<button class="btn btn-info btn-sm" @click="addPrize">添加</button>
|
||||
<button class="btn btn-info btn-sm" @click="resetDefault">默认列表</button>
|
||||
<button class="btn btn-error btn-sm" @click="delAll">全部删除</button>
|
||||
<button class="btn btn-info btn-sm" @click="addPrize">{{$t('button.add')}}</button>
|
||||
<button class="btn btn-info btn-sm" @click="resetDefault">{{$t('button.resetDefault')}}</button>
|
||||
<button class="btn btn-error btn-sm" @click="delAll">{{$t('button.allDelete')}}</button>
|
||||
|
||||
</div>
|
||||
<div role="alert" class="w-full my-4 alert alert-info">
|
||||
@@ -159,7 +159,7 @@ watch(() => prizeList.value, (val: IPrizeConfig[]) => {
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||
d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"></path>
|
||||
</svg>
|
||||
<span>进行操作可能会重置数据,请谨慎操作</span>
|
||||
<span>{{$t('dialog.tipResetPrize')}}</span>
|
||||
</div>
|
||||
<ul class="p-0 m-0">
|
||||
<li v-for="item in prizeList" :key="item.id" class="flex gap-10"
|
||||
@@ -176,25 +176,25 @@ watch(() => prizeList.value, (val: IPrizeConfig[]) => {
|
||||
</label>
|
||||
<label class="w-1/2 max-w-xs mb-10 form-control">
|
||||
<div class="label">
|
||||
<span class="label-text">名称</span>
|
||||
<span class="label-text">{{ $t('table.prizeName') }}</span>
|
||||
</div>
|
||||
<input type="text" v-model="item.name" placeholder="名称"
|
||||
class="w-full max-w-xs input-sm input input-bordered" />
|
||||
</label>
|
||||
<label class="w-1/2 max-w-xs mb-10 form-control">
|
||||
<div class="label">
|
||||
<span class="label-text">全员参加</span>
|
||||
<span class="label-text">{{ $t('table.fullParticipation') }}</span>
|
||||
</div>
|
||||
<input type="checkbox" :checked="item.isAll" @change="item.isAll = !item.isAll"
|
||||
class="mt-2 border-solid checkbox checkbox-secondary border-1" />
|
||||
</label>
|
||||
<label class="w-1/2 max-w-xs mb-10 form-control">
|
||||
<div class="label">
|
||||
<span class="label-text">抽奖人数</span>
|
||||
<span class="label-text">{{ $t('table.numberParticipants') }}</span>
|
||||
</div>
|
||||
<input type="number" v-model="item.count" placeholder="获奖人数" @change="changePrizePerson(item)"
|
||||
class="w-full max-w-xs p-0 m-0 input-sm input input-bordered" />
|
||||
<div class="tooltip tooltip-bottom" :data-tip="'已抽取:' + item.isUsedCount + '/' + item.count">
|
||||
<div class="tooltip tooltip-bottom" :data-tip="$t('table.isDone') + item.isUsedCount + '/' + item.count">
|
||||
<progress class="w-full progress" :value="item.isUsedCount" :max="item.count"></progress>
|
||||
</div>
|
||||
</label>
|
||||
@@ -207,14 +207,14 @@ watch(() => prizeList.value, (val: IPrizeConfig[]) => {
|
||||
</label> -->
|
||||
<label class="w-1/2 max-w-xs mb-10 form-control">
|
||||
<div class="label">
|
||||
<span class="label-text">已抽取</span>
|
||||
<span class="label-text">{{ $t('table.isDone') }}</span>
|
||||
</div>
|
||||
<input type="checkbox" :checked="item.isUsed" @change="changePrizeStatus(item)"
|
||||
class="mt-2 border-solid checkbox checkbox-secondary border-1" />
|
||||
</label>
|
||||
<label class="w-full max-w-xs mb-10 form-control">
|
||||
<div class="label">
|
||||
<span class="label-text">图片</span>
|
||||
<span class="label-text">{{ $t('table.image') }}</span>
|
||||
</div>
|
||||
<select class="w-full max-w-xs select select-warning select-sm" v-model="item.picture">
|
||||
<option v-if="item.picture.id" :value="{ id: '', name: '', url: '' }"><span>❌</span></option>
|
||||
@@ -225,7 +225,7 @@ watch(() => prizeList.value, (val: IPrizeConfig[]) => {
|
||||
</label>
|
||||
<label class="w-full max-w-xs mb-10 form-control" v-if="item.separateCount">
|
||||
<div class="label">
|
||||
<span class="label-text">单次抽取个数</span>
|
||||
<span class="label-text">{{ $t('table.onceNumber') }}</span>
|
||||
</div>
|
||||
<div class="flex justify-start w-full h-full" @click="selectPrize(item)">
|
||||
<ul class="flex flex-wrap w-full h-full gap-1 p-0 pt-1 m-0 cursor-pointer"
|
||||
@@ -240,15 +240,15 @@ watch(() => prizeList.value, (val: IPrizeConfig[]) => {
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
<button v-else class="btn btn-secondary btn-xs">设置</button>
|
||||
<button v-else class="btn btn-secondary btn-xs">{{ $t('button.setting') }}</button>
|
||||
</div>
|
||||
</label>
|
||||
<label class="w-full max-w-xs mb-10 form-control">
|
||||
<div class="label">
|
||||
<span class="label-text">操作</span>
|
||||
<span class="label-text">{{ $t('table.operation') }}</span>
|
||||
</div>
|
||||
<div class="flex gap-2">
|
||||
<button class="btn btn-error btn-sm" @click="delItem(item)">删除</button>
|
||||
<button class="btn btn-error btn-sm" @click="delItem(item)">{{ $t('button.delete') }}</button>
|
||||
</div>
|
||||
</label>
|
||||
</li>
|
||||
|
||||
@@ -64,10 +64,10 @@ const skip = (path: string) => {
|
||||
</div>
|
||||
<footer class="p-10 rounded footer footer-center bg-base-200 text-base-content">
|
||||
<nav class="grid grid-flow-col gap-4">
|
||||
<a class="cursor-pointer link link-hover text-inherit" target="_blank" href="https://1kw20.fun">行有不得,反求诸己</a>
|
||||
<a class="cursor-pointer link link-hover text-inherit" target="_blank" href="https://1kw20.fun">{{ $t('footer.self-reflection') }}</a>
|
||||
</nav>
|
||||
<nav>
|
||||
<a class="cursor-pointer link link-hover text-inherit" target="_blank" href="https://1kw20.fun">破山中贼易,破心中贼难</a>
|
||||
<a class="cursor-pointer link link-hover text-inherit" target="_blank" href="https://1kw20.fun">{{ $t('footer.thiefEasy') }}</a>
|
||||
</nav>
|
||||
<nav>
|
||||
<div class="grid grid-flow-col gap-4">
|
||||
|
||||
@@ -10,6 +10,7 @@ import Icons from 'unplugin-icons/vite';
|
||||
import IconsResolver from 'unplugin-icons/resolver';
|
||||
import { visualizer } from 'rollup-plugin-visualizer';
|
||||
import viteCompression from 'vite-plugin-compression';
|
||||
import vueDevTools from 'vite-plugin-vue-devtools'
|
||||
// import vueDevTools from 'vite-plugin-vue-devtools'
|
||||
// https://vitejs.dev/config/
|
||||
export default defineConfig(({ mode }) => {
|
||||
@@ -20,7 +21,7 @@ export default defineConfig(({ mode }) => {
|
||||
base:'/log-lottery/',
|
||||
plugins: [
|
||||
vue(),
|
||||
// vueDevTools(),
|
||||
vueDevTools(),
|
||||
viteCompression({
|
||||
verbose: true,
|
||||
disable: false,
|
||||
|
||||
Reference in New Issue
Block a user