96 UI optimization (#136)
* fix(home): 🐛 解决多次切换路由后页面卡顿的问题 #96 卸载路由时清除requestAnimationFrame * feat: ✨ 文件存储使用Blob格式 * style: 💄 修改部分类型any为具体类型 * feat: ✨ 界面设置中模块使用瀑布流布局 #96 * fix: 🐛 md文档更换文件夹解决控制台警告 * style: 💄 switch按钮改回使用daisyui组件 * refactor: ♻️ 所有人员列表提取tableColumn * style: 💄 奖项列表中的图片类型修复 * fix(globalConfig): 修复当前音乐项类型缺失问题 * feat: ✨ single person not done * feat: ✨ 可添加单人 #96 * build(.gitignore): 添加 auto-imports.d.ts 到忽略文件 * fix: 🐛 上传、下载excel文件时修复路径错误 打包成应用和网页端的baseUrl不一样,使用环境变量来表示 * fix: 🐛 导入人员列表时处理有值为空的情况 * style: 💄 改变toaster的组件 * fix: 🐛 上传文件、解析数据与存储/读取数据的处理 、 * fix(Config): 更新备案信息链接样式 将备案信息的段落标签替换为可点击的链接标签,使用户能够直接跳转到工信部备案查询页面。同时添加了悬停效果样式,提升用户体验。 * feat: ✨ 首页奖项列表样式修改 not done #96 * chore(deps): ✏️ 更新依赖版本 * chore: ✏️ gsap list demo * build: 🏗️ docker构建优化 * chore: ✏️ gsap scroll demo * style: 💄 gsap demno * feat: ✨ demo smooth scroll gsap scrolltrigger * feat(Demo): 添加更多颜色选项并注释GSAP动画 * refactor(PrizeList): 重构奖品列表组件结构 * feat(PrizeList): 重构奖品列表组件并添加滚动动画 * feat: ✨ 增加定时抽取功能 #96 * feat: ✨ 添加定时抽取功能的说明 * feat: ✨ 优化gsap #96 项数不多时不触发gsap * style: 💄 文本修改 * feat: ✨ 优化 * feat: ✨ 优化奖项列表 * fix(Home): 修复奖品列表滚动检测逻辑 * fix(home): 修复抽奖停止逻辑避免重复执行;调整卡片垂直居中位置计算 * feat: ✨ 播放中奖音频 #96
This commit is contained in:
@@ -8,6 +8,7 @@ import { CSS3DObject, CSS3DRenderer } from 'three-css3d'
|
||||
import { TrackballControls } from 'three/examples/jsm/controls/TrackballControls.js'
|
||||
import { nextTick, onMounted, onUnmounted, ref } from 'vue'
|
||||
import { useToast } from 'vue-toast-notification'
|
||||
import enterAudio from '@/assets/audio/enter.wav'
|
||||
import { useElementPosition, useElementStyle } from '@/hooks/useElement'
|
||||
import i18n from '@/locales/i18n'
|
||||
import useStore from '@/store'
|
||||
@@ -16,6 +17,7 @@ import { rgba } from '@/utils/color'
|
||||
import { LotteryStatus } from './type'
|
||||
import { confettiFire, createSphereVertices, createTableVertices, getRandomElements, initTableData } from './utils'
|
||||
|
||||
const maxAudioLimit = 10
|
||||
export function useViewModel() {
|
||||
const toast = useToast()
|
||||
// store里面存储的值
|
||||
@@ -26,7 +28,21 @@ export function useViewModel() {
|
||||
getNotThisPrizePersonList: notThisPrizePersonList,
|
||||
} = storeToRefs(personConfig)
|
||||
const { getCurrentPrize: currentPrize } = storeToRefs(prizeConfig)
|
||||
const { getCardColor: cardColor, getPatterColor: patternColor, getPatternList: patternList, getTextColor: textColor, getLuckyColor: luckyColor, getCardSize: cardSize, getTextSize: textSize, getRowCount: rowCount, getIsShowAvatar: isShowAvatar, getTitleFont: titleFont, getTitleFontSyncGlobal: titleFontSyncGlobal } = storeToRefs(globalConfig)
|
||||
const {
|
||||
getCardColor: cardColor,
|
||||
getPatterColor: patternColor,
|
||||
getPatternList: patternList,
|
||||
getTextColor: textColor,
|
||||
getLuckyColor: luckyColor,
|
||||
getCardSize: cardSize,
|
||||
getTextSize: textSize,
|
||||
getRowCount: rowCount,
|
||||
getIsShowAvatar: isShowAvatar,
|
||||
getTitleFont: titleFont,
|
||||
getTitleFontSyncGlobal: titleFontSyncGlobal,
|
||||
getDefiniteTime: definiteTime,
|
||||
getWinMusic: isPlayWinMusic,
|
||||
} = storeToRefs(globalConfig)
|
||||
// three初始值
|
||||
const ballRotationY = ref(0)
|
||||
const containerRef = ref<HTMLElement>()
|
||||
@@ -53,7 +69,7 @@ export function useViewModel() {
|
||||
const intervalTimer = ref<any>(null)
|
||||
const isInitialDone = ref<boolean>(false)
|
||||
const animationFrameId = ref<any>(null)
|
||||
|
||||
const playingAudios = ref<HTMLAudioElement[]>([])
|
||||
function initThreeJs() {
|
||||
const felidView = 40
|
||||
const width = window.innerWidth
|
||||
@@ -367,14 +383,6 @@ export function useViewModel() {
|
||||
personPool.value.splice(index, 1)
|
||||
}
|
||||
})
|
||||
// for (let i = 0; i < luckyCount.value; i++) {
|
||||
// if (personPool.value.length > 0) {
|
||||
// // 解决随机元素概率过于不均等问题
|
||||
// const randomIndex = Math.floor(Math.random() * (personPool.value.length - 1))
|
||||
// luckyTargets.value.push(personPool.value[randomIndex])
|
||||
// personPool.value.splice(randomIndex, 1)
|
||||
// }
|
||||
// }
|
||||
|
||||
toast.open({
|
||||
// message: `现在抽取${currentPrize.value.name} ${leftover}人`,
|
||||
@@ -385,6 +393,13 @@ export function useViewModel() {
|
||||
})
|
||||
currentStatus.value = LotteryStatus.running
|
||||
rollBall(10, 3000)
|
||||
if (definiteTime.value) {
|
||||
setTimeout(() => {
|
||||
if (currentStatus.value === LotteryStatus.running) {
|
||||
stopLottery()
|
||||
}
|
||||
}, definiteTime.value * 1000)
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @description: 停止抽奖,抽出幸运人
|
||||
@@ -429,11 +444,41 @@ export function useViewModel() {
|
||||
.easing(TWEEN.Easing.Exponential.InOut)
|
||||
.start()
|
||||
.onComplete(() => {
|
||||
if (isPlayWinMusic.value) {
|
||||
playWinMusic()
|
||||
}
|
||||
confettiFire()
|
||||
resetCamera()
|
||||
})
|
||||
})
|
||||
}
|
||||
// 播放音频,中将卡片越多audio对象越多,声音越大
|
||||
function playWinMusic() {
|
||||
if (playingAudios.value.length > maxAudioLimit) {
|
||||
console.log('音频播放数量已达到上限,请勿重复播放')
|
||||
return
|
||||
}
|
||||
const enterNewAudio = new Audio(enterAudio)
|
||||
playingAudios.value.push(enterNewAudio)
|
||||
enterNewAudio.play()
|
||||
.then(() => {
|
||||
// 当音频播放结束后,从数组中移除
|
||||
enterNewAudio.onended = () => {
|
||||
const index = playingAudios.value.indexOf(enterNewAudio)
|
||||
if (index > -1) {
|
||||
playingAudios.value.splice(index, 1)
|
||||
}
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error('播放音频失败:', error)
|
||||
// 如果播放失败,也从数组中移除
|
||||
const index = playingAudios.value.indexOf(enterNewAudio)
|
||||
if (index > -1) {
|
||||
playingAudios.value.splice(index, 1)
|
||||
}
|
||||
})
|
||||
}
|
||||
/**
|
||||
* @description: 继续,意味着这抽奖作数,计入数据库
|
||||
*/
|
||||
@@ -441,7 +486,6 @@ export function useViewModel() {
|
||||
if (!canOperate.value) {
|
||||
return
|
||||
}
|
||||
|
||||
const customCount = currentPrize.value.separateCount
|
||||
if (customCount && customCount.enable && customCount.countList.length > 0) {
|
||||
for (let i = 0; i < customCount.countList.length; i++) {
|
||||
@@ -627,11 +671,6 @@ export function useViewModel() {
|
||||
intervalTimer.value = null
|
||||
window.removeEventListener('keydown', listenKeyboard)
|
||||
})
|
||||
// watch(() => allPersonList.value, (newVal) => {
|
||||
// if (newVal.length) {
|
||||
// init()
|
||||
// }
|
||||
// })
|
||||
|
||||
return {
|
||||
setDefaultPersonList,
|
||||
|
||||
Reference in New Issue
Block a user