feat: festive Chinese red background and prize config unification

- Change all big screen backgrounds to pure Chinese red (#c41230)
- Remove vignette effect for consistent display on different screens
- Unify all prize data to match prizes.json configuration
- Add demo participants fallback when no data imported
- Fix particle visibility reset in startGalaxy()

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
empty
2026-01-23 16:33:21 +08:00
parent a442d050e4
commit 22141c9263
10 changed files with 90 additions and 88 deletions

View File

@@ -10,7 +10,8 @@ html, body {
width: 100%; width: 100%;
height: 100%; height: 100%;
overflow: hidden; overflow: hidden;
background: $color-bg-dark; // Chinese New Year festive pure red background
background: #c41230;
font-family: 'PingFang SC', 'Microsoft YaHei', sans-serif; font-family: 'PingFang SC', 'Microsoft YaHei', sans-serif;
color: $color-text-light; color: $color-text-light;
-webkit-font-smoothing: antialiased; -webkit-font-smoothing: antialiased;

View File

@@ -11,10 +11,10 @@ $color-gold-light: #ffd966;
$color-gold-dark: #d4a84b; $color-gold-dark: #d4a84b;
$color-gold-deep: #b8923f; $color-gold-deep: #b8923f;
// Cinematic background // Cinematic background - Festive Chinese Red
$color-bg-dark: #0a0a0a; $color-bg-dark: #c41230;
$color-bg-wine: #2a0a0e; $color-bg-wine: #c41230;
$color-bg-gradient: linear-gradient(180deg, #2a0a0e 0%, #1a0808 50%, #0a0505 100%); $color-bg-gradient: linear-gradient(180deg, #d4232a 0%, #c41230 50%, #a01028 100%);
// Text // Text
$color-text-light: #ffffff; $color-text-light: #ffffff;

View File

@@ -2,7 +2,7 @@ import { Application, Container, Graphics, Ticker } from 'pixi.js';
// Cinematic color palette // Cinematic color palette
const COLORS = { const COLORS = {
wineRed: 0x2a0a0e, wineRed: 0xc41230, // Festive bright Chinese red
gold: 0xf0c239, gold: 0xf0c239,
goldDark: 0xd4a84b, goldDark: 0xd4a84b,
goldLight: 0xffd700, goldLight: 0xffd700,
@@ -81,24 +81,8 @@ export class BackgroundEffect {
} }
private drawVignette(): void { private drawVignette(): void {
const vignette = new Graphics(); // Disabled vignette for pure solid color background
const w = this.app.screen.width; // Keep method for potential future use
const h = this.app.screen.height;
const cx = w / 2;
const cy = h / 2;
const maxRadius = Math.sqrt(cx * cx + cy * cy);
// Create radial gradient effect with multiple circles
for (let i = 20; i >= 0; i--) {
const ratio = i / 20;
const radius = maxRadius * (0.3 + ratio * 0.7);
const alpha = ratio * 0.8;
vignette.circle(cx, cy, radius);
vignette.fill({ color: 0x000000, alpha });
}
this.app.stage.addChildAt(vignette, 0);
} }
private initDustParticles(): void { private initDustParticles(): void {

View File

@@ -11,7 +11,7 @@ const COLORS = {
red: 0xc21f30, red: 0xc21f30,
redLight: 0xe63946, redLight: 0xe63946,
redDark: 0x8b0000, redDark: 0x8b0000,
wineRed: 0x2a0a0e, wineRed: 0xc41230, // Festive bright Chinese red
black: 0x000000, black: 0x000000,
white: 0xffffff, white: 0xffffff,
}; };
@@ -245,9 +245,13 @@ export class LotteryMachine {
this.confettiContainer.removeChildren(); this.confettiContainer.removeChildren();
this.dimOverlay.clear(); this.dimOverlay.clear();
// Reset particles // Reset particles - restore visibility
this.nameParticles.forEach((p) => { this.nameParticles.forEach((p) => {
p.isWinner = false; p.isWinner = false;
if (p.text) {
p.text.visible = true;
p.text.alpha = 1;
}
}); });
this.phase = 'galaxy'; this.phase = 'galaxy';

View File

@@ -138,7 +138,7 @@ $color-text-muted: #888;
height: 100%; height: 100%;
position: relative; position: relative;
overflow: hidden; overflow: hidden;
background: #0a0a0a; background: #c41230;
} }
.race-canvas { .race-canvas {

View File

@@ -144,12 +144,22 @@ function startGalaxy() {
// Clear previous winners // Clear previous winners
winners.value = []; winners.value = [];
// 使用真实参与者数据如果有的话) // 使用真实参与者数据如果没有则使用演示数据
const participants = realParticipants.length > 0 ? realParticipants : []; let participants = realParticipants.length > 0 ? realParticipants : [];
if (participants.length === 0) { if (participants.length === 0) {
console.warn('[抽奖] 无参与者数据,请先导入名单'); console.warn('[抽奖] 无参与者数据,使用演示数据');
return; // 演示数据
participants = [
{ id: 'demo1', name: '张三', department: '技术部', zodiac: 'horse', age: 30 },
{ id: 'demo2', name: '李四', department: '市场部', zodiac: 'other', age: 28 },
{ id: 'demo3', name: '王五', department: '财务部', zodiac: 'horse', age: 32 },
{ id: 'demo4', name: '赵六', department: '人事部', zodiac: 'other', age: 26 },
{ id: 'demo5', name: '钱七', department: '运营部', zodiac: 'horse', age: 35 },
{ id: 'demo6', name: '孙八', department: '技术部', zodiac: 'other', age: 29 },
{ id: 'demo7', name: '周九', department: '市场部', zodiac: 'horse', age: 31 },
{ id: 'demo8', name: '吴十', department: '财务部', zodiac: 'other', age: 27 },
];
} }
// Set participants and start galaxy view // Set participants and start galaxy view

View File

@@ -1,42 +1,42 @@
{ {
"prizes": [ "prizes": [
{ {
"round": 1, "round": 1,
"level": "第一轮抽奖", "level": "第一轮抽奖",
"name": "幸运伴手礼", "name": "幸运伴手礼",
"winnerCount": 7, "winnerCount": 7,
"poolTag": "6070", "poolTag": "6070",
"description": "60/70年代" "description": "60/70年代"
}, },
{ {
"round": 2, "round": 2,
"level": "第二轮抽奖", "level": "第二轮抽奖",
"name": "幸运伴手礼", "name": "幸运伴手礼",
"winnerCount": 3, "winnerCount": 3,
"poolTag": "80", "poolTag": "80",
"description": "80年代" "description": "80年代"
}, },
{ {
"round": 3, "round": 3,
"level": "第三轮抽奖", "level": "第三轮抽奖",
"name": "幸运伴手礼", "name": "幸运伴手礼",
"winnerCount": 4, "winnerCount": 4,
"poolTag": "90", "poolTag": "90",
"description": "90年代" "description": "90年代"
}, },
{ {
"round": 4, "round": 4,
"level": "第四轮抽奖", "level": "第四轮抽奖",
"name": "幸运伴手礼", "name": "幸运伴手礼",
"winnerCount": 1, "winnerCount": 1,
"poolTag": "horse", "poolTag": "horse",
"zodiacFilter": "horse", "zodiacFilter": "horse",
"description": "属马特供" "description": "属马特供"
}
],
"settings": {
"minStormDuration": 3000,
"revealAnimationDuration": 2000,
"allowRepeatWinner": false
} }
],
"settings": {
"minStormDuration": 3000,
"revealAnimationDuration": 2000,
"allowRepeatWinner": false
}
} }

View File

@@ -419,9 +419,9 @@ class AdminService {
this.state.lottery = { this.state.lottery = {
round: 1, round: 1,
subPhase: 'IDLE', subPhase: 'IDLE',
prizeLevel: firstPrize?.level || '特等奖', prizeLevel: firstPrize?.level || '第一轮抽奖',
prizeName: firstPrize?.name || '待配置', prizeName: firstPrize?.name || '幸运伴手礼',
winnerCount: firstPrize?.winnerCount || 1, winnerCount: firstPrize?.winnerCount || 7,
currentWinners: [], currentWinners: [],
}; };
break; break;
@@ -497,12 +497,15 @@ class AdminService {
} }
if (scope === 'all' || scope === 'lottery') { if (scope === 'all' || scope === 'lottery') {
// 从配置获取第一轮奖项
const prizes = prizeConfigService.getPrizes();
const firstPrize = prizes.find(p => p.round === 1) || prizes[0];
this.state.lottery = { this.state.lottery = {
round: 1, round: 1,
subPhase: 'IDLE', subPhase: 'IDLE',
prizeLevel: '特等奖', prizeLevel: firstPrize?.level || '第一轮抽奖',
prizeName: 'iPhone 16 Pro Max', prizeName: firstPrize?.name || '幸运伴手礼',
winnerCount: 1, winnerCount: firstPrize?.winnerCount || 7,
currentWinners: [], currentWinners: [],
}; };
} }

View File

@@ -61,10 +61,10 @@ class PrizeConfigService {
private getDefaults(): PrizeConfigFile { private getDefaults(): PrizeConfigFile {
return { return {
prizes: [ prizes: [
{ round: 1 as LotteryRound, level: '特等奖', name: 'iPhone 16 Pro Max', winnerCount: 1 }, { round: 1 as LotteryRound, level: '第一轮抽奖', name: '幸运伴手礼', winnerCount: 7 },
{ round: 2 as LotteryRound, level: '一等奖', name: 'iPad Pro', winnerCount: 3 }, { round: 2 as LotteryRound, level: '第二轮抽奖', name: '幸运伴手礼', winnerCount: 3 },
{ round: 3 as LotteryRound, level: '二等奖', name: 'AirPods Pro', winnerCount: 5 }, { round: 3 as LotteryRound, level: '第三轮抽奖', name: '幸运伴手礼', winnerCount: 4 },
{ round: 4 as LotteryRound, level: '三等奖', name: '京东卡 500元', winnerCount: 10, zodiacFilter: 'horse' }, { round: 4 as LotteryRound, level: '第四轮抽奖', name: '幸运伴手礼', winnerCount: 1, zodiacFilter: 'horse' },
], ],
settings: { settings: {
minStormDuration: 3000, minStormDuration: 3000,

View File

@@ -140,10 +140,10 @@ export interface PrizeConfig {
} }
export const PRIZE_CONFIG: PrizeConfig[] = [ export const PRIZE_CONFIG: PrizeConfig[] = [
{ round: 1, level: '特等奖', name: 'iPhone 16 Pro Max', winnerCount: 1 }, { round: 1, level: '第一轮抽奖', name: '幸运伴手礼', winnerCount: 7 },
{ round: 2, level: '一等奖', name: 'iPad Pro', winnerCount: 3 }, { round: 2, level: '第二轮抽奖', name: '幸运伴手礼', winnerCount: 3 },
{ round: 3, level: '二等奖', name: 'AirPods Pro', winnerCount: 5 }, { round: 3, level: '第三轮抽奖', name: '幸运伴手礼', winnerCount: 4 },
{ round: 4, level: '三等奖', name: '京东卡 500元', winnerCount: 10, zodiacFilter: 'horse' }, { round: 4, level: '第四轮抽奖', name: '幸运伴手礼', winnerCount: 1, zodiacFilter: 'horse' },
]; ];
// Default programs for voting // Default programs for voting
@@ -175,9 +175,9 @@ export const INITIAL_ADMIN_STATE: AdminState = {
lottery: { lottery: {
round: 1, round: 1,
subPhase: 'IDLE', subPhase: 'IDLE',
prizeLevel: '特等奖', prizeLevel: '第一轮抽奖',
prizeName: 'iPhone 16 Pro Max', prizeName: '幸运伴手礼',
winnerCount: 1, winnerCount: 7,
currentWinners: [], currentWinners: [],
}, },
music: { music: {