import { defineStore } from 'pinia' import { getRandomElements } from '@/views/Home/utils/random' import { defaultPersonList } from './data' import type { IPersonConfig } from '@/types/storeType' export interface PrizeConfig { id: string name: string description: string totalCount: number remainingCount: number color: string order: number } export interface DrawResult { id: string drawIndex: number prizeId: string prizeName: string prizeDescription: string drawTime: string } export const usePrizeDrawStore = defineStore('prizeDraw', { state: () => ({ // 配置版本号 - 修改此版本号会强制重新初始化 configVersion: 2, // 奖品配置 prizeConfigs: [ { id: 'prize-1', name: '快乐通勤奖', description: '可提前1小时下班或晚到1小时', totalCount: 25, remainingCount: 25, color: '#10b981', order: 1, }, { id: 'prize-2', name: '跑马场自由日', description: '可选在家或其他场所办公', totalCount: 18, remainingCount: 18, color: '#3b82f6', order: 2, }, { id: 'prize-3', name: '前途光明奖', description: '获得boss 1对1畅聊1小时', totalCount: 2, remainingCount: 2, color: '#f59e0b', order: 3, }, { id: 'prize-4', name: '现金红包', description: '500元', totalCount: 3, remainingCount: 3, color: '#ef4444', order: 4, }, { id: 'prize-5', name: '现金红包', description: '300元', totalCount: 8, remainingCount: 8, color: '#f97316', order: 5, }, { id: 'prize-6', name: '现金红包', description: '200元', totalCount: 15, remainingCount: 15, color: '#ec4899', order: 6, }, { id: 'prize-7', name: '现金红包', description: '100元', totalCount: 17, remainingCount: 17, color: '#8b5cf6', order: 7, }, ] as PrizeConfig[], // 奖品池(用于抽取) prizePool: [] as string[], // 人员池 personPool: [] as IPersonConfig[], // 抽奖结果 drawResults: [] as DrawResult[], // 当前状态 currentDrawIndex: 0, isInitialized: false, }), getters: { // 进度百分比 progress: (state) => { if (state.currentDrawIndex === 0) return 0 return Math.round((state.currentDrawIndex / 88) * 100) }, // 剩余人数 remainingPersons: state => state.personPool.length, // 剩余奖品数 remainingPrizes: state => state.prizePool.length, // 是否完成 isCompleted: state => state.currentDrawIndex >= 88, // 总人数 totalPersons: () => 88, }, actions: { // 初始化 init() { // 检查版本号,如果不匹配则强制重新初始化 const expectedVersion = 2 if (this.configVersion !== expectedVersion) { console.log(`配置版本不匹配 (${this.configVersion} !== ${expectedVersion}),重新初始化...`) this.reset() this.configVersion = expectedVersion } if (this.isInitialized && this.personPool.length > 0) { console.log('已初始化,跳过') return } console.log('初始化抽奖系统...') // 从 data.ts 加载88人 this.personPool = defaultPersonList.map((p, index) => ({ ...p, uuid: `uuid-${index}`, })) // 构建奖品池(88个奖品) this.prizePool = [ ...Array(25).fill('prize-1'), ...Array(18).fill('prize-2'), ...Array(2).fill('prize-3'), ...Array(3).fill('prize-4'), ...Array(8).fill('prize-5'), ...Array(15).fill('prize-6'), ...Array(17).fill('prize-7'), ] // 重置奖品剩余数量 this.prizeConfigs.forEach((config) => { config.remainingCount = config.totalCount }) this.isInitialized = true console.log(`初始化完成: ${this.personPool.length}人, ${this.prizePool.length}个奖品`) }, // 执行一次抽奖 async executeDraw(): Promise { if (this.prizePool.length === 0) { console.log('抽奖已完成') return null } try { // 从奖品池中随机抽取1个奖品 const [prizeId] = getRandomElements(this.prizePool, 1) // 找到奖品配置 const prizeConfig = this.prizeConfigs.find(p => p.id === prizeId) if (!prizeConfig) { throw new Error(`未找到奖品配置: ${prizeId}`) } // 从奖品池中移除 const prizeIndex = this.prizePool.indexOf(prizeId) if (prizeIndex > -1) { this.prizePool.splice(prizeIndex, 1) } // 更新奖品剩余数量 prizeConfig.remainingCount-- // 记录结果 const result: DrawResult = { id: `draw-${Date.now()}-${Math.random()}`, drawIndex: ++this.currentDrawIndex, prizeId, prizeName: prizeConfig.name, prizeDescription: prizeConfig.description, drawTime: new Date().toISOString(), } this.drawResults.unshift(result) console.log(`抽奖结果: ${result.prizeName}`) return result } catch (error) { console.error('抽奖失败:', error) return null } }, // 撤销最后一次抽奖 undoLastDraw() { if (this.drawResults.length === 0) { console.log('没有可撤销的抽奖记录') return false } const lastResult = this.drawResults[0] // 找回奖品 this.prizePool.push(lastResult.prizeId) // 恢复奖品数量 const prizeConfig = this.prizeConfigs.find(p => p.id === lastResult.prizeId) if (prizeConfig) { prizeConfig.remainingCount++ } // 移除记录 this.drawResults.shift() this.currentDrawIndex-- console.log(`已撤销: ${lastResult.prizeName}`) return true }, // 重置所有数据 reset() { this.prizePool = [] this.personPool = [] this.drawResults = [] this.currentDrawIndex = 0 this.isInitialized = false // 重新初始化 this.init() console.log('已重置抽奖系统') }, // 导出结果为Excel exportToExcel() { if (this.drawResults.length === 0) { console.log('没有抽奖记录可导出') return } // 动态导入xlsx import('xlsx').then((XLSX) => { // 准备数据(按抽奖顺序) const results = this.drawResults.slice().reverse() const data = results.map(result => ({ 序号: result.drawIndex, 奖品名称: result.prizeName, 奖品描述: result.prizeDescription, 抽奖时间: new Date(result.drawTime).toLocaleString('zh-CN'), })) // 创建工作表 const ws = XLSX.utils.json_to_sheet(data) // 设置列宽 ws['!cols'] = [ { wch: 8 }, // 序号 { wch: 12 }, // 人员编号 { wch: 12 }, // 人员姓名 { wch: 20 }, // 奖品名称 { wch: 30 }, // 奖品描述 { wch: 20 }, // 抽奖时间 ] // 创建工作簿 const wb = XLSX.utils.book_new() XLSX.utils.book_append_sheet(wb, ws, '抽奖结果') // 导出文件 const fileName = `抽奖结果-${new Date().toLocaleDateString('zh-CN').replace(/\//g, '-')}.xlsx` XLSX.writeFile(wb, fileName) console.log('已导出抽奖结果到Excel') }).catch((error) => { console.error('导出Excel失败:', error) }) }, }, persist: { enabled: true, strategies: [ { key: 'prizeDraw', storage: localStorage, }, ], }, })