Feature action (#149)
* ci: 👷 整合github action配置文件 * docs: 📝 贡献文档修改 * style: 💄 更新版本 * style: 💄 cargo.lock版本更新 * feat(husky): 增强Git标签版本校验脚本 添加了对Git标签指向提交与release分支一致性的校验功能。 脚本现在会检查tag指向的提交是否与当前或任何release分支的最新提交一致, 确保发布流程的准确性。如果当前在release分支上,直接比较分支HEAD与tag指向的提交; 如果不在release分支上,则遍历所有release分支查找匹配的提交。 * feat: ✨ 国际化
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import fs from 'fs';
|
||||
import { execSync } from 'child_process';
|
||||
|
||||
try {
|
||||
// 读取 package.json 中的版本号
|
||||
@@ -24,6 +25,81 @@ try {
|
||||
} else {
|
||||
console.log('✅ Git tag 版本校验通过');
|
||||
}
|
||||
|
||||
// 获取 tag 指向的提交哈希
|
||||
const tagCommit = execSync(`git rev-list -1 ${tag}`, { encoding: 'utf-8' }).trim();
|
||||
|
||||
// 获取当前分支名称
|
||||
let currentBranch;
|
||||
try {
|
||||
currentBranch = execSync('git branch --show-current', { encoding: 'utf-8' }).trim();
|
||||
} catch (e) {
|
||||
console.error('无法获取当前分支名称');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
// 检查当前分支是否为 release 分支
|
||||
if (currentBranch.startsWith('release/')) {
|
||||
// 如果当前在 release 分支上,检查当前分支的 HEAD 提交是否与 tag 指向的提交一致
|
||||
const currentBranchCommit = execSync(`git rev-parse ${currentBranch}`, { encoding: 'utf-8' }).trim();
|
||||
|
||||
if (tagCommit !== currentBranchCommit) {
|
||||
console.log('🏷️ Git tag 指向的提交与当前 release 分支的最新提交不一致');
|
||||
console.error(`当前 release 分支 "${currentBranch}" 的最新提交为: ${currentBranchCommit}`);
|
||||
console.error(`Tag "${tag}" 指向的提交为: ${tagCommit}`);
|
||||
process.exit(1);
|
||||
} else {
|
||||
console.log('✅ Git tag 指向的提交与当前 release 分支的最新提交一致');
|
||||
}
|
||||
} else {
|
||||
// 如果当前不在 release 分支上,查找所有 release 分支并检查是否有分支的 HEAD 与 tag 指向的提交一致
|
||||
console.log(`🔍 当前在 "${currentBranch}" 分支,检查 tag 指向的提交是否与任何 release 分支的最新提交一致`);
|
||||
|
||||
// 获取所有本地分支
|
||||
const localBranchesOutput = execSync('git branch --format="%(refname:short)"', { encoding: 'utf-8' });
|
||||
const localBranches = localBranchesOutput.split('\n').map(b => b.trim()).filter(b => b);
|
||||
|
||||
// 过滤出 release 分支
|
||||
const releaseBranches = localBranches.filter(branch => branch.startsWith('release/'));
|
||||
|
||||
if (releaseBranches.length === 0) {
|
||||
console.log('⚠️ 未找到 release 分支');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
let foundMatchingBranch = false;
|
||||
let matchingBranchName = '';
|
||||
|
||||
for (const branch of releaseBranches) {
|
||||
try {
|
||||
// 获取 release 分支的最新提交
|
||||
const releaseBranchCommit = execSync(`git rev-parse ${branch}`, { encoding: 'utf-8' }).trim();
|
||||
|
||||
// 检查是否与 tag 指向的提交一致
|
||||
if (tagCommit === releaseBranchCommit) {
|
||||
foundMatchingBranch = true;
|
||||
matchingBranchName = branch;
|
||||
break;
|
||||
}
|
||||
} catch (e) {
|
||||
// 如果无法获取分支信息,继续尝试下一个分支
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (!foundMatchingBranch) {
|
||||
console.log('🏷️ Git tag 指向的提交与任何 release 分支的最新提交都不一致');
|
||||
console.error(`提供的 tag 为: ${tag}`);
|
||||
console.error(`tag 指向的提交为: ${tagCommit}`);
|
||||
console.log(`检查了以下 release 分支:`, releaseBranches);
|
||||
console.log('可能的原因:');
|
||||
console.log('1. release 分支不是最新的');
|
||||
console.log('2. tag 指向的提交不在 release 分支上');
|
||||
process.exit(1);
|
||||
} else {
|
||||
console.log(`✅ Git tag 指向的提交与 release 分支 "${matchingBranchName}" 的最新提交一致`);
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('❌ 校验过程中发生错误:', error.message);
|
||||
process.exit(1);
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
<script setup lang='ts'>
|
||||
import type { LoadingOptions } from './loading-context'
|
||||
import { inject } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { loadingKey } from './loading-context'
|
||||
|
||||
// 注入全局状态
|
||||
const loading = inject(loadingKey) as LoadingOptions
|
||||
|
||||
const { t } = useI18n()
|
||||
// 解构状态(响应式)
|
||||
const { visible, text } = loading
|
||||
</script>
|
||||
@@ -13,7 +15,7 @@ const { visible, text } = loading
|
||||
<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>
|
||||
<span>{{ text ? text : t('button.loading') }}</span>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -1,153 +1,14 @@
|
||||
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',
|
||||
noInfoAndImport: 'No Info and import it',
|
||||
useDefault: 'Use Default Data',
|
||||
},
|
||||
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',
|
||||
setLuckyNumber: 'Set Lucky Number',
|
||||
luckyPeopleNumber: 'Lucky People Number',
|
||||
import { button, data, dialog, error, footer, placeHolder, sidebar, table, tooltip, viewTitle } from './modules'
|
||||
|
||||
detail: 'Detail',
|
||||
noneData: 'No Data',
|
||||
// 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',
|
||||
avatarDisplay: 'Show avatars or not',
|
||||
selectPicture: 'Select a Picture',
|
||||
backgroundImage: 'Select Background Image',
|
||||
},
|
||||
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 and cant recover, 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',
|
||||
},
|
||||
error: {
|
||||
require: 'required field',
|
||||
requireNumber: 'please enter a number',
|
||||
minNumber1: 'the minimum is 1',
|
||||
maxNumber100: 'the maximum is 100',
|
||||
uploadSuccess: 'Upload Success',
|
||||
uploadFail: 'Upload Failed',
|
||||
notImage: 'Not Image',
|
||||
personIsAllDone: 'All Person Is Done',
|
||||
personNotEnough: 'Person Is Not Enough',
|
||||
startDraw: 'Now Draw {count} {leftover} people',
|
||||
completeInformation: 'Please provide complete information',
|
||||
},
|
||||
placeHolder: {
|
||||
enterTitle: 'Enter Title',
|
||||
name: 'Name',
|
||||
winnerCount: 'Lucky Person Count',
|
||||
},
|
||||
data: {
|
||||
yes: 'Yes',
|
||||
no: 'No',
|
||||
number: 'Number',
|
||||
isWin: 'isWin',
|
||||
avatar: 'avatar',
|
||||
department: 'Department',
|
||||
name: 'Name',
|
||||
identity: 'Identity',
|
||||
prizeName: 'Prize Name',
|
||||
prizeTime: 'Prize Time',
|
||||
operation: 'Operation',
|
||||
delete: 'Delete',
|
||||
removePerson: 'Remove the Person',
|
||||
defaultTitle: 'The Prelude to the Six Ministries of the Ming Dynasty Cabinet',
|
||||
xlsxName: 'personListTemplate-en.xlsx',
|
||||
readmeName: 'readme-en.md',
|
||||
},
|
||||
footer: {
|
||||
'self-reflection': 'Turn inward and examine yourself when you encounter difficulties in life.',
|
||||
'thiefEasy': 'Thief difficult mountain thief easily, breaking heart.',
|
||||
},
|
||||
export default {
|
||||
button: button.en,
|
||||
sidebar: sidebar.en,
|
||||
viewTitle: viewTitle.en,
|
||||
table: table.en,
|
||||
dialog: dialog.en,
|
||||
tooltip: tooltip.en,
|
||||
error: error.en,
|
||||
placeHolder: placeHolder.en,
|
||||
data: data.en,
|
||||
footer: footer.en,
|
||||
}
|
||||
|
||||
63
src/locales/modules/button.ts
Normal file
63
src/locales/modules/button.ts
Normal file
@@ -0,0 +1,63 @@
|
||||
export const buttonEn = {
|
||||
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',
|
||||
noInfoAndImport: 'No Info and import it',
|
||||
useDefault: 'Use Default Data',
|
||||
loading: 'Loading...',
|
||||
}
|
||||
|
||||
export const buttonZhCn = {
|
||||
enterLottery: '进入抽奖',
|
||||
start: '开始',
|
||||
selectLucky: '抽取幸运儿',
|
||||
continue: '继续',
|
||||
confirm: '确认',
|
||||
cancel: '取消',
|
||||
setting: '设置',
|
||||
delete: '删除',
|
||||
allDelete: '删除全部',
|
||||
downloadTemplate: '下载模板',
|
||||
importData: '导入数据',
|
||||
resetData: '重置数据',
|
||||
exportResult: '导出结果',
|
||||
add: '添加',
|
||||
resetDefault: '重置为默认',
|
||||
resetAllData: '重置所有数据',
|
||||
clearPattern: '清除图案',
|
||||
DefaultPattern: '默认图案',
|
||||
upload: '上传',
|
||||
reset: '重置',
|
||||
play: '播放',
|
||||
setLayout: '重设布局',
|
||||
close: '关闭',
|
||||
noInfoAndImport: '暂无人员信息,前往导入',
|
||||
useDefault: '使用默认数据',
|
||||
loading: '加载中...',
|
||||
}
|
||||
|
||||
// 导出一个值
|
||||
export const button = {
|
||||
en: buttonEn,
|
||||
zhCn: buttonZhCn,
|
||||
}
|
||||
42
src/locales/modules/data.ts
Normal file
42
src/locales/modules/data.ts
Normal file
@@ -0,0 +1,42 @@
|
||||
export const dataEn = {
|
||||
yes: 'Yes',
|
||||
no: 'No',
|
||||
number: 'Number',
|
||||
isWin: 'isWin',
|
||||
avatar: 'avatar',
|
||||
department: 'Department',
|
||||
name: 'Name',
|
||||
identity: 'Identity',
|
||||
prizeName: 'Prize Name',
|
||||
prizeTime: 'Prize Time',
|
||||
operation: 'Operation',
|
||||
delete: 'Delete',
|
||||
removePerson: 'Remove the Person',
|
||||
defaultTitle: 'The Prelude to the Six Ministries of the Ming Dynasty Cabinet',
|
||||
xlsxName: 'personListTemplate-en.xlsx',
|
||||
readmeName: 'readme-en.md',
|
||||
}
|
||||
|
||||
export const dataZhCn = {
|
||||
yes: '是',
|
||||
no: '否',
|
||||
number: '编号',
|
||||
isWin: '是否中奖',
|
||||
avatar: '头像',
|
||||
department: '部门',
|
||||
name: '姓名',
|
||||
identity: '身份',
|
||||
prizeName: '获奖',
|
||||
prizeTime: '获奖时间',
|
||||
operation: '操作',
|
||||
delete: '删除',
|
||||
removePerson: '移入未中奖名单',
|
||||
defaultTitle: '大明内阁六部御前奏对',
|
||||
xlsxName: '人口登记表-zhCn.xlsx',
|
||||
readmeName: 'readme-zhCn.md',
|
||||
}
|
||||
|
||||
export const data = {
|
||||
en: dataEn,
|
||||
zhCn: dataZhCn,
|
||||
}
|
||||
34
src/locales/modules/dialog.ts
Normal file
34
src/locales/modules/dialog.ts
Normal file
@@ -0,0 +1,34 @@
|
||||
export const dialogEn = {
|
||||
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 and cant recover, please proceed with caution',
|
||||
uploadFileTitle: 'Upload File',
|
||||
uploadImageTitle: 'Upload Image',
|
||||
uploadAudioTitle: 'Upload Audio',
|
||||
}
|
||||
|
||||
export const dialogZhCn = {
|
||||
titleTip: '提示!',
|
||||
titleTemporary: '增加临时抽奖',
|
||||
dialogPCWeb: '请使用PC进行访问以获得最佳显示效果',
|
||||
dialogDelAllPerson: '该操作会删除所有人员数据,是否继续?',
|
||||
dialogResetWinner: '该操作会清空人员中奖信息,是否继续?',
|
||||
dialogResetAllData: '该操作会重置所有数据,是否继续?',
|
||||
dialogSingleDrawLimit: '单次抽取只能抽取10位',
|
||||
dialogLatestBrowser: '请使用最新版Chrome或者Edge浏览器',
|
||||
tipResetPrize: '进行操作可能会重置数据并不可恢复,请谨慎操作',
|
||||
uploadFileTitle: '上传文件',
|
||||
uploadImageTitle: '上传图片',
|
||||
uploadAudioTitle: '上传音频',
|
||||
}
|
||||
|
||||
export const dialog = {
|
||||
en: dialogEn,
|
||||
zhCn: dialogZhCn,
|
||||
}
|
||||
60
src/locales/modules/error.ts
Normal file
60
src/locales/modules/error.ts
Normal file
@@ -0,0 +1,60 @@
|
||||
import { success } from 'zod'
|
||||
|
||||
export const errorEn = {
|
||||
require: 'required field',
|
||||
requireNumber: 'please enter a number',
|
||||
minNumber1: 'the minimum is 1',
|
||||
maxNumber100: 'the maximum is 100',
|
||||
uploadSuccess: 'Upload Success',
|
||||
uploadFail: 'Upload Failed',
|
||||
notImage: 'Not Image',
|
||||
personIsAllDone: 'All Person Is Done',
|
||||
personNotEnough: 'Person Is Not Enough',
|
||||
startDraw: 'Now Draw {count} {leftover} people',
|
||||
completeInformation: 'Please provide complete information',
|
||||
notJsonFile: 'it isn\'t a JSON file',
|
||||
notAudioFile: 'it isn\'t an audio file',
|
||||
personNameEmpty: 'Please enter name',
|
||||
excelFileError: 'The header is inconsistent, please download the template, modify it, and then upload it',
|
||||
exportSuccess: 'Export Success',
|
||||
exportFail: 'Export Failed',
|
||||
importSuccess: 'Import Success',
|
||||
importFail: 'Import Failed',
|
||||
downloadSuccess: '下载成功',
|
||||
deleteSuccess: '删除成功',
|
||||
deleteFail: '删除失败',
|
||||
success: 'Success',
|
||||
fail: 'Failed',
|
||||
}
|
||||
|
||||
export const errorZhCn = {
|
||||
require: '必填项',
|
||||
requireNumber: '请输入数字',
|
||||
minNumber1: '最小为1',
|
||||
maxNumber100: '最大为100',
|
||||
uploadSuccess: '上传成功',
|
||||
uploadFail: '上传失败',
|
||||
notImage: '不是图片',
|
||||
personIsAllDone: '抽奖抽完了',
|
||||
personNotEnough: '抽奖人数不足',
|
||||
startDraw: '现在抽取{count}{leftover}人',
|
||||
completeInformation: '请填写完整信息',
|
||||
notJsonFile: '这不是一个JSON文件',
|
||||
notAudioFile: '这不是一个音频文件',
|
||||
personNameEmpty: '请填写姓名',
|
||||
excelFileError: '表头不一致,请先下载模板然后修改后再上传',
|
||||
exportSuccess: '导出成功',
|
||||
exportFail: '导出失败',
|
||||
importSuccess: '导入成功',
|
||||
importFail: '导入失败',
|
||||
downloadSuccess: '下载成功',
|
||||
deleteSuccess: '删除成功',
|
||||
deleteFail: '删除失败',
|
||||
success: '成功',
|
||||
fail: '失败',
|
||||
}
|
||||
|
||||
export const error = {
|
||||
en: errorEn,
|
||||
zhCn: errorZhCn,
|
||||
}
|
||||
14
src/locales/modules/footer.ts
Normal file
14
src/locales/modules/footer.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
export const footerEn = {
|
||||
'self-reflection': 'Turn inward and examine yourself when you encounter difficulties in life.',
|
||||
'thiefEasy': 'Thief difficult mountain thief easily, breaking heart.',
|
||||
}
|
||||
|
||||
export const footerZhCn = {
|
||||
'self-reflection': '行有不得,反求诸己',
|
||||
'thiefEasy': '破山中贼易,破心中贼难',
|
||||
}
|
||||
|
||||
export const footer = {
|
||||
en: footerEn,
|
||||
zhCn: footerZhCn,
|
||||
}
|
||||
11
src/locales/modules/index.ts
Normal file
11
src/locales/modules/index.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
// 导出该文件夹下的内容
|
||||
export * from './button'
|
||||
export * from './data'
|
||||
export * from './dialog'
|
||||
export * from './error'
|
||||
export * from './footer'
|
||||
export * from './placeHolder'
|
||||
export * from './sidebar'
|
||||
export * from './table'
|
||||
export * from './tooltip'
|
||||
export * from './viewTitle'
|
||||
24
src/locales/modules/placeHolder.ts
Normal file
24
src/locales/modules/placeHolder.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
export const placeHolderEn = {
|
||||
enterTitle: 'Enter Title',
|
||||
name: 'Name',
|
||||
winnerCount: 'Lucky Person Count',
|
||||
selectFont: 'Select Font',
|
||||
timedStop: 'will stop at a scheduled time after starting',
|
||||
imageName: 'Image Name',
|
||||
personName: 'Please enter name',
|
||||
}
|
||||
|
||||
export const placeHolderZhCn = {
|
||||
enterTitle: '输入标题',
|
||||
name: '名称',
|
||||
winnerCount: '中奖人数',
|
||||
selectFont: '选择字体',
|
||||
timedStop: '开始后定时抽取',
|
||||
imageName: '图片名称',
|
||||
personName: '请填写姓名',
|
||||
}
|
||||
|
||||
export const placeHolder = {
|
||||
en: placeHolderEn,
|
||||
zhCn: placeHolderZhCn,
|
||||
}
|
||||
28
src/locales/modules/sidebar.ts
Normal file
28
src/locales/modules/sidebar.ts
Normal file
@@ -0,0 +1,28 @@
|
||||
export const sidebarEn = {
|
||||
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',
|
||||
}
|
||||
|
||||
export const sidebarZhCn = {
|
||||
personConfiguration: '人员配置',
|
||||
personList: '人员列表',
|
||||
winnerList: '中奖人员',
|
||||
prizeConfiguration: '奖品配置',
|
||||
globalSetting: '全局配置',
|
||||
viewSetting: '界面设置',
|
||||
imagesManagement: '图片管理',
|
||||
musicManagement: '音乐管理',
|
||||
operatingInstructions: '操作说明',
|
||||
}
|
||||
|
||||
export const sidebar = {
|
||||
en: sidebarEn,
|
||||
zhCn: sidebarZhCn,
|
||||
}
|
||||
104
src/locales/modules/table.ts
Normal file
104
src/locales/modules/table.ts
Normal file
@@ -0,0 +1,104 @@
|
||||
import { reset } from 'canvas-confetti'
|
||||
import { time } from 'zod/v4/core/regexes.cjs'
|
||||
|
||||
export const tableEn = {
|
||||
// field block name
|
||||
abilitySetting: 'Ability Setting',
|
||||
dataSetting: 'Data Setting',
|
||||
layoutSetting: 'Layout Setting',
|
||||
patternSetting: 'Pattern Setting',
|
||||
textSetting: 'Text Setting',
|
||||
themeSetting: 'Theme Setting',
|
||||
// person configuration
|
||||
number: 'Number',
|
||||
name: 'Name',
|
||||
prizeName: 'Name',
|
||||
department: 'Department',
|
||||
identity: 'Identity',
|
||||
isLucky: 'Is Lucky',
|
||||
operation: 'Operation',
|
||||
setLuckyNumber: 'Set Lucky Number',
|
||||
luckyPeopleNumber: 'Lucky People Number',
|
||||
detail: 'Detail',
|
||||
noneData: 'No Data',
|
||||
// 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',
|
||||
alwaysDisplay: 'Always Display Prize List',
|
||||
avatarDisplay: 'Show avatars or not',
|
||||
selectPicture: 'Select a Picture',
|
||||
backgroundImage: 'Select Background Image',
|
||||
timedStop: 'Timed Stop',
|
||||
playWinMusic: 'Play Win Music',
|
||||
resetAllData: 'Reset All Data',
|
||||
}
|
||||
|
||||
export const tableZhCn = {
|
||||
// field block name
|
||||
abilitySetting: '功能设置',
|
||||
dataSetting: '数据设置',
|
||||
layoutSetting: '布局设置',
|
||||
patternSetting: '图案设置',
|
||||
textSetting: '文字设置',
|
||||
themeSetting: '主题设置',
|
||||
// person configuration
|
||||
number: '编号',
|
||||
name: '姓名',
|
||||
prizeName: '名称',
|
||||
department: '部门',
|
||||
identity: '身份',
|
||||
isLucky: '是否中奖',
|
||||
operation: '操作',
|
||||
setLuckyNumber: '设置中奖人数',
|
||||
luckyPeopleNumber: '中奖人数',
|
||||
detail: '详细信息',
|
||||
noneData: '暂无数据',
|
||||
// prize configuration
|
||||
fullParticipation: '可重复',
|
||||
numberParticipants: '抽奖人数',
|
||||
isDone: '已抽取',
|
||||
image: '图片',
|
||||
onceNumber: '单次抽取个数',
|
||||
time: '时间',
|
||||
// view setting
|
||||
title: '主标题',
|
||||
columnNumber: '列数',
|
||||
theme: '主题',
|
||||
language: '语言',
|
||||
cardColor: '卡片颜色',
|
||||
winnerColor: '中奖卡片颜色',
|
||||
textColor: '文字颜色',
|
||||
cardWidth: '卡片宽度',
|
||||
cardHeight: '卡片高度',
|
||||
textSize: '文字大小',
|
||||
highlightColor: '高亮颜色',
|
||||
alwaysDisplay: '常显奖项列表',
|
||||
avatarDisplay: '是否显示头像',
|
||||
selectPicture: '选择一张图片',
|
||||
backgroundImage: '选择背景图片',
|
||||
timedStop: '定时停止',
|
||||
playWinMusic: '播放中奖音乐',
|
||||
resetAllData: '重置数据',
|
||||
|
||||
}
|
||||
|
||||
export const table = {
|
||||
en: tableEn,
|
||||
zhCn: tableZhCn,
|
||||
}
|
||||
44
src/locales/modules/tooltip.ts
Normal file
44
src/locales/modules/tooltip.ts
Normal file
@@ -0,0 +1,44 @@
|
||||
export const tooltipEn = {
|
||||
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',
|
||||
timedStop: 'After the lottery begins, it will stop at a scheduled time by default, set to 0, with the unit in seconds. A value of 0 disables the scheduled stopping function',
|
||||
uploadImage: 'Upload Image',
|
||||
pleaseGoto: 'Please go to',
|
||||
}
|
||||
|
||||
export const tooltipZhCn = {
|
||||
settingConfiguration: '设置/配置',
|
||||
nextSong: '右键点击下一首',
|
||||
noSongPlay: '没有音乐可以播放',
|
||||
prizeList: '奖项列表',
|
||||
addActivity: '添加抽奖',
|
||||
downloadTemplateTip: '下载文件后,请在excel中填写数据,并保存为xlsx格式',
|
||||
uploadExcelTip: '上传修改好的excel文件',
|
||||
leftClick: '左键切割',
|
||||
toHome: '主页',
|
||||
resetLayout: '该项比较耗费时间和性能',
|
||||
defaultLayout: '默认图案设置针对17列时有效,其他列数请自行设置',
|
||||
doneCount: '已抽取',
|
||||
edit: '编辑',
|
||||
delete: '删除',
|
||||
timedStop: '开始抽奖过后定时停止,默认为0,单位为秒,0为关闭定时停止功能',
|
||||
uploadImage: '上传图片',
|
||||
pleaseGoto: '请先前往',
|
||||
}
|
||||
|
||||
export const tooltip = {
|
||||
en: tooltipEn,
|
||||
zhCn: tooltipZhCn,
|
||||
}
|
||||
20
src/locales/modules/viewTitle.ts
Normal file
20
src/locales/modules/viewTitle.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
export const viewTitleEn = {
|
||||
personManagement: 'Person Management',
|
||||
winnerManagement: 'Winner Management',
|
||||
prizeManagement: 'Prize Management',
|
||||
globalSetting: 'Global Setting',
|
||||
operatingInstructions: 'Operating Instructions',
|
||||
}
|
||||
|
||||
export const viewTitleZhCn = {
|
||||
personManagement: '人员管理',
|
||||
winnerManagement: '已中奖人员管理',
|
||||
prizeManagement: '奖项配置',
|
||||
globalSetting: '全局配置',
|
||||
operatingInstructions: '操作说明',
|
||||
}
|
||||
|
||||
export const viewTitle = {
|
||||
en: viewTitleEn,
|
||||
zhCn: viewTitleZhCn,
|
||||
}
|
||||
@@ -1,153 +1,14 @@
|
||||
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: '关闭',
|
||||
noInfoAndImport: '暂无人员信息,前往导入',
|
||||
useDefault: '使用默认数据',
|
||||
},
|
||||
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: '操作',
|
||||
setLuckyNumber: '设置中奖人数',
|
||||
luckyPeopleNumber: '中奖人数',
|
||||
import { button, data, dialog, error, footer, placeHolder, sidebar, table, tooltip, viewTitle } from './modules'
|
||||
|
||||
detail: '详细信息',
|
||||
noneData: '暂无数据',
|
||||
// prize configuration
|
||||
fullParticipation: '可重复',
|
||||
numberParticipants: '抽奖人数',
|
||||
isDone: '已抽取',
|
||||
image: '图片',
|
||||
onceNumber: '单次抽取个数',
|
||||
time: '时间',
|
||||
// view setting
|
||||
title: '主标题',
|
||||
columnNumber: '列数',
|
||||
theme: '主题',
|
||||
language: '语言',
|
||||
cardColor: '卡片颜色',
|
||||
winnerColor: '中奖卡片颜色',
|
||||
textColor: '文字颜色',
|
||||
cardWidth: '卡片宽度',
|
||||
cardHeight: '卡片高度',
|
||||
textSize: '文字大小',
|
||||
highlightColor: '高亮颜色',
|
||||
patternSetting: '图案设置',
|
||||
alwaysDisplay: '常显奖项列表',
|
||||
avatarDisplay: '是否显示头像',
|
||||
selectPicture: '选择一张图片',
|
||||
backgroundImage: '选择背景图片',
|
||||
},
|
||||
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: '删除',
|
||||
},
|
||||
error: {
|
||||
require: '必填项',
|
||||
requireNumber: '请输入数字',
|
||||
minNumber1: '最小为1',
|
||||
maxNumber100: '最大为100',
|
||||
uploadSuccess: '上传成功',
|
||||
uploadFail: '上传失败',
|
||||
notImage: '不是图片',
|
||||
personIsAllDone: '抽奖抽完了',
|
||||
personNotEnough: '抽奖人数不足',
|
||||
startDraw: '现在抽取{count}{leftover}人',
|
||||
completeInformation: '请填写完整信息',
|
||||
},
|
||||
placeHolder: {
|
||||
enterTitle: '输入标题',
|
||||
name: '名称',
|
||||
winnerCount: '中奖人数',
|
||||
},
|
||||
data: {
|
||||
yes: '是',
|
||||
no: '否',
|
||||
number: '编号',
|
||||
isWin: '是否中奖',
|
||||
avatar: '头像',
|
||||
department: '部门',
|
||||
name: '姓名',
|
||||
identity: '身份',
|
||||
prizeName: '获奖',
|
||||
prizeTime: '获奖时间',
|
||||
operation: '操作',
|
||||
delete: '删除',
|
||||
removePerson: '移入未中奖名单',
|
||||
defaultTitle: '大明内阁六部御前奏对',
|
||||
xlsxName: '人口登记表-zhCn.xlsx',
|
||||
readmeName: 'readme-zhCn.md',
|
||||
},
|
||||
footer: {
|
||||
'self-reflection': '行有不得,反求诸己',
|
||||
'thiefEasy': '破山中贼易,破心中贼难',
|
||||
},
|
||||
export default {
|
||||
button: button.zhCn,
|
||||
sidebar: sidebar.zhCn,
|
||||
viewTitle: viewTitle.zhCn,
|
||||
table: table.zhCn,
|
||||
dialog: dialog.zhCn,
|
||||
tooltip: tooltip.zhCn,
|
||||
error: error.zhCn,
|
||||
placeHolder: placeHolder.zhCn,
|
||||
data: data.zhCn,
|
||||
footer: footer.zhCn,
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ import { refDebounced } from '@vueuse/core'
|
||||
import { ChevronRight, ChevronsUpDownIcon } from 'lucide-vue-next'
|
||||
import { PopoverArrow } from 'reka-ui'
|
||||
import { computed, ref } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import {
|
||||
Command,
|
||||
@@ -31,7 +32,7 @@ const { getFonts, disabled: browserDisabled, fonts } = useLocalFonts()
|
||||
const open = ref(false)
|
||||
const activeKey = ref('')
|
||||
const debouncedActiveKey = refDebounced(activeKey, 20)
|
||||
|
||||
const { t } = useI18n()
|
||||
function selectFont(selectedValue: any) {
|
||||
open.value = false
|
||||
activeKey.value = ''
|
||||
@@ -67,7 +68,7 @@ const disabledStyle = computed(() => {
|
||||
@click="getFonts"
|
||||
>
|
||||
<span class="w-7/8 text-left truncate" :style="{ fontFamily: `${selectedFont}` }">
|
||||
{{ selectedFont || "选择字体..." }}
|
||||
{{ selectedFont || t('placeHolder.selectFont') }}
|
||||
</span>
|
||||
<ChevronsUpDownIcon class="opacity-50" />
|
||||
</Button>
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
<script setup lang='ts'>
|
||||
import type { IFileData } from '@/components/FileUpload/type'
|
||||
import localforage from 'localforage'
|
||||
import { v4 as uuidv4 } from 'uuid'
|
||||
import { computed, ref, watch } from 'vue'
|
||||
import { ref, watch } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { useToast } from 'vue-toast-notification'
|
||||
import CustomDialog from '@/components/Dialog/index.vue'
|
||||
import FileUpload from '@/components/FileUpload/index.vue'
|
||||
@@ -19,7 +18,7 @@ const visible = defineModel('visible', {
|
||||
required: true,
|
||||
})
|
||||
const jsonFileData = ref<IFileData | null>(null)
|
||||
|
||||
const { t } = useI18n()
|
||||
const uploadDialogRef = ref()
|
||||
|
||||
async function uploadFile(fileData: IFileData | null) {
|
||||
@@ -30,7 +29,7 @@ async function uploadFile(fileData: IFileData | null) {
|
||||
const isJson = /application\/json/.test(fileData?.type || '')
|
||||
if (!isJson) {
|
||||
toast.open({
|
||||
message: '不是json文件,请检查',
|
||||
message: t('error.notJsonFile'),
|
||||
type: 'error',
|
||||
position: 'top-right',
|
||||
})
|
||||
@@ -57,7 +56,7 @@ watch(visible, (newVal) => {
|
||||
<CustomDialog
|
||||
ref="uploadDialogRef"
|
||||
v-model:visible="visible"
|
||||
title="设置文件上传"
|
||||
:title="t('dialog.uploadFileTitle')"
|
||||
:submit-func="submitUpload"
|
||||
class=""
|
||||
>
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
<script setup lang='ts'>
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
const { t } = useI18n()
|
||||
const definiteTime = defineModel<number | null>('definiteTime', { required: true })
|
||||
const winMusic = defineModel<boolean>('winMusic', { required: true })
|
||||
</script>
|
||||
@@ -6,22 +9,22 @@ const winMusic = defineModel<boolean>('winMusic', { required: true })
|
||||
<template>
|
||||
<fieldset class="p-4 border text-setting fieldset bg-base-200 border-base-300 rounded-box w-xs pb-10">
|
||||
<legend class="fieldset-legend">
|
||||
功能设置
|
||||
{{ t('table.abilitySetting') }}
|
||||
</legend>
|
||||
|
||||
<label class="flex flex-row items-center form-control">
|
||||
<div class="">
|
||||
<div class="label flex flex-col justify-start items-start">
|
||||
<label class="label">
|
||||
<span class="label-text text-left">定时停止</span>
|
||||
<div class="tooltip" data-tip="开始抽奖过后定时停止,默认为0,单位为秒,0为关闭定时停止功能">
|
||||
<span class="label-text text-left">{{ t('table.timedStop') }}</span>
|
||||
<div class="tooltip" :data-tip="t('tooltip.timedStop')">
|
||||
<button class="btn btn-circle h-4 hover:bg-base-300">
|
||||
?
|
||||
</button>
|
||||
</div>
|
||||
</label>
|
||||
<input
|
||||
v-model="definiteTime" type="number" placeholder="开始后定时抽取"
|
||||
v-model="definiteTime" type="number" :placeholder="t('placeHolder.timedStop')"
|
||||
class="w-full max-w-xs input input-bordered"
|
||||
>
|
||||
</div>
|
||||
@@ -29,7 +32,7 @@ const winMusic = defineModel<boolean>('winMusic', { required: true })
|
||||
</label>
|
||||
<div class="flex items-center justify-between w-full max-w-xs gap-2 mb-3 form-control">
|
||||
<div class="label">
|
||||
<span class="label-text">播放获奖音乐</span>
|
||||
<span class="label-text">{{ t('table.playWinMusic') }}</span>
|
||||
</div>
|
||||
<input
|
||||
type="checkbox" :checked="winMusic" class="border-solid checkbox checkbox-secondary border"
|
||||
|
||||
@@ -19,7 +19,7 @@ const uploadVisible = ref(false)
|
||||
<template>
|
||||
<fieldset class="p-4 border text-setting fieldset bg-base-200 border-base-300 rounded-box w-xs pb-10">
|
||||
<legend class="fieldset-legend">
|
||||
数据操作
|
||||
{{ t('table.DataSetting') }}
|
||||
</legend>
|
||||
<dialog id="my_modal_1" ref="resetDataDialogRef" class="border-none modal">
|
||||
<div class="modal-box">
|
||||
@@ -46,7 +46,7 @@ const uploadVisible = ref(false)
|
||||
<label class="flex flex-row items-center form-control">
|
||||
<div class="">
|
||||
<div class="label flex flex-col justify-start items-start">
|
||||
<span class="label-text text-left">重置数据</span>
|
||||
<span class="label-text text-left">{{ t('table.resetAllData') }}</span>
|
||||
<div class="help">
|
||||
<button class="btn btn-sm btn-primary" @click="resetDataDialogRef.showModal()">
|
||||
{{ t('button.resetAllData') }}
|
||||
|
||||
@@ -18,7 +18,7 @@ const isShowAvatarValue = defineModel<boolean>('isShowAvatarValue', { required:
|
||||
<template>
|
||||
<fieldset class="p-4 border text-setting fieldset bg-base-200 border-base-300 rounded-box w-xs pb-10">
|
||||
<legend class="fieldset-legend">
|
||||
布局设置
|
||||
{{ t('table.layoutSetting') }}
|
||||
</legend>
|
||||
<label class="flex flex-row items-center form-control">
|
||||
<div class="">
|
||||
|
||||
@@ -17,7 +17,7 @@ const { t } = useI18n()
|
||||
<template>
|
||||
<fieldset class="p-4 border text-setting fieldset bg-base-200 border-base-300 rounded-box w-xs pb-10">
|
||||
<legend class="fieldset-legend">
|
||||
图案设置
|
||||
{{ t('table.patternSetting') }}
|
||||
</legend>
|
||||
<div class="items-center gap-24 mb-0 form-control">
|
||||
<div>
|
||||
|
||||
@@ -15,7 +15,7 @@ const titleFontSyncGlobalValue = defineModel<boolean>('titleFontSyncGlobalValue'
|
||||
<template>
|
||||
<fieldset class="p-4 border text-setting fieldset bg-base-200 border-base-300 rounded-box w-xs pb-10">
|
||||
<legend class="fieldset-legend">
|
||||
文本设置
|
||||
{{ t('table.textSetting') }}
|
||||
</legend>
|
||||
<label class="label">
|
||||
<div class="label">
|
||||
|
||||
@@ -26,7 +26,7 @@ const patternColorValue = defineModel<string>('patternColorValue')
|
||||
<template>
|
||||
<fieldset class="p-4 border text-setting fieldset bg-base-200 border-base-300 rounded-box w-xs pb-10">
|
||||
<legend class="fieldset-legend">
|
||||
主题设置
|
||||
{{ t('table.themeSetting') }}
|
||||
</legend>
|
||||
|
||||
<div class="w-full max-w-xs form-control">
|
||||
@@ -62,11 +62,12 @@ const patternColorValue = defineModel<string>('patternColorValue')
|
||||
<span class="truncate w-option-xs">{{ item.name }}</span>
|
||||
</option>
|
||||
</select>
|
||||
<span class="label">请先前往
|
||||
<span class="label">
|
||||
{{ t('tooltip.pleaseGoto') }}
|
||||
<a class="link link-info" @click="() => { router.push('image') }">
|
||||
图片管理
|
||||
{{ t('sidebar.imagesManagement') }}
|
||||
</a>
|
||||
上传图片</span>
|
||||
{{ t('tooltip.uploadImage') }}</span>
|
||||
</div>
|
||||
<div class="grid w-full grid-cols-2 gap-4">
|
||||
<div class="flex flex-col items-center max-w-xs gap-1 form-control">
|
||||
|
||||
@@ -96,14 +96,14 @@ watch(visible, (newVal) => {
|
||||
<CustomDialog
|
||||
ref="uploadDialogRef"
|
||||
v-model:visible="visible"
|
||||
title="图片上传"
|
||||
:title="t('dialog.uploadImageTitle')"
|
||||
:submit-func="submitUpload"
|
||||
class=""
|
||||
>
|
||||
<template #content>
|
||||
<div class="flex flex-col items-center gap-6 w-full px-12">
|
||||
<FileUpload v-if="visible" :limit-type="limitType" @upload-file="uploadFile" />
|
||||
<input v-model="fileName" :disabled="imageData === null" type="text" placeholder="图片名称" class="input w-full">
|
||||
<input v-model="fileName" :disabled="imageData === null" type="text" :placeholder="t('placeHolder.imageName')" class="input w-full">
|
||||
</div>
|
||||
</template>
|
||||
</CustomDialog>
|
||||
|
||||
@@ -9,6 +9,7 @@ import CustomDialog from '@/components/Dialog/index.vue'
|
||||
import FileUpload from '@/components/FileUpload/index.vue'
|
||||
import useStore from '@/store'
|
||||
|
||||
const { t } = useI18n()
|
||||
const toast = useToast()
|
||||
const limitType = ref('audio/*')
|
||||
const visible = defineModel('visible', {
|
||||
@@ -41,7 +42,7 @@ async function uploadFile(fileData: IFileData | null) {
|
||||
const isAudio = /audio*/.test(fileData?.type || '')
|
||||
if (!isAudio) {
|
||||
toast.open({
|
||||
message: '不是音频文件',
|
||||
message: t('error.notAudioFile'),
|
||||
type: 'error',
|
||||
position: 'top-right',
|
||||
})
|
||||
@@ -71,7 +72,7 @@ function submitUpload() {
|
||||
})
|
||||
.then(() => {
|
||||
toast.open({
|
||||
message: '上传成功',
|
||||
message: t('error.uploadSuccess'),
|
||||
type: 'success',
|
||||
position: 'top-right',
|
||||
})
|
||||
@@ -79,7 +80,7 @@ function submitUpload() {
|
||||
})
|
||||
.catch(() => {
|
||||
toast.open({
|
||||
message: '上传失败',
|
||||
message: t('error.uploadFail'),
|
||||
type: 'error',
|
||||
position: 'top-right',
|
||||
})
|
||||
@@ -97,14 +98,14 @@ watch(visible, (newVal) => {
|
||||
<CustomDialog
|
||||
ref="uploadDialogRef"
|
||||
v-model:visible="visible"
|
||||
title="音乐上传"
|
||||
:title="t('dialog.uploadAudioTitle')"
|
||||
:submit-func="submitUpload"
|
||||
class=""
|
||||
>
|
||||
<template #content>
|
||||
<div class="flex flex-col items-center gap-6 w-full px-12">
|
||||
<FileUpload v-if="visible" :limit-type="limitType" @upload-file="uploadFile" />
|
||||
<input v-model="fileName" :disabled="audioData === null" type="text" placeholder="图片名称" class="input w-full">
|
||||
<input v-model="fileName" :disabled="audioData === null" type="text" class="input w-full">
|
||||
</div>
|
||||
</template>
|
||||
</CustomDialog>
|
||||
|
||||
@@ -5,6 +5,7 @@ import { storeToRefs } from 'pinia'
|
||||
import { ref } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import PageHeader from '@/components/PageHeader/index.vue'
|
||||
import { sidebar } from '@/locales/modules'
|
||||
import useStore from '@/store'
|
||||
import UploadDialog from './components/UploadDialog.vue'
|
||||
|
||||
@@ -41,7 +42,7 @@ function deleteAll() {
|
||||
<template>
|
||||
<UploadDialog v-model:visible="uploadVisible" />
|
||||
<div>
|
||||
<PageHeader title="音乐管理">
|
||||
<PageHeader :title="t('sidebar.musicManagement')">
|
||||
<template #buttons>
|
||||
<div class="flex gap-3">
|
||||
<button class="btn btn-primary btn-sm" @click="resetMusic">
|
||||
|
||||
@@ -1,42 +1,45 @@
|
||||
<script setup lang='ts'>
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
defineProps<{
|
||||
addOnePersonDrawerRef: any
|
||||
addOnePerson: (addOnePersonDrawerRef: any, event: any) => void
|
||||
}>()
|
||||
|
||||
const { t } = useI18n()
|
||||
const singlePersonData = defineModel<any>('singlePersonData', { required: true })
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<form class="fieldset rounded-box w-xs p-4" @submit="(e) => addOnePerson(addOnePersonDrawerRef, e)">
|
||||
<label class="fieldset">
|
||||
<span class="label">编号</span>
|
||||
<input v-model="singlePersonData.uid" type="text" class="input validator" placeholder="编号">
|
||||
<span class="label">{{ t('table.number') }}</span>
|
||||
<input v-model="singlePersonData.uid" type="text" class="input validator" :placeholder="t('placeHolder.number')">
|
||||
</label>
|
||||
<fieldset class="fieldset">
|
||||
<label class="label" required>姓名<span class="text-red-500">*</span></label>
|
||||
<input v-model="singlePersonData.name" type="text" class="input validator" placeholder="姓名" required minlength="1">
|
||||
<label class="label" required>{{ t('table.name') }}<span class="text-red-500">*</span></label>
|
||||
<input v-model="singlePersonData.name" type="text" class="input validator" :placeholder="t('placeHolder.name')" required minlength="1">
|
||||
<p class="validator-hint hidden">
|
||||
请填写姓名
|
||||
{{ t('error.personNameEmpty') }}
|
||||
</p>
|
||||
</fieldset>
|
||||
<label class="fieldset">
|
||||
<span class="label">部门</span>
|
||||
<input v-model="singlePersonData.department" type="text" class="input validator" placeholder="部门">
|
||||
<span class="label">{{ t('table.department') }}</span>
|
||||
<input v-model="singlePersonData.department" type="text" class="input validator" :placeholder="t('placeHolder.department')">
|
||||
</label>
|
||||
<label class="fieldset">
|
||||
<span class="label">头像</span>
|
||||
<input v-model="singlePersonData.avatar" type="text" class="input validator" placeholder="头像">
|
||||
<span class="label">{{ t('table.avatar') }}</span>
|
||||
<input v-model="singlePersonData.avatar" type="text" class="input validator" :placeholder="t('placeHolder.avatar')">
|
||||
</label>
|
||||
<label class="fieldset">
|
||||
<span class="label">身份</span>
|
||||
<input v-model="singlePersonData.identity" type="text" class="input validator" placeholder="身份">
|
||||
<span class="label">{{ t('table.identity') }}</span>
|
||||
<input v-model="singlePersonData.identity" type="text" class="input validator" :placeholder="t('placeHolder.identity')">
|
||||
</label>
|
||||
<button class="btn btn-neutral mt-4" type="submit">
|
||||
确定
|
||||
{{ t('button.submit') }}
|
||||
</button>
|
||||
<button class="btn btn-ghost mt-1" type="reset" @click="addOnePersonDrawerRef.closeDrawer()">
|
||||
取消
|
||||
{{ t('button.cancel') }}
|
||||
</button>
|
||||
</form>
|
||||
</template>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import * as XLSX from 'xlsx'
|
||||
import i18n from '@/locales/i18n'
|
||||
import { addOtherInfo } from '@/utils'
|
||||
// 定义消息类型
|
||||
interface WorkerMessage {
|
||||
@@ -13,7 +14,6 @@ function headersEqual(template: string[], actual: string[]): boolean {
|
||||
return template.length >= actual.length
|
||||
&& actual.some(item => template.includes(item))
|
||||
}
|
||||
|
||||
// 接收主线程消息
|
||||
globalThis.onmessage = async (e: MessageEvent<WorkerMessage>) => {
|
||||
switch (e.data.type) {
|
||||
@@ -37,7 +37,7 @@ globalThis.onmessage = async (e: MessageEvent<WorkerMessage>) => {
|
||||
globalThis.postMessage({
|
||||
type: 'error',
|
||||
data: null,
|
||||
message: '表头不一致,请先下载模板然后修改',
|
||||
message: i18n.global.t('error.excelFileError'),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
@@ -87,7 +87,7 @@ const limitType = '.xlsx,.xls'
|
||||
{{ t('button.exportResult') }}
|
||||
</button>
|
||||
<button class="btn btn-neutral btn-sm" @click="addOnePersonDrawerRef.showDrawer()">
|
||||
添加
|
||||
{{ t('button.add') }}
|
||||
</button>
|
||||
<div>
|
||||
<span>{{ t('table.luckyPeopleNumber') }}:</span>
|
||||
|
||||
@@ -3,6 +3,7 @@ import type { IPersonConfig } from '@/types/storeType'
|
||||
import { storeToRefs } from 'pinia'
|
||||
import { v4 as uuidv4 } from 'uuid'
|
||||
import { inject, ref, toRaw } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { useToast } from 'vue-toast-notification'
|
||||
import * as XLSX from 'xlsx'
|
||||
import { loadingKey } from '@/components/Loading'
|
||||
@@ -16,6 +17,7 @@ import ImportExcelWorker from './importExcel.worker?worker'
|
||||
type IBasePersonConfig = Pick<IPersonConfig, 'uid' | 'name' | 'department' | 'identity' | 'avatar'>
|
||||
|
||||
export function useViewModel({ exportInputFileRef }: { exportInputFileRef: Ref<HTMLInputElement> }) {
|
||||
const { t } = useI18n()
|
||||
const baseUrl = import.meta.env.BASE_URL
|
||||
const toast = useToast()
|
||||
const worker: Worker | null = new ImportExcelWorker()
|
||||
@@ -65,7 +67,7 @@ export function useViewModel({ exportInputFileRef }: { exportInputFileRef: Ref<H
|
||||
personConfig.addNotPersonList(e.data.data)
|
||||
// 提示导入成功
|
||||
toast.open({
|
||||
message: '导入成功',
|
||||
message: t('error.importSuccess'),
|
||||
type: 'success',
|
||||
position: 'top-right',
|
||||
})
|
||||
@@ -74,7 +76,7 @@ export function useViewModel({ exportInputFileRef }: { exportInputFileRef: Ref<H
|
||||
}
|
||||
if (e.data.type === 'error') {
|
||||
toast.open({
|
||||
message: e.data.message || '导入错误',
|
||||
message: e.data.message || t('error.importFail'),
|
||||
type: 'error',
|
||||
position: 'top-right',
|
||||
})
|
||||
@@ -105,7 +107,7 @@ export function useViewModel({ exportInputFileRef }: { exportInputFileRef: Ref<H
|
||||
a.download = templateFileName
|
||||
a.click()
|
||||
toast.open({
|
||||
message: '下载成功',
|
||||
message: t('error.downloadSuccess'),
|
||||
type: 'success',
|
||||
position: 'top-right',
|
||||
})
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import DaiysuiTable from '@/components/DaiysuiTable/index.vue'
|
||||
import PageHeader from '@/components/PageHeader/index.vue'
|
||||
import { Switch } from '@/components/ui/switch'
|
||||
import { useViewModel } from './useViewModel'
|
||||
|
||||
const { t } = useI18n()
|
||||
|
||||
@@ -80,7 +80,7 @@ export function usePrizeConfig() {
|
||||
|
||||
function delItem(item: IPrizeConfig) {
|
||||
prizeConfig.deletePrizeConfig(item.id)
|
||||
toast.success('删除成功')
|
||||
toast.success(i18n.global.t('error.deleteSuccess'))
|
||||
}
|
||||
function addPrize() {
|
||||
const defaultPrizeCOnfig: IPrizeConfig = {
|
||||
@@ -105,16 +105,16 @@ export function usePrizeConfig() {
|
||||
frequency: 1,
|
||||
}
|
||||
prizeList.value.push(defaultPrizeCOnfig)
|
||||
toast.success('添加成功')
|
||||
toast.success(i18n.global.t('error.success'))
|
||||
}
|
||||
function resetDefault() {
|
||||
prizeConfig.resetDefault()
|
||||
prizeList.value = cloneDeep(localPrizeList.value)
|
||||
toast.success('重置成功')
|
||||
toast.success(i18n.global.t('error.success'))
|
||||
}
|
||||
async function delAll() {
|
||||
prizeList.value = []
|
||||
toast.success('删除成功')
|
||||
toast.success(i18n.global.t('error.success'))
|
||||
}
|
||||
onMounted(() => {
|
||||
getImageDbStore()
|
||||
|
||||
@@ -69,7 +69,7 @@ function skip(path: string) {
|
||||
</ul>
|
||||
<router-view class="flex-1 mt-5" />
|
||||
</div>
|
||||
<footer class="p-10 rounded footer footer-center bg-base-200 h-[280px] flex flex-col gap-4 text-base-content">
|
||||
<footer class="p-10 rounded footer footer-center bg-base-200 h-70 flex flex-col gap-4 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">{{ t('footer.self-reflection') }}</a>
|
||||
</nav>
|
||||
|
||||
@@ -64,7 +64,7 @@ const { t } = useI18n()
|
||||
<!-- 加载中 -->
|
||||
<div v-else class="flex gap-3 items-center">
|
||||
<span class="loading loading-spinner loading-xl" />
|
||||
<span>加载中</span>
|
||||
<span>{{ t('button.loading') }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
Reference in New Issue
Block a user