From c1869d7314883c5873c4159e5229208f1bc320c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B5=85=E5=BF=B5?= Date: Wed, 23 Sep 2026 11:54:26 +0800 Subject: [PATCH] feat(admin): photo upload in album photos tab (same staging pipeline as app) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 照片页签工具栏加「上传照片」(多选 jpeg/png/heic)→ /v1/uploads init → PUT staging → complete(clientTaskId 幂等;categoryId 随当前分类筛选) - 逐张结果:部分成功语义(成功 N 张 toast + 失败明细前 3 条);完成后 reload - 类型 UploadInitPayload/UploadSession/UploadCompleteResponse + api/uploads.ts - 问题1 修复说明:详情页 404 系并行部署把 2618ad3 server 覆盖回 8e674a9, 已重滚双栈至 ui06-2618ad3(assets 端点恢复 200,详情页零失败请求) Co-Authored-By: Claude Code --- apps/admin/src/api/uploads.ts | 18 +++++ apps/admin/src/locales/langs/en.json | 6 +- apps/admin/src/locales/langs/zh.json | 6 +- apps/admin/src/types/api/album.d.ts | 23 ++++++ .../src/views/albums/detail/AlbumPhotos.vue | 81 +++++++++++++++++++ 5 files changed, 132 insertions(+), 2 deletions(-) create mode 100644 apps/admin/src/api/uploads.ts diff --git a/apps/admin/src/api/uploads.ts b/apps/admin/src/api/uploads.ts new file mode 100644 index 0000000..9d70905 --- /dev/null +++ b/apps/admin/src/api/uploads.ts @@ -0,0 +1,18 @@ +/** + * 照片直传域(对齐 @photo/contracts tags [uploads]): + * init(预签名)→ PUT staging → complete(受理;处理异步)。 + * 管理端「上传照片」与 App 同链路(clientTaskId 幂等)。 + */ +import request from '@/utils/http' + +/** 初始化照片直传(返回 staging 直传凭证) */ +export function fetchInitUpload(data: Api.Album.UploadInitPayload) { + return request.post({ url: '/v1/uploads', data }) +} + +/** 完成直传(服务端核验后受理照片处理;返回 photoId) */ +export function fetchCompleteUpload(uploadId: string) { + return request.post({ + url: `/v1/uploads/${uploadId}/complete` + }) +} diff --git a/apps/admin/src/locales/langs/en.json b/apps/admin/src/locales/langs/en.json index a48ad6b..10eeea5 100644 --- a/apps/admin/src/locales/langs/en.json +++ b/apps/admin/src/locales/langs/en.json @@ -503,7 +503,11 @@ "batchColReason": "Reason", "view": "Details", "selectedCount": "{n} selected", - "onlyPublicSelectable": "Only published photos can be selected" + "onlyPublicSelectable": "Only published photos can be selected", + "upload": "Upload photos", + "uploadBadType": "unsupported type", + "uploadResult": "Uploaded: {ok} ok, {fail} failed", + "uploadResultAllOk": "Uploaded {ok}; visible when processed" }, "transfer": { "entry": "Transfer Owner", diff --git a/apps/admin/src/locales/langs/zh.json b/apps/admin/src/locales/langs/zh.json index 325fdb7..0d51a74 100644 --- a/apps/admin/src/locales/langs/zh.json +++ b/apps/admin/src/locales/langs/zh.json @@ -503,7 +503,11 @@ "batchColReason": "原因", "view": "详情", "selectedCount": "{n} 张已选", - "onlyPublicSelectable": "仅已公开照片可批量选择" + "onlyPublicSelectable": "仅已公开照片可批量选择", + "upload": "上传照片", + "uploadBadType": "类型不支持", + "uploadResult": "上传完成:成功 {ok} 张,失败 {fail} 张", + "uploadResultAllOk": "已上传 {ok} 张,处理完成后显示" }, "transfer": { "entry": "负责人交接", diff --git a/apps/admin/src/types/api/album.d.ts b/apps/admin/src/types/api/album.d.ts index 21dc9ec..e794d6e 100644 --- a/apps/admin/src/types/api/album.d.ts +++ b/apps/admin/src/types/api/album.d.ts @@ -202,6 +202,29 @@ declare namespace Api { /** 照片可见性 */ type PhotoVisibility = 'unpublished' | 'published' | 'hidden' | 'deleted' + /** 照片直传初始化请求(POST /v1/uploads;与 App 同链路) */ + interface UploadInitPayload { + albumId: string + clientTaskId: string + filename: string + bytes: number + contentType: 'image/jpeg' | 'image/png' | 'image/heic' + categoryId?: string + } + + /** 直传会话(init/renew 响应;PUT staging 后 complete 换取处理受理) */ + interface UploadSession { + uploadId: string + objectKey: string + credential: UploadCredential + } + + /** 直传完成响应(受理:处理异步,状态经照片列表 processingState 观察) */ + interface UploadCompleteResponse { + photoId: string + state: string + } + /** 照片处理状态 */ type PhotoProcessingState = 'pending_upload' | 'uploaded' | 'processing' | 'ready' | 'processing_failed' diff --git a/apps/admin/src/views/albums/detail/AlbumPhotos.vue b/apps/admin/src/views/albums/detail/AlbumPhotos.vue index 8bc6695..9a9e71f 100644 --- a/apps/admin/src/views/albums/detail/AlbumPhotos.vue +++ b/apps/admin/src/views/albums/detail/AlbumPhotos.vue @@ -37,6 +37,25 @@ :label="categoryLabel(category)" /> + + {{ t('albumsManage.photos.upload') }} + ({{ uploadingCount }}) + +