diff --git a/src/App.vue b/src/App.vue index 285524e..23caa76 100644 --- a/src/App.vue +++ b/src/App.vue @@ -1,6 +1,7 @@ + + + + diff --git a/src/hooks/useAudio.ts b/src/hooks/useAudio.ts new file mode 100644 index 0000000..c8a295c --- /dev/null +++ b/src/hooks/useAudio.ts @@ -0,0 +1,40 @@ +import {ref} from 'vue' + +export const useAudio = () => { + const audio = ref(new Audio) + const audioPaused=ref(true) + const setAudioSrc = (src: string) => { + audio.value.src = src + } + const play = () => { + audio.value.play() + setPaused(false) + } + const pause = () => { + audio.value.pause() + setPaused(true) + } + const setPaused=(paused:boolean)=>{ + audioPaused.value=paused + } + const stop = () => { + audio.value.pause() + audio.value.currentTime = 0 + } + const nextPlay = (src:string) => { + pause() + setAudioSrc(src) + play() + } + + return { + audio, + audioPaused, + play, + nextPlay, + setPaused, + pause, + stop, + setAudioSrc + } +} diff --git a/src/hooks/useElement.ts b/src/hooks/useElement.ts new file mode 100644 index 0000000..bea7122 --- /dev/null +++ b/src/hooks/useElement.ts @@ -0,0 +1,38 @@ +import { rgba } from '@/utils/color' + +export const useElementStyle=(element:any,cardColor:string,cardSize:{width:number,height:number},textSize:number,mod:'default'|'lucky'='default')=>{ + element.style.backgroundColor = rgba(cardColor, Math.random() * 0.5 + 0.25) + element.style.border = `1px solid ${rgba(cardColor, 0.25)}` + element.style.boxShadow = `0 0 12px ${rgba(cardColor, 0.5)}` + element.style.width = `${cardSize.width}px`; + element.style.height = `${cardSize.height}px`; + // 等比放大 + + element.addEventListener('mouseenter', (ev:MouseEvent)=> { + // 子元素无效 + // ev.stopPropagation() + // ev.preventDefault() + const target = ev.target as HTMLElement + target.style.border = `1px solid ${rgba(cardColor, 0.75)}` + target.style.boxShadow = `0 0 12px ${rgba(cardColor, 0.75)}` + }) + element.addEventListener('mouseleave', (ev:MouseEvent)=>{ + // ev.stopPropagation() + // ev.preventDefault() + const target=ev.target as HTMLElement + target.style.border = `1px solid ${rgba(cardColor, 0.25)}` + target.style.boxShadow = `0 0 12px ${rgba(cardColor, 0.5)}` + }) + element.children[0].style.fontSize = textSize*0.5+'px' + + element.children[1].style.fontSize = textSize+'px' + element.children[1].style.textShadow = `0 0 12px ${rgba(cardColor, 0.95)}` + + element.children[2].style.fontSize = textSize*0.5+'px' + + return element +} + +export const useElementPosition=(element:any,count:number,cardSize:{width:number,height:number},containerSize:{width:number,height:number})=>{ + +} diff --git a/src/icons/add.svg b/src/icons/add.svg new file mode 100644 index 0000000..e0430ee --- /dev/null +++ b/src/icons/add.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/icons/arrow_left.svg b/src/icons/arrow_left.svg new file mode 100644 index 0000000..9108721 --- /dev/null +++ b/src/icons/arrow_left.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/icons/arrow_right.svg b/src/icons/arrow_right.svg new file mode 100644 index 0000000..42acaff --- /dev/null +++ b/src/icons/arrow_right.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/icons/home.svg b/src/icons/home.svg new file mode 100644 index 0000000..6f2bb6f --- /dev/null +++ b/src/icons/home.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/icons/iov-next.svg b/src/icons/iov-next.svg new file mode 100644 index 0000000..a716fbc --- /dev/null +++ b/src/icons/iov-next.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/icons/pause.svg b/src/icons/pause.svg new file mode 100644 index 0000000..88ad35a --- /dev/null +++ b/src/icons/pause.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/icons/play.svg b/src/icons/play.svg new file mode 100644 index 0000000..b3b08b0 --- /dev/null +++ b/src/icons/play.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/icons/setting.svg b/src/icons/setting.svg new file mode 100644 index 0000000..d0504b1 --- /dev/null +++ b/src/icons/setting.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/store/data.ts b/src/store/data.ts index e4f99a2..f806c14 100644 --- a/src/store/data.ts +++ b/src/store/data.ts @@ -72,6 +72,7 @@ export const defaultPrizeList=[ }, desc:'一等奖', isShow:true, + isUsed:false, frequency:1, }, { @@ -87,6 +88,7 @@ export const defaultPrizeList=[ }, desc:'二等奖', isShow:true, + isUsed:false, frequency:1, }, { @@ -102,6 +104,7 @@ export const defaultPrizeList=[ }, desc:'三等奖', isShow:true, + isUsed:false, frequency:1, }, { @@ -117,6 +120,7 @@ export const defaultPrizeList=[ }, desc:'超级大奖', isShow:true, + isUsed:false, frequency:1, }, { @@ -132,6 +136,7 @@ export const defaultPrizeList=[ }, desc:'特别奖', isShow:true, + isUsed:false, frequency:1, } ] diff --git a/src/store/globalConfig.ts b/src/store/globalConfig.ts index cf1ba0b..8a7982b 100644 --- a/src/store/globalConfig.ts +++ b/src/store/globalConfig.ts @@ -6,6 +6,7 @@ export const useGlobalConfig = defineStore('global', { return { globalConfig: { rowCount: 12, + isSHowPrizeList:true, theme: { name: 'dark', detail: { primary: '#0f5fd3' }, @@ -13,6 +14,7 @@ export const useGlobalConfig = defineStore('global', { cardWidth: 140, cardHeight: 200, textColor: '#ffffff', + luckyCardColor:'#ECB1AC', textSize: 30 }, musicList: defaultMusicList, @@ -37,6 +39,10 @@ export const useGlobalConfig = defineStore('global', { getCardColor(state) { return state.globalConfig.theme.cardColor; }, + // 获取中奖颜色 + getLuckyColor(state) { + return state.globalConfig.theme.luckyCardColor; + }, // 获取文字颜色 getTextColor(state) { return state.globalConfig.theme.textColor; @@ -59,6 +65,10 @@ export const useGlobalConfig = defineStore('global', { // 获取图片列表 getImageList(state) { return state.globalConfig.imageList; + }, + // 获取是否显示奖品列表 + getIsShowPrizeList(state) { + return state.globalConfig.isSHowPrizeList; } }, @@ -77,6 +87,10 @@ export const useGlobalConfig = defineStore('global', { setCardColor(cardColor: string) { this.globalConfig.theme.cardColor = cardColor; }, + // 设置中奖颜色 + setLuckyCardColor(luckyCardColor: string) { + this.globalConfig.theme.luckyCardColor = luckyCardColor; + }, // 设置文字颜色 setTextColor(textColor: string) { this.globalConfig.theme.textColor = textColor; @@ -143,14 +157,20 @@ export const useGlobalConfig = defineStore('global', { clearImageList() { this.globalConfig.imageList = []; }, + // 设置是否显示奖品列表 + setIsShowPrizeList(isShowPrizeList: boolean) { + this.globalConfig.isSHowPrizeList = isShowPrizeList; + }, // 重置所有配置 reset() { this.globalConfig = { rowCount: 12, + isSHowPrizeList:true, theme: { name: 'dark', detail: { primary: '#0f5fd3' }, cardColor: 'rgba(0, 255, 255)', + luckyCardColor:'#ECB1AC', cardWidth: 200, cardHeight: 140, textColor: '#ffffff', diff --git a/src/store/personConfig.ts b/src/store/personConfig.ts index 9663973..74d0e41 100644 --- a/src/store/personConfig.ts +++ b/src/store/personConfig.ts @@ -1,114 +1,114 @@ import { defineStore } from 'pinia'; import { IPersonConfig } from '@/types/personConfig'; export const usePersonConfig = defineStore('person', { - state() { - return { - personConfig:{ - alreadyPersonList:[] as IPersonConfig[], - notPersonList:[] as IPersonConfig[], - tableRowCount:12, - showField:[] as any[] - } - }; - }, - getters: { - // 获取全部配置 - getPersonConfig(state) { - return state.personConfig; + state() { + return { + personConfig: { + alreadyPersonList: [] as IPersonConfig[], + notPersonList: [] as IPersonConfig[], + tableRowCount: 12, + showField: [] as any[] + } + }; }, - // 获取已中奖人员名单 - getAlreadyPersonList(state) { - return state.personConfig.alreadyPersonList; - }, - // 获取未中奖人员名单 - getNotPersonList(state) { - return state.personConfig.notPersonList; - }, - // 获取所有人员名单 - getAllPersonList(state) { - return state.personConfig.alreadyPersonList.concat(state.personConfig.notPersonList); - }, - // 获取table列数 - getTableRowCount(state) { - return state.personConfig.tableRowCount; - }, - // 获取要展示那些字段 - getShowField(state) { - return state.personConfig.showField; - } - }, - actions: { - // 添加未中奖人员 - addNotPersonList(personList: IPersonConfig[]) { - if(personList.length<=0){ - return - } - personList.forEach((item: IPersonConfig) => { - this.personConfig.notPersonList.push(item); - }); - }, - // 添加已中奖人员 - addAlreadyPersonList(personList: IPersonConfig[]) { - if(personList.length<=0){ - return - } - personList.forEach((item: IPersonConfig) => { - this.personConfig.alreadyPersonList.push(item); - this.personConfig.notPersonList = this.personConfig.notPersonList.filter((item: IPersonConfig) => item.id!== item.id); - }); - }, - // 删除指定人员 - deletePerson(person:IPersonConfig){ - console.log('delperson:',person); - if(person.id!=undefined||person.id!=null){ - this.personConfig.alreadyPersonList = this.personConfig.alreadyPersonList.filter((item: IPersonConfig) => item.id!== person.id); - this.personConfig.notPersonList = this.personConfig.notPersonList.filter((item: IPersonConfig) => item.id!== person.id); + getters: { + // 获取全部配置 + getPersonConfig(state) { + return state.personConfig; + }, + // 获取已中奖人员名单 + getAlreadyPersonList(state) { + return state.personConfig.alreadyPersonList; + }, + // 获取未中奖人员名单 + getNotPersonList(state) { + return state.personConfig.notPersonList; + }, + // 获取所有人员名单 + getAllPersonList(state) { + return state.personConfig.alreadyPersonList.concat(state.personConfig.notPersonList); + }, + // 获取table列数 + getTableRowCount(state) { + return state.personConfig.tableRowCount; + }, + // 获取要展示那些字段 + getShowField(state) { + return state.personConfig.showField; } }, - // 删除所有人员 - deleteAllPerson() { - this.personConfig.alreadyPersonList = []; - this.personConfig.notPersonList = []; - }, - // 设置table列数 - setTableRowCount(tableRowCount: number) { - this.personConfig.tableRowCount = tableRowCount; - }, - // 设置要展示那些字段 - setShowFields(showField: any[]) { - this.personConfig.showField = showField; - }, - // 重置所有人员 - resetPerson() { - this.personConfig.alreadyPersonList = []; - this.personConfig.notPersonList = []; - }, - // 重置已中奖人员 - resetAlreadyPerson() { - // 把已中奖人员合并到未中奖人员,要验证是否已存在 - if(this.personConfig.alreadyPersonList.length>0){ - this.personConfig.notPersonList = this.personConfig.notPersonList.concat(this.personConfig.alreadyPersonList); + actions: { + // 添加未中奖人员 + addNotPersonList(personList: IPersonConfig[]) { + if (personList.length <= 0) { + return + } + personList.forEach((item: IPersonConfig) => { + this.personConfig.notPersonList.push(item); + }); + }, + // 添加已中奖人员 + addAlreadyPersonList(personList: IPersonConfig[]) { + if (personList.length <= 0) { + return + } + personList.forEach((person: IPersonConfig) => { + this.personConfig.notPersonList = this.personConfig.notPersonList.filter((item: IPersonConfig) => + item.id !== person.id) + this.personConfig.alreadyPersonList.push(person); + }); + }, + // 删除指定人员 + deletePerson(person: IPersonConfig) { + if (person.id != undefined || person.id != null) { + this.personConfig.alreadyPersonList = this.personConfig.alreadyPersonList.filter((item: IPersonConfig) => item.id !== person.id); + this.personConfig.notPersonList = this.personConfig.notPersonList.filter((item: IPersonConfig) => item.id !== person.id); + } + }, + // 删除所有人员 + deleteAllPerson() { this.personConfig.alreadyPersonList = []; - } + this.personConfig.notPersonList = []; + }, + // 设置table列数 + setTableRowCount(tableRowCount: number) { + this.personConfig.tableRowCount = tableRowCount; + }, + // 设置要展示那些字段 + setShowFields(showField: any[]) { + this.personConfig.showField = showField; + }, + // 重置所有人员 + resetPerson() { + this.personConfig.alreadyPersonList = []; + this.personConfig.notPersonList = []; + }, + // 重置已中奖人员 + resetAlreadyPerson() { + // 把已中奖人员合并到未中奖人员,要验证是否已存在 + if (this.personConfig.alreadyPersonList.length > 0) { + this.personConfig.notPersonList = this.personConfig.notPersonList.concat(this.personConfig.alreadyPersonList); + this.personConfig.alreadyPersonList = []; + } + }, + // 重置所有配置 + reset() { + this.personConfig = { + alreadyPersonList: [] as IPersonConfig[], + notPersonList: [] as IPersonConfig[], + tableRowCount: 12, + showField: [] as string[] + } + }, }, - // 重置所有配置 - reset() { - this.personConfig = { - alreadyPersonList:[] as IPersonConfig[], - notPersonList:[] as IPersonConfig[], - tableRowCount:12, - showField:[] as string[] - } + persist: { + enabled: true, + strategies: [ + { + // 如果要存储在localStorage中 + storage: localStorage, + key: 'personConfig', + }, + ], }, - }, - persist: { - enabled: true, - strategies: [ - { - // 如果要存储在localStorage中 - storage: localStorage, - key: 'personConfig', - }, - ], - }, }); diff --git a/src/store/prizeConfig.ts b/src/store/prizeConfig.ts index 93bb49e..c25df9a 100644 --- a/src/store/prizeConfig.ts +++ b/src/store/prizeConfig.ts @@ -1,68 +1,108 @@ import { defineStore } from 'pinia'; import { IPrizeConfig } from '@/types/prizeConfig'; -import {defaultPrizeList} from './data'; +import { defaultPrizeList } from './data'; export const usePrizeConfig = defineStore('prize', { - state() { - return { - prizeConfig:{ - prizeList:defaultPrizeList, - } - }; - }, - getters: { - // 获取全部配置 - getPrizeConfigAll(state) { - return state.prizeConfig; + state() { + return { + prizeConfig: { + prizeList: defaultPrizeList, + currentPrize: { + id: '001', + name: '一等奖', + sort: 1, + isAll: true, + count: 1, + picture: { + id: '0', + name: '一等奖', + url: 'https://24years.top/resource/image/image1.png' + }, + desc: '一等奖', + isShow: true, + isUsed: false, + frequency: 1, + } as IPrizeConfig + } + }; }, - // 获取奖品列表 - getPrizeConfig(state) { - return state.prizeConfig.prizeList; + getters: { + // 获取全部配置 + getPrizeConfigAll(state) { + return state.prizeConfig; + }, + // 获取奖品列表 + getPrizeConfig(state) { + return state.prizeConfig.prizeList; + }, + // 根据id获取配置 + getPrizeConfigById(state) { + return (id: number | string) => { + return state.prizeConfig.prizeList.find(item => item.id === id); + } + }, + // 获取当前奖项 + getCurrentPrize(state) { + return state.prizeConfig.currentPrize; + }, + }, - // 根据id获取配置 - getPrizeConfigById(state) { - return (id: number|string) => { - return state.prizeConfig.prizeList.find(item => item.id === id); - } - }, - - }, - actions: { - // 设置奖项 - setPrizeConfig(prizeList:IPrizeConfig[]) { - this.prizeConfig.prizeList = prizeList; - }, - // 添加奖项 - addPrizeConfig(prizeConfigItem: IPrizeConfig) { - this.prizeConfig.prizeList.push(prizeConfigItem); - }, - // 删除奖项 - deletePrizeConfig(prizeConfigItemId: number|string) { - this.prizeConfig.prizeList = this.prizeConfig.prizeList.filter(item => item.id!== prizeConfigItemId); - }, - // 更新奖项数据 - updatePrizeConfig(prizeConfigItem: IPrizeConfig) { - const index = this.prizeConfig.prizeList.findIndex(item => item.id === prizeConfigItem.id); - this.prizeConfig.prizeList[index] = prizeConfigItem; - }, - // 删除全部奖项 - deleteAllPrizeConfig() { - this.prizeConfig.prizeList = []; - }, - // 重置所有配置 - resetDefault() { - this.prizeConfig = { - prizeList:defaultPrizeList, + actions: { + // 设置奖项 + setPrizeConfig(prizeList: IPrizeConfig[]) { + this.prizeConfig.prizeList = prizeList; + }, + // 添加奖项 + addPrizeConfig(prizeConfigItem: IPrizeConfig) { + this.prizeConfig.prizeList.push(prizeConfigItem); + }, + // 删除奖项 + deletePrizeConfig(prizeConfigItemId: number | string) { + this.prizeConfig.prizeList = this.prizeConfig.prizeList.filter(item => item.id !== prizeConfigItemId); + }, + // 更新奖项数据 + updatePrizeConfig(prizeConfigItem: IPrizeConfig) { + const index = this.prizeConfig.prizeList.findIndex(item => item.id === prizeConfigItem.id); + this.prizeConfig.prizeList[index] = prizeConfigItem; + }, + // 删除全部奖项 + deleteAllPrizeConfig() { + this.prizeConfig.prizeList = []; + }, + // 设置当前奖项 + setCurrentPrize(prizeConfigItem: IPrizeConfig) { + this.prizeConfig.currentPrize = prizeConfigItem; + }, + // 重置所有配置 + resetDefault() { + this.prizeConfig = { + prizeList: defaultPrizeList, + currentPrize: { + id: '001', + name: '一等奖', + sort: 1, + isAll: true, + count: 1, + picture: { + id: '0', + name: '一等奖', + url: 'https://24years.top/resource/image/image1.png' + }, + desc: '一等奖', + isShow: true, + isUsed: false, + frequency: 1, + }, + } } }, - }, - persist: { - enabled: true, - strategies: [ - { - // 如果要存储在localStorage中 - storage: localStorage, - key: 'personConfig', - }, - ], - }, + persist: { + enabled: true, + strategies: [ + { + // 如果要存储在localStorage中 + storage: localStorage, + key: 'personConfig', + }, + ], + }, }); diff --git a/src/style.css b/src/style.css index 3e49490..f6f41de 100644 --- a/src/style.css +++ b/src/style.css @@ -8,6 +8,7 @@ html { padding: 0; overflow-y: overlay; overflow-y: hidden; + overflow-x: hidden; } ul { diff --git a/src/style/style.scss b/src/style/style.scss index 1ba3356..0121991 100644 --- a/src/style/style.scss +++ b/src/style/style.scss @@ -26,3 +26,32 @@ bottom: 15px; } } + +.lucky-element-card { + cursor: default; + text-align: center; + + .lucky-card-id { + position: absolute; + top: 20px; + right: 20px; + } + + .lucky-card-name { + position: absolute; + top: 40px; + left: 0px; + right: 0; + font-weight: bold; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + } + + .lucky-card-detail { + position: absolute; + left: 0; + right: 0; + bottom: 15px; + } +} diff --git a/src/types/prizeConfig.ts b/src/types/prizeConfig.ts index 79a57d2..47df5e6 100644 --- a/src/types/prizeConfig.ts +++ b/src/types/prizeConfig.ts @@ -11,5 +11,6 @@ export interface IPrizeConfig { }; desc:string; isShow:boolean; + isUsed:boolean, frequency:number; } diff --git a/src/utils/file.ts b/src/utils/file.ts index 0c633f6..ca46a8f 100644 --- a/src/utils/file.ts +++ b/src/utils/file.ts @@ -28,3 +28,4 @@ export const readMusic = (file: any): Promise => { } }) } + diff --git a/src/utils/index.ts b/src/utils/index.ts new file mode 100644 index 0000000..dc4c3a1 --- /dev/null +++ b/src/utils/index.ts @@ -0,0 +1,17 @@ +// 筛选人员数据 +export const filterData = (tableData: any[],localRowCount: number) => { + const dataLength = tableData.length + let j = 0; + for (let i = 0; i < dataLength; i++) { + if (i % localRowCount === 0) { + j++; + } + tableData[i].x = i % localRowCount + 1; + tableData[i].y = j; + tableData[i].id = i; + // 是否中奖 + tableData[i].isWin = false + } + +return tableData +} diff --git a/src/utils/store.ts b/src/utils/store.ts index 6d3ee86..adee905 100644 --- a/src/utils/store.ts +++ b/src/utils/store.ts @@ -8,3 +8,4 @@ export const extractFields = (data: any) => { return keys.map(key => ({label:key,value:true})); } }; + diff --git a/src/views/Config/Global/FaceConfig.vue b/src/views/Config/Global/FaceConfig.vue index 5b646da..85653a1 100644 --- a/src/views/Config/Global/FaceConfig.vue +++ b/src/views/Config/Global/FaceConfig.vue @@ -1,34 +1,37 @@ diff --git a/src/views/Config/Person/PersonAll.vue b/src/views/Config/Person/PersonAll.vue index 8922cc9..48cf80c 100644 --- a/src/views/Config/Person/PersonAll.vue +++ b/src/views/Config/Person/PersonAll.vue @@ -5,11 +5,13 @@ import useStore from '@/store' import {storeToRefs } from 'pinia' import * as XLSX from 'xlsx' import { readFile } from '@/utils/file' +import {filterData} from '@/utils' import DaiysuiTable from '@/components/DaiysuiTable/index.vue' const personConfig = useStore().personConfig - -const { getAllPersonList:allPersonList,getTableRowCount:rowCount} = storeToRefs(personConfig) +const globalConfig = useStore().globalConfig +const { getAllPersonList:allPersonList} = storeToRefs(personConfig) +const {getRowCount:rowCount}=storeToRefs(globalConfig) const limitType = '.xlsx,.xls' const excelData = ref([]) // const personList = ref([]) @@ -26,22 +28,6 @@ const handleFileChange = async (e: any) => { personConfig.addNotPersonList(uploadData) } -const filterData = (tableData: any[],localRowCount: number) => { - const dataLength = tableData.length - let j = 0; - for (let i = 0; i < dataLength; i++) { - if (i % localRowCount === 0) { - j++; - } - tableData[i].x = i % localRowCount + 1; - tableData[i].y = j; - tableData[i].id = i; - // 是否中奖 - tableData[i].isWin = false - } - -return tableData -} const deleteAll = () => { personConfig.deleteAllPerson() } diff --git a/src/views/Config/Prize/PrizeConfig.vue b/src/views/Config/Prize/PrizeConfig.vue index 0949fb9..37b73f6 100644 --- a/src/views/Config/Prize/PrizeConfig.vue +++ b/src/views/Config/Prize/PrizeConfig.vue @@ -28,6 +28,7 @@ const addPrize = () => { url:'' }, desc: '', + isUsed: false, isShow: true, frequency: 1, } diff --git a/src/views/Home/LuckyThree.vue b/src/views/Home/LuckyThree.vue new file mode 100644 index 0000000..fffd4fb --- /dev/null +++ b/src/views/Home/LuckyThree.vue @@ -0,0 +1,225 @@ + + + + + diff --git a/src/views/Home/PlayMusic.vue b/src/views/Home/PlayMusic.vue deleted file mode 100644 index 43746cd..0000000 --- a/src/views/Home/PlayMusic.vue +++ /dev/null @@ -1,75 +0,0 @@ - - - - - diff --git a/src/views/Home/PrizeList.vue b/src/views/Home/PrizeList.vue index 428a56b..d7907c2 100644 --- a/src/views/Home/PrizeList.vue +++ b/src/views/Home/PrizeList.vue @@ -1,11 +1,23 @@ +.prize-list-leave-active { + -webkit-animation: slide-left 0.5s cubic-bezier(0.250, 0.460, 0.450, 0.940) both; + animation: slide-left 0.5s cubic-bezier(0.250, 0.460, 0.450, 0.940) both; +} + +.prize-operate-enter-active { + // 延时显示 + animation: show-operate 0.6s; + -webkit-animation: show-operate 0.6s; +} + +// .prize-operate-leave-active { +// -webkit-animation-delay: 0.5s; +// -webkit-animation: slide-right 0.5s cubic-bezier(0.250, 0.460, 0.450, 0.940) both; +// animation-delay: 0.5s; +// animation: slide-right 0.5s cubic-bezier(0.250, 0.460, 0.450, 0.940) both; +// } +.current-prize { + position: relative; + display: block; + overflow: hidden; + isolation: isolate; + + border-radius: 20px; + padding: 3px; +} + +.current-prize::before { + content: ""; + position: absolute; + top: 0; + left: 0; + width: 400%; + height: 100%; + background: linear-gradient(115deg, #4fcf70, #fad648, #a767e5, #12bcfe, #44ce7b); + background-size: 25% 100%; + animation: an-at-keyframe-css-at-rule-that-translates-via-the-transform-property-the-background-by-negative-25-percent-of-its-width-so-that-it-gives-a-nice-border-animation_-We-use-the-translate-property-to-have-a-nice-transition-so-it_s-not-a-jerk-of-a-start-or-stop .75s linear infinite; + // animation-play-state: paused; + translate: -5% 0%; + transition: translate 0.25s ease-out; + + animation-play-state: running; + transition-duration: 0.75s; + translate: 0% 0%; +} + + +.current-prize::after { + content: ""; + position: absolute; + inset: 4px; + border-top-left-radius: 20px; + border-bottom-right-radius: 20px; + z-index: -1; +} + +@keyframes an-at-keyframe-css-at-rule-that-translates-via-the-transform-property-the-background-by-negative-25-percent-of-its-width-so-that-it-gives-a-nice-border-animation_-We-use-the-translate-property-to-have-a-nice-transition-so-it_s-not-a-jerk-of-a-start-or-stop { + to { + transform: translateX(-25%); + } +} + +@-webkit-keyframes slide-right { + 0% { + -webkit-transform: translateX(0); + transform: translateX(0); + } + + 100% { + -webkit-transform: translateX(30px); + transform: translateX(30px); + } +} + +@keyframes slide-right { + 0% { + -webkit-transform: translateX(-200px); + transform: translateX(-200px); + } + + 100% { + -webkit-transform: translateX(0); + transform: translateX(0); + } +} + +@-webkit-keyframes slide-left { + 0% { + -webkit-transform: translateX(0); + transform: translateX(0); + } + + 100% { + -webkit-transform: translateX(-100px); + transform: translateX(-100px); + } +} + +@keyframes slide-left { + 0% { + -webkit-transform: translateX(0); + transform: translateX(0); + } + + 100% { + -webkit-transform: translateX(-400px); + transform: translateX(-400px); + } +} + +@-webkit-keyframes show-operate { + 0% { + opacity: 0; + } + + 99% { + opacity: 0; + } + + 100% { + opacity: 1; + } +} + +@keyframes show-operate { + 0% { + opacity: 0; + } + + 99% { + opacity: 0; + } + + 100% { + opacity: 1; + } +} diff --git a/src/views/Home/index.vue b/src/views/Home/index.vue index c78e7a7..c6d05fc 100644 --- a/src/views/Home/index.vue +++ b/src/views/Home/index.vue @@ -2,9 +2,11 @@ import { ref, onMounted } from 'vue' // import { tableData2 as tableData } from './data' import { rgba } from '@/utils/color' -import PlayMusic from './PlayMusic.vue' +// import PlayMusic from './PlayMusic.vue' import PrizeList from './PrizeList.vue' +import { useElementStyle } from '@/hooks/useElement' import StarsBackground from '@/components/StarsBackground/index.vue' +import LuckyView from './LuckyThree.vue' import * as THREE from 'three' import { CSS3DRenderer, CSS3DObject @@ -13,17 +15,22 @@ import { TrackballControls } from 'three/examples/jsm/controls/TrackballControls import TWEEN from 'three/examples/jsm/libs/tween.module.js'; import useStore from '@/store' + const personConfig = useStore().personConfig const globalConfig = useStore().globalConfig -// const globalConfig = useStore().globalConfig +const prizeConfig = useStore().prizeConfig -const { getAlreadyPersonList: alreadyPersonList, getNotPersonList: notPersonList, getTableRowCount: rowCount } = personConfig -const { getCardColor: cardColor, getTextColor: textColor, getCardSize: cardSize, getTextSize: textSize } = globalConfig +const { getAlreadyPersonList: alreadyPersonList, getNotPersonList: notPersonList } = personConfig +const { getCurrentPrize: currentPrize } = prizeConfig +const { getCardColor: cardColor, getTextColor: textColor, getCardSize: cardSize, getTextSize: textSize, getRowCount: rowCount } = globalConfig const tableData = ref( alreadyPersonList.concat(notPersonList) ) +const currentStatus = ref(0) // 0为初始状态, 1为抽奖准备状态,2为抽奖中状态,3为抽奖结束状态 +const ballRotationY = ref(0) const containerRef = ref() +// const LuckyViewRef= ref() const scene = ref() const camera = ref() @@ -38,6 +45,8 @@ const targets = { sphere: [] }; +const luckyTargets = ref([]) +const luckyCardList = ref([]) const init = () => { const felidView = 40; const width = window.innerWidth; @@ -65,23 +74,25 @@ const init = () => { const tableLen = tableData.value.length for (let i = 0; i < tableLen; i++) { - const element = document.createElement('div'); + let element = document.createElement('div'); element.className = 'element-card'; // element.style.backgroundColor = `rgba( 0, 127, 127, ${Math.random() * 0.5 + 0.25} )`; - element.style.backgroundColor = rgba(cardColor, Math.random() * 0.5 + 0.25) - element.style.border = `1px solid ${rgba(cardColor, 0.25)}` - element.style.boxShadow = `0 0 12px ${rgba(cardColor, 0.5)}` + // element.style.backgroundColor = rgba(cardColor, Math.random() * 0.5 + 0.25) + // element.style.border = `1px solid ${rgba(cardColor, 0.25)}` + // element.style.boxShadow = `0 0 12px ${rgba(cardColor, 0.5)}` + // element.style.width = `${cardSize.width}px`; + // element.style.height = `${cardSize.height}px`; + // element.addEventListener('mouseover', function () { + // console.log(this) + // this.style.border = `1px solid ${rgba(cardColor, 0.75)}` + // this.style.boxShadow = `0 0 12px ${rgba(cardColor, 0.75)}` + // }) + // element.addEventListener('mouseout', function () { + // this.style.border = `1px solid ${rgba(cardColor, 0.25)}` + // this.style.boxShadow = `0 0 12px ${rgba(cardColor, 0.5)}` + // }) // hover style - element.addEventListener('mouseover', function () { - this.style.border = `1px solid ${rgba(cardColor, 0.75)}` - this.style.boxShadow = `0 0 12px ${rgba(cardColor, 0.75)}` - }) - element.addEventListener('mouseout', function () { - this.style.border = `1px solid ${rgba(cardColor, 0.25)}` - this.style.boxShadow = `0 0 12px ${rgba(cardColor, 0.5)}` - }) - element.style.width = `${cardSize.width}px`; - element.style.height = `${cardSize.height}px`; + // element.style.color=localTheme.detail.primary @@ -89,22 +100,23 @@ const init = () => { number.className = 'card-id'; // number.textContent = (i / 5 + 1).toString(); number.textContent = tableData.value[i].uid; - number.style.fontSize = `${textSize * 0.5}px`; + // number.style.fontSize = `${textSize * 0.5}px`; element.appendChild(number); const symbol = document.createElement('div'); symbol.className = 'card-name'; symbol.textContent = tableData.value[i].name; - symbol.style.textShadow = `0 0 12px ${rgba(cardColor, 0.95)}` - symbol.style.fontSize = `${textSize}px`; + // symbol.style.textShadow = `0 0 12px ${rgba(cardColor, 0.95)}` + // symbol.style.fontSize = `${textSize}px`; element.appendChild(symbol); const detail = document.createElement('div'); detail.className = 'card-detail'; detail.innerHTML = `${tableData.value[i].department}
${tableData.value[i].other}`; - detail.style.fontSize = `${textSize * 0.5}px`; + // detail.style.fontSize = `${textSize * 0.5}px`; element.appendChild(detail); + element = useElementStyle(element, cardColor, cardSize, textSize) const object = new CSS3DObject(element); object.position.x = Math.random() * 4000 - 2000; object.position.y = Math.random() * 4000 - 2000; @@ -178,7 +190,7 @@ const init = () => { } } window.addEventListener('resize', onWindowResize, false); - transform(targets.table, 2000) + transform(targets.table, 1000) render(); } @@ -198,7 +210,15 @@ const transform = (targets: any[], duration: number) => { new TWEEN.Tween(object.rotation) .to({ x: target.rotation.x, y: target.rotation.y, z: target.rotation.z }, Math.random() * duration + duration) .easing(TWEEN.Easing.Exponential.InOut) - .start(); + .start() + .onComplete(() => { + if (luckyCardList.value.length) { + luckyCardList.value.forEach((item: any) => { + return useElementStyle(item.element, cardColor, { width: cardSize.width, height: cardSize.height }, textSize) + }) + } + luckyCardList.value = []; + }); } // 这个补间用来在位置与旋转补间同步执行,通过onUpdate在每次更新数据后渲染scene和camera @@ -229,24 +249,95 @@ function animation() { } // // 自动旋转的动画 -function autoRotate() { - const rotateObj= new TWEEN.Tween(scene.value.rotation); - rotateObj - .to( - { - y: Math.PI * Math.random() * 1000, - x:Math.PI*Math.random()*1000, - }, - 3000 * 1000 - ) - .onUpdate(render) - .start(); +function rollBall(rotateY: number, duration: number, mod: 'default' | 'restore' = 'default') { + TWEEN.removeAll(); + + return new Promise((resolve, reject) => { + scene.value.rotation.y = 0; + ballRotationY.value = Math.PI * rotateY * 1000 + const rotateObj = new TWEEN.Tween(scene.value.rotation); + rotateObj + .to( + { + // x: Math.PI * rotateX * 1000, + x: 0, + y: ballRotationY.value, + // z: Math.PI * rotateZ * 1000 + z: 0 + }, + duration * 1000 + ) + .onUpdate(render) + .start() + .onStop(() => { + scene.value.rotation.y = 0; + resolve('') + }) + .onComplete(() => { + resolve('') + }) + }) } function render() { renderer.value.render(scene.value, camera.value); } +const enterLottery = async () => { + transform(targets.sphere, 1000) + currentStatus.value = 1 + // setTimeout(() => { + // rollBall(0.1,3000) + // }, 3000) +} +// 开始抽奖 +const startLottery = () => { + currentStatus.value = 2 + rollBall(10, 3000) +} + +const stopLottery = async () => { + TWEEN.removeAll(); + rollBall(0, 1) + // scene正面 + currentStatus.value = 0 + // 从notPersonList随机抽取currentPrize.count个 + const notPersonListLength = notPersonList.length; + for (let i = 0; i < currentPrize.count; i++) { + if (notPersonListLength > 0) { + const randomIndex = Math.floor(Math.random() * notPersonListLength); + luckyTargets.value.push(notPersonList[randomIndex]) + + let LuckyCard = objects.value[randomIndex] + console.log(LuckyCard) + LuckyCard.element = useElementStyle(LuckyCard.element, '#ffd700', { width: cardSize.width * 2, height: cardSize.height * 2 }, textSize * 2, 'lucky') + // 重新设置位置 + LuckyCard.position.x = 100 + LuckyCard.position.y = 300 + LuckyCard.position.z = 0 + // LuckyCard.rotation.x = 0 + // LuckyCard.rotation.y = 0 + // LuckyCard.rotation.z = 0 + new TWEEN.Tween(LuckyCard.position) + .to({ + x: LuckyCard.x, + y: LuckyCard.y, + z: 1200 + }, 1000) + .start() + new TWEEN.Tween(LuckyCard.rotation) + .to({ + x: 0, + y: 0, + z: 0 + }, 1000) + .start() + luckyCardList.value.push(LuckyCard) + } + } + + personConfig.addAlreadyPersonList(luckyTargets.value) +} onMounted(() => { init(); @@ -260,18 +351,22 @@ onMounted(() => {
- - - + + + +