From c9efd62e344c138d271799c31082fb7f6f1f8c8f Mon Sep 17 00:00:00 2001 From: LOG1997 <2694233102@qq.com> Date: Thu, 11 Dec 2025 23:18:10 +0800 Subject: [PATCH] =?UTF-8?q?refactor:=20=E2=99=BB=EF=B8=8F=20=E7=95=8C?= =?UTF-8?q?=E9=9D=A2=E8=AE=BE=E7=BD=AE=E9=A1=B5=E9=9D=A2=E9=87=8D=E6=9E=84?= =?UTF-8?q?=EF=BC=8C=E6=8A=BD=E7=A6=BB=E9=80=BB=E8=BE=91=20#96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/FileUpload/index.vue | 13 +- src/store/globalConfig.ts | 7 +- src/utils/file.ts | 10 + .../{PatternSetting.vue => PatternEdit.vue} | 0 .../FaceConfig/components/UploadDialog.vue | 75 +++ src/views/Config/Global/FaceConfig/index.vue | 467 ++---------------- .../Global/FaceConfig/parts/DataSetting.vue | 87 ++++ .../Global/FaceConfig/parts/LayoutSetting.vue | 91 ++++ .../FaceConfig/parts/PatternSetting.vue | 50 ++ .../Global/FaceConfig/parts/TextSetting.vue | 72 +++ .../Global/FaceConfig/parts/ThemeSetting.vue | 101 ++++ .../Config/Global/FaceConfig/parts/index.ts | 5 + .../Config/Global/FaceConfig/useViewModel.ts | 207 ++++++++ .../MusicConfig/components/UploadDialog.vue | 1 - 14 files changed, 756 insertions(+), 430 deletions(-) rename src/views/Config/Global/FaceConfig/components/{PatternSetting.vue => PatternEdit.vue} (100%) create mode 100644 src/views/Config/Global/FaceConfig/components/UploadDialog.vue create mode 100644 src/views/Config/Global/FaceConfig/parts/DataSetting.vue create mode 100644 src/views/Config/Global/FaceConfig/parts/LayoutSetting.vue create mode 100644 src/views/Config/Global/FaceConfig/parts/PatternSetting.vue create mode 100644 src/views/Config/Global/FaceConfig/parts/TextSetting.vue create mode 100644 src/views/Config/Global/FaceConfig/parts/ThemeSetting.vue create mode 100644 src/views/Config/Global/FaceConfig/parts/index.ts create mode 100644 src/views/Config/Global/FaceConfig/useViewModel.ts diff --git a/src/components/FileUpload/index.vue b/src/components/FileUpload/index.vue index 2b809f2..1cc2b5e 100644 --- a/src/components/FileUpload/index.vue +++ b/src/components/FileUpload/index.vue @@ -2,10 +2,11 @@ import type { IFileData } from './type' import { ListMusic, Upload, X } from 'lucide-vue-next' import { ref } from 'vue' -import { readFileData } from '@/utils/file' +import { readFileAsJsonData, readFileData } from '@/utils/file' -defineProps<{ +const props = defineProps<{ limitType?: string + mode?: 'file' | 'json' }>() const emits = defineEmits<{ @@ -17,6 +18,14 @@ const fileData = ref(null) async function handleFileChange(e: Event) { const file = ((e.target as HTMLInputElement).files as FileList)[0] const type = file.type + if (props.mode === 'json') { + const fileRes = await readFileAsJsonData(file) + const jsonData = JSON.parse(fileRes) + fileData.value = { dataUrl: jsonData, fileName: file.name, type } + originFileName.value = file.name + emits('uploadFile', fileData.value) + return + } const { dataUrl, fileName } = await readFileData(file) fileData.value = { dataUrl, fileName, type } originFileName.value = fileName diff --git a/src/store/globalConfig.ts b/src/store/globalConfig.ts index 738d3a8..d89d64a 100644 --- a/src/store/globalConfig.ts +++ b/src/store/globalConfig.ts @@ -127,6 +127,10 @@ export const useGlobalConfig = defineStore('global', { }, }, actions: { + // 设置全局配置 + setGlobalConfig(data: any) { + this.globalConfig = data + }, // 设置rowCount setRowCount(rowCount: number) { this.globalConfig.rowCount = rowCount @@ -137,9 +141,8 @@ export const useGlobalConfig = defineStore('global', { }, // 设置主题 setTheme(theme: any) { - const { name, detail } = theme + const { name } = theme this.globalConfig.theme.name = name - this.globalConfig.theme.detail = detail }, // 设置卡片颜色 setCardColor(cardColor: string) { diff --git a/src/utils/file.ts b/src/utils/file.ts index f4b05c7..fd4fd6a 100644 --- a/src/utils/file.ts +++ b/src/utils/file.ts @@ -23,3 +23,13 @@ export async function readLocalFileAsArraybuffer(path: string): Promise { + return new Promise((resolve) => { + const reader = new FileReader() + reader.readAsText(file, 'utf-8') + reader.onload = (ev: any) => { + resolve(ev.target.result) + } + }) +} diff --git a/src/views/Config/Global/FaceConfig/components/PatternSetting.vue b/src/views/Config/Global/FaceConfig/components/PatternEdit.vue similarity index 100% rename from src/views/Config/Global/FaceConfig/components/PatternSetting.vue rename to src/views/Config/Global/FaceConfig/components/PatternEdit.vue diff --git a/src/views/Config/Global/FaceConfig/components/UploadDialog.vue b/src/views/Config/Global/FaceConfig/components/UploadDialog.vue new file mode 100644 index 0000000..45002ff --- /dev/null +++ b/src/views/Config/Global/FaceConfig/components/UploadDialog.vue @@ -0,0 +1,75 @@ + + + + + diff --git a/src/views/Config/Global/FaceConfig/index.vue b/src/views/Config/Global/FaceConfig/index.vue index 7603048..e94b45c 100644 --- a/src/views/Config/Global/FaceConfig/index.vue +++ b/src/views/Config/Global/FaceConfig/index.vue @@ -1,443 +1,60 @@ diff --git a/src/views/Config/Global/FaceConfig/parts/DataSetting.vue b/src/views/Config/Global/FaceConfig/parts/DataSetting.vue new file mode 100644 index 0000000..9aa14f7 --- /dev/null +++ b/src/views/Config/Global/FaceConfig/parts/DataSetting.vue @@ -0,0 +1,87 @@ + + + + + diff --git a/src/views/Config/Global/FaceConfig/parts/LayoutSetting.vue b/src/views/Config/Global/FaceConfig/parts/LayoutSetting.vue new file mode 100644 index 0000000..31952c3 --- /dev/null +++ b/src/views/Config/Global/FaceConfig/parts/LayoutSetting.vue @@ -0,0 +1,91 @@ + + + + + diff --git a/src/views/Config/Global/FaceConfig/parts/PatternSetting.vue b/src/views/Config/Global/FaceConfig/parts/PatternSetting.vue new file mode 100644 index 0000000..43439ac --- /dev/null +++ b/src/views/Config/Global/FaceConfig/parts/PatternSetting.vue @@ -0,0 +1,50 @@ + + + + + diff --git a/src/views/Config/Global/FaceConfig/parts/TextSetting.vue b/src/views/Config/Global/FaceConfig/parts/TextSetting.vue new file mode 100644 index 0000000..e60fa4c --- /dev/null +++ b/src/views/Config/Global/FaceConfig/parts/TextSetting.vue @@ -0,0 +1,72 @@ + + + + + diff --git a/src/views/Config/Global/FaceConfig/parts/ThemeSetting.vue b/src/views/Config/Global/FaceConfig/parts/ThemeSetting.vue new file mode 100644 index 0000000..f78b41b --- /dev/null +++ b/src/views/Config/Global/FaceConfig/parts/ThemeSetting.vue @@ -0,0 +1,101 @@ + + + + + diff --git a/src/views/Config/Global/FaceConfig/parts/index.ts b/src/views/Config/Global/FaceConfig/parts/index.ts new file mode 100644 index 0000000..4ce76b6 --- /dev/null +++ b/src/views/Config/Global/FaceConfig/parts/index.ts @@ -0,0 +1,5 @@ +export { default as DataSetting } from './DataSetting.vue' +export { default as LayoutSetting } from './LayoutSetting.vue' +export { default as PatternSetting } from './PatternSetting.vue' +export { default as TextSetting } from './TextSetting.vue' +export { default as ThemeSetting } from './ThemeSetting.vue' diff --git a/src/views/Config/Global/FaceConfig/useViewModel.ts b/src/views/Config/Global/FaceConfig/useViewModel.ts new file mode 100644 index 0000000..1b35d30 --- /dev/null +++ b/src/views/Config/Global/FaceConfig/useViewModel.ts @@ -0,0 +1,207 @@ +import { storeToRefs } from 'pinia' +import { onMounted, ref, watch } from 'vue' +import { z as zod } from 'zod' +import i18n, { languageList } from '@/locales/i18n' +import useStore from '@/store' +import { themeChange } from '@/utils' +import { clearAllDbStore } from '@/utils/localforage' + +export function useViewModel() { + type ValidatePayload = zod.infer + const globalConfig = useStore().globalConfig + const personConfig = useStore().personConfig + const prizeConfig = useStore().prizeConfig + const { getGlobalConfig: globalConfigData, getTopTitle: topTitle, getTheme: localTheme, getPatterColor: patternColor, getPatternList: patternList, getCardColor: cardColor, getLuckyColor: luckyCardColor, getTextColor: textColor, getCardSize: cardSize, getTextSize: textSize, getRowCount: rowCount, getIsShowPrizeList: isShowPrizeList, getLanguage: userLanguage, getBackground: backgroundImage, getFont: currentFont, getTitleFont: currentTitleFont, getTitleFontSyncGlobal: titleFontSyncGlobal, getImageList: imageList, getIsShowAvatar: isShowAvatar, + } = storeToRefs(globalConfig) + const { getAlreadyPersonList: alreadyPersonList, getNotPersonList: notPersonList } = storeToRefs(personConfig) + + const isRowCountChange = ref(0) // 0未改变,1改变,2加载中 + const themeValue = ref(localTheme.value.name) + const topTitleValue = ref(structuredClone(topTitle.value)) + const cardColorValue = ref(structuredClone(cardColor.value)) + const luckyCardColorValue = ref(structuredClone(luckyCardColor.value)) + 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 isShowAvatarValue = ref(structuredClone(isShowAvatar.value)) + const patternColorValue = ref(structuredClone(patternColor.value)) + const backgroundImageValue = ref(backgroundImage.value) + const currentFontValue = ref(structuredClone(currentFont.value)) + const currentTitleFontValue = ref(structuredClone(currentTitleFont.value)) + const titleFontSyncGlobalValue = ref(structuredClone(titleFontSyncGlobal.value)) + const formData = ref({ + rowCount: rowCountValue, + }) + const formErr = ref({ + rowCount: '', + }) + const schema = zod.object({ + rowCount: zod.number({ + error: i18n.global.t('error.require'), + // required_error: i18n.global.t('error.require'), + // invalid_type_error: i18n.global.t('error.requireNumber'), + }) + .min(1, i18n.global.t('error.minNumber1')) + .max(100, i18n.global.t('error.maxNumber100')), + // 格式化 + + }) + const payload: ValidatePayload = { + rowCount: formData.value.rowCount, + } + function parseSchema(props: ValidatePayload) { + return schema.parseAsync(props) + } + + function resetPersonLayout() { + isRowCountChange.value = 2 + setTimeout(() => { + const alreadyLen = alreadyPersonList.value.length + const notLen = notPersonList.value.length + if (alreadyLen <= 0 && notLen <= 0) { + return + } + const allPersonList = alreadyPersonList.value.concat(notPersonList.value) + const newAlreadyPersonList = allPersonList.slice(0, alreadyLen) + const newNotPersonList = allPersonList.slice(alreadyLen, notLen + alreadyLen) + personConfig.deleteAllPerson() + personConfig.addNotPersonList(newNotPersonList) + personConfig.addAlreadyPersonList(newAlreadyPersonList, null) + + isRowCountChange.value = 0 + }, 1000) + } + + function clearPattern() { + globalConfig.setPatternList([] as number[]) + } + function resetPattern() { + globalConfig.resetPatternList() + } + + function resetData() { + globalConfig.reset() + personConfig.reset() + prizeConfig.resetDefault() + // 删除所有indexDb + clearAllDbStore() + // 刷新页面 + window.location.reload() + } + + function exportAllConfigData() { + // const globalConfigData = globalConfig.getGlobalConfig() + // console.log(globalConfigData.value) + // const globalConfigData = globalConfig.getGlobalConfig() + const dataStr = JSON.stringify(globalConfigData.value, null, 2) + const dataUri = `data:application/json;charset=utf-8,${encodeURIComponent(dataStr)}` + + const exportFileDefaultName = 'global-config.json' + + const linkElement = document.createElement('a') + linkElement.setAttribute('href', dataUri) + linkElement.setAttribute('download', exportFileDefaultName) + linkElement.click() + } + function importAllConfigData(data: any) { + globalConfig.setGlobalConfig(data) + window.location.reload() + } + + watch(() => formData.value.rowCount, () => { + payload.rowCount = formData.value.rowCount + parseSchema(payload).then((res) => { + if (res.rowCount) { + isRowCountChange.value = 1 + globalConfig.setRowCount(res.rowCount) + } + }).catch((err) => { + formErr.value.rowCount = err.issues[0].message + }) + }) + + watch(topTitleValue, (val) => { + globalConfig.setTopTitle(val) + }) + watch(themeValue, (val: any) => { + globalConfig.setTheme({ name: val }) + themeChange(val) + }, { deep: true }) + + watch(cardColorValue, (val: string) => { + globalConfig.setCardColor(val) + }, { deep: true }) + watch(luckyCardColorValue, (val: string) => { + globalConfig.setLuckyCardColor(val) + }, { deep: true }) + watch(patternColorValue, (val: string) => { + globalConfig.setPatterColor(val) + }) + watch(textColorValue, (val: string) => { + globalConfig.setTextColor(val) + }, { deep: true }) + + watch(cardSizeValue, (val: { width: number, height: number }) => { + globalConfig.setCardSize(val) + }, { deep: true }) + + watch(isShowPrizeListValue, () => { + globalConfig.setIsShowPrizeList(isShowPrizeListValue.value) + }) + watch(backgroundImageValue, (val) => { + globalConfig.setBackground(val) + }) + watch(currentFontValue, (val) => { + globalConfig.setFont(val) + document.documentElement.style.setProperty('--app-font-family', `"${val}", -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif`) + }) + watch(currentTitleFontValue, (val) => { + globalConfig.setTitleFont(val) + }) + watch(titleFontSyncGlobalValue, (val) => { + globalConfig.setTitleFontSyncGlobal(val) + }) + watch(languageValue, (val: string) => { + globalConfig.setLanguage(val) + }) + watch(isShowAvatarValue, () => { + globalConfig.setIsShowAvatar(isShowAvatarValue.value) + }) + onMounted(() => { + }) + return { + resetData, + topTitleValue, + languageValue, + textSizeValue, + currentFontValue, + currentTitleFontValue, + titleFontSyncGlobalValue, + languageList, + formErr, + formData, + cardSizeValue, + isShowPrizeListValue, + isShowAvatarValue, + resetPersonLayout, + isRowCountChange, + themeValue, + backgroundImageValue, + cardColorValue, + luckyCardColorValue, + textColorValue, + patternColorValue, + imageList, + rowCount, + cardColor, + patternColor, + patternList, + clearPattern, + resetPattern, + exportAllConfigData, + importAllConfigData, + } +} diff --git a/src/views/Config/Global/MusicConfig/components/UploadDialog.vue b/src/views/Config/Global/MusicConfig/components/UploadDialog.vue index f04b939..be5bc00 100644 --- a/src/views/Config/Global/MusicConfig/components/UploadDialog.vue +++ b/src/views/Config/Global/MusicConfig/components/UploadDialog.vue @@ -10,7 +10,6 @@ import FileUpload from '@/components/FileUpload/index.vue' import useStore from '@/store' const toast = useToast() -const { t } = useI18n() const limitType = ref('audio/*') const visible = defineModel('visible', { type: Boolean,