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 Sparticles from 'sparticles';
import { ref, onMounted, onUnmounted } from 'vue'; import { ref, onMounted, onUnmounted } from 'vue';
import { useElementSize } from '@vueuse/core'; 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 starRef = ref();
const { width, height } = useElementSize(starRef); 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(() => { onMounted(() => {
getImageStoreItem(props.homeBackground).then((image) => {
imgUrl.value = image
})
addSparticles(starRef.value, width.value, height.value); addSparticles(starRef.value, width.value, height.value);
listenWindowSize() listenWindowSize()
}) })
@@ -30,8 +60,13 @@ onUnmounted(()=>{
</script> </script>
<template> <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> </div>
</template> </template>
<style lang='scss' scoped></style> <style lang='scss' scoped>
</style>

View File

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

View File

@@ -39,3 +39,33 @@ export function rgba(color: string, opacity: number) {
return rgbaStr 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 globalConfig = useStore().globalConfig
const personConfig = useStore().personConfig const personConfig = useStore().personConfig
const prizeConfig = useStore().prizeConfig 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 { getAlreadyPersonList: alreadyPersonList, getNotPersonList: notPersonList } = storeToRefs(personConfig)
const colorPickerRef = ref() const colorPickerRef = ref()
const resetDataDialogRef = ref() const resetDataDialogRef = ref()
@@ -33,13 +46,13 @@ const isShowPrizeListValue = ref(structuredClone(isShowPrizeList.value))
const patternColorValue = ref(structuredClone(patternColor.value)) const patternColorValue = ref(structuredClone(patternColor.value))
const themeList = ref(Object.keys(daisyuiThemes)) const themeList = ref(Object.keys(daisyuiThemes))
const daisyuiThemeList = ref<ThemeDaType>(daisyuiThemes) const daisyuiThemeList = ref<ThemeDaType>(daisyuiThemes)
const backgroundImageValue = ref(backgroundImage.value)
const formData = ref({ const formData = ref({
rowCount: rowCountValue, rowCount: rowCountValue,
}) })
const formErr = ref({ const formErr = ref({
rowCount: '', rowCount: '',
}) })
const schema = zod.object({ const schema = zod.object({
rowCount: zod.number({ rowCount: zod.number({
required_error: '必填项', required_error: '必填项',
@@ -138,13 +151,15 @@ watch(patternColorValue, (val: string) => {
watch(textColorValue, (val: string) => { watch(textColorValue, (val: string) => {
globalConfig.setTextColor(val) globalConfig.setTextColor(val)
}, { deep: true }) }, { deep: true })
watch(cardSizeValue, (val: { width: number; height: number; }) => { watch(cardSizeValue, (val: { width: number; height: number; }) => {
globalConfig.setCardSize(val) globalConfig.setCardSize(val)
}, { deep: true }), }, { deep: true }),
watch(isShowPrizeListValue, () => { watch(isShowPrizeListValue, () => {
globalConfig.setIsShowPrizeList(isShowPrizeListValue.value) globalConfig.setIsShowPrizeList(isShowPrizeListValue.value)
}) })
watch(backgroundImageValue, (val: {}) => {
globalConfig.setBackground(val)
})
onMounted(() => { onMounted(() => {
}) })
</script> </script>
@@ -192,7 +207,8 @@ onMounted(() => {
</div> </div>
<div> <div>
<div class="tooltip" data-tip="该项比较耗费时间和性能"> <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>重设布局</span>
<span class="loading loading-ring loading-md" v-show="isRowCountChange == 2"></span> <span class="loading loading-ring loading-md" v-show="isRowCountChange == 2"></span>
</button> </button>
@@ -208,11 +224,23 @@ onMounted(() => {
<option v-for="(item, index) in themeList" :key="index" :value="item">{{ item }}</option> <option v-for="(item, index) in themeList" :key="index" :value="item">{{ item }}</option>
</select> </select>
</label> </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"> <label class="w-full max-w-xs form-control">
<div class="label"> <div class="label">
<span class="label-text">卡片颜色</span> <span class="label-text">卡片颜色</span>
</div> </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>
<label class="w-full max-w-xs form-control"> <label class="w-full max-w-xs form-control">
<div class="label"> <div class="label">
@@ -226,7 +254,8 @@ onMounted(() => {
<div class="label"> <div class="label">
<span class="label-text">文字颜色</span> <span class="label-text">文字颜色</span>
</div> </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>
<label class="flex flex-row w-full max-w-xs gap-10 mb-10 form-control"> <label class="flex flex-row w-full max-w-xs gap-10 mb-10 form-control">
<div> <div>
@@ -284,7 +313,8 @@ onMounted(() => {
<div class="label"> <div class="label">
<span class="label-text">是否常显奖品列表</span> <span class="label-text">是否常显奖品列表</span>
</div> </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" /> class="mt-2 border-solid checkbox checkbox-secondary border-1" />
</label> </label>

View File

@@ -29,9 +29,22 @@ const personConfig = useStore().personConfig
const globalConfig = useStore().globalConfig const globalConfig = useStore().globalConfig
const prizeConfig = useStore().prizeConfig 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 { 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[]>([])
// const tableData = ref<any[]>(JSON.parse(JSON.stringify(alreadyPersonList.value)).concat(JSON.parse(JSON.stringify(notPersonList.value)))) // 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为抽奖结束状态 const currentStatus = ref(0) // 0为初始状态 1为抽奖准备状态2为抽奖中状态3为抽奖结束状态
@@ -646,7 +659,8 @@ onUnmounted(() => {
<!-- 选中菜单结构 start--> <!-- 选中菜单结构 start-->
<div id="menu"> <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"> <div class="start" v-if="currentStatus == 1">
<button class="btn-start" @click="startLottery"><strong>开始</strong> <button class="btn-start" @click="startLottery"><strong>开始</strong>
@@ -696,7 +710,7 @@ onUnmounted(() => {
</div> </div>
<!-- end --> <!-- end -->
</div> </div>
<StarsBackground></StarsBackground> <StarsBackground :home-background="homeBackground"></StarsBackground>
<!-- <LuckyView :luckyPersonList="luckyTargets" ref="LuckyViewRef"></LuckyView> --> <!-- <LuckyView :luckyPersonList="luckyTargets" ref="LuckyViewRef"></LuckyView> -->
<!-- <PlayMusic class="absolute right-0 bottom-1/2"></PlayMusic> --> <!-- <PlayMusic class="absolute right-0 bottom-1/2"></PlayMusic> -->