feat: WC2026 赛事 seed、生产上线初始化脚本与目录归档
重构 seed 为 WC2026 72 场小组赛与 48 强优胜盘;新增 production 模式仅保留 admin 与赛事示例;提供 prod-init-db 全量重置脚本;管理端 i18n 分包与赛事归档能力。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -59,6 +59,33 @@ function selectMethod(m: PaymentMethod) {
|
||||
selectedMethod.value = m;
|
||||
}
|
||||
|
||||
const MAX_ORIGINAL_BYTES = 10 * 1024 * 1024;
|
||||
const MAX_SCREENSHOT_BYTES = 1024 * 1024;
|
||||
|
||||
async function compressScreenshot(file: File): Promise<File> {
|
||||
const baseOptions = {
|
||||
maxSizeMB: 1,
|
||||
maxWidthOrHeight: 1920,
|
||||
useWebWorker: true,
|
||||
maxIteration: 15,
|
||||
} as const;
|
||||
|
||||
const attempts = [
|
||||
{ ...baseOptions, initialQuality: 0.85 },
|
||||
{ ...baseOptions, initialQuality: 0.65, maxWidthOrHeight: 1600 },
|
||||
{ ...baseOptions, initialQuality: 0.5, maxWidthOrHeight: 1280 },
|
||||
];
|
||||
|
||||
for (const options of attempts) {
|
||||
const compressed = (await imageCompression(file, options)) as File;
|
||||
if (compressed.size <= MAX_SCREENSHOT_BYTES) {
|
||||
return compressed;
|
||||
}
|
||||
}
|
||||
|
||||
throw new Error('COMPRESS_TOO_LARGE');
|
||||
}
|
||||
|
||||
async function handleFileChange(event: Event) {
|
||||
const input = event.target as HTMLInputElement;
|
||||
const file = input.files?.[0];
|
||||
@@ -70,27 +97,22 @@ async function handleFileChange(event: Event) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Max 10MB before compression
|
||||
if (file.size > 10 * 1024 * 1024) {
|
||||
if (file.size > MAX_ORIGINAL_BYTES) {
|
||||
alert(t('recharge.file_too_large'));
|
||||
input.value = '';
|
||||
return;
|
||||
}
|
||||
|
||||
// Compress image
|
||||
compressing.value = true;
|
||||
try {
|
||||
const compressed = await imageCompression(file, {
|
||||
maxSizeMB: 1,
|
||||
maxWidthOrHeight: 1920,
|
||||
useWebWorker: true,
|
||||
});
|
||||
screenshotFile.value = compressed as File;
|
||||
const compressed = await compressScreenshot(file);
|
||||
screenshotFile.value = compressed;
|
||||
screenshotPreview.value = URL.createObjectURL(compressed);
|
||||
} catch {
|
||||
// Fallback: use original if compression fails
|
||||
screenshotFile.value = file;
|
||||
screenshotPreview.value = URL.createObjectURL(file);
|
||||
alert(t('recharge.compress_failed'));
|
||||
screenshotFile.value = null;
|
||||
screenshotPreview.value = '';
|
||||
input.value = '';
|
||||
} finally {
|
||||
compressing.value = false;
|
||||
}
|
||||
@@ -115,6 +137,10 @@ async function handleSubmit() {
|
||||
alert(t('recharge.upload_screenshot'));
|
||||
return;
|
||||
}
|
||||
if (screenshotFile.value.size > MAX_SCREENSHOT_BYTES) {
|
||||
alert(t('recharge.compress_failed'));
|
||||
return;
|
||||
}
|
||||
|
||||
submitting.value = true;
|
||||
try {
|
||||
|
||||
Reference in New Issue
Block a user