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:
@@ -112,10 +112,18 @@ export class PublicService {
|
||||
where: { albumId: album.id, kind: 'banner', state: 'effective' },
|
||||
orderBy: [{ createdAt: 'desc' }, { id: 'desc' }],
|
||||
});
|
||||
const bannerRow =
|
||||
let bannerRow =
|
||||
bannerAssets.find((row) => row.locale === resolved.locale) ??
|
||||
bannerAssets.find((row) => row.locale === null) ??
|
||||
null;
|
||||
// 宣传图/封面共用(用户决策 2026-09-23):banner 缺失回退最新 effective
|
||||
// cover 行(传一张即可两用;与 ov 公开侧同语义)。
|
||||
if (bannerRow === null) {
|
||||
bannerRow = await this.prisma.album_assets.findFirst({
|
||||
where: { albumId: album.id, kind: 'cover', state: 'effective' },
|
||||
orderBy: [{ createdAt: 'desc' }, { id: 'desc' }],
|
||||
});
|
||||
}
|
||||
const banner =
|
||||
bannerRow === null ? null : await this.presign(bannerRow.objectKey);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user