From cdd49728705105aed6d0ca805adae6f1c28b330c Mon Sep 17 00:00:00 2001
From: log1997 <2694233102@qq.com>
Date: Thu, 4 Dec 2025 13:47:28 +0800
Subject: [PATCH 04/11] =?UTF-8?q?feat(imgConfig):=20=E4=BC=98=E5=8C=96?=
=?UTF-8?q?=E5=9B=BE=E7=89=87=E5=AD=98=E5=82=A8=E7=BB=93=E6=9E=84?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
新增uuid依赖用于生成唯一ID,改进图片上传功能中的本地存储结构,
使用uuid替代时间戳作为键名以避免冲突,并调整从indexedDB读取数据的方式。
---
package.json | 1 +
pnpm-lock.yaml | 9 +
src/components/ImageSync/index.vue | 3 +-
src/store/globalConfig.ts | 542 +++++++++---------
src/utils/localforage/index.ts | 13 +
src/views/Config/Global/FaceConfig/index.vue | 12 +-
.../ImageConfig/components/UploadDialog.vue | 13 +-
7 files changed, 309 insertions(+), 284 deletions(-)
create mode 100644 src/utils/localforage/index.ts
diff --git a/package.json b/package.json
index 7c958b4..6643602 100644
--- a/package.json
+++ b/package.json
@@ -31,6 +31,7 @@
"sparticles": "^1.3.1",
"three": "^0.166.0",
"three-css3d": "^1.0.6",
+ "uuid": "^13.0.0",
"vue": "^3.5.13",
"vue-dompurify-html": "^5.2.0",
"vue-i18n": "^11.1.12",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 69c5728..626f357 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -53,6 +53,9 @@ importers:
three-css3d:
specifier: ^1.0.6
version: 1.0.6(three@0.166.0)
+ uuid:
+ specifier: ^13.0.0
+ version: 13.0.0
vue:
specifier: ^3.5.13
version: 3.5.13(typescript@5.5.3)
@@ -5135,6 +5138,10 @@ packages:
util@0.10.4:
resolution: {integrity: sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A==}
+ uuid@13.0.0:
+ resolution: {integrity: sha512-XQegIaBTVUjSHliKqcnFqYypAd4S+WCYt5NIeRs6w/UAry7z8Y9j5ZwRRL4kzq9U3sD6v+85er9FvkEaBpji2w==}
+ hasBin: true
+
vary@1.1.2:
resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==}
engines: {node: '>= 0.8'}
@@ -10877,6 +10884,8 @@ snapshots:
dependencies:
inherits: 2.0.3
+ uuid@13.0.0: {}
+
vary@1.1.2: {}
vite-dev-rpc@1.1.0(vite@7.1.6(@types/node@24.5.2)(jiti@2.5.1)(lightningcss@1.30.1)(sass@1.81.0)(terser@5.36.0)(yaml@2.8.1)):
diff --git a/src/components/ImageSync/index.vue b/src/components/ImageSync/index.vue
index 6dd2ae0..cfe50de 100644
--- a/src/components/ImageSync/index.vue
+++ b/src/components/ImageSync/index.vue
@@ -18,7 +18,8 @@ async function getImageStoreItem(item: any): Promise
{
let image = ''
if (item.url === 'Storage') {
const key = item.id
- image = await imageDbStore.getItem(key) as string
+ const imageData = await imageDbStore.getItem(key) as any
+ image = imageData.dataUrl
}
else {
image = item.url
diff --git a/src/store/globalConfig.ts b/src/store/globalConfig.ts
index 0fc7a22..de55b4c 100644
--- a/src/store/globalConfig.ts
+++ b/src/store/globalConfig.ts
@@ -1,280 +1,280 @@
import type { IImage, IMusic } from '@/types/storeType'
-import i18n, { browserLanguage } from '@/locales/i18n'
import { defineStore } from 'pinia'
+import i18n, { browserLanguage } from '@/locales/i18n'
import { defaultImageList, defaultMusicList, defaultPatternList } from './data'
// import { IPrizeConfig } from '@/types/storeType';
export const useGlobalConfig = defineStore('global', {
- state() {
- return {
- globalConfig: {
- rowCount: 17,
- isSHowPrizeList: true,
- isShowAvatar: false,
- topTitle: i18n.global.t('data.defaultTitle'),
- language: browserLanguage,
- theme: {
- name: 'dracula',
- detail: { primary: '#0f5fd3' },
- cardColor: '#ff79c6',
- cardWidth: 140,
- cardHeight: 200,
- textColor: '#ffffff',
- luckyCardColor: '#ECB1AC',
- textSize: 30,
- patternColor: '#1b66c9',
- patternList: defaultPatternList as number[],
- background: {}, // 背景颜色或图片
+ state() {
+ return {
+ globalConfig: {
+ rowCount: 17,
+ isSHowPrizeList: true,
+ isShowAvatar: false,
+ topTitle: i18n.global.t('data.defaultTitle'),
+ language: browserLanguage,
+ theme: {
+ name: 'dracula',
+ detail: { primary: '#0f5fd3' },
+ cardColor: '#ff79c6',
+ cardWidth: 140,
+ cardHeight: 200,
+ textColor: '#ffffff',
+ luckyCardColor: '#ECB1AC',
+ textSize: 30,
+ patternColor: '#1b66c9',
+ patternList: defaultPatternList as number[],
+ background: {}, // 背景颜色或图片
+ },
+ musicList: defaultMusicList as IMusic[],
+ imageList: defaultImageList as IImage[],
+ },
+ currentMusic: {
+ item: defaultMusicList[0],
+ paused: true,
+ },
+ }
+ },
+ getters: {
+ // 获取全部配置
+ getGlobalConfig(state) {
+ return state.globalConfig
},
- musicList: defaultMusicList as IMusic[],
- imageList: defaultImageList as IImage[],
- },
- currentMusic: {
- item: defaultMusicList[0],
- paused: true,
- },
- }
- },
- getters: {
- // 获取全部配置
- getGlobalConfig(state) {
- return state.globalConfig
- },
- // 获取标题
- getTopTitle(state) {
- return state.globalConfig.topTitle
- },
- // 获取行数
- getRowCount(state) {
- return state.globalConfig.rowCount
- },
- // 获取主题
- getTheme(state) {
- return state.globalConfig.theme
- },
- // 获取卡片颜色
- getCardColor(state) {
- return state.globalConfig.theme.cardColor
- },
- // 获取中奖颜色
- getLuckyColor(state) {
- return state.globalConfig.theme.luckyCardColor
- },
- // 获取文字颜色
- getTextColor(state) {
- return state.globalConfig.theme.textColor
- },
- // 获取卡片宽高
- getCardSize(state) {
- return {
- width: state.globalConfig.theme.cardWidth,
- height: state.globalConfig.theme.cardHeight,
- }
- },
- // 获取文字大小
- getTextSize(state) {
- return state.globalConfig.theme.textSize
- },
- // 获取图案颜色
- getPatterColor(state) {
- return state.globalConfig.theme.patternColor
- },
- // 获取图案列表
- getPatternList(state) {
- return state.globalConfig.theme.patternList
- },
- // 获取音乐列表
- getMusicList(state) {
- return state.globalConfig.musicList
- },
- // 获取当前音乐
- getCurrentMusic(state) {
- return state.currentMusic
- },
- // 获取图片列表
- getImageList(state) {
- return state.globalConfig.imageList
- },
- // 获取是否显示奖品列表
- getIsShowPrizeList(state) {
- return state.globalConfig.isSHowPrizeList
- },
- // 获取当前语言
- getLanguage(state) {
- return state.globalConfig.language
- },
- // 获取背景图片设置
- getBackground(state) {
- return state.globalConfig.theme.background
- },
- // 获取是否显示头像
- getIsShowAvatar(state) {
- return state.globalConfig.isShowAvatar
- },
- },
- actions: {
- // 设置rowCount
- setRowCount(rowCount: number) {
- this.globalConfig.rowCount = rowCount
- },
- // 设置标题
- setTopTitle(topTitle: string) {
- this.globalConfig.topTitle = topTitle
- },
- // 设置主题
- setTheme(theme: any) {
- const { name, detail } = theme
- this.globalConfig.theme.name = name
- this.globalConfig.theme.detail = detail
- },
- // 设置卡片颜色
- setCardColor(cardColor: string) {
- this.globalConfig.theme.cardColor = cardColor
- },
- // 设置中奖颜色
- setLuckyCardColor(luckyCardColor: string) {
- this.globalConfig.theme.luckyCardColor = luckyCardColor
- },
- // 设置文字颜色
- setTextColor(textColor: string) {
- this.globalConfig.theme.textColor = textColor
- },
- // 设置卡片宽高
- setCardSize(cardSize: { width: number, height: number }) {
- this.globalConfig.theme.cardWidth = cardSize.width
- this.globalConfig.theme.cardHeight = cardSize.height
- },
- // 设置文字大小
- setTextSize(textSize: number) {
- this.globalConfig.theme.textSize = textSize
- },
- // 设置图案颜色
- setPatterColor(patterColor: string) {
- this.globalConfig.theme.patternColor = patterColor
- },
- // 设置图案列表
- setPatternList(patternList: number[]) {
- this.globalConfig.theme.patternList = patternList
- },
- // 重置图案列表
- resetPatternList() {
- this.globalConfig.theme.patternList = defaultPatternList
- },
- // 添加音乐
- addMusic(music: IMusic) {
- // 验证音乐是否已存在,看name字段
- for (let i = 0; i < this.globalConfig.musicList.length; i++) {
- if (this.globalConfig.musicList[i].name === music.name) {
- return
- }
- }
- this.globalConfig.musicList.push(music)
- },
- // 删除音乐
- removeMusic(musicId: string) {
- for (let i = 0; i < this.globalConfig.musicList.length; i++) {
- if (this.globalConfig.musicList[i].id === musicId) {
- this.globalConfig.musicList.splice(i, 1)
- break
- }
- }
- },
- // 设置当前播放音乐
- setCurrentMusic(musicItem: IMusic, paused: boolean = true) {
- this.currentMusic = {
- item: musicItem,
- paused,
- }
- },
- // 重置音乐列表
- resetMusicList() {
- this.globalConfig.musicList = JSON.parse(JSON.stringify(defaultMusicList)) as IMusic[]
- },
- // 清空音乐列表
- clearMusicList() {
- this.globalConfig.musicList = [] as IMusic[]
- },
- // 添加图片
- addImage(image: IImage) {
- for (let i = 0; i < this.globalConfig.imageList.length; i++) {
- if (this.globalConfig.imageList[i].name === image.name) {
- return
- }
- }
- this.globalConfig.imageList.push(image)
- },
- // 删除图片
- removeImage(imageId: string) {
- for (let i = 0; i < this.globalConfig.imageList.length; i++) {
- if (this.globalConfig.imageList[i].id === imageId) {
- this.globalConfig.imageList.splice(i, 1)
- break
- }
- }
- },
- // 重置图片列表
- resetImageList() {
- this.globalConfig.imageList = defaultImageList as IImage[]
- },
- // 清空图片列表
- clearImageList() {
- this.globalConfig.imageList = [] as IImage[]
- },
- // 设置是否显示奖品列表
- setIsShowPrizeList(isShowPrizeList: boolean) {
- this.globalConfig.isSHowPrizeList = isShowPrizeList
- },
- // 设置
- setLanguage(language: string) {
- this.globalConfig.language = language
- i18n.global.locale.value = language
- },
- // 设置背景图片
- setBackground(background: any) {
- this.globalConfig.theme.background = background
- },
- // 设置是否显示头像
- setIsShowAvatar(isShowAvatar: boolean) {
- this.globalConfig.isShowAvatar = isShowAvatar
- },
- // 重置所有配置
- reset() {
- this.globalConfig = {
- rowCount: 17,
- isSHowPrizeList: true,
- isShowAvatar: false,
- topTitle: i18n.global.t('data.defaultTitle'),
- language: browserLanguage,
- theme: {
- name: 'dracula',
- detail: { primary: '#0f5fd3' },
- cardColor: '#ff79c6',
- cardWidth: 140,
- cardHeight: 200,
- textColor: '#ffffff',
- luckyCardColor: '#ECB1AC',
- textSize: 30,
- patternColor: '#1b66c9',
- patternList: defaultPatternList as number[],
- background: {}, // 背景颜色或图片
+ // 获取标题
+ getTopTitle(state) {
+ return state.globalConfig.topTitle
+ },
+ // 获取行数
+ getRowCount(state) {
+ return state.globalConfig.rowCount
+ },
+ // 获取主题
+ getTheme(state) {
+ return state.globalConfig.theme
+ },
+ // 获取卡片颜色
+ getCardColor(state) {
+ return state.globalConfig.theme.cardColor
+ },
+ // 获取中奖颜色
+ getLuckyColor(state) {
+ return state.globalConfig.theme.luckyCardColor
+ },
+ // 获取文字颜色
+ getTextColor(state) {
+ return state.globalConfig.theme.textColor
+ },
+ // 获取卡片宽高
+ getCardSize(state) {
+ return {
+ width: state.globalConfig.theme.cardWidth,
+ height: state.globalConfig.theme.cardHeight,
+ }
+ },
+ // 获取文字大小
+ getTextSize(state) {
+ return state.globalConfig.theme.textSize
+ },
+ // 获取图案颜色
+ getPatterColor(state) {
+ return state.globalConfig.theme.patternColor
+ },
+ // 获取图案列表
+ getPatternList(state) {
+ return state.globalConfig.theme.patternList
+ },
+ // 获取音乐列表
+ getMusicList(state) {
+ return state.globalConfig.musicList
+ },
+ // 获取当前音乐
+ getCurrentMusic(state) {
+ return state.currentMusic
+ },
+ // 获取图片列表
+ getImageList(state) {
+ return state.globalConfig.imageList
+ },
+ // 获取是否显示奖品列表
+ getIsShowPrizeList(state) {
+ return state.globalConfig.isSHowPrizeList
+ },
+ // 获取当前语言
+ getLanguage(state) {
+ return state.globalConfig.language
+ },
+ // 获取背景图片设置
+ getBackground(state) {
+ return state.globalConfig.theme.background
+ },
+ // 获取是否显示头像
+ getIsShowAvatar(state) {
+ return state.globalConfig.isShowAvatar
},
- musicList: defaultMusicList as IMusic[],
- imageList: defaultImageList as IImage[],
- }
- this.currentMusic = {
- item: defaultMusicList[0],
- paused: true,
- }
},
- },
- persist: {
- enabled: true,
- strategies: [
- {
- // 如果要存储在localStorage中
- storage: localStorage,
- key: 'globalConfig',
- paths: ['globalConfig'],
- },
- ],
- },
+ actions: {
+ // 设置rowCount
+ setRowCount(rowCount: number) {
+ this.globalConfig.rowCount = rowCount
+ },
+ // 设置标题
+ setTopTitle(topTitle: string) {
+ this.globalConfig.topTitle = topTitle
+ },
+ // 设置主题
+ setTheme(theme: any) {
+ const { name, detail } = theme
+ this.globalConfig.theme.name = name
+ this.globalConfig.theme.detail = detail
+ },
+ // 设置卡片颜色
+ setCardColor(cardColor: string) {
+ this.globalConfig.theme.cardColor = cardColor
+ },
+ // 设置中奖颜色
+ setLuckyCardColor(luckyCardColor: string) {
+ this.globalConfig.theme.luckyCardColor = luckyCardColor
+ },
+ // 设置文字颜色
+ setTextColor(textColor: string) {
+ this.globalConfig.theme.textColor = textColor
+ },
+ // 设置卡片宽高
+ setCardSize(cardSize: { width: number, height: number }) {
+ this.globalConfig.theme.cardWidth = cardSize.width
+ this.globalConfig.theme.cardHeight = cardSize.height
+ },
+ // 设置文字大小
+ setTextSize(textSize: number) {
+ this.globalConfig.theme.textSize = textSize
+ },
+ // 设置图案颜色
+ setPatterColor(patterColor: string) {
+ this.globalConfig.theme.patternColor = patterColor
+ },
+ // 设置图案列表
+ setPatternList(patternList: number[]) {
+ this.globalConfig.theme.patternList = patternList
+ },
+ // 重置图案列表
+ resetPatternList() {
+ this.globalConfig.theme.patternList = defaultPatternList
+ },
+ // 添加音乐
+ addMusic(music: IMusic) {
+ // 验证音乐是否已存在,看name字段
+ for (let i = 0; i < this.globalConfig.musicList.length; i++) {
+ if (this.globalConfig.musicList[i].name === music.name) {
+ return
+ }
+ }
+ this.globalConfig.musicList.push(music)
+ },
+ // 删除音乐
+ removeMusic(musicId: string) {
+ for (let i = 0; i < this.globalConfig.musicList.length; i++) {
+ if (this.globalConfig.musicList[i].id === musicId) {
+ this.globalConfig.musicList.splice(i, 1)
+ break
+ }
+ }
+ },
+ // 设置当前播放音乐
+ setCurrentMusic(musicItem: IMusic, paused: boolean = true) {
+ this.currentMusic = {
+ item: musicItem,
+ paused,
+ }
+ },
+ // 重置音乐列表
+ resetMusicList() {
+ this.globalConfig.musicList = JSON.parse(JSON.stringify(defaultMusicList)) as IMusic[]
+ },
+ // 清空音乐列表
+ clearMusicList() {
+ this.globalConfig.musicList = [] as IMusic[]
+ },
+ // 添加图片
+ addImage(image: IImage) {
+ for (let i = 0; i < this.globalConfig.imageList.length; i++) {
+ if (this.globalConfig.imageList[i].name === image.name) {
+ return
+ }
+ }
+ this.globalConfig.imageList.push(image)
+ },
+ // 删除图片
+ removeImage(imageId: string) {
+ for (let i = 0; i < this.globalConfig.imageList.length; i++) {
+ if (this.globalConfig.imageList[i].id === imageId) {
+ this.globalConfig.imageList.splice(i, 1)
+ break
+ }
+ }
+ },
+ // 重置图片列表
+ resetImageList() {
+ this.globalConfig.imageList = defaultImageList as IImage[]
+ },
+ // 清空图片列表
+ clearImageList() {
+ this.globalConfig.imageList = [] as IImage[]
+ },
+ // 设置是否显示奖品列表
+ setIsShowPrizeList(isShowPrizeList: boolean) {
+ this.globalConfig.isSHowPrizeList = isShowPrizeList
+ },
+ // 设置
+ setLanguage(language: string) {
+ this.globalConfig.language = language
+ i18n.global.locale.value = language
+ },
+ // 设置背景图片
+ setBackground(background: any) {
+ this.globalConfig.theme.background = background
+ },
+ // 设置是否显示头像
+ setIsShowAvatar(isShowAvatar: boolean) {
+ this.globalConfig.isShowAvatar = isShowAvatar
+ },
+ // 重置所有配置
+ reset() {
+ this.globalConfig = {
+ rowCount: 17,
+ isSHowPrizeList: true,
+ isShowAvatar: false,
+ topTitle: i18n.global.t('data.defaultTitle'),
+ language: browserLanguage,
+ theme: {
+ name: 'dracula',
+ detail: { primary: '#0f5fd3' },
+ cardColor: '#ff79c6',
+ cardWidth: 140,
+ cardHeight: 200,
+ textColor: '#ffffff',
+ luckyCardColor: '#ECB1AC',
+ textSize: 30,
+ patternColor: '#1b66c9',
+ patternList: defaultPatternList as number[],
+ background: {}, // 背景颜色或图片
+ },
+ musicList: defaultMusicList as IMusic[],
+ imageList: defaultImageList as IImage[],
+ }
+ this.currentMusic = {
+ item: defaultMusicList[0],
+ paused: true,
+ }
+ },
+ },
+ persist: {
+ enabled: true,
+ strategies: [
+ {
+ // 如果要存储在localStorage中
+ storage: localStorage,
+ key: 'globalConfig',
+ paths: ['globalConfig'],
+ },
+ ],
+ },
})
diff --git a/src/utils/localforage/index.ts b/src/utils/localforage/index.ts
new file mode 100644
index 0000000..4ae3a20
--- /dev/null
+++ b/src/utils/localforage/index.ts
@@ -0,0 +1,13 @@
+import localforage from 'localforage'
+
+const imageDbStore = localforage.createInstance({
+ name: 'imgStore',
+})
+
+async function clearImageDbStore() {
+ await imageDbStore.clear()
+}
+
+export function clearAllDbStore() {
+ clearImageDbStore()
+}
diff --git a/src/views/Config/Global/FaceConfig/index.vue b/src/views/Config/Global/FaceConfig/index.vue
index 699f266..6ea0362 100644
--- a/src/views/Config/Global/FaceConfig/index.vue
+++ b/src/views/Config/Global/FaceConfig/index.vue
@@ -1,4 +1,5 @@
+
+
+
+
+ {{ t('error.uploadFail') }}
+
+
+ {{ t('error.uploadSuccess') }}
+
+
+ {{ t('error.notImage') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/views/Config/Global/MusicConfig/index.vue b/src/views/Config/Global/MusicConfig/index.vue
index 2b83151..6e878fd 100644
--- a/src/views/Config/Global/MusicConfig/index.vue
+++ b/src/views/Config/Global/MusicConfig/index.vue
@@ -2,22 +2,21 @@
import type { IMusic } from '@/types/storeType'
import localforage from 'localforage'
import { storeToRefs } from 'pinia'
-import { onMounted, ref } from 'vue'
+import { ref } from 'vue'
import { useI18n } from 'vue-i18n'
import PageHeader from '@/components/PageHeader/index.vue'
import useStore from '@/store'
-import { readFileData } from '@/utils/file'
+import UploadDialog from './components/UploadDialog.vue'
const { t } = useI18n()
-const audioUploadToast = ref(0) // 0是不显示,1是成功,2是失败,3是不是图片
const audioDbStore = localforage.createInstance({
name: 'audioStore',
})
const globalConfig = useStore().globalConfig
const { getMusicList: localMusicList } = storeToRefs(globalConfig)
-const limitType = ref('audio/*')
const localMusicListValue = ref(localMusicList)
+const uploadVisible = ref(false)
async function play(item: IMusic) {
globalConfig.setCurrentMusic(item, false)
}
@@ -37,42 +36,10 @@ function deleteAll() {
globalConfig.clearMusicList()
audioDbStore.clear()
}
-async function getMusicDbStore() {
- const keys = await audioDbStore.keys()
- if (keys.length > 0) {
- audioDbStore.iterate((value: string, key: string) => {
- globalConfig.addMusic({
- id: key + new Date().getTime().toString(),
- name: key,
- url: 'Storage',
- })
- })
- }
-}
-async function handleFileChange(e: Event) {
- const isAudio = /audio*/.test(((e.target as HTMLInputElement).files as FileList)[0].type)
- if (!isAudio) {
- audioUploadToast.value = 3
-
- return
- }
- const { dataUrl, fileName } = await readFileData(((e.target as HTMLInputElement).files as FileList)[0])
- audioDbStore.setItem(`${new Date().getTime().toString()}+${fileName}`, dataUrl)
- .then(() => {
- audioUploadToast.value = 1
- getMusicDbStore()
- })
- .catch(() => {
- audioUploadToast.value = 2
- })
-}
-
-onMounted(() => {
- getMusicDbStore()
-})
+
@@ -81,11 +48,7 @@ onMounted(() => {
{{ t('button.reset') }}
-
-
- -
+
-
-
+
{{ t('table.isDone') }}
-
+
{{ t('table.image') }}
-
-
+
{{ t('table.onceNumber') }}
@@ -274,16 +261,16 @@ watch(() => prizeList.value, (val: IPrizeConfig[]) => {
-
+
{{ t('table.operation') }}
-
+
-
-
+
+