feat: 更换背景图片
This commit is contained in:
@@ -1,37 +1,72 @@
|
||||
<script setup lang='ts'>
|
||||
import Sparticles from 'sparticles';
|
||||
import {ref,onMounted,onUnmounted} from 'vue';
|
||||
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 starRef=ref();
|
||||
|
||||
const { width, height}=useElementSize(starRef);
|
||||
let options = ref({ shape: 'star',parallax:1.2,rotate:true,twinkle:true, speed: 10,count:200 });
|
||||
function addSparticles(node:any,width:number,height:number) {
|
||||
new Sparticles(node, options.value,width,height);
|
||||
const { width, height } = useElementSize(starRef);
|
||||
let options = ref({ shape: 'star', parallax: 1.2, rotate: true, twinkle: true, speed: 10, count: 200 });
|
||||
function addSparticles(node: any, width: number, height: number) {
|
||||
new Sparticles(node, options.value, width, height);
|
||||
}
|
||||
// 页面大小改变时
|
||||
const listenWindowSize=()=>{
|
||||
window.addEventListener('resize',()=>{
|
||||
const listenWindowSize = () => {
|
||||
window.addEventListener('resize', () => {
|
||||
if (width.value && height.value) {
|
||||
addSparticles(starRef.value,width.value,height.value);
|
||||
addSparticles(starRef.value, width.value, height.value);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
onMounted(()=>{
|
||||
addSparticles(starRef.value,width.value,height.value);
|
||||
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()
|
||||
})
|
||||
onUnmounted(()=>{
|
||||
window.removeEventListener('resize',listenWindowSize)
|
||||
onUnmounted(() => {
|
||||
window.removeEventListener('resize', listenWindowSize)
|
||||
})
|
||||
|
||||
</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>
|
||||
|
||||
@@ -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[],
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -12,11 +12,24 @@ 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 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,
|
||||
getBackground: backgroundImage,
|
||||
getImageList: imageList
|
||||
} = storeToRefs(globalConfig)
|
||||
const { getAlreadyPersonList: alreadyPersonList, getNotPersonList: notPersonList } = storeToRefs(personConfig)
|
||||
const colorPickerRef = ref()
|
||||
const resetDataDialogRef=ref()
|
||||
const resetDataDialogRef = ref()
|
||||
interface ThemeDaType {
|
||||
[key: string]: any
|
||||
}
|
||||
@@ -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: '必填项',
|
||||
@@ -85,7 +98,7 @@ const resetPattern = () => {
|
||||
globalConfig.resetPatternList()
|
||||
}
|
||||
|
||||
const resetData=()=>{
|
||||
const resetData = () => {
|
||||
globalConfig.reset();
|
||||
personConfig.reset();
|
||||
prizeConfig.resetDefault();
|
||||
@@ -138,19 +151,21 @@ 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>
|
||||
|
||||
<template>
|
||||
<dialog id="my_modal_1" ref="resetDataDialogRef" class="border-none modal">
|
||||
<dialog id="my_modal_1" ref="resetDataDialogRef" class="border-none modal">
|
||||
<div class="modal-box">
|
||||
<h3 class="text-lg font-bold">提示!</h3>
|
||||
<p class="py-4">该操作会重置所有数据,是否继续?</p>
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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为抽奖结束状态
|
||||
@@ -77,8 +90,8 @@ function initTableData() {
|
||||
tableData.value = tableData.value.concat(JSON.parse(JSON.stringify(orginPersonData)))
|
||||
}
|
||||
}
|
||||
else{
|
||||
tableData.value=orginPersonData.slice(0, totalCount)
|
||||
else {
|
||||
tableData.value = orginPersonData.slice(0, totalCount)
|
||||
}
|
||||
tableData.value = filterData(tableData.value.slice(0, totalCount), rowCount.value)
|
||||
}
|
||||
@@ -356,9 +369,9 @@ const enterLottery = async () => {
|
||||
randomBallData()
|
||||
}
|
||||
if (patternList.value.length) {
|
||||
for(let i=0;i<patternList.value.length;i++){
|
||||
if(i<rowCount.value*7){
|
||||
objects.value[patternList.value[i]-1].element.style.backgroundColor = rgba(cardColor.value, Math.random() * 0.5 + 0.25)
|
||||
for (let i = 0; i < patternList.value.length; i++) {
|
||||
if (i < rowCount.value * 7) {
|
||||
objects.value[patternList.value[i] - 1].element.style.backgroundColor = rgba(cardColor.value, Math.random() * 0.5 + 0.25)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -418,7 +431,7 @@ const startLottery = () => {
|
||||
}
|
||||
toast.open({
|
||||
message: `现在抽取${currentPrize.value.name} ${leftover}人`,
|
||||
type:'default',
|
||||
type: 'default',
|
||||
position: 'top-right',
|
||||
duration: 8000
|
||||
})
|
||||
@@ -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> -->
|
||||
|
||||
Reference in New Issue
Block a user