feat: 更换背景图片

This commit is contained in:
LOG1997
2024-12-20 23:56:24 +08:00
parent 46f5e977de
commit 13687636da
5 changed files with 157 additions and 39 deletions

View File

@@ -2,7 +2,21 @@
import Sparticles from 'sparticles';
import { ref, onMounted, onUnmounted } from 'vue';
import { useElementSize } from '@vueuse/core';
import localforage from 'localforage'
const props = defineProps({
homeBackground: {
type: Object,
default: () => ({
id: '',
name: '',
url: ''
})
}
})
const imageDbStore = localforage.createInstance({
name: 'imgStore'
})
const imgUrl = ref('')
const starRef = ref();
const { width, height } = useElementSize(starRef);
@@ -19,7 +33,23 @@ const listenWindowSize=()=>{
});
}
const getImageStoreItem = async (item: any): Promise<string> => {
let image = ''
if (item.url == 'Storage') {
const key = item.id;
image = await imageDbStore.getItem(key) as string
}
else {
image = item.url
}
return image
}
onMounted(() => {
getImageStoreItem(props.homeBackground).then((image) => {
imgUrl.value = image
})
addSparticles(starRef.value, width.value, height.value);
listenWindowSize()
})
@@ -30,8 +60,13 @@ onUnmounted(()=>{
</script>
<template>
<div class="w-screen h-screen overflow-hidden bg-transparent" ref="starRef">
<div class="home-background w-screen h-screen overflow-hidden" v-if="homeBackground.url">
<img :src="imgUrl" class="w-full h-full object-cover" alt="">
</div>
<div v-else class="w-screen h-screen overflow-hidden" ref="starRef">
</div>
</template>
<style lang='scss' scoped></style>
<style lang='scss' scoped>
</style>

View File

@@ -20,6 +20,7 @@ export const useGlobalConfig = defineStore('global', {
textSize: 30,
patternColor: '#1b66c9',
patternList: defaultPatternList as number[],
background:{}, // 背景颜色或图片
},
musicList: defaultMusicList as IMusic[],
imageList: defaultImageList as IImage[],
@@ -93,8 +94,11 @@ export const useGlobalConfig = defineStore('global', {
// 获取是否显示奖品列表
getIsShowPrizeList(state) {
return state.globalConfig.isSHowPrizeList;
}
},
// 获取背景图片设置
getBackground(state){
return state.globalConfig.theme.background
},
},
actions: {
// 设置rowCount
@@ -208,6 +212,10 @@ export const useGlobalConfig = defineStore('global', {
setIsShowPrizeList(isShowPrizeList: boolean) {
this.globalConfig.isSHowPrizeList = isShowPrizeList;
},
// 设置背景图片
setBackground(background:{}){
this.globalConfig.theme.background = background
},
// 重置所有配置
reset() {
this.globalConfig = {
@@ -225,6 +233,7 @@ export const useGlobalConfig = defineStore('global', {
textSize: 30,
patternColor: '#1b66c9',
patternList: defaultPatternList as number[],
background:{}, // 背景图片
},
musicList: defaultMusicList as IMusic[],
imageList: defaultImageList as IImage[],

View File

@@ -39,3 +39,33 @@ export function rgba(color: string, opacity: number) {
return rgbaStr
}
export function rgbToHex(color:string) {
// 去掉字符串中的空格
color = color.replace(/\s+/g, '');
// 匹配rgba或rgb格式的字符串
const rgbaMatch = color.match(/^rgba?\((\d+),(\d+),(\d+),?(\d*\.?\d+)?\)$/i);
if (!rgbaMatch) {
throw new Error('Invalid color format');
}
const r = parseInt(rgbaMatch[1], 10);
const g = parseInt(rgbaMatch[2], 10);
const b = parseInt(rgbaMatch[3], 10);
const a = rgbaMatch[4] !== undefined ? parseFloat(rgbaMatch[4]) : undefined;
// 将RGB值转换为十六进制
let hex = "#" + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1).toUpperCase();
// 如果提供了alpha值则将其转换为十六进制并附加到结果中
if (a !== undefined) {
let alphaHex = Math.round(a * 255).toString(16).toUpperCase();
if (alphaHex.length === 1) {
alphaHex = "0" + alphaHex; // 确保alpha值是两位数
}
hex += alphaHex;
}
return hex;
}

View File

@@ -13,7 +13,20 @@ import PatternSetting from './components/PatternSetting.vue'
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,
getBackground: backgroundImage,
getImageList: imageList
} = storeToRefs(globalConfig)
const { getAlreadyPersonList: alreadyPersonList, getNotPersonList: notPersonList } = storeToRefs(personConfig)
const colorPickerRef = ref()
const resetDataDialogRef = ref()
@@ -33,13 +46,13 @@ const isShowPrizeListValue = ref(structuredClone(isShowPrizeList.value))
const patternColorValue = ref(structuredClone(patternColor.value))
const themeList = ref(Object.keys(daisyuiThemes))
const daisyuiThemeList = ref<ThemeDaType>(daisyuiThemes)
const backgroundImageValue = ref(backgroundImage.value)
const formData = ref({
rowCount: rowCountValue,
})
const formErr = ref({
rowCount: '',
})
const schema = zod.object({
rowCount: zod.number({
required_error: '必填项',
@@ -138,13 +151,15 @@ watch(patternColorValue, (val: string) => {
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)
})
onMounted(() => {
})
</script>
@@ -192,7 +207,8 @@ onMounted(() => {
</div>
<div>
<div class="tooltip" data-tip="该项比较耗费时间和性能">
<button class="mt-5 btn btn-info btn-sm" :disabled="isRowCountChange != 1" @click="resetPersonLayout">
<button class="mt-5 btn btn-info btn-sm" :disabled="isRowCountChange != 1"
@click="resetPersonLayout">
<span>重设布局</span>
<span class="loading loading-ring loading-md" v-show="isRowCountChange == 2"></span>
</button>
@@ -208,11 +224,23 @@ onMounted(() => {
<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>
</div>
<select data-choose-theme class="w-full max-w-xs border-solid select border-1"
v-model="backgroundImageValue">
<option disabled selected>选取背景图片</option>
<option v-for="(item, index) in [{ name: '无', url: '', id: '' }, ...imageList]" :key="index"
:value="item">{{ item.name }}</option>
</select>
</label>
<label class="w-full max-w-xs form-control">
<div class="label">
<span class="label-text">卡片颜色</span>
</div>
<ColorPicker ref="colorPickerRef" v-model="cardColorValue" v-model:pure-color="cardColorValue"></ColorPicker>
<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">
@@ -226,7 +254,8 @@ onMounted(() => {
<div class="label">
<span class="label-text">文字颜色</span>
</div>
<ColorPicker ref="colorPickerRef" v-model="textColorValue" v-model:pure-color="textColorValue"></ColorPicker>
<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>
@@ -284,7 +313,8 @@ onMounted(() => {
<div class="label">
<span class="label-text">是否常显奖品列表</span>
</div>
<input type="checkbox" :checked="isShowPrizeListValue" @change="isShowPrizeListValue = !isShowPrizeListValue"
<input type="checkbox" :checked="isShowPrizeListValue"
@change="isShowPrizeListValue = !isShowPrizeListValue"
class="mt-2 border-solid checkbox checkbox-secondary border-1" />
</label>

View File

@@ -29,9 +29,22 @@ const personConfig = useStore().personConfig
const globalConfig = useStore().globalConfig
const prizeConfig = useStore().prizeConfig
const { getAllPersonList: allPersonList, getNotPersonList: notPersonList, getNotThisPrizePersonList: notThisPrizePersonList } = storeToRefs(personConfig)
const { getAllPersonList: allPersonList,
getNotPersonList: notPersonList,
getNotThisPrizePersonList: notThisPrizePersonList
} = storeToRefs(personConfig)
const { getCurrentPrize: currentPrize } = storeToRefs(prizeConfig)
const { getTopTitle: topTitle, getCardColor: cardColor, getPatterColor: patternColor, getPatternList: patternList, getTextColor: textColor, getLuckyColor: luckyColor, getCardSize: cardSize, getTextSize: textSize, getRowCount: rowCount } = storeToRefs(globalConfig)
const { getTopTitle: topTitle,
getCardColor: cardColor,
getPatterColor: patternColor,
getPatternList: patternList,
getTextColor: textColor,
getLuckyColor: luckyColor,
getCardSize: cardSize,
getTextSize: textSize,
getRowCount: rowCount,
getBackground: homeBackground,
} = storeToRefs(globalConfig)
const tableData = ref<any[]>([])
// const tableData = ref<any[]>(JSON.parse(JSON.stringify(alreadyPersonList.value)).concat(JSON.parse(JSON.stringify(notPersonList.value))))
const currentStatus = ref(0) // 0为初始状态 1为抽奖准备状态2为抽奖中状态3为抽奖结束状态
@@ -646,7 +659,8 @@ onUnmounted(() => {
<!-- 选中菜单结构 start-->
<div id="menu">
<button class="btn-end " @click="enterLottery" v-if="currentStatus == 0 && tableData.length > 0">进入抽奖</button>
<button class="btn-end " @click="enterLottery"
v-if="currentStatus == 0 && tableData.length > 0">进入抽奖</button>
<div class="start" v-if="currentStatus == 1">
<button class="btn-start" @click="startLottery"><strong>开始</strong>
@@ -696,7 +710,7 @@ onUnmounted(() => {
</div>
<!-- end -->
</div>
<StarsBackground></StarsBackground>
<StarsBackground :home-background="homeBackground"></StarsBackground>
<!-- <LuckyView :luckyPersonList="luckyTargets" ref="LuckyViewRef"></LuckyView> -->
<!-- <PlayMusic class="absolute right-0 bottom-1/2"></PlayMusic> -->