chore: sync various improvements and fixes

- Update gitignore and serena config
- Improve connection and voting stores
- Enhance admin routes and socket handling
- Update client-screen views
- Add auth middleware

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
empty
2026-02-03 23:31:38 +08:00
parent 39caecdd95
commit 83bf1d3a43
25 changed files with 284 additions and 122 deletions

View File

@@ -4,6 +4,7 @@ import { useRouter } from 'vue-router';
import { useAdminStore } from '../stores/admin';
import { PRIZE_CONFIG } from '@gala/shared/types';
import type { PrizeConfig, LotteryRound } from '@gala/shared/types';
import { ADMIN_TOKEN_KEY } from '../router';
// 简单的防抖函数
function debounce<T extends (...args: any[]) => void>(fn: T, delay: number = 300): (...args: Parameters<T>) => void {
@@ -35,6 +36,15 @@ function debounceLeading<T extends (...args: any[]) => void>(fn: T, delay: numbe
const router = useRouter();
const admin = useAdminStore();
const adminToken = () => localStorage.getItem(ADMIN_TOKEN_KEY) || '';
function getAdminHeaders(extra?: Record<string, string>) {
return {
'Content-Type': 'application/json',
'x-session-token': adminToken(),
...extra,
};
}
// Local UI state
const confirmResetCode = ref('');
@@ -89,7 +99,9 @@ async function readJsonSafe(res: Response): Promise<any> {
async function loadPrizeConfig() {
prizeConfigLoading.value = true;
try {
const res = await fetch('/api/admin/prizes');
const res = await fetch('/api/admin/prizes', {
headers: getAdminHeaders(),
});
const data = await readJsonSafe(res);
if (!res.ok) {
throw new Error(data?.error || data?.message || `加载奖项配置失败(${res.status})`);
@@ -112,7 +124,7 @@ async function savePrizeConfig() {
try {
const res = await fetch('/api/admin/prizes', {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
headers: getAdminHeaders(),
body: JSON.stringify({ prizes: editingPrizes.value }),
});
const data = await readJsonSafe(res);
@@ -172,6 +184,7 @@ async function importParticipants() {
const response = await fetch('/api/admin/participants/import', {
method: 'POST',
headers: { 'x-session-token': adminToken() },
body: formData,
});
@@ -219,7 +232,9 @@ const tagLabels: Record<string, string> = {
// Load existing participants from server
async function loadParticipants() {
try {
const response = await fetch('/api/admin/participants');
const response = await fetch('/api/admin/participants', {
headers: getAdminHeaders(),
});
const data = await readJsonSafe(response);
if (!response.ok) {
throw new Error(data?.error || data?.message || `加载参与者失败(${response.status})`);
@@ -331,7 +346,7 @@ async function redrawCurrentRound() {
try {
const res = await fetch('/api/admin/lottery/redraw', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
headers: getAdminHeaders(),
});
const data = await res.json();
if (data.success) {
@@ -386,7 +401,7 @@ async function confirmAdvancedCleanup() {
try {
const res = await fetch('/api/admin/cleanup', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
headers: getAdminHeaders(),
body: JSON.stringify({
lottery: cleanupOptions.value.lottery,
voting: cleanupOptions.value.voting,