feat(albums): soft-delete albums (admin+owner, hidden & irreversible, both app entries)
契约 deleteAlbum(DELETE /albums/{albumId} → 204 幂等)+ status enum 'deleted':
- 服务端:softDelete(canView 404→canManage 403 防枚举;乐观锁 claim +
outbox album.updated priority=high + audit album.delete);列表/详情/更新/
成员/资产/分类/水印/照片/展示位绑定全部 deleted→404;公开端 cn
(status!=='active')与 ov(isAlbumVisibleOv)天然屏蔽;ov 副本经
album.updated 载荷 status 直投自动下线
- Admin:列表表格操作「删除」+ 详情页头「删除相册」(确认含不可恢复说明)
- App:操作面板「删除相册」(红字、二次确认、成功退回列表并刷新)
- 验证:API 56/56、App 397/397(analyze 0)、admin typecheck/lint/test/build 绿
Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
+113
-16
@@ -32,7 +32,13 @@
|
||||
"navUploads": "Uploads",
|
||||
"navSettings": "Settings",
|
||||
"badgeUploading": "{count} tasks",
|
||||
"@badgeUploading": { "placeholders": { "count": { "type": "int" } } },
|
||||
"@badgeUploading": {
|
||||
"placeholders": {
|
||||
"count": {
|
||||
"type": "int"
|
||||
}
|
||||
}
|
||||
},
|
||||
"albumUploadsOn": "Uploads on",
|
||||
"albumUploadsOff": "Uploads off",
|
||||
"albumPublicOff": "Not public",
|
||||
@@ -116,7 +122,13 @@
|
||||
"actionEdit": "Edit",
|
||||
"membersTitle": "Members",
|
||||
"membersTitleCount": "Members ({count})",
|
||||
"@membersTitleCount": { "placeholders": { "count": { "type": "int" } } },
|
||||
"@membersTitleCount": {
|
||||
"placeholders": {
|
||||
"count": {
|
||||
"type": "int"
|
||||
}
|
||||
}
|
||||
},
|
||||
"ownerGroup": "Owner",
|
||||
"collaboratorsGroup": "Collaborators",
|
||||
"noCollaborators": "No collaborators yet",
|
||||
@@ -127,7 +139,13 @@
|
||||
"newCategory": "New category",
|
||||
"editCategory": "Edit category",
|
||||
"deleteCategoryConfirm": "Delete \"{name}\"? Its photos will become uncategorized.",
|
||||
"@deleteCategoryConfirm": { "placeholders": { "name": { "type": "String" } } },
|
||||
"@deleteCategoryConfirm": {
|
||||
"placeholders": {
|
||||
"name": {
|
||||
"type": "String"
|
||||
}
|
||||
}
|
||||
},
|
||||
"noCategories": "No categories yet",
|
||||
"albumCategories": "Categories",
|
||||
"shareQrTitle": "Share QR code",
|
||||
@@ -143,7 +161,13 @@
|
||||
"memberInvited": "Invited",
|
||||
"removeMember": "Remove member",
|
||||
"removeMemberConfirm": "Remove {name} from this album?",
|
||||
"@removeMemberConfirm": { "placeholders": { "name": { "type": "String" } } },
|
||||
"@removeMemberConfirm": {
|
||||
"placeholders": {
|
||||
"name": {
|
||||
"type": "String"
|
||||
}
|
||||
}
|
||||
},
|
||||
"roleOwner": "Owner",
|
||||
"roleCollaborator": "Collaborator",
|
||||
"selfMarker": " (you)",
|
||||
@@ -183,7 +207,13 @@
|
||||
"queueSummaryWaiting": "waiting",
|
||||
"queueSummaryNeedAttention": "need attention",
|
||||
"queueRowUploadingPercent": "Uploading {percent}%",
|
||||
"@queueRowUploadingPercent": { "placeholders": { "percent": { "type": "int" } } },
|
||||
"@queueRowUploadingPercent": {
|
||||
"placeholders": {
|
||||
"percent": {
|
||||
"type": "int"
|
||||
}
|
||||
}
|
||||
},
|
||||
"queueRowConfirming": "Confirming upload",
|
||||
"queueRowWaitingUpload": "Waiting to upload",
|
||||
"queueRowPreparing": "Preparing photo",
|
||||
@@ -202,9 +232,21 @@
|
||||
"queueEmpty": "No upload tasks",
|
||||
"queueRetryAllFailed": "Retry all failed",
|
||||
"queueAttemptCount": "{count} attempt(s)",
|
||||
"@queueAttemptCount": { "placeholders": { "count": { "type": "int" } } },
|
||||
"@queueAttemptCount": {
|
||||
"placeholders": {
|
||||
"count": {
|
||||
"type": "int"
|
||||
}
|
||||
}
|
||||
},
|
||||
"captureQueued": "{count} queued",
|
||||
"@captureQueued": { "placeholders": { "count": { "type": "int" } } },
|
||||
"@captureQueued": {
|
||||
"placeholders": {
|
||||
"count": {
|
||||
"type": "int"
|
||||
}
|
||||
}
|
||||
},
|
||||
"captureFlipCamera": "Switch camera",
|
||||
"captureFlash": "Flash",
|
||||
"uploadsHistory": "History",
|
||||
@@ -255,17 +297,41 @@
|
||||
"captureCategoryDefault": "Default category",
|
||||
"captureSwitchHint": "Switching only affects photos captured afterwards",
|
||||
"capturePendingBadge": "Pending {count}",
|
||||
"@capturePendingBadge": { "placeholders": { "count": { "type": "int" } } },
|
||||
"@capturePendingBadge": {
|
||||
"placeholders": {
|
||||
"count": {
|
||||
"type": "int"
|
||||
}
|
||||
}
|
||||
},
|
||||
"captureFailedBadge": "Failed {count}",
|
||||
"@captureFailedBadge": { "placeholders": { "count": { "type": "int" } } },
|
||||
"@captureFailedBadge": {
|
||||
"placeholders": {
|
||||
"count": {
|
||||
"type": "int"
|
||||
}
|
||||
}
|
||||
},
|
||||
"capturePickFromGallery": "Pick from gallery",
|
||||
"captureShutter": "Capture",
|
||||
"captureQueuedBadge": "Queued {count}",
|
||||
"@captureQueuedBadge": { "placeholders": { "count": { "type": "int" } } },
|
||||
"@captureQueuedBadge": {
|
||||
"placeholders": {
|
||||
"count": {
|
||||
"type": "int"
|
||||
}
|
||||
}
|
||||
},
|
||||
"captureEnqueuedFeedback": "Added to queue",
|
||||
"captureExitTitle": "Leave shooting?",
|
||||
"captureExitBody": "{count} photo(s) are still uploading. Tasks will continue in the background after you leave.",
|
||||
"@captureExitBody": { "placeholders": { "count": { "type": "int" } } },
|
||||
"@captureExitBody": {
|
||||
"placeholders": {
|
||||
"count": {
|
||||
"type": "int"
|
||||
}
|
||||
}
|
||||
},
|
||||
"captureKeepShooting": "Keep shooting",
|
||||
"captureExitConfirm": "Leave",
|
||||
"cameraPermissionDenied": "Camera unavailable. Allow camera access in system settings",
|
||||
@@ -274,7 +340,13 @@
|
||||
"uploadActionPick": "Pick from gallery",
|
||||
"uploadAction": "Upload",
|
||||
"uploadEnqueuedCount": "Added {count} photo(s) to the upload queue",
|
||||
"@uploadEnqueuedCount": { "placeholders": { "count": { "type": "int" } } },
|
||||
"@uploadEnqueuedCount": {
|
||||
"placeholders": {
|
||||
"count": {
|
||||
"type": "int"
|
||||
}
|
||||
}
|
||||
},
|
||||
"uploadPickNone": "No photos selected",
|
||||
"albumManagePhotos": "Manage photos",
|
||||
"albumTakeFirstPhoto": "Take the first photo",
|
||||
@@ -309,16 +381,41 @@
|
||||
"readonlyMember": "You can browse photos shared by others",
|
||||
"moreActions": "More actions",
|
||||
"photosTitle": "{count} photos",
|
||||
"@photosTitle": { "placeholders": { "count": { "type": "int" } } },
|
||||
"@photosTitle": {
|
||||
"placeholders": {
|
||||
"count": {
|
||||
"type": "int"
|
||||
}
|
||||
}
|
||||
},
|
||||
"photoUploadedBy": "Uploaded by {name}",
|
||||
"@photoUploadedBy": { "placeholders": { "name": { "type": "String" } } },
|
||||
"@photoUploadedBy": {
|
||||
"placeholders": {
|
||||
"name": {
|
||||
"type": "String"
|
||||
}
|
||||
}
|
||||
},
|
||||
"photoDimensions": "{width}×{height}",
|
||||
"@photoDimensions": { "placeholders": { "width": { "type": "int" }, "height": { "type": "int" } } },
|
||||
"@photoDimensions": {
|
||||
"placeholders": {
|
||||
"width": {
|
||||
"type": "int"
|
||||
},
|
||||
"height": {
|
||||
"type": "int"
|
||||
}
|
||||
}
|
||||
},
|
||||
"photoStatus": "Status",
|
||||
"photoHideAction": "Hide photo",
|
||||
"photoPublishAction": "Publish again",
|
||||
"shareScanHint": "Scan to view photos",
|
||||
"shareNotPublic": "This link is not publicly accessible yet",
|
||||
"hidePhotoTitle": "Hide this photo?",
|
||||
"hidePhotoBody": "Viewers will no longer see this photo. Authorized album managers can publish it again."
|
||||
"hidePhotoBody": "Viewers will no longer see this photo. Authorized album managers can publish it again.",
|
||||
"deleteAlbum": "Delete album",
|
||||
"deleteAlbumConfirmTitle": "Delete this album?",
|
||||
"deleteAlbumConfirmBody": "The album becomes invisible immediately and cannot be restored. Data is retained; recovery requires operations.",
|
||||
"albumDeleted": "Album deleted"
|
||||
}
|
||||
|
||||
@@ -1933,6 +1933,30 @@ abstract class AppLocalizations {
|
||||
/// In zh, this message translates to:
|
||||
/// **'观众将不再看到这张照片。相册管理者可重新发布。'**
|
||||
String get hidePhotoBody;
|
||||
|
||||
/// No description provided for @deleteAlbum.
|
||||
///
|
||||
/// In zh, this message translates to:
|
||||
/// **'删除相册'**
|
||||
String get deleteAlbum;
|
||||
|
||||
/// No description provided for @deleteAlbumConfirmTitle.
|
||||
///
|
||||
/// In zh, this message translates to:
|
||||
/// **'删除这个相册?'**
|
||||
String get deleteAlbumConfirmTitle;
|
||||
|
||||
/// No description provided for @deleteAlbumConfirmBody.
|
||||
///
|
||||
/// In zh, this message translates to:
|
||||
/// **'删除后立即不可见且不可恢复。数据保留,恢复需运维处理。'**
|
||||
String get deleteAlbumConfirmBody;
|
||||
|
||||
/// No description provided for @albumDeleted.
|
||||
///
|
||||
/// In zh, this message translates to:
|
||||
/// **'相册已删除'**
|
||||
String get albumDeleted;
|
||||
}
|
||||
|
||||
class _AppLocalizationsDelegate
|
||||
|
||||
@@ -987,4 +987,17 @@ class AppLocalizationsEn extends AppLocalizations {
|
||||
@override
|
||||
String get hidePhotoBody =>
|
||||
'Viewers will no longer see this photo. Authorized album managers can publish it again.';
|
||||
|
||||
@override
|
||||
String get deleteAlbum => 'Delete album';
|
||||
|
||||
@override
|
||||
String get deleteAlbumConfirmTitle => 'Delete this album?';
|
||||
|
||||
@override
|
||||
String get deleteAlbumConfirmBody =>
|
||||
'The album becomes invisible immediately and cannot be restored. Data is retained; recovery requires operations.';
|
||||
|
||||
@override
|
||||
String get albumDeleted => 'Album deleted';
|
||||
}
|
||||
|
||||
@@ -956,4 +956,16 @@ class AppLocalizationsZh extends AppLocalizations {
|
||||
|
||||
@override
|
||||
String get hidePhotoBody => '观众将不再看到这张照片。相册管理者可重新发布。';
|
||||
|
||||
@override
|
||||
String get deleteAlbum => '删除相册';
|
||||
|
||||
@override
|
||||
String get deleteAlbumConfirmTitle => '删除这个相册?';
|
||||
|
||||
@override
|
||||
String get deleteAlbumConfirmBody => '删除后立即不可见且不可恢复。数据保留,恢复需运维处理。';
|
||||
|
||||
@override
|
||||
String get albumDeleted => '相册已删除';
|
||||
}
|
||||
|
||||
+113
-16
@@ -32,7 +32,13 @@
|
||||
"navUploads": "上传",
|
||||
"navSettings": "设置",
|
||||
"badgeUploading": "{count} 个任务",
|
||||
"@badgeUploading": { "placeholders": { "count": { "type": "int" } } },
|
||||
"@badgeUploading": {
|
||||
"placeholders": {
|
||||
"count": {
|
||||
"type": "int"
|
||||
}
|
||||
}
|
||||
},
|
||||
"albumUploadsOn": "开放上传",
|
||||
"albumUploadsOff": "上传已关闭",
|
||||
"albumPublicOff": "未公开",
|
||||
@@ -116,7 +122,13 @@
|
||||
"actionEdit": "编辑",
|
||||
"membersTitle": "成员",
|
||||
"membersTitleCount": "成员({count})",
|
||||
"@membersTitleCount": { "placeholders": { "count": { "type": "int" } } },
|
||||
"@membersTitleCount": {
|
||||
"placeholders": {
|
||||
"count": {
|
||||
"type": "int"
|
||||
}
|
||||
}
|
||||
},
|
||||
"ownerGroup": "创建者",
|
||||
"collaboratorsGroup": "协作者",
|
||||
"noCollaborators": "还没有协作者",
|
||||
@@ -127,7 +139,13 @@
|
||||
"newCategory": "新增分类",
|
||||
"editCategory": "编辑分类",
|
||||
"deleteCategoryConfirm": "删除「{name}」?该分类下的照片将变为未分类。",
|
||||
"@deleteCategoryConfirm": { "placeholders": { "name": { "type": "String" } } },
|
||||
"@deleteCategoryConfirm": {
|
||||
"placeholders": {
|
||||
"name": {
|
||||
"type": "String"
|
||||
}
|
||||
}
|
||||
},
|
||||
"noCategories": "暂无分类",
|
||||
"albumCategories": "分类管理",
|
||||
"shareQrTitle": "分享二维码",
|
||||
@@ -143,7 +161,13 @@
|
||||
"memberInvited": "已邀请",
|
||||
"removeMember": "移除成员",
|
||||
"removeMemberConfirm": "确定将 {name} 从该相册移除?",
|
||||
"@removeMemberConfirm": { "placeholders": { "name": { "type": "String" } } },
|
||||
"@removeMemberConfirm": {
|
||||
"placeholders": {
|
||||
"name": {
|
||||
"type": "String"
|
||||
}
|
||||
}
|
||||
},
|
||||
"roleOwner": "创建者",
|
||||
"roleCollaborator": "协作者",
|
||||
"selfMarker": "(我)",
|
||||
@@ -183,7 +207,13 @@
|
||||
"queueSummaryWaiting": "等待中",
|
||||
"queueSummaryNeedAttention": "需关注",
|
||||
"queueRowUploadingPercent": "上传中 {percent}%",
|
||||
"@queueRowUploadingPercent": { "placeholders": { "percent": { "type": "int" } } },
|
||||
"@queueRowUploadingPercent": {
|
||||
"placeholders": {
|
||||
"percent": {
|
||||
"type": "int"
|
||||
}
|
||||
}
|
||||
},
|
||||
"queueRowConfirming": "正在确认上传",
|
||||
"queueRowWaitingUpload": "等待上传",
|
||||
"queueRowPreparing": "正在准备照片",
|
||||
@@ -202,9 +232,21 @@
|
||||
"queueEmpty": "暂无上传任务",
|
||||
"queueRetryAllFailed": "一键重试全部失败",
|
||||
"queueAttemptCount": "已尝试 {count} 次",
|
||||
"@queueAttemptCount": { "placeholders": { "count": { "type": "int" } } },
|
||||
"@queueAttemptCount": {
|
||||
"placeholders": {
|
||||
"count": {
|
||||
"type": "int"
|
||||
}
|
||||
}
|
||||
},
|
||||
"captureQueued": "{count} 张待传",
|
||||
"@captureQueued": { "placeholders": { "count": { "type": "int" } } },
|
||||
"@captureQueued": {
|
||||
"placeholders": {
|
||||
"count": {
|
||||
"type": "int"
|
||||
}
|
||||
}
|
||||
},
|
||||
"captureFlipCamera": "切换前后摄像头",
|
||||
"captureFlash": "闪光灯",
|
||||
"uploadsHistory": "历史记录",
|
||||
@@ -255,17 +297,41 @@
|
||||
"captureCategoryDefault": "默认分类",
|
||||
"captureSwitchHint": "切换分类仅影响之后拍摄的照片",
|
||||
"capturePendingBadge": "待传 {count}",
|
||||
"@capturePendingBadge": { "placeholders": { "count": { "type": "int" } } },
|
||||
"@capturePendingBadge": {
|
||||
"placeholders": {
|
||||
"count": {
|
||||
"type": "int"
|
||||
}
|
||||
}
|
||||
},
|
||||
"captureFailedBadge": "失败 {count}",
|
||||
"@captureFailedBadge": { "placeholders": { "count": { "type": "int" } } },
|
||||
"@captureFailedBadge": {
|
||||
"placeholders": {
|
||||
"count": {
|
||||
"type": "int"
|
||||
}
|
||||
}
|
||||
},
|
||||
"capturePickFromGallery": "从相册选择",
|
||||
"captureShutter": "拍摄",
|
||||
"captureQueuedBadge": "待传 {count}",
|
||||
"@captureQueuedBadge": { "placeholders": { "count": { "type": "int" } } },
|
||||
"@captureQueuedBadge": {
|
||||
"placeholders": {
|
||||
"count": {
|
||||
"type": "int"
|
||||
}
|
||||
}
|
||||
},
|
||||
"captureEnqueuedFeedback": "已加入队列",
|
||||
"captureExitTitle": "退出拍摄?",
|
||||
"captureExitBody": "还有 {count} 张照片未上传,退出后任务将在后台继续。",
|
||||
"@captureExitBody": { "placeholders": { "count": { "type": "int" } } },
|
||||
"@captureExitBody": {
|
||||
"placeholders": {
|
||||
"count": {
|
||||
"type": "int"
|
||||
}
|
||||
}
|
||||
},
|
||||
"captureKeepShooting": "继续拍摄",
|
||||
"captureExitConfirm": "退出",
|
||||
"cameraPermissionDenied": "无法访问相机,请在系统设置中允许相机权限",
|
||||
@@ -274,7 +340,13 @@
|
||||
"uploadActionPick": "从相册选择",
|
||||
"uploadAction": "上传",
|
||||
"uploadEnqueuedCount": "已加入 {count} 张上传队列",
|
||||
"@uploadEnqueuedCount": { "placeholders": { "count": { "type": "int" } } },
|
||||
"@uploadEnqueuedCount": {
|
||||
"placeholders": {
|
||||
"count": {
|
||||
"type": "int"
|
||||
}
|
||||
}
|
||||
},
|
||||
"uploadPickNone": "未选择照片",
|
||||
"albumManagePhotos": "管理照片",
|
||||
"albumTakeFirstPhoto": "拍摄第一张照片",
|
||||
@@ -309,16 +381,41 @@
|
||||
"readonlyMember": "您可以浏览其他人分享的照片",
|
||||
"moreActions": "更多操作",
|
||||
"photosTitle": "{count} 张照片",
|
||||
"@photosTitle": { "placeholders": { "count": { "type": "int" } } },
|
||||
"@photosTitle": {
|
||||
"placeholders": {
|
||||
"count": {
|
||||
"type": "int"
|
||||
}
|
||||
}
|
||||
},
|
||||
"photoUploadedBy": "上传者 {name}",
|
||||
"@photoUploadedBy": { "placeholders": { "name": { "type": "String" } } },
|
||||
"@photoUploadedBy": {
|
||||
"placeholders": {
|
||||
"name": {
|
||||
"type": "String"
|
||||
}
|
||||
}
|
||||
},
|
||||
"photoDimensions": "{width}×{height}",
|
||||
"@photoDimensions": { "placeholders": { "width": { "type": "int" }, "height": { "type": "int" } } },
|
||||
"@photoDimensions": {
|
||||
"placeholders": {
|
||||
"width": {
|
||||
"type": "int"
|
||||
},
|
||||
"height": {
|
||||
"type": "int"
|
||||
}
|
||||
}
|
||||
},
|
||||
"photoStatus": "状态",
|
||||
"photoHideAction": "隐藏照片",
|
||||
"photoPublishAction": "重新发布",
|
||||
"shareScanHint": "扫码查看照片",
|
||||
"shareNotPublic": "该链接目前无法公开浏览",
|
||||
"hidePhotoTitle": "隐藏这张照片?",
|
||||
"hidePhotoBody": "观众将不再看到这张照片。相册管理者可重新发布。"
|
||||
"hidePhotoBody": "观众将不再看到这张照片。相册管理者可重新发布。",
|
||||
"deleteAlbum": "删除相册",
|
||||
"deleteAlbumConfirmTitle": "删除这个相册?",
|
||||
"deleteAlbumConfirmBody": "删除后立即不可见且不可恢复。数据保留,恢复需运维处理。",
|
||||
"albumDeleted": "相册已删除"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user