feat: redesign Big Screen voting view with philatelic postcard UI

- Add PostcardItem.vue component with Chinese postal aesthetics
- Add PostcardGrid.vue container with 4x2 CSS Grid layout
- Add Postmark.vue component for real-time vote stamp visualization
- Update LiveVotingView.vue with cream paper theme (#FDFBF7)
- Add Year of the Horse 2026 stamp image
- Add responsive breakpoints for different screen sizes
- Enhance admin service with program voting control
- Add vote stamp accumulation for big screen display

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
empty
2026-01-16 15:15:17 +08:00
parent 30cd29d45d
commit 84be8c4b5c
19 changed files with 2056 additions and 382 deletions

View File

@@ -33,6 +33,9 @@ export const useAdminStore = defineStore('admin', () => {
const votingOpen = ref(false);
const votingPaused = ref(false);
const totalVotes = ref(0);
const programs = ref<Array<{ id: string; name: string; teamName: string; order: number; status: string; votes: number; stamps: any[] }>>([]);
const allowLateCatch = ref(true);
const currentProgramId = ref<string | null>(null);
// Lottery State
const lotteryRound = ref<LotteryRound>(1);
@@ -143,7 +146,7 @@ export const useAdminStore = defineStore('admin', () => {
userId: 'admin_main',
userName: 'Admin Console',
role: 'admin',
}, () => {});
}, () => { });
// Request state sync
socketInstance.emit(SOCKET_EVENTS.ADMIN_STATE_SYNC as any, {});
@@ -177,6 +180,9 @@ export const useAdminStore = defineStore('admin', () => {
votingOpen.value = state.voting.subPhase === 'OPEN';
votingPaused.value = state.voting.subPhase === 'PAUSED';
totalVotes.value = state.voting.totalVotes;
programs.value = state.voting.programs || [];
allowLateCatch.value = state.voting.allowLateCatch ?? true;
currentProgramId.value = state.voting.currentProgramId || null;
lotteryRound.value = state.lottery.round;
lotterySubPhase.value = state.lottery.subPhase;
currentWinners.value = state.lottery.currentWinners;
@@ -361,6 +367,9 @@ export const useAdminStore = defineStore('admin', () => {
votingOpen,
votingPaused,
totalVotes,
programs,
allowLateCatch,
currentProgramId,
lotteryRound,
lotterySubPhase,
stormStartedAt,
@@ -387,5 +396,6 @@ export const useAdminStore = defineStore('admin', () => {
emergencyReset,
controlMusic,
clearError,
getSocket: () => socket.value,
};
});