From 9a40769e0d21560f5feb9505d6db67b73b9659bf Mon Sep 17 00:00:00 2001 From: hailin Date: Fri, 6 Mar 2026 10:11:07 -0800 Subject: [PATCH] fix(admin-web): remove double-upload on app version page - Remove auto-parse on file select (was uploading 48MB twice, took 100+ sec) - Backend /upload already parses APK internally, version fields are now optional - Show file name + size after selection - Show progress hint during upload - Better error extraction from API response - Clear error when new file is selected Co-Authored-By: Claude Sonnet 4.6 --- frontend/admin-web/src/i18n/locales.ts | 3 + .../app-versions/AppVersionManagementPage.tsx | 57 +++++++++---------- 2 files changed, 29 insertions(+), 31 deletions(-) diff --git a/frontend/admin-web/src/i18n/locales.ts b/frontend/admin-web/src/i18n/locales.ts index 428fac9..8462b3e 100644 --- a/frontend/admin-web/src/i18n/locales.ts +++ b/frontend/admin-web/src/i18n/locales.ts @@ -152,6 +152,7 @@ const translations: Record> = { 'app_version_upload_file': '选择 APK/IPA 文件', 'app_version_parsing': '解析中...', 'app_version_uploading': '上传中...', + 'optional_auto_from_apk': '选填,自动从安装包提取', 'app_version_confirm_delete': '确定删除此版本?此操作不可撤销。', 'app_version_no_versions': '暂无版本记录', 'app_version_edit': '编辑版本', @@ -918,6 +919,7 @@ const translations: Record> = { 'app_version_upload_file': 'Select APK/IPA File', 'app_version_parsing': 'Parsing...', 'app_version_uploading': 'Uploading...', + 'optional_auto_from_apk': 'optional, auto-extracted from package', 'app_version_confirm_delete': 'Delete this version? This action cannot be undone.', 'app_version_no_versions': 'No versions found', 'app_version_edit': 'Edit Version', @@ -1684,6 +1686,7 @@ const translations: Record> = { 'app_version_upload_file': 'APK/IPAファイルを選択', 'app_version_parsing': '解析中...', 'app_version_uploading': 'アップロード中...', + 'optional_auto_from_apk': '省略可、パッケージから自動抽出', 'app_version_confirm_delete': 'このバージョンを削除しますか?この操作は元に戻せません。', 'app_version_no_versions': 'バージョンが見つかりません', 'app_version_edit': 'バージョンを編集', diff --git a/frontend/admin-web/src/views/app-versions/AppVersionManagementPage.tsx b/frontend/admin-web/src/views/app-versions/AppVersionManagementPage.tsx index f824284..ec89949 100644 --- a/frontend/admin-web/src/views/app-versions/AppVersionManagementPage.tsx +++ b/frontend/admin-web/src/views/app-versions/AppVersionManagementPage.tsx @@ -299,40 +299,21 @@ const UploadModal: React.FC<{ const [changelog, setChangelog] = useState(''); const [minOsVersion, setMinOsVersion] = useState(''); const [isForceUpdate, setIsForceUpdate] = useState(false); - const [parsing, setParsing] = useState(false); const [uploading, setUploading] = useState(false); const [error, setError] = useState(''); - const handleFileChange = async (e: React.ChangeEvent) => { + const handleFileChange = (e: React.ChangeEvent) => { const f = e.target.files?.[0]; if (!f) return; setFile(f); - - // Auto-detect platform + setError(''); + // Auto-detect platform from extension if (f.name.endsWith('.apk')) setPlatform('ANDROID'); else if (f.name.endsWith('.ipa')) setPlatform('IOS'); - - // Auto-parse - setParsing(true); - try { - const formData = new FormData(); - formData.append('file', f); - const info = await apiClient.post<{ - versionCode?: number; versionName?: string; minSdkVersion?: string; - }>('/api/v1/admin/versions/parse', formData, { - timeout: 120000, - }); - if (info?.versionName) setVersionName(info.versionName); - if (info?.versionCode) setBuildNumber(String(info.versionCode)); - if (info?.minSdkVersion) setMinOsVersion(info.minSdkVersion); - } catch { - // Parsing failed, allow manual entry - } - setParsing(false); }; const handleSubmit = async () => { - if (!file || !versionName) { + if (!file) { setError(t('app_version_upload_file')); return; } @@ -343,10 +324,10 @@ const UploadModal: React.FC<{ formData.append('file', file); formData.append('appType', appType); formData.append('platform', platform); - formData.append('versionName', versionName); - formData.append('buildNumber', buildNumber || '1'); - formData.append('changelog', changelog); - formData.append('minOsVersion', minOsVersion); + if (versionName) formData.append('versionName', versionName); + if (buildNumber) formData.append('buildNumber', buildNumber); + if (changelog) formData.append('changelog', changelog); + if (minOsVersion) formData.append('minOsVersion', minOsVersion); formData.append('isForceUpdate', String(isForceUpdate)); await apiClient.post('/api/v1/admin/versions/upload', formData, { @@ -354,7 +335,7 @@ const UploadModal: React.FC<{ }); onSuccess(); } catch (err: any) { - setError(err?.message || 'Upload failed'); + setError(err?.response?.data?.message || err?.message || 'Upload failed'); } setUploading(false); }; @@ -370,7 +351,11 @@ const UploadModal: React.FC<{ onChange={handleFileChange} style={{ ...inputStyle, padding: '8px 12px', height: 'auto' }} /> - {parsing &&
{t('app_version_parsing')}
} + {file && ( +
+ {file.name} ({(file.size / 1024 / 1024).toFixed(1)} MB) +
+ )}
@@ -382,7 +367,12 @@ const UploadModal: React.FC<{ ))}
- + setVersionName(e.target.value)} placeholder="1.0.0" /> @@ -405,12 +395,17 @@ const UploadModal: React.FC<{ {error &&
{error}
} + {uploading && ( +
+ {t('app_version_uploading_hint') || '正在上传,大文件需要较长时间,请耐心等待...'} +
+ )}
-