feat(for): for
This commit is contained in:
@@ -38,7 +38,7 @@ module.exports = {
|
|||||||
],
|
],
|
||||||
"no-console": "warn",
|
"no-console": "warn",
|
||||||
"no-debugger": "warn",
|
"no-debugger": "warn",
|
||||||
complexity: ["warn", { max: 5 }],
|
// complexity: ["warn", { max: 5 }],
|
||||||
// 禁止使用多个空格
|
// 禁止使用多个空格
|
||||||
"no-multi-spaces": "error",
|
"no-multi-spaces": "error",
|
||||||
// 最大连续空行数
|
// 最大连续空行数
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
"@tsparticles/vue3": "^3.0.0",
|
"@tsparticles/vue3": "^3.0.0",
|
||||||
"@vueuse/core": "^10.6.1",
|
"@vueuse/core": "^10.6.1",
|
||||||
"axios": "^1.6.1",
|
"axios": "^1.6.1",
|
||||||
|
"canvas-confetti": "^1.9.2",
|
||||||
"localforage": "^1.10.0",
|
"localforage": "^1.10.0",
|
||||||
"particles.vue3": "^2.12.0",
|
"particles.vue3": "^2.12.0",
|
||||||
"pinia": "^2.1.7",
|
"pinia": "^2.1.7",
|
||||||
@@ -36,6 +37,7 @@
|
|||||||
"vue": "^3.3.8",
|
"vue": "^3.3.8",
|
||||||
"vue-accessible-color-picker": "^5.0.1",
|
"vue-accessible-color-picker": "^5.0.1",
|
||||||
"vue-router": "^4.2.5",
|
"vue-router": "^4.2.5",
|
||||||
|
"vue-toast-notification": "^3",
|
||||||
"vue3-colorpicker": "^2.2.3",
|
"vue3-colorpicker": "^2.2.3",
|
||||||
"xlsx": "^0.18.5",
|
"xlsx": "^0.18.5",
|
||||||
"zod": "^3.22.4"
|
"zod": "^3.22.4"
|
||||||
@@ -45,6 +47,7 @@
|
|||||||
"@iconify-json/fluent": "^1.1.40",
|
"@iconify-json/fluent": "^1.1.40",
|
||||||
"@tailwindcss/typography": "^0.5.10",
|
"@tailwindcss/typography": "^0.5.10",
|
||||||
"@testing-library/vue": "^8.0.0",
|
"@testing-library/vue": "^8.0.0",
|
||||||
|
"@types/canvas-confetti": "^1.6.4",
|
||||||
"@types/node": "^20.9.0",
|
"@types/node": "^20.9.0",
|
||||||
"@types/three": "^0.160.0",
|
"@types/three": "^0.160.0",
|
||||||
"@typescript-eslint/eslint-plugin": "^6.11.0",
|
"@typescript-eslint/eslint-plugin": "^6.11.0",
|
||||||
|
|||||||
26
pnpm-lock.yaml
generated
26
pnpm-lock.yaml
generated
@@ -29,6 +29,9 @@ dependencies:
|
|||||||
axios:
|
axios:
|
||||||
specifier: ^1.6.1
|
specifier: ^1.6.1
|
||||||
version: 1.6.1
|
version: 1.6.1
|
||||||
|
canvas-confetti:
|
||||||
|
specifier: ^1.9.2
|
||||||
|
version: 1.9.2
|
||||||
localforage:
|
localforage:
|
||||||
specifier: ^1.10.0
|
specifier: ^1.10.0
|
||||||
version: 1.10.0
|
version: 1.10.0
|
||||||
@@ -74,6 +77,9 @@ dependencies:
|
|||||||
vue-router:
|
vue-router:
|
||||||
specifier: ^4.2.5
|
specifier: ^4.2.5
|
||||||
version: 4.2.5(vue@3.3.8)
|
version: 4.2.5(vue@3.3.8)
|
||||||
|
vue-toast-notification:
|
||||||
|
specifier: ^3
|
||||||
|
version: 3.1.2(vue@3.3.8)
|
||||||
vue3-colorpicker:
|
vue3-colorpicker:
|
||||||
specifier: ^2.2.3
|
specifier: ^2.2.3
|
||||||
version: 2.2.3(@aesoper/normal-utils@0.1.5)(@popperjs/core@2.11.8)(@vueuse/core@10.6.1)(gradient-parser@1.0.2)(lodash-es@4.17.21)(tinycolor2@1.6.0)(vue-types@4.2.1)(vue@3.3.8)
|
version: 2.2.3(@aesoper/normal-utils@0.1.5)(@popperjs/core@2.11.8)(@vueuse/core@10.6.1)(gradient-parser@1.0.2)(lodash-es@4.17.21)(tinycolor2@1.6.0)(vue-types@4.2.1)(vue@3.3.8)
|
||||||
@@ -97,6 +103,9 @@ devDependencies:
|
|||||||
'@testing-library/vue':
|
'@testing-library/vue':
|
||||||
specifier: ^8.0.0
|
specifier: ^8.0.0
|
||||||
version: 8.0.0(@vue/compiler-sfc@3.4.5)(vue@3.3.8)
|
version: 8.0.0(@vue/compiler-sfc@3.4.5)(vue@3.3.8)
|
||||||
|
'@types/canvas-confetti':
|
||||||
|
specifier: ^1.6.4
|
||||||
|
version: 1.6.4
|
||||||
'@types/node':
|
'@types/node':
|
||||||
specifier: ^20.9.0
|
specifier: ^20.9.0
|
||||||
version: 20.9.0
|
version: 20.9.0
|
||||||
@@ -1098,6 +1107,10 @@ packages:
|
|||||||
resolution: {integrity: sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==}
|
resolution: {integrity: sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/@types/canvas-confetti@1.6.4:
|
||||||
|
resolution: {integrity: sha512-fNyZ/Fdw/Y92X0vv7B+BD6ysHL4xVU5dJcgzgxLdGbn8O3PezZNIJpml44lKM0nsGur+o/6+NZbZeNTt00U1uA==}
|
||||||
|
dev: true
|
||||||
|
|
||||||
/@types/chai-subset@1.3.5:
|
/@types/chai-subset@1.3.5:
|
||||||
resolution: {integrity: sha512-c2mPnw+xHtXDoHmdtcCXGwyLMiauiAyxWMzhGpqHC4nqI/Y5G2XhTampslK2rb59kpcuHon03UH8W6iYUzw88A==}
|
resolution: {integrity: sha512-c2mPnw+xHtXDoHmdtcCXGwyLMiauiAyxWMzhGpqHC4nqI/Y5G2XhTampslK2rb59kpcuHon03UH8W6iYUzw88A==}
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -2161,6 +2174,10 @@ packages:
|
|||||||
resolution: {integrity: sha512-kfte3Hym//51EdX4239i+Rmp20EsLIYGdPkERegTgU19hQWCRhsRFGKHTliUlsry53tv17K7n077Kqa0WJU4ng==}
|
resolution: {integrity: sha512-kfte3Hym//51EdX4239i+Rmp20EsLIYGdPkERegTgU19hQWCRhsRFGKHTliUlsry53tv17K7n077Kqa0WJU4ng==}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/canvas-confetti@1.9.2:
|
||||||
|
resolution: {integrity: sha512-6Xi7aHHzKwxZsem4mCKoqP6YwUG3HamaHHAlz1hTNQPCqXhARFpSXnkC9TWlahHY5CG6hSL5XexNjxK8irVErg==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/cfb@1.2.2:
|
/cfb@1.2.2:
|
||||||
resolution: {integrity: sha512-KfdUZsSOw19/ObEWasvBP/Ac4reZvAGauZhs6S/gqNhXhI7cKwvlH7ulj+dOEYnca4bm4SGo8C1bTAQvnTjgQA==}
|
resolution: {integrity: sha512-KfdUZsSOw19/ObEWasvBP/Ac4reZvAGauZhs6S/gqNhXhI7cKwvlH7ulj+dOEYnca4bm4SGo8C1bTAQvnTjgQA==}
|
||||||
engines: {node: '>=0.8'}
|
engines: {node: '>=0.8'}
|
||||||
@@ -6191,6 +6208,15 @@ packages:
|
|||||||
he: 1.2.0
|
he: 1.2.0
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/vue-toast-notification@3.1.2(vue@3.3.8):
|
||||||
|
resolution: {integrity: sha512-oNRL/W9aaHoeScp+iTIW7k09vM16/+8aptp2maa+7qTB43JuxmAgKdXKFYtf+uvSNOYYq2BIWgLCeJ61pwom/A==}
|
||||||
|
engines: {node: '>=12.15.0'}
|
||||||
|
peerDependencies:
|
||||||
|
vue: ^3.0
|
||||||
|
dependencies:
|
||||||
|
vue: 3.3.8(typescript@5.2.2)
|
||||||
|
dev: false
|
||||||
|
|
||||||
/vue-tsc@1.8.22(typescript@5.2.2):
|
/vue-tsc@1.8.22(typescript@5.2.2):
|
||||||
resolution: {integrity: sha512-j9P4kHtW6eEE08aS5McFZE/ivmipXy0JzrnTgbomfABMaVKx37kNBw//irL3+LlE3kOo63XpnRigyPC3w7+z+A==}
|
resolution: {integrity: sha512-j9P4kHtW6eEE08aS5McFZE/ivmipXy0JzrnTgbomfABMaVKx37kNBw//irL3+LlE3kOo63XpnRigyPC3w7+z+A==}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
|||||||
33
src/App.vue
33
src/App.vue
@@ -1,24 +1,43 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { onMounted } from 'vue'
|
import { onMounted } from 'vue'
|
||||||
import useStore from '@/store'
|
import useStore from '@/store'
|
||||||
|
import { storeToRefs } from 'pinia'
|
||||||
import PlayMusic from '@/components/PlayMusic/index.vue'
|
import PlayMusic from '@/components/PlayMusic/index.vue'
|
||||||
|
|
||||||
import { themeChange } from 'theme-change'
|
import { themeChange } from 'theme-change'
|
||||||
|
|
||||||
const globalConfig = useStore().globalConfig
|
const globalConfig = useStore().globalConfig
|
||||||
const { getTheme: localTheme } = globalConfig
|
const prizeConfig = useStore().prizeConfig
|
||||||
const setLocalTheme=(theme: any)=>{
|
const { getTheme: localTheme } = storeToRefs(globalConfig)
|
||||||
|
const { getPrizeConfig: prizeList } = storeToRefs(prizeConfig)
|
||||||
|
const setLocalTheme = (theme: any) => {
|
||||||
themeChange(theme.name)
|
themeChange(theme.name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 设置当前奖列表
|
||||||
|
const setCurrentPrize = () => {
|
||||||
|
if (prizeList.value.length <= 0) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for (let i = 0; i < prizeList.value.length; i++) {
|
||||||
|
if (!prizeList.value[i].isUsed) {
|
||||||
|
prizeConfig.setCurrentPrize(prizeList.value[i])
|
||||||
|
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
setLocalTheme(localTheme)
|
setLocalTheme(localTheme.value)
|
||||||
|
setCurrentPrize()
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<router-view></router-view>
|
<router-view></router-view>
|
||||||
<PlayMusic class="absolute right-0 bottom-1/2"></PlayMusic>
|
<PlayMusic class="absolute right-0 bottom-1/2"></PlayMusic>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss"></style>
|
||||||
</style>
|
|
||||||
|
|||||||
1
src/components.d.ts
vendored
1
src/components.d.ts
vendored
@@ -16,5 +16,6 @@ declare module 'vue' {
|
|||||||
StarsBackground: typeof import('./components/StarsBackground/index.vue')['default']
|
StarsBackground: typeof import('./components/StarsBackground/index.vue')['default']
|
||||||
SvgIcon: typeof import('./components/SvgIcon/index.vue')['default']
|
SvgIcon: typeof import('./components/SvgIcon/index.vue')['default']
|
||||||
Table: typeof import('./components/Table/index.vue')['default']
|
Table: typeof import('./components/Table/index.vue')['default']
|
||||||
|
ToTop: typeof import('./components/ToTop/index.vue')['default']
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,9 +14,9 @@ const imageDbStore = localforage.createInstance({
|
|||||||
const imgUrl=ref('')
|
const imgUrl=ref('')
|
||||||
|
|
||||||
|
|
||||||
const getImageStoreItem=async (item:any)=>{
|
const getImageStoreItem=async (item:any):Promise<string>=>{
|
||||||
const key=item.id;
|
const key=item.id;
|
||||||
const image=await imageDbStore.getItem(key)
|
const image=await imageDbStore.getItem(key) as string
|
||||||
|
|
||||||
return image
|
return image
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -67,6 +67,7 @@ const enterHome = () => {
|
|||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
currentMusic.value = localMusicListValue.value[0]
|
currentMusic.value = localMusicListValue.value[0]
|
||||||
onPlayEnd()
|
onPlayEnd()
|
||||||
|
// 不使用空格控制audio
|
||||||
})
|
})
|
||||||
onUnmounted(() => {
|
onUnmounted(() => {
|
||||||
audio.value.removeEventListener('ended', nextPlay)
|
audio.value.removeEventListener('ended', nextPlay)
|
||||||
|
|||||||
13
src/components/ToTop/index.vue
Normal file
13
src/components/ToTop/index.vue
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
<script setup lang='ts'>
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="fixed z-50 flex items-center justify-center w-10 h-10 rounded-full shadow-lg cursor-pointer right-12 bottom-12 bg-slate-700 hover:bg-slate-600">
|
||||||
|
<svg-icon name="totop"></svg-icon>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang='scss' scoped>
|
||||||
|
|
||||||
|
</style>
|
||||||
@@ -33,6 +33,23 @@ export const useElementStyle=(element:any,cardColor:string,cardSize:{width:numbe
|
|||||||
return element
|
return element
|
||||||
}
|
}
|
||||||
|
|
||||||
export const useElementPosition=(element:any,count:number,cardSize:{width:number,height:number},containerSize:{width:number,height:number})=>{
|
export const useElementPosition=(element:any,count:number,cardSize:{width:number,height:number},windowSize:{width:number,height:number},cardIndex:number)=>{
|
||||||
|
const rowCount=Math.floor(windowSize.width/(cardSize.width+100))
|
||||||
|
const colCount=Math.ceil(count/rowCount)
|
||||||
|
const centerPosition={
|
||||||
|
x:0,
|
||||||
|
y:windowSize.height/2-cardSize.height/2
|
||||||
|
}
|
||||||
|
const index =cardIndex%5
|
||||||
|
if(index==0){
|
||||||
|
element.position.x=centerPosition.x
|
||||||
|
element.position.y=centerPosition.y-Math.floor(cardIndex/5)*(cardSize.height+60)
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
element.position.x=index%2===0?Math.ceil(index/2)*(cardSize.width+100):-Math.ceil(index/2)*(cardSize.width+100)
|
||||||
|
element.position.y=centerPosition.y-Math.floor(cardIndex/5)*(cardSize.height+60)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return element
|
||||||
}
|
}
|
||||||
|
|||||||
1
src/icons/totop.svg
Normal file
1
src/icons/totop.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1704702652534" class="icon" viewBox="0 0 1025 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4194" xmlns:xlink="http://www.w3.org/1999/xlink" width="200.1953125" height="200"><path d="M1013.64736 885.56544H11.13088c-6.12352 0-11.13088 5.00736-11.13088 11.14112v83.53792c0 6.12352 5.00736 11.14112 11.13088 11.14112h1002.50624c6.13376 0 11.14112-5.0176 11.14112-11.14112v-83.53792c0.01024-6.12352-4.99712-11.14112-11.13088-11.14112zM338.33984 253.00992h102.90176v471.04c0 6.12352 5.00736 11.14112 11.14112 11.14112h83.53792c6.12352 0 11.13088-5.0176 11.13088-11.14112v-471.04h103.17824c9.32864 0 14.47936-10.72128 8.76544-17.96096L503.06048 37.61152c-4.4544-5.71392-13.08672-5.71392-17.54112 0L329.5744 234.91584c-5.71392 7.3728-0.5632 18.09408 8.76544 18.09408z m0 0" p-id="4195"></path></svg>
|
||||||
|
After Width: | Height: | Size: 951 B |
@@ -1,6 +1,17 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
// import Header from './Header/index.vue';
|
// import Header from './Header/index.vue';
|
||||||
// import Footer from './Footer/index.vue';
|
// import Footer from './Footer/index.vue';
|
||||||
|
import {ref} from 'vue';
|
||||||
|
import ToTop from '@/components/ToTop/index.vue'
|
||||||
|
import { useScroll } from '@vueuse/core'
|
||||||
|
|
||||||
|
const mainContainer = ref<HTMLElement | null>(null)
|
||||||
|
|
||||||
|
const { y} = useScroll(mainContainer)
|
||||||
|
|
||||||
|
const scrollToTop=()=>{
|
||||||
|
y.value=0
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@@ -8,8 +19,10 @@
|
|||||||
<!-- <header class="shadow-2xl head-container h-14">
|
<!-- <header class="shadow-2xl head-container h-14">
|
||||||
<Header></Header>
|
<Header></Header>
|
||||||
</header> -->
|
</header> -->
|
||||||
<main class="box-content w-screen h-screen overflow-x-hidden overflow-y-auto main-container">
|
<ToTop @click="scrollToTop" v-if="y>400"></ToTop>
|
||||||
|
<main ref="mainContainer" class="box-content w-screen h-screen overflow-x-hidden overflow-y-auto main-container">
|
||||||
<router-view class="h-full main-container-content"></router-view>
|
<router-view class="h-full main-container-content"></router-view>
|
||||||
|
|
||||||
</main>
|
</main>
|
||||||
<!-- <footer class="w-screen footer-container">
|
<!-- <footer class="w-screen footer-container">
|
||||||
<Footer></Footer>
|
<Footer></Footer>
|
||||||
|
|||||||
@@ -65,6 +65,7 @@ export const defaultPrizeList=<IPrizeConfig[]>[
|
|||||||
sort:1,
|
sort:1,
|
||||||
isAll:true,
|
isAll:true,
|
||||||
count:1,
|
count:1,
|
||||||
|
isUsedCount:0,
|
||||||
picture:{
|
picture:{
|
||||||
id:'0',
|
id:'0',
|
||||||
name:'一等奖',
|
name:'一等奖',
|
||||||
@@ -81,6 +82,7 @@ export const defaultPrizeList=<IPrizeConfig[]>[
|
|||||||
sort:2,
|
sort:2,
|
||||||
isAll:true,
|
isAll:true,
|
||||||
count:1,
|
count:1,
|
||||||
|
isUsedCount:0,
|
||||||
picture: {
|
picture: {
|
||||||
id:'1',
|
id:'1',
|
||||||
name:'二等奖',
|
name:'二等奖',
|
||||||
@@ -97,6 +99,7 @@ export const defaultPrizeList=<IPrizeConfig[]>[
|
|||||||
sort:3,
|
sort:3,
|
||||||
isAll:true,
|
isAll:true,
|
||||||
count:1,
|
count:1,
|
||||||
|
isUsedCount:0,
|
||||||
picture: {
|
picture: {
|
||||||
id:'2',
|
id:'2',
|
||||||
name:'三等奖',
|
name:'三等奖',
|
||||||
@@ -113,6 +116,7 @@ export const defaultPrizeList=<IPrizeConfig[]>[
|
|||||||
sort:4,
|
sort:4,
|
||||||
isAll:true,
|
isAll:true,
|
||||||
count:1,
|
count:1,
|
||||||
|
isUsedCount:0,
|
||||||
picture: {
|
picture: {
|
||||||
id:'3',
|
id:'3',
|
||||||
name:'超级奖',
|
name:'超级奖',
|
||||||
@@ -129,6 +133,7 @@ export const defaultPrizeList=<IPrizeConfig[]>[
|
|||||||
sort:5,
|
sort:5,
|
||||||
isAll:true,
|
isAll:true,
|
||||||
count:1,
|
count:1,
|
||||||
|
isUsedCount:0,
|
||||||
picture:{
|
picture:{
|
||||||
id:'4',
|
id:'4',
|
||||||
name:'特别奖',
|
name:'特别奖',
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ export const useGlobalConfig = defineStore('global', {
|
|||||||
globalConfig: {
|
globalConfig: {
|
||||||
rowCount: 12,
|
rowCount: 12,
|
||||||
isSHowPrizeList:true,
|
isSHowPrizeList:true,
|
||||||
|
topTitle:'大明内阁六部御前奏对',
|
||||||
theme: {
|
theme: {
|
||||||
name: 'dark',
|
name: 'dark',
|
||||||
detail: { primary: '#0f5fd3' },
|
detail: { primary: '#0f5fd3' },
|
||||||
@@ -27,6 +28,10 @@ export const useGlobalConfig = defineStore('global', {
|
|||||||
getGlobalConfig(state) {
|
getGlobalConfig(state) {
|
||||||
return state.globalConfig;
|
return state.globalConfig;
|
||||||
},
|
},
|
||||||
|
// 获取标题
|
||||||
|
getTopTitle(state) {
|
||||||
|
return state.globalConfig.topTitle;
|
||||||
|
},
|
||||||
// 获取行数
|
// 获取行数
|
||||||
getRowCount(state) {
|
getRowCount(state) {
|
||||||
return state.globalConfig.rowCount;
|
return state.globalConfig.rowCount;
|
||||||
@@ -77,6 +82,10 @@ export const useGlobalConfig = defineStore('global', {
|
|||||||
setRowCount(rowCount: number) {
|
setRowCount(rowCount: number) {
|
||||||
this.globalConfig.rowCount = rowCount;
|
this.globalConfig.rowCount = rowCount;
|
||||||
},
|
},
|
||||||
|
// 设置标题
|
||||||
|
setTopTitle(topTitle: string) {
|
||||||
|
this.globalConfig.topTitle = topTitle;
|
||||||
|
},
|
||||||
// 设置主题
|
// 设置主题
|
||||||
setTheme(theme: any) {
|
setTheme(theme: any) {
|
||||||
const { name, detail } = theme;
|
const { name, detail } = theme;
|
||||||
@@ -165,6 +174,7 @@ export const useGlobalConfig = defineStore('global', {
|
|||||||
reset() {
|
reset() {
|
||||||
this.globalConfig = {
|
this.globalConfig = {
|
||||||
rowCount: 12,
|
rowCount: 12,
|
||||||
|
topTitle:'大明内阁六部御前奏对',
|
||||||
isSHowPrizeList:true,
|
isSHowPrizeList:true,
|
||||||
theme: {
|
theme: {
|
||||||
name: 'dark',
|
name: 'dark',
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { defineStore } from 'pinia';
|
import { defineStore } from 'pinia';
|
||||||
import { IPersonConfig } from '@/types/personConfig';
|
import { IPersonConfig } from '@/types/personConfig';
|
||||||
|
import { IPrizeConfig } from '@/types/prizeConfig';
|
||||||
export const usePersonConfig = defineStore('person', {
|
export const usePersonConfig = defineStore('person', {
|
||||||
state() {
|
state() {
|
||||||
return {
|
return {
|
||||||
@@ -48,16 +49,31 @@ export const usePersonConfig = defineStore('person', {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
// 添加已中奖人员
|
// 添加已中奖人员
|
||||||
addAlreadyPersonList(personList: IPersonConfig[]) {
|
addAlreadyPersonList(personList: IPersonConfig[], prize: IPrizeConfig | null) {
|
||||||
if (personList.length <= 0) {
|
if (personList.length <= 0) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
personList.forEach((person: IPersonConfig) => {
|
personList.forEach((person: IPersonConfig) => {
|
||||||
this.personConfig.notPersonList = this.personConfig.notPersonList.filter((item: IPersonConfig) =>
|
this.personConfig.notPersonList = this.personConfig.notPersonList.filter((item: IPersonConfig) =>
|
||||||
item.id !== person.id)
|
item.id !== person.id)
|
||||||
|
if (prize != null) {
|
||||||
|
person.isWin = true
|
||||||
|
person.prizeName = prize.name
|
||||||
|
person.prizeTime = new Date().toString()
|
||||||
|
}
|
||||||
this.personConfig.alreadyPersonList.push(person);
|
this.personConfig.alreadyPersonList.push(person);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
// 从已中奖移动到未中奖
|
||||||
|
moveAlreadyToNot(person: IPersonConfig) {
|
||||||
|
if (person.id != undefined || person.id != null) {
|
||||||
|
this.personConfig.alreadyPersonList = this.personConfig.alreadyPersonList.filter((item: IPersonConfig) => item.id !== person.id);
|
||||||
|
person.isWin = false
|
||||||
|
person.prizeTime = ''
|
||||||
|
person.prizeName = ''
|
||||||
|
this.personConfig.notPersonList.push(person);
|
||||||
|
}
|
||||||
|
},
|
||||||
// 删除指定人员
|
// 删除指定人员
|
||||||
deletePerson(person: IPersonConfig) {
|
deletePerson(person: IPersonConfig) {
|
||||||
if (person.id != undefined || person.id != null) {
|
if (person.id != undefined || person.id != null) {
|
||||||
@@ -70,14 +86,7 @@ export const usePersonConfig = defineStore('person', {
|
|||||||
this.personConfig.alreadyPersonList = [];
|
this.personConfig.alreadyPersonList = [];
|
||||||
this.personConfig.notPersonList = [];
|
this.personConfig.notPersonList = [];
|
||||||
},
|
},
|
||||||
// 设置table列数
|
|
||||||
setTableRowCount(tableRowCount: number) {
|
|
||||||
this.personConfig.tableRowCount = tableRowCount;
|
|
||||||
},
|
|
||||||
// 设置要展示那些字段
|
|
||||||
setShowFields(showField: any[]) {
|
|
||||||
this.personConfig.showField = showField;
|
|
||||||
},
|
|
||||||
// 重置所有人员
|
// 重置所有人员
|
||||||
resetPerson() {
|
resetPerson() {
|
||||||
this.personConfig.alreadyPersonList = [];
|
this.personConfig.alreadyPersonList = [];
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ export const usePrizeConfig = defineStore('prize', {
|
|||||||
sort: 1,
|
sort: 1,
|
||||||
isAll: true,
|
isAll: true,
|
||||||
count: 1,
|
count: 1,
|
||||||
|
isUsedCount:0,
|
||||||
picture: {
|
picture: {
|
||||||
id: '0',
|
id: '0',
|
||||||
name: '一等奖',
|
name: '一等奖',
|
||||||
@@ -63,6 +64,10 @@ export const usePrizeConfig = defineStore('prize', {
|
|||||||
updatePrizeConfig(prizeConfigItem: IPrizeConfig) {
|
updatePrizeConfig(prizeConfigItem: IPrizeConfig) {
|
||||||
const index = this.prizeConfig.prizeList.findIndex(item => item.id === prizeConfigItem.id);
|
const index = this.prizeConfig.prizeList.findIndex(item => item.id === prizeConfigItem.id);
|
||||||
this.prizeConfig.prizeList[index] = prizeConfigItem;
|
this.prizeConfig.prizeList[index] = prizeConfigItem;
|
||||||
|
if(prizeConfigItem.isUsed&&index+1<this.prizeConfig.prizeList.length){
|
||||||
|
// 设置下一个为currentPrize
|
||||||
|
this.setCurrentPrize(this.prizeConfig.prizeList[index+1]);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
// 删除全部奖项
|
// 删除全部奖项
|
||||||
deleteAllPrizeConfig() {
|
deleteAllPrizeConfig() {
|
||||||
@@ -82,6 +87,7 @@ export const usePrizeConfig = defineStore('prize', {
|
|||||||
sort: 1,
|
sort: 1,
|
||||||
isAll: true,
|
isAll: true,
|
||||||
count: 1,
|
count: 1,
|
||||||
|
isUsedCount:0,
|
||||||
picture: {
|
picture: {
|
||||||
id: '0',
|
id: '0',
|
||||||
name: '一等奖',
|
name: '一等奖',
|
||||||
@@ -101,7 +107,7 @@ export const usePrizeConfig = defineStore('prize', {
|
|||||||
{
|
{
|
||||||
// 如果要存储在localStorage中
|
// 如果要存储在localStorage中
|
||||||
storage: localStorage,
|
storage: localStorage,
|
||||||
key: 'personConfig',
|
key: 'prizeConfig',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -3,8 +3,11 @@ export interface IPersonConfig {
|
|||||||
uid: string;
|
uid: string;
|
||||||
name: string;
|
name: string;
|
||||||
department:string;
|
department:string;
|
||||||
other:string;
|
|
||||||
isWin:boolean;
|
isWin:boolean;
|
||||||
x:number;
|
x:number;
|
||||||
y:number
|
y:number
|
||||||
|
createTime: string;
|
||||||
|
updateTime: string;
|
||||||
|
prizeName: string;
|
||||||
|
prizeTime: string;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ export interface IPrizeConfig {
|
|||||||
sort:number;
|
sort:number;
|
||||||
isAll:boolean;
|
isAll:boolean;
|
||||||
count:number;
|
count:number;
|
||||||
|
isUsedCount:number,
|
||||||
picture:{
|
picture:{
|
||||||
id:string|number,
|
id:string|number,
|
||||||
name:string,
|
name:string,
|
||||||
|
|||||||
@@ -15,3 +15,15 @@ export const filterData = (tableData: any[],localRowCount: number) => {
|
|||||||
|
|
||||||
return tableData
|
return tableData
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const addOtherInfo=(personList:any[])=>{
|
||||||
|
const len=personList.length;
|
||||||
|
for(let i=0;i<len;i++){
|
||||||
|
personList[i].createTime=new Date().toString();
|
||||||
|
personList[i].updateTime=new Date().toString();
|
||||||
|
personList[i].prizeName='';
|
||||||
|
personList[i].prizeTime='';
|
||||||
|
}
|
||||||
|
|
||||||
|
return personList
|
||||||
|
}
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import { isRgbOrRgba, isHex } from '@/utils/color'
|
|||||||
|
|
||||||
const globalConfig = useStore().globalConfig
|
const globalConfig = useStore().globalConfig
|
||||||
const personConfig = useStore().personConfig
|
const personConfig = useStore().personConfig
|
||||||
const { getTheme: localTheme, getCardColor: cardColor,getLuckyColor:luckyCardColor, getTextColor: textColor, getCardSize: cardSize, getTextSize: textSize, getRowCount: rowCount,getIsShowPrizeList:isShowPrizeList } = storeToRefs(globalConfig)
|
const {getTopTitle:topTitle, getTheme: localTheme, getCardColor: cardColor,getLuckyColor:luckyCardColor, getTextColor: textColor, getCardSize: cardSize, getTextSize: textSize, getRowCount: rowCount,getIsShowPrizeList:isShowPrizeList } = storeToRefs(globalConfig)
|
||||||
const { getAlreadyPersonList: alreadyPersonList, getNotPersonList: notPersonList } = storeToRefs(personConfig)
|
const { getAlreadyPersonList: alreadyPersonList, getNotPersonList: notPersonList } = storeToRefs(personConfig)
|
||||||
const colorPickerRef = ref()
|
const colorPickerRef = ref()
|
||||||
|
|
||||||
@@ -21,6 +21,7 @@ interface ThemeDaType {
|
|||||||
}
|
}
|
||||||
const isRowCountChange = ref(0) //0未改变,1改变,2加载中
|
const isRowCountChange = ref(0) //0未改变,1改变,2加载中
|
||||||
const themeValue = ref(localTheme.value.name)
|
const themeValue = ref(localTheme.value.name)
|
||||||
|
const topTitleValue= ref(structuredClone(topTitle.value))
|
||||||
const cardColorValue = ref(structuredClone(cardColor.value))
|
const cardColorValue = ref(structuredClone(cardColor.value))
|
||||||
const luckyCardColorValue = ref(structuredClone(luckyCardColor.value))
|
const luckyCardColorValue = ref(structuredClone(luckyCardColor.value))
|
||||||
const textColorValue = ref(structuredClone(textColor.value))
|
const textColorValue = ref(structuredClone(textColor.value))
|
||||||
@@ -71,7 +72,7 @@ const resetPersonLayout = () => {
|
|||||||
const newNotPersonList = newList.slice(alreadyLen, notLen + alreadyLen)
|
const newNotPersonList = newList.slice(alreadyLen, notLen + alreadyLen)
|
||||||
personConfig.deleteAllPerson()
|
personConfig.deleteAllPerson()
|
||||||
personConfig.addNotPersonList(newNotPersonList)
|
personConfig.addNotPersonList(newNotPersonList)
|
||||||
personConfig.addAlreadyPersonList(newAlreadyPersonList)
|
personConfig.addAlreadyPersonList(newAlreadyPersonList,null)
|
||||||
|
|
||||||
isRowCountChange.value = 0
|
isRowCountChange.value = 0
|
||||||
}, 1000)
|
}, 1000)
|
||||||
@@ -130,6 +131,15 @@ onMounted(() => {
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
|
<label class="flex flex-row items-center w-full gap-24 mb-10 form-control">
|
||||||
|
<div class="">
|
||||||
|
<div class="label">
|
||||||
|
<span class="label-text">标题</span>
|
||||||
|
</div>
|
||||||
|
<input type="text" v-model="topTitleValue" placeholder="输入标题"
|
||||||
|
class="w-full max-w-xs input input-bordered" />
|
||||||
|
</div>
|
||||||
|
</label>
|
||||||
<label class="flex flex-row items-center w-full gap-24 mb-10 form-control">
|
<label class="flex flex-row items-center w-full gap-24 mb-10 form-control">
|
||||||
<div class="">
|
<div class="">
|
||||||
<div class="label">
|
<div class="label">
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import useStore from '@/store'
|
|||||||
import {storeToRefs } from 'pinia'
|
import {storeToRefs } from 'pinia'
|
||||||
import * as XLSX from 'xlsx'
|
import * as XLSX from 'xlsx'
|
||||||
import { readFile } from '@/utils/file'
|
import { readFile } from '@/utils/file'
|
||||||
import {filterData} from '@/utils'
|
import {filterData,addOtherInfo} from '@/utils'
|
||||||
import DaiysuiTable from '@/components/DaiysuiTable/index.vue'
|
import DaiysuiTable from '@/components/DaiysuiTable/index.vue'
|
||||||
|
|
||||||
const personConfig = useStore().personConfig
|
const personConfig = useStore().personConfig
|
||||||
@@ -23,9 +23,9 @@ const handleFileChange = async (e: any) => {
|
|||||||
let workSheet = workBook.Sheets[workBook.SheetNames[0]]
|
let workSheet = workBook.Sheets[workBook.SheetNames[0]]
|
||||||
excelData.value = XLSX.utils.sheet_to_json(workSheet)
|
excelData.value = XLSX.utils.sheet_to_json(workSheet)
|
||||||
const uploadData = filterData(excelData.value,rowCount.value)
|
const uploadData = filterData(excelData.value,rowCount.value)
|
||||||
|
const allData=addOtherInfo(uploadData);
|
||||||
personConfig.resetPerson()
|
personConfig.resetPerson()
|
||||||
personConfig.addNotPersonList(uploadData)
|
personConfig.addNotPersonList(allData)
|
||||||
}
|
}
|
||||||
|
|
||||||
const deleteAll = () => {
|
const deleteAll = () => {
|
||||||
|
|||||||
@@ -2,19 +2,22 @@
|
|||||||
<script setup lang='ts'>
|
<script setup lang='ts'>
|
||||||
import { ref } from 'vue';
|
import { ref } from 'vue';
|
||||||
import useStore from '@/store'
|
import useStore from '@/store'
|
||||||
|
import { storeToRefs } from 'pinia';
|
||||||
import DaiysuiTable from '@/components/DaiysuiTable/index.vue'
|
import DaiysuiTable from '@/components/DaiysuiTable/index.vue'
|
||||||
|
|
||||||
const personConfig = useStore().personConfig
|
const personConfig = useStore().personConfig
|
||||||
|
|
||||||
const { getAlreadyPersonList: alreadyPersonList } = personConfig
|
const { getAlreadyPersonList: alreadyPersonList } = storeToRefs(personConfig)
|
||||||
const personList = ref<any[]>(
|
// const personList = ref<any[]>(
|
||||||
alreadyPersonList
|
// alreadyPersonList
|
||||||
)
|
// )
|
||||||
|
|
||||||
|
|
||||||
const deleteAll = () => {
|
const deleteAll = () => {
|
||||||
personConfig.deleteAllPerson()
|
personConfig.deleteAllPerson()
|
||||||
personList.value = alreadyPersonList
|
}
|
||||||
|
const handleMoveNotPerson=(row:any)=>{
|
||||||
|
personConfig.moveAlreadyToNot(row)
|
||||||
}
|
}
|
||||||
|
|
||||||
const tableColumns = [
|
const tableColumns = [
|
||||||
@@ -34,14 +37,23 @@ const tableColumns = [
|
|||||||
label: '职位',
|
label: '职位',
|
||||||
props: 'other',
|
props: 'other',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
label:'奖品',
|
||||||
|
props:'prizeName'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '中奖时间',
|
||||||
|
props: 'prizeTime',
|
||||||
|
|
||||||
|
},
|
||||||
{
|
{
|
||||||
label: '操作',
|
label: '操作',
|
||||||
actions: [
|
actions: [
|
||||||
{
|
{
|
||||||
label: '编辑',
|
label: '移入未中奖名单',
|
||||||
type: 'btn-info',
|
type: 'btn-info',
|
||||||
onClick: (row: any) => {
|
onClick: (row: any) => {
|
||||||
console.log('编辑:', row)
|
handleMoveNotPerson(row)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -63,7 +75,7 @@ const tableColumns = [
|
|||||||
<button class="btn btn-error btn-sm" @click="deleteAll">全部删除</button>
|
<button class="btn btn-error btn-sm" @click="deleteAll">全部删除</button>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<DaiysuiTable :tableColumns="tableColumns" :data="personList"></DaiysuiTable>
|
<DaiysuiTable :tableColumns="tableColumns" :data="alreadyPersonList"></DaiysuiTable>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<script setup lang='ts'>
|
<script setup lang='ts'>
|
||||||
import { ref, onMounted,watch } from 'vue'
|
import { ref, onMounted, watch } from 'vue'
|
||||||
import useStore from '@/store'
|
import useStore from '@/store'
|
||||||
import {storeToRefs } from 'pinia'
|
import { storeToRefs } from 'pinia'
|
||||||
import localforage from 'localforage'
|
import localforage from 'localforage'
|
||||||
import { IPrizeConfig } from '@/types/prizeConfig';
|
import { IPrizeConfig } from '@/types/prizeConfig';
|
||||||
|
|
||||||
@@ -10,9 +10,9 @@ const imageDbStore = localforage.createInstance({
|
|||||||
})
|
})
|
||||||
const prizeConfig = useStore().prizeConfig
|
const prizeConfig = useStore().prizeConfig
|
||||||
const globalConfig = useStore().globalConfig
|
const globalConfig = useStore().globalConfig
|
||||||
const { getPrizeConfig:localPrizeList} = storeToRefs(prizeConfig)
|
const { getPrizeConfig: localPrizeList, getCurrentPrize: currentPrize } = storeToRefs(prizeConfig)
|
||||||
|
|
||||||
const { getImageList:localImageList} = storeToRefs(globalConfig)
|
const { getImageList: localImageList } = storeToRefs(globalConfig)
|
||||||
const prizeList = ref(localPrizeList)
|
const prizeList = ref(localPrizeList)
|
||||||
const imgList = ref<any[]>([])
|
const imgList = ref<any[]>([])
|
||||||
const addPrize = () => {
|
const addPrize = () => {
|
||||||
@@ -22,10 +22,11 @@ const addPrize = () => {
|
|||||||
sort: 0,
|
sort: 0,
|
||||||
isAll: true,
|
isAll: true,
|
||||||
count: 1,
|
count: 1,
|
||||||
|
isUsedCount:0,
|
||||||
picture: {
|
picture: {
|
||||||
id:'',
|
id: '',
|
||||||
name:'',
|
name: '',
|
||||||
url:''
|
url: ''
|
||||||
},
|
},
|
||||||
desc: '',
|
desc: '',
|
||||||
isUsed: false,
|
isUsed: false,
|
||||||
@@ -34,7 +35,7 @@ const addPrize = () => {
|
|||||||
}
|
}
|
||||||
prizeConfig.addPrizeConfig(defaultPrizeCOnfig)
|
prizeConfig.addPrizeConfig(defaultPrizeCOnfig)
|
||||||
}
|
}
|
||||||
const resetDefault=()=>{
|
const resetDefault = () => {
|
||||||
prizeConfig.resetDefault()
|
prizeConfig.resetDefault()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -50,60 +51,65 @@ const getImageDbStore = async () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const sort = (item:any,isUp:number) => {
|
const sort = (item: any, isUp: number) => {
|
||||||
const itemIndex=prizeList.value.indexOf(item)
|
const itemIndex = prizeList.value.indexOf(item)
|
||||||
if(isUp==1){
|
if (isUp == 1) {
|
||||||
prizeList.value.splice(itemIndex,1)
|
prizeList.value.splice(itemIndex, 1)
|
||||||
prizeList.value.splice(itemIndex-1,0,item)
|
prizeList.value.splice(itemIndex - 1, 0, item)
|
||||||
}else{
|
} else {
|
||||||
prizeList.value.splice(itemIndex,1)
|
prizeList.value.splice(itemIndex, 1)
|
||||||
prizeList.value.splice(itemIndex+1,0,item)
|
prizeList.value.splice(itemIndex + 1, 0, item)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const delItem=(item:IPrizeConfig)=>{
|
const delItem = (item: IPrizeConfig) => {
|
||||||
prizeConfig.deletePrizeConfig(item.id)
|
prizeConfig.deletePrizeConfig(item.id)
|
||||||
// 更新奖项列表
|
// 更新奖项列表
|
||||||
}
|
}
|
||||||
const delAll=async ()=>{
|
const delAll = async () => {
|
||||||
await prizeConfig.deleteAllPrizeConfig()
|
await prizeConfig.deleteAllPrizeConfig()
|
||||||
}
|
}
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
getImageDbStore()
|
getImageDbStore()
|
||||||
})
|
})
|
||||||
watch(()=>prizeList,()=>{
|
watch(() => prizeList, () => {
|
||||||
prizeConfig.setPrizeConfig(prizeList.value)
|
prizeConfig.setPrizeConfig(prizeList.value)
|
||||||
},{deep:true})
|
}, { deep: true })
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<h2>奖项配置</h2>
|
<h2>奖项配置</h2>
|
||||||
<div class="flex w-full gap-3">
|
<div class="flex w-full gap-3">
|
||||||
<button class="btn btn-info btn-sm" @click="addPrize">添加</button>
|
<button class="btn btn-info btn-sm" @click="addPrize">添加</button>
|
||||||
<button class="btn btn-info btn-sm" @click="resetDefault">默认列表</button>
|
<button class="btn btn-info btn-sm" @click="resetDefault">默认列表</button>
|
||||||
<button class="btn btn-error btn-sm" @click="delAll">全部删除</button>
|
<button class="btn btn-error btn-sm" @click="delAll">全部删除</button>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<ul>
|
<ul>
|
||||||
<li v-for="item in prizeList" :key="item.id" class="flex gap-10">
|
<li v-for="item in prizeList" :key="item.id" class="flex gap-10"
|
||||||
|
:class="currentPrize.id == item.id ? 'border-1 border-solid rounded-xl' : null">
|
||||||
<label class="max-w-xs mb-10 form-control">
|
<label class="max-w-xs mb-10 form-control">
|
||||||
<!-- 向上向下 -->
|
<!-- 向上向下 -->
|
||||||
<div class="flex flex-col items-center gap-2 pt-5">
|
<div class="flex flex-col items-center gap-2 pt-5">
|
||||||
<svg-icon class="cursor-pointer hover:text-blue-400" :class="prizeList.indexOf(item)==0?'opacity-0 cursor-default':''" name="up" @click="sort(item,1)"></svg-icon>
|
<svg-icon class="cursor-pointer hover:text-blue-400"
|
||||||
<svg-icon class="cursor-pointer hover:text-blue-400" name="down" @click="sort(item,0)" :class="prizeList.indexOf(item)==prizeList.length-1?'opacity-0 cursor-default':''"></svg-icon>
|
:class="prizeList.indexOf(item) == 0 ? 'opacity-0 cursor-default' : ''" name="up"
|
||||||
|
@click="sort(item, 1)"></svg-icon>
|
||||||
|
<svg-icon class="cursor-pointer hover:text-blue-400" name="down" @click="sort(item, 0)"
|
||||||
|
:class="prizeList.indexOf(item) == prizeList.length - 1 ? 'opacity-0 cursor-default' : ''"></svg-icon>
|
||||||
</div>
|
</div>
|
||||||
</label>
|
</label>
|
||||||
<label class="w-full max-w-xs mb-10 form-control">
|
<label class="w-full max-w-xs mb-10 form-control">
|
||||||
<div class="label">
|
<div class="label">
|
||||||
<span class="label-text">名称</span>
|
<span class="label-text">名称</span>
|
||||||
</div>
|
</div>
|
||||||
<input type="text" v-model="item.name" placeholder="名称" class="w-full max-w-xs input-sm input input-bordered" />
|
<input type="text" v-model="item.name" placeholder="名称"
|
||||||
|
class="w-full max-w-xs input-sm input input-bordered" />
|
||||||
</label>
|
</label>
|
||||||
<label class="w-full max-w-xs mb-10 form-control">
|
<label class="w-full max-w-xs mb-10 form-control">
|
||||||
<div class="label">
|
<div class="label">
|
||||||
<span class="label-text">是否全员参加</span>
|
<span class="label-text">是否全员参加</span>
|
||||||
</div>
|
</div>
|
||||||
<input type="checkbox" :checked="item.isAll" @change="item.isAll =!item.isAll"
|
<input type="checkbox" :checked="item.isAll" @change="item.isAll = !item.isAll"
|
||||||
class="mt-2 border-solid checkbox checkbox-secondary border-1" />
|
class="mt-2 border-solid checkbox checkbox-secondary border-1" />
|
||||||
</label>
|
</label>
|
||||||
<label class="w-full max-w-xs mb-10 form-control">
|
<label class="w-full max-w-xs mb-10 form-control">
|
||||||
@@ -113,39 +119,46 @@ watch(()=>prizeList,()=>{
|
|||||||
<input type="number" v-model="item.count" placeholder="获奖人数"
|
<input type="number" v-model="item.count" placeholder="获奖人数"
|
||||||
class="w-full max-w-xs input-sm input input-bordered" />
|
class="w-full max-w-xs input-sm input input-bordered" />
|
||||||
</label>
|
</label>
|
||||||
|
<label class="w-full max-w-xs mb-10 form-control">
|
||||||
|
<div class="label">
|
||||||
|
<span class="label-text">已获奖人数</span>
|
||||||
|
</div>
|
||||||
|
<input disabled type="number" v-model="item.isUsedCount" placeholder="获奖人数" class="w-full max-w-xs input-sm input input-bordered" />
|
||||||
|
</label>
|
||||||
<label class="w-full max-w-xs mb-10 form-control">
|
<label class="w-full max-w-xs mb-10 form-control">
|
||||||
<div class="label">
|
<div class="label">
|
||||||
<span class="label-text">图片</span>
|
<span class="label-text">图片</span>
|
||||||
</div>
|
</div>
|
||||||
<select class="w-full max-w-xs select select-warning select-sm" v-model="item.picture">
|
<select class="w-full max-w-xs select select-warning select-sm" v-model="item.picture">
|
||||||
<option disabled selected>选择一张图片</option>
|
<option disabled selected>选择一张图片</option>
|
||||||
<option v-for="picItem in localImageList" :key="picItem.id" :value="picItem">{{ picItem.name }}</option>
|
<option v-for="picItem in localImageList" :key="picItem.id" :value="picItem">{{ picItem.name }}
|
||||||
|
</option>
|
||||||
</select>
|
</select>
|
||||||
</label>
|
</label>
|
||||||
<label class="w-full max-w-xs mb-10 form-control">
|
<label class="w-full max-w-xs mb-10 form-control">
|
||||||
<div class="label">
|
<div class="label">
|
||||||
<span class="label-text">展示在主界面</span>
|
<span class="label-text">展示在主界面</span>
|
||||||
</div>
|
</div>
|
||||||
<input type="checkbox" :checked="item.isShow" @change="item.isShow =!item.isShow"
|
<input type="checkbox" :checked="item.isShow" @change="item.isShow = !item.isShow"
|
||||||
class="mt-2 border-solid checkbox checkbox-secondary border-1" />
|
class="mt-2 border-solid checkbox checkbox-secondary border-1" />
|
||||||
</label>
|
</label>
|
||||||
<label class="w-full max-w-xs mb-10 form-control">
|
<label class="w-full max-w-xs mb-10 form-control">
|
||||||
<div class="label">
|
<div class="label">
|
||||||
<span class="label-text">抽取次数</span>
|
<span class="label-text">抽取次数</span>
|
||||||
</div>
|
</div>
|
||||||
<input type="text" v-model="item.frequency" placeholder="抽取次数" class="w-full max-w-xs input-sm input input-bordered" />
|
<input type="text" v-model="item.frequency" placeholder="抽取次数"
|
||||||
|
class="w-full max-w-xs input-sm input input-bordered" />
|
||||||
</label>
|
</label>
|
||||||
<label class="w-full max-w-xs mb-10 form-control">
|
<label class="w-full max-w-xs mb-10 form-control">
|
||||||
<div class="label">
|
<div class="label">
|
||||||
<span class="label-text">操作</span>
|
<span class="label-text">操作</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex gap-2">
|
<div class="flex gap-2">
|
||||||
<button class="btn btn-error btn-sm" @click="delItem(item)">删除</button>
|
<button class="btn btn-error btn-sm" @click="delItem(item)">删除</button>
|
||||||
</div>
|
</div>
|
||||||
</label>
|
</label>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div></template>
|
||||||
</template>
|
|
||||||
|
|
||||||
<style lang='scss' scoped></style>
|
<style lang='scss' scoped></style>
|
||||||
|
|||||||
@@ -71,11 +71,9 @@ const skip = (path: string) => {
|
|||||||
</nav>
|
</nav>
|
||||||
<nav>
|
<nav>
|
||||||
<div class="grid grid-flow-col gap-4">
|
<div class="grid grid-flow-col gap-4">
|
||||||
<a><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" class="fill-current">
|
<a href="https://github.com/LOG1997/log-lottery" target="_blank" class="cursor-pointer">
|
||||||
<path
|
<svg-icon name="github"></svg-icon>
|
||||||
d="M24 4.557c-.883.392-1.832.656-2.828.775 1.017-.609 1.798-1.574 2.165-2.724-.951.564-2.005.974-3.127 1.195-.897-.957-2.178-1.555-3.594-1.555-3.179 0-5.515 2.966-4.797 6.045-4.091-.205-7.719-2.165-10.148-5.144-1.29 2.213-.669 5.108 1.523 6.574-.806-.026-1.566-.247-2.229-.616-.054 2.281 1.581 4.415 3.949 4.89-.693.188-1.452.232-2.224.084.626 1.956 2.444 3.379 4.6 3.419-2.07 1.623-4.678 2.348-7.29 2.04 2.179 1.397 4.768 2.212 7.548 2.212 9.142 0 14.307-7.721 13.995-14.646.962-.695 1.797-1.562 2.457-2.549z">
|
</a>
|
||||||
</path>
|
|
||||||
</svg></a>
|
|
||||||
<a><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" class="fill-current">
|
<a><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" class="fill-current">
|
||||||
<path
|
<path
|
||||||
d="M19.615 3.184c-3.604-.246-11.631-.245-15.23 0-3.897.266-4.356 2.62-4.385 8.816.029 6.185.484 8.549 4.385 8.816 3.6.245 11.626.246 15.23 0 3.897-.266 4.356-2.62 4.385-8.816-.029-6.185-.484-8.549-4.385-8.816zm-10.615 12.816v-8l8 3.993-8 4.007z">
|
d="M19.615 3.184c-3.604-.246-11.631-.245-15.23 0-3.897.266-4.356 2.62-4.385 8.816.029 6.185.484 8.549 4.385 8.816 3.6.245 11.626.246 15.23 0 3.897-.266 4.356-2.62 4.385-8.816-.029-6.185-.484-8.549-4.385-8.816zm-10.615 12.816v-8l8 3.993-8 4.007z">
|
||||||
|
|||||||
@@ -1,225 +0,0 @@
|
|||||||
<script setup lang="ts">
|
|
||||||
import { ref, onMounted,computed,watch,toRef } from 'vue'
|
|
||||||
// import { tableData2 as tableData } from './data'
|
|
||||||
import { rgba } from '@/utils/color'
|
|
||||||
|
|
||||||
import {filterData} from '@/utils'
|
|
||||||
import * as THREE from 'three'
|
|
||||||
import {
|
|
||||||
CSS3DRenderer, CSS3DObject
|
|
||||||
} from 'three/examples/jsm/renderers/CSS3DRenderer.js';
|
|
||||||
import { TrackballControls } from 'three/examples/jsm/controls/TrackballControls.js';
|
|
||||||
import TWEEN from 'three/examples/jsm/libs/tween.module.js';
|
|
||||||
import useStore from '@/store'
|
|
||||||
|
|
||||||
const props=defineProps({
|
|
||||||
luckyPersonList:{
|
|
||||||
type:Array as ()=>Array<any>,
|
|
||||||
default:()=>{[]}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
// const emits=defineEmits()=
|
|
||||||
|
|
||||||
const globalConfig = useStore().globalConfig
|
|
||||||
|
|
||||||
const { getLuckyColor: luckyCardColor, getTextColor: textColor, getCardSize: cardSize, getTextSize: textSize, getRowCount: rowCount } = globalConfig
|
|
||||||
const tableData = computed(()=>{
|
|
||||||
console.log('pppppprops:',props.luckyPersonList)
|
|
||||||
const cloneData=toRef(props.luckyPersonList)
|
|
||||||
|
|
||||||
console.log(props.luckyPersonList,cloneData.value)
|
|
||||||
const luckyList=filterData(cloneData.value,Math.floor(rowCount/2))
|
|
||||||
console.log('lucskskskskksks:',luckyList)
|
|
||||||
|
|
||||||
return luckyList
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
const luckyContainerRef = ref<HTMLElement>()
|
|
||||||
|
|
||||||
const scene = ref()
|
|
||||||
const camera = ref()
|
|
||||||
const renderer = ref()
|
|
||||||
const controls = ref()
|
|
||||||
const objects = ref<any[]>([])
|
|
||||||
|
|
||||||
const targets = {
|
|
||||||
table: <any[]>[],
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
const init = () => {
|
|
||||||
const felidView = 40;
|
|
||||||
const width = window.innerWidth;
|
|
||||||
const height = window.innerHeight;
|
|
||||||
const aspect = width / height;
|
|
||||||
const nearPlane = 1;
|
|
||||||
const farPlane = 10000;
|
|
||||||
const WebGLoutput = luckyContainerRef.value
|
|
||||||
|
|
||||||
scene.value = new THREE.Scene();
|
|
||||||
camera.value = new THREE.PerspectiveCamera(felidView, aspect, nearPlane, farPlane);
|
|
||||||
camera.value.position.z = 3000;
|
|
||||||
|
|
||||||
renderer.value = new CSS3DRenderer()
|
|
||||||
renderer.value.setSize(width, height)
|
|
||||||
renderer.value.domElement.style.position = 'absolute';
|
|
||||||
WebGLoutput!.appendChild(renderer.value.domElement);
|
|
||||||
|
|
||||||
controls.value = new TrackballControls(camera.value, renderer.value.domElement);
|
|
||||||
controls.value.rotateSpeed = 1;
|
|
||||||
controls.value.staticMoving = true;
|
|
||||||
controls.value.minDistance = 500;
|
|
||||||
controls.value.maxDistance = 6000;
|
|
||||||
controls.value.addEventListener('change', render);
|
|
||||||
|
|
||||||
const tableLen = tableData.value.length
|
|
||||||
for (let i = 0; i < tableLen; i++) {
|
|
||||||
const element = document.createElement('div');
|
|
||||||
element.className = 'lucky-element-card';
|
|
||||||
// element.style.backgroundColor = `rgba( 0, 127, 127, ${Math.random() * 0.5 + 0.25} )`;
|
|
||||||
element.style.backgroundColor = rgba(luckyCardColor, Math.random() * 0.5 + 0.25)
|
|
||||||
element.style.border = `1px solid ${rgba(luckyCardColor, 0.25)}`
|
|
||||||
element.style.boxShadow = `0 0 12px ${rgba(luckyCardColor, 0.5)}`
|
|
||||||
// hover style
|
|
||||||
element.addEventListener('mouseover', function () {
|
|
||||||
this.style.border = `1px solid ${rgba(luckyCardColor, 0.75)}`
|
|
||||||
this.style.boxShadow = `0 0 12px ${rgba(luckyCardColor, 0.75)}`
|
|
||||||
})
|
|
||||||
element.addEventListener('mouseout', function () {
|
|
||||||
this.style.border = `1px solid ${rgba(luckyCardColor, 0.25)}`
|
|
||||||
this.style.boxShadow = `0 0 12px ${rgba(luckyCardColor, 0.5)}`
|
|
||||||
})
|
|
||||||
element.style.width = `${cardSize.width*2}px`;
|
|
||||||
element.style.height = `${cardSize.height*2}px`;
|
|
||||||
|
|
||||||
// element.style.color=localTheme.detail.primary
|
|
||||||
|
|
||||||
const number = document.createElement('div');
|
|
||||||
number.className = 'lucky-card-id';
|
|
||||||
// number.textContent = (i / 5 + 1).toString();
|
|
||||||
number.textContent = tableData.value[i].uid;
|
|
||||||
number.style.fontSize = `${textSize}px`;
|
|
||||||
element.appendChild(number);
|
|
||||||
|
|
||||||
const symbol = document.createElement('div');
|
|
||||||
symbol.className = 'lucky-card-name';
|
|
||||||
symbol.textContent = tableData.value[i].name;
|
|
||||||
symbol.style.textShadow = `0 0 12px ${rgba(luckyCardColor, 0.95)}`
|
|
||||||
symbol.style.fontSize = `${textSize*2}px`;
|
|
||||||
element.appendChild(symbol);
|
|
||||||
|
|
||||||
const detail = document.createElement('div');
|
|
||||||
detail.className = 'lucky-card-detail';
|
|
||||||
detail.innerHTML = `${tableData.value[i].department}<br/>${tableData.value[i].other}`;
|
|
||||||
detail.style.fontSize = `${textSize}px`;
|
|
||||||
element.appendChild(detail);
|
|
||||||
|
|
||||||
const object = new CSS3DObject(element);
|
|
||||||
object.position.x = Math.random() * 4000 - 2000;
|
|
||||||
object.position.y = Math.random() * 4000 - 2000;
|
|
||||||
object.position.z = Math.random() * 4000 - 2000;
|
|
||||||
scene.value.add(object);
|
|
||||||
|
|
||||||
objects.value.push(object);
|
|
||||||
}
|
|
||||||
|
|
||||||
createTableVertices();
|
|
||||||
|
|
||||||
function createTableVertices() {
|
|
||||||
const tableLen = tableData.value.length;
|
|
||||||
|
|
||||||
for (let i = 0; i < tableLen; i++) {
|
|
||||||
const object = new THREE.Object3D();
|
|
||||||
|
|
||||||
object.position.x = tableData.value[i].x * (cardSize.width*2 + 40) - rowCount * 90;
|
|
||||||
object.position.y = -tableData.value[i].y * (cardSize.height*2 + 20) + 1000;
|
|
||||||
object.position.z = 0;
|
|
||||||
|
|
||||||
targets.table.push(object);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
window.addEventListener('resize', onWindowResize, false);
|
|
||||||
transform(targets.table, 2000)
|
|
||||||
render();
|
|
||||||
}
|
|
||||||
|
|
||||||
const transform = (targets: any[], duration: number) => {
|
|
||||||
TWEEN.removeAll();
|
|
||||||
const objLength = objects.value.length;
|
|
||||||
for (let i = 0; i < objLength; ++i) {
|
|
||||||
let object = objects.value[i];
|
|
||||||
let target = targets[i];
|
|
||||||
new TWEEN.Tween(object.position)
|
|
||||||
.to({ x: target.position.x, y: target.position.y, z: target.position.z },
|
|
||||||
Math.random() * duration + duration)
|
|
||||||
.easing(TWEEN.Easing.Exponential.InOut)
|
|
||||||
.start();
|
|
||||||
|
|
||||||
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();
|
|
||||||
}
|
|
||||||
|
|
||||||
// 这个补间用来在位置与旋转补间同步执行,通过onUpdate在每次更新数据后渲染scene和camera
|
|
||||||
new TWEEN.Tween({})
|
|
||||||
.to({}, duration * 2)
|
|
||||||
.onUpdate(render)
|
|
||||||
.start();
|
|
||||||
// 整体自动旋转
|
|
||||||
}
|
|
||||||
function onWindowResize() {
|
|
||||||
camera.value.aspect = window.innerWidth / window.innerHeight
|
|
||||||
camera.value.updateProjectionMatrix();
|
|
||||||
|
|
||||||
renderer.value.setSize(window.innerWidth, window.innerHeight);
|
|
||||||
render();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* [animation update all tween && controls]
|
|
||||||
*/
|
|
||||||
function animation() {
|
|
||||||
TWEEN.update();
|
|
||||||
controls.value.update();
|
|
||||||
// 设置自动旋转
|
|
||||||
// console.log('animation',controls.value.target);
|
|
||||||
// 设置相机位置
|
|
||||||
requestAnimationFrame(animation);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function render() {
|
|
||||||
renderer.value.render(scene.value, camera.value);
|
|
||||||
}
|
|
||||||
|
|
||||||
const submit=()=>{
|
|
||||||
tableData.value.length=0;
|
|
||||||
}
|
|
||||||
onMounted(() => {
|
|
||||||
});
|
|
||||||
|
|
||||||
watch(()=>props.luckyPersonList,()=>{
|
|
||||||
luckyContainerRef.value!.style.zIndex='100'
|
|
||||||
init();
|
|
||||||
animation();
|
|
||||||
luckyContainerRef.value!.style.color = `${textColor}`
|
|
||||||
|
|
||||||
console.log('tableData',tableData.value)
|
|
||||||
},{deep:true})
|
|
||||||
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<div class="absolute top-0 w-full h-full bg-gray-400/10 -z-50" ref="luckyContainerRef">
|
|
||||||
<button class="btn glass" @click="submit">确定</button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<style scoped lang="scss">
|
|
||||||
|
|
||||||
</style>
|
|
||||||
@@ -19,17 +19,6 @@ const getPrizeListHeight = () => {
|
|||||||
}
|
}
|
||||||
const prizeShow = ref(structuredClone(isShowPrizeList.value))
|
const prizeShow = ref(structuredClone(isShowPrizeList.value))
|
||||||
|
|
||||||
const delAll = () => {
|
|
||||||
prizeConfig.deleteAllPrizeConfig()
|
|
||||||
}
|
|
||||||
|
|
||||||
const resetDefault = () => {
|
|
||||||
prizeConfig.resetDefault()
|
|
||||||
}
|
|
||||||
|
|
||||||
const print = () => {
|
|
||||||
console.log(prizeConfig)
|
|
||||||
}
|
|
||||||
const addTemporaryPrize = () => {
|
const addTemporaryPrize = () => {
|
||||||
console.log('addTemporaryPrize')
|
console.log('addTemporaryPrize')
|
||||||
}
|
}
|
||||||
@@ -44,23 +33,25 @@ onMounted(() => {
|
|||||||
<transition name="prize-list" :appear="true">
|
<transition name="prize-list" :appear="true">
|
||||||
<div v-if="prizeShow" class="flex items-center">
|
<div v-if="prizeShow" class="flex items-center">
|
||||||
<ul class="flex flex-col gap-1 p-2 rounded-xl bg-slate-500/50" ref="prizeListRef">
|
<ul class="flex flex-col gap-1 p-2 rounded-xl bg-slate-500/50" ref="prizeListRef">
|
||||||
|
|
||||||
<li v-for="item in localPrizeList" :key="item.id"
|
<li v-for="item in localPrizeList" :key="item.id"
|
||||||
:class="currentPrize.id == item.id ? 'current-prize' : ''">
|
:class="currentPrize.id == item.id ? 'current-prize' : ''">
|
||||||
<div
|
<div
|
||||||
class="relative flex flex-row items-center justify-between w-64 h-20 shadow-xl card bg-base-100">
|
class="relative flex flex-row items-center justify-between w-64 h-20 shadow-xl card bg-base-100" v-if="item.isShow">
|
||||||
<div v-if="item.isUsed" class="absolute w-full h-full bg-gray-800/90 item-mask z-200 rounded-xl"></div>
|
<div v-if="item.isUsed" class="absolute z-50 w-full h-full bg-gray-800/70 item-mask rounded-xl"></div>
|
||||||
<figure class="w-10 h-10 rounded-xl">
|
<figure class="w-10 h-10 rounded-xl">
|
||||||
<img :src="item.picture.url" alt="Shoes" class="object-cover h-full rounded-xl" />
|
<img :src="item.picture.url" alt="Shoes" class="object-cover h-full rounded-xl" />
|
||||||
</figure>
|
</figure>
|
||||||
<div class="items-center text-center card-body">
|
<div class="items-center p-0 text-center card-body">
|
||||||
<h2 class="card-title">{{ item.name }}</h2>
|
<h2 class="p-0 m-0 card-title">{{ item.name }}</h2>
|
||||||
|
<p class="absolute z-40 p-0 m-0 text-gray-300/80 pt-9">{{ item.isUsedCount }}/{{ item.count }}</p>
|
||||||
|
<progress class="w-3/4 h-6 progress progress-primary" :value="item.isUsedCount" :max="item.count"></progress>
|
||||||
|
<!-- <p class="p-0 m-0">{{ item.isUsedCount }}/{{ item.count }}</p> -->
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
<div class="flex flex-col gap-3">
|
<div class="flex flex-col gap-3">
|
||||||
<div class="tooltip" data-tip="抽奖">
|
<div class="tooltip" data-tip="奖项列表">
|
||||||
<div class="flex items-center w-6 h-8 rounded-r-lg cursor-pointer prize-option bg-slate-500/50"
|
<div class="flex items-center w-6 h-8 rounded-r-lg cursor-pointer prize-option bg-slate-500/50"
|
||||||
@click="prizeShow = !prizeShow">
|
@click="prizeShow = !prizeShow">
|
||||||
<svg-icon name="arrow_left" class="w-full h-full"></svg-icon>
|
<svg-icon name="arrow_left" class="w-full h-full"></svg-icon>
|
||||||
@@ -78,7 +69,7 @@ onMounted(() => {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<transition name="prize-operate" :appear="true">
|
<transition name="prize-operate" :appear="true">
|
||||||
<div class="tooltip" data-tip="抽奖" v-show="!prizeShow">
|
<div class="tooltip" data-tip="奖项列表" v-show="!prizeShow">
|
||||||
<div class="flex items-center w-6 h-8 rounded-r-lg cursor-pointer prize-option bg-slate-500/50"
|
<div class="flex items-center w-6 h-8 rounded-r-lg cursor-pointer prize-option bg-slate-500/50"
|
||||||
@click="prizeShow = !prizeShow">
|
@click="prizeShow = !prizeShow">
|
||||||
<svg-icon name="arrow_right" class="w-full h-full"></svg-icon>
|
<svg-icon name="arrow_right" class="w-full h-full"></svg-icon>
|
||||||
|
|||||||
@@ -1,12 +1,9 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, onMounted } from 'vue'
|
import { ref, onMounted,onUnmounted, watch } from 'vue'
|
||||||
// import { tableData2 as tableData } from './data'
|
|
||||||
import { rgba } from '@/utils/color'
|
|
||||||
// import PlayMusic from './PlayMusic.vue'
|
|
||||||
import PrizeList from './PrizeList.vue'
|
import PrizeList from './PrizeList.vue'
|
||||||
import { useElementStyle } from '@/hooks/useElement'
|
import { useElementStyle, useElementPosition } from '@/hooks/useElement'
|
||||||
import StarsBackground from '@/components/StarsBackground/index.vue'
|
import StarsBackground from '@/components/StarsBackground/index.vue'
|
||||||
import LuckyView from './LuckyThree.vue'
|
import confetti from 'canvas-confetti'
|
||||||
import * as THREE from 'three'
|
import * as THREE from 'three'
|
||||||
import {
|
import {
|
||||||
CSS3DRenderer, CSS3DObject
|
CSS3DRenderer, CSS3DObject
|
||||||
@@ -14,23 +11,26 @@ import {
|
|||||||
import { TrackballControls } from 'three/examples/jsm/controls/TrackballControls.js';
|
import { TrackballControls } from 'three/examples/jsm/controls/TrackballControls.js';
|
||||||
import TWEEN from 'three/examples/jsm/libs/tween.module.js';
|
import TWEEN from 'three/examples/jsm/libs/tween.module.js';
|
||||||
import useStore from '@/store'
|
import useStore from '@/store'
|
||||||
|
import { storeToRefs } from 'pinia'
|
||||||
|
import { useToast } from 'vue-toast-notification';
|
||||||
|
import 'vue-toast-notification/dist/theme-sugar.css';
|
||||||
|
|
||||||
|
const toast = useToast();
|
||||||
const personConfig = useStore().personConfig
|
const personConfig = useStore().personConfig
|
||||||
const globalConfig = useStore().globalConfig
|
const globalConfig = useStore().globalConfig
|
||||||
const prizeConfig = useStore().prizeConfig
|
const prizeConfig = useStore().prizeConfig
|
||||||
|
|
||||||
const { getAlreadyPersonList: alreadyPersonList, getNotPersonList: notPersonList } = personConfig
|
const { getAlreadyPersonList: alreadyPersonList, getNotPersonList: notPersonList } = storeToRefs(personConfig)
|
||||||
const { getCurrentPrize: currentPrize } = prizeConfig
|
const { getCurrentPrize: currentPrize } = storeToRefs(prizeConfig)
|
||||||
const { getCardColor: cardColor, getTextColor: textColor, getCardSize: cardSize, getTextSize: textSize, getRowCount: rowCount } = globalConfig
|
const {getTopTitle:topTitle, getCardColor: cardColor, getTextColor: textColor, getLuckyColor: luckyColor, getCardSize: cardSize, getTextSize: textSize, getRowCount: rowCount } = storeToRefs(globalConfig)
|
||||||
const tableData = ref(
|
const tableData = ref(JSON.parse(JSON.stringify(alreadyPersonList.value)).concat(JSON.parse(JSON.stringify(notPersonList.value))))
|
||||||
alreadyPersonList.concat(notPersonList)
|
|
||||||
)
|
|
||||||
|
|
||||||
const currentStatus = ref(0) // 0为初始状态, 1为抽奖准备状态,2为抽奖中状态,3为抽奖结束状态
|
const currentStatus = ref(0) // 0为初始状态, 1为抽奖准备状态,2为抽奖中状态,3为抽奖结束状态
|
||||||
const ballRotationY = ref(0)
|
const ballRotationY = ref(0)
|
||||||
const containerRef = ref<HTMLElement>()
|
const containerRef = ref<HTMLElement>()
|
||||||
// const LuckyViewRef= ref()
|
// const LuckyViewRef= ref()
|
||||||
|
const canOperate = ref(true)
|
||||||
|
const cameraZ = ref(3000)
|
||||||
|
|
||||||
const scene = ref()
|
const scene = ref()
|
||||||
const camera = ref()
|
const camera = ref()
|
||||||
@@ -47,6 +47,7 @@ const targets = {
|
|||||||
|
|
||||||
const luckyTargets = ref<any[]>([])
|
const luckyTargets = ref<any[]>([])
|
||||||
const luckyCardList = ref<any[]>([])
|
const luckyCardList = ref<any[]>([])
|
||||||
|
const currentPrizeValue=ref(JSON.parse(JSON.stringify(currentPrize.value)))
|
||||||
const init = () => {
|
const init = () => {
|
||||||
const felidView = 40;
|
const felidView = 40;
|
||||||
const width = window.innerWidth;
|
const width = window.innerWidth;
|
||||||
@@ -58,11 +59,27 @@ const init = () => {
|
|||||||
|
|
||||||
scene.value = new THREE.Scene();
|
scene.value = new THREE.Scene();
|
||||||
camera.value = new THREE.PerspectiveCamera(felidView, aspect, nearPlane, farPlane);
|
camera.value = new THREE.PerspectiveCamera(felidView, aspect, nearPlane, farPlane);
|
||||||
camera.value.position.z = 3000;
|
camera.value.position.z = cameraZ.value
|
||||||
|
// 侦听camera position变化
|
||||||
|
// watch(() => camera.value.position.z, (value) => {
|
||||||
|
// console.log('code line-63 \n\r😍 camara posi:\n\r',value);
|
||||||
|
// console.log('code line-63 \n\r😍 camara rrrr:\n\r',camera.value.rotation);
|
||||||
|
|
||||||
|
// cameraZ.value = value
|
||||||
|
// })
|
||||||
|
// watch(() => camera.value.rotation.z, (value) => {
|
||||||
|
// console.log('code line-68 \n\r😁 camraea rotation:\n\r',value);
|
||||||
|
|
||||||
|
// // cameraZ.value = value
|
||||||
|
// })
|
||||||
renderer.value = new CSS3DRenderer()
|
renderer.value = new CSS3DRenderer()
|
||||||
renderer.value.setSize(width, height)
|
renderer.value.setSize(width, height*0.9)
|
||||||
renderer.value.domElement.style.position = 'absolute';
|
renderer.value.domElement.style.position = 'absolute';
|
||||||
|
// 垂直居中
|
||||||
|
renderer.value.domElement.style.paddingTop = '50px'
|
||||||
|
renderer.value.domElement.style.top = '50%';
|
||||||
|
renderer.value.domElement.style.left = '50%';
|
||||||
|
renderer.value.domElement.style.transform = 'translate(-50%, -50%)';
|
||||||
WebGLoutput!.appendChild(renderer.value.domElement);
|
WebGLoutput!.appendChild(renderer.value.domElement);
|
||||||
|
|
||||||
controls.value = new TrackballControls(camera.value, renderer.value.domElement);
|
controls.value = new TrackballControls(camera.value, renderer.value.domElement);
|
||||||
@@ -76,25 +93,6 @@ const init = () => {
|
|||||||
for (let i = 0; i < tableLen; i++) {
|
for (let i = 0; i < tableLen; i++) {
|
||||||
let element = document.createElement('div');
|
let element = document.createElement('div');
|
||||||
element.className = 'element-card';
|
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.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.style.color=localTheme.detail.primary
|
|
||||||
|
|
||||||
const number = document.createElement('div');
|
const number = document.createElement('div');
|
||||||
number.className = 'card-id';
|
number.className = 'card-id';
|
||||||
@@ -116,7 +114,7 @@ const init = () => {
|
|||||||
// detail.style.fontSize = `${textSize * 0.5}px`;
|
// detail.style.fontSize = `${textSize * 0.5}px`;
|
||||||
element.appendChild(detail);
|
element.appendChild(detail);
|
||||||
|
|
||||||
element = useElementStyle(element, cardColor, cardSize, textSize)
|
element = useElementStyle(element, cardColor.value, cardSize.value, textSize.value)
|
||||||
const object = new CSS3DObject(element);
|
const object = new CSS3DObject(element);
|
||||||
object.position.x = Math.random() * 4000 - 2000;
|
object.position.x = Math.random() * 4000 - 2000;
|
||||||
object.position.y = Math.random() * 4000 - 2000;
|
object.position.y = Math.random() * 4000 - 2000;
|
||||||
@@ -136,8 +134,8 @@ const init = () => {
|
|||||||
for (let i = 0; i < tableLen; i++) {
|
for (let i = 0; i < tableLen; i++) {
|
||||||
const object = new THREE.Object3D();
|
const object = new THREE.Object3D();
|
||||||
|
|
||||||
object.position.x = tableData.value[i].x * (cardSize.width + 40) - rowCount * 90;
|
object.position.x = tableData.value[i].x * (cardSize.value.width + 40) - rowCount.value * 90;
|
||||||
object.position.y = -tableData.value[i].y * (cardSize.height + 20) + 1000;
|
object.position.y = -tableData.value[i].y * (cardSize.value.height + 20) + 1000;
|
||||||
object.position.z = 0;
|
object.position.z = 0;
|
||||||
|
|
||||||
targets.table.push(object);
|
targets.table.push(object);
|
||||||
@@ -214,10 +212,12 @@ const transform = (targets: any[], duration: number) => {
|
|||||||
.onComplete(() => {
|
.onComplete(() => {
|
||||||
if (luckyCardList.value.length) {
|
if (luckyCardList.value.length) {
|
||||||
luckyCardList.value.forEach((item: any) => {
|
luckyCardList.value.forEach((item: any) => {
|
||||||
return useElementStyle(item.element, cardColor, { width: cardSize.width, height: cardSize.height }, textSize)
|
return useElementStyle(item.element, cardColor.value, cardSize.value, textSize.value)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
luckyCardList.value = [];
|
luckyCardList.value = [];
|
||||||
|
|
||||||
|
canOperate.value = true
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -248,11 +248,11 @@ function animation() {
|
|||||||
requestAnimationFrame(animation);
|
requestAnimationFrame(animation);
|
||||||
}
|
}
|
||||||
|
|
||||||
// // 自动旋转的动画
|
// // 旋转的动画
|
||||||
function rollBall(rotateY: number, duration: number, mod: 'default' | 'restore' = 'default') {
|
function rollBall(rotateY: number, duration: number) {
|
||||||
TWEEN.removeAll();
|
TWEEN.removeAll();
|
||||||
|
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve) => {
|
||||||
scene.value.rotation.y = 0;
|
scene.value.rotation.y = 0;
|
||||||
ballRotationY.value = Math.PI * rotateY * 1000
|
ballRotationY.value = Math.PI * rotateY * 1000
|
||||||
const rotateObj = new TWEEN.Tween(scene.value.rotation);
|
const rotateObj = new TWEEN.Tween(scene.value.rotation);
|
||||||
@@ -270,85 +270,240 @@ function rollBall(rotateY: number, duration: number, mod: 'default' | 'restore'
|
|||||||
.onUpdate(render)
|
.onUpdate(render)
|
||||||
.start()
|
.start()
|
||||||
.onStop(() => {
|
.onStop(() => {
|
||||||
scene.value.rotation.y = 0;
|
|
||||||
resolve('')
|
resolve('')
|
||||||
})
|
})
|
||||||
.onComplete(() => {
|
.onComplete(() => {
|
||||||
resolve('')
|
resolve('')
|
||||||
|
canOperate.value = true
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
// 将视野转回正面
|
||||||
|
function resetCamera() {
|
||||||
|
new TWEEN.Tween(camera.value.position)
|
||||||
|
.to(
|
||||||
|
{
|
||||||
|
x: 0,
|
||||||
|
y: 0,
|
||||||
|
z: 3000
|
||||||
|
},
|
||||||
|
1000
|
||||||
|
)
|
||||||
|
.onUpdate(render)
|
||||||
|
.start()
|
||||||
|
.onComplete(() => {
|
||||||
|
new TWEEN.Tween(camera.value.rotation)
|
||||||
|
.to(
|
||||||
|
{
|
||||||
|
x: 0,
|
||||||
|
y: 0,
|
||||||
|
z: 0
|
||||||
|
},
|
||||||
|
1000
|
||||||
|
)
|
||||||
|
.onUpdate(render)
|
||||||
|
.start()
|
||||||
|
.onComplete(() => {
|
||||||
|
canOperate.value = true // 相机恢复原位
|
||||||
|
// camera.value.lookAt(scene.value.position)
|
||||||
|
camera.value.position.y = 0
|
||||||
|
camera.value.position.x = 0
|
||||||
|
camera.value.position.z = 3000
|
||||||
|
camera.value.rotation.x = 0
|
||||||
|
camera.value.rotation.y = 0
|
||||||
|
camera.value.rotation.z = -0
|
||||||
|
controls.value.reset()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
function render() {
|
function render() {
|
||||||
renderer.value.render(scene.value, camera.value);
|
renderer.value.render(scene.value, camera.value);
|
||||||
}
|
}
|
||||||
const enterLottery = async () => {
|
const enterLottery = async () => {
|
||||||
|
if (!canOperate.value) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
canOperate.value = false
|
||||||
transform(targets.sphere, 1000)
|
transform(targets.sphere, 1000)
|
||||||
currentStatus.value = 1
|
currentStatus.value = 1
|
||||||
// setTimeout(() => {
|
setTimeout(() => {
|
||||||
// rollBall(0.1,3000)
|
rollBall(0.1, 2000)
|
||||||
// }, 3000)
|
}, 2000)
|
||||||
}
|
}
|
||||||
// 开始抽奖
|
// 开始抽奖
|
||||||
const startLottery = () => {
|
const startLottery = () => {
|
||||||
|
if (!canOperate.value) {
|
||||||
|
return
|
||||||
|
}
|
||||||
currentStatus.value = 2
|
currentStatus.value = 2
|
||||||
rollBall(10, 3000)
|
rollBall(10, 3000)
|
||||||
}
|
}
|
||||||
|
|
||||||
const stopLottery = async () => {
|
const stopLottery = async () => {
|
||||||
|
if (!canOperate.value) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
canOperate.value = false
|
||||||
TWEEN.removeAll();
|
TWEEN.removeAll();
|
||||||
rollBall(0, 1)
|
rollBall(0, 1)
|
||||||
// scene正面
|
|
||||||
currentStatus.value = 0
|
currentStatus.value = 0
|
||||||
// 从notPersonList随机抽取currentPrize.count个
|
const notPersonListLength = notPersonList.value.length;
|
||||||
const notPersonListLength = notPersonList.length;
|
|
||||||
for (let i = 0; i < currentPrize.count; i++) {
|
// 每次最多抽十个
|
||||||
|
let luckyCount = 10
|
||||||
|
const leftover = currentPrize.value.count - currentPrize.value.isUsedCount
|
||||||
|
leftover < luckyCount ? luckyCount = leftover : luckyCount
|
||||||
|
if (notPersonListLength < luckyCount) {
|
||||||
|
toast.open({
|
||||||
|
message: '抽奖人数不够',
|
||||||
|
type: 'warning',
|
||||||
|
position: 'top-right',
|
||||||
|
duration: 10000
|
||||||
|
})
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
for (let i = 0; i < luckyCount; i++) {
|
||||||
if (notPersonListLength > 0) {
|
if (notPersonListLength > 0) {
|
||||||
const randomIndex = Math.floor(Math.random() * notPersonListLength);
|
const randomIndex = Math.floor(Math.random() * notPersonListLength);
|
||||||
luckyTargets.value.push(notPersonList[randomIndex])
|
luckyTargets.value.push(notPersonList.value[randomIndex])
|
||||||
|
|
||||||
let LuckyCard = objects.value[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)
|
luckyCardList.value.push(LuckyCard)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
const luckyCardListLength = luckyCardList.value.length;
|
||||||
personConfig.addAlreadyPersonList(luckyTargets.value)
|
const windowSize = { width: window.innerWidth, height: window.innerHeight }
|
||||||
|
luckyCardListLength && luckyCardList.value.forEach((item: any, index: number) => {
|
||||||
|
item.element = useElementStyle(item.element, luckyColor.value, { width: cardSize.value.width * 2, height: cardSize.value.height * 2 }, textSize.value * 2, 'lucky')
|
||||||
|
item = useElementPosition(item, rowCount.value, { width: cardSize.value.width * 2, height: cardSize.value.height * 2 }, windowSize, index)
|
||||||
|
new TWEEN.Tween(item.position)
|
||||||
|
.to({
|
||||||
|
x: item.x,
|
||||||
|
y: item.y,
|
||||||
|
z: 1000
|
||||||
|
}, 700)
|
||||||
|
.start()
|
||||||
|
new TWEEN.Tween(item.rotation)
|
||||||
|
.to({
|
||||||
|
x: 0,
|
||||||
|
y: 0,
|
||||||
|
z: 0
|
||||||
|
}, 600)
|
||||||
|
.start()
|
||||||
|
.onComplete(() => {
|
||||||
|
confettiFire()
|
||||||
|
resetCamera()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
currentPrizeValue.value.isUsedCount += luckyCount
|
||||||
|
if(currentPrizeValue.value.isUsedCount>=currentPrizeValue.value.count){
|
||||||
|
currentPrizeValue.value.isUsed=true
|
||||||
|
}
|
||||||
|
prizeConfig.setCurrentPrize(currentPrizeValue.value)
|
||||||
|
prizeConfig.updatePrizeConfig(currentPrizeValue.value)
|
||||||
|
personConfig.addAlreadyPersonList(luckyTargets.value, currentPrize.value)
|
||||||
}
|
}
|
||||||
|
// 庆祝动画
|
||||||
|
const confettiFire = () => {
|
||||||
|
var duration = 3 * 1000;
|
||||||
|
var end = Date.now() + duration;
|
||||||
|
(function frame() {
|
||||||
|
// launch a few confetti from the left edge
|
||||||
|
confetti({
|
||||||
|
particleCount: 2,
|
||||||
|
angle: 60,
|
||||||
|
spread: 55,
|
||||||
|
origin: { x: 0 }
|
||||||
|
});
|
||||||
|
// and launch a few from the right edge
|
||||||
|
confetti({
|
||||||
|
particleCount: 2,
|
||||||
|
angle: 120,
|
||||||
|
spread: 55,
|
||||||
|
origin: { x: 1 }
|
||||||
|
});
|
||||||
|
|
||||||
|
// keep going until we are out of time
|
||||||
|
if (Date.now() < end) {
|
||||||
|
requestAnimationFrame(frame);
|
||||||
|
}
|
||||||
|
}());
|
||||||
|
centerFire(0.25, {
|
||||||
|
spread: 26,
|
||||||
|
startVelocity: 55,
|
||||||
|
});
|
||||||
|
centerFire(0.2, {
|
||||||
|
spread: 60,
|
||||||
|
});
|
||||||
|
centerFire(0.35, {
|
||||||
|
spread: 100,
|
||||||
|
decay: 0.91,
|
||||||
|
scalar: 0.8
|
||||||
|
});
|
||||||
|
centerFire(0.1, {
|
||||||
|
spread: 120,
|
||||||
|
startVelocity: 25,
|
||||||
|
decay: 0.92,
|
||||||
|
scalar: 1.2
|
||||||
|
});
|
||||||
|
centerFire(0.1, {
|
||||||
|
spread: 120,
|
||||||
|
startVelocity: 45,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
const centerFire = (particleRatio: number, opts: any) => {
|
||||||
|
const count = 200
|
||||||
|
confetti({
|
||||||
|
origin: { y: 0.7 },
|
||||||
|
...opts,
|
||||||
|
particleCount: Math.floor(count * particleRatio)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
// 监听空格键
|
||||||
|
const listenSpaceKey=()=>{
|
||||||
|
window.addEventListener('keydown', (e) => {
|
||||||
|
console.log('code line-468 \n\r😒 e:\n\r',e);
|
||||||
|
//
|
||||||
|
|
||||||
|
if (e.code !== 'Space') {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if(currentStatus.value==0){
|
||||||
|
enterLottery()
|
||||||
|
}
|
||||||
|
else if(currentStatus.value==1){
|
||||||
|
startLottery()
|
||||||
|
}
|
||||||
|
else if(currentStatus.value==2){
|
||||||
|
stopLottery()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
init();
|
init();
|
||||||
animation();
|
animation();
|
||||||
containerRef.value!.style.color = `${textColor}`
|
containerRef.value!.style.color = `${textColor}`
|
||||||
|
listenSpaceKey()
|
||||||
});
|
});
|
||||||
|
onUnmounted(() => {
|
||||||
|
window.removeEventListener('keydown', listenSpaceKey)
|
||||||
|
})
|
||||||
|
watch(()=>currentPrizeValue.value.isUsed,(val)=>{
|
||||||
|
if(val){
|
||||||
|
currentPrizeValue.value=JSON.parse(JSON.stringify(currentPrize.value))
|
||||||
|
}
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div id="container" ref="containerRef">
|
|
||||||
|
<h2 class="absolute w-full pt-12 m-0 font-mono tracking-wide text-center leading-12" :style="{fontSize:textSize*1.5+'px',color:textColor}">{{ topTitle }}</h2>
|
||||||
|
<div id="container" ref="containerRef" class="3dContainer">
|
||||||
|
|
||||||
<!-- 选中菜单结构 start-->
|
<!-- 选中菜单结构 start-->
|
||||||
<div id="menu">
|
<div id="menu">
|
||||||
<button class="btn glass" @click="enterLottery" v-if="currentStatus == 0">进入抽奖</button>
|
<button class="btn glass" @click="enterLottery" v-if="currentStatus == 0">进入抽奖</button>
|
||||||
@@ -356,8 +511,10 @@ onMounted(() => {
|
|||||||
<button class="btn glass" @click="startLottery" v-if="currentStatus == 1">开始</button>
|
<button class="btn glass" @click="startLottery" v-if="currentStatus == 1">开始</button>
|
||||||
|
|
||||||
<button class="btn glass" @click="stopLottery" v-if="currentStatus == 2">结束</button>
|
<button class="btn glass" @click="stopLottery" v-if="currentStatus == 2">结束</button>
|
||||||
<button id="table" @click="transform(targets.table, 2000)">TABLE</button>
|
|
||||||
<button id="helix" @click="transform(targets.helix, 2000)">HELIX</button>
|
|
||||||
|
<!-- <button id="table" @click="transform(targets.table, 2000)">TABLE</button> -->
|
||||||
|
<!-- <button id="helix" @click="transform(targets.helix, 2000)">HELIX</button> -->
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<!-- end -->
|
<!-- end -->
|
||||||
|
|||||||
Reference in New Issue
Block a user