fix(test-round): 测试清单一批 bug 修复 + 团队月限额持久化

后端:
- accounts: 团队级月限额持久化(Team.monthly_credit_limit 三态 + PATCH/GET
  /api/auth/team/settings/,刷新不丢,PMC#12);头像上传 500→502 可读错误;
  设备下线真失效(删并重建 token,旧 token 401)
- assets: 审核类目加 model_portrait,消除三视图"无需审核"误报
- ai/projects/products: 模特已有三视图复用、产品三视图同步回商品库
  (metadata.view=three_view)、真人模特三视图回写

前端:
- 商品图删除判断改用真实图片数;团队成员弹窗禁点外部关闭
- 图片预览骨架铺满占位;平台套图左侧栏折叠改导航同款;收件箱长文换行对齐
- 团队月限额改真落库(乐观更新+失败回滚)

测试:新增 TeamSettingsTests(5 条),accounts 全套 36 tests 通过;前端 build 0 error

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
zyc
2026-06-29 18:50:22 +08:00
co-authored by Claude Opus 4.8
parent ca0c3e2300
commit b0b3ac2348
20 changed files with 476 additions and 57 deletions
+4 -2
View File
@@ -128,7 +128,7 @@ export function TeamModal({ open, title, subtitle, icon, close, children, footer
);
}
export function ConfirmModal({ open, title, detail, confirmText, subtitle = "// CONFIRM", icon, onCancel, onConfirm }: {
export function ConfirmModal({ open, title, detail, confirmText, subtitle = "// CONFIRM", icon, onCancel, onConfirm, dismissable = true }: {
open: boolean;
title: string;
detail: string;
@@ -137,13 +137,15 @@ export function ConfirmModal({ open, title, detail, confirmText, subtitle = "//
icon?: ReactNode;
onCancel: () => void;
onConfirm: () => void | Promise<unknown>;
/** 是否允许点击遮罩关闭弹窗。默认 true(保持原有行为);传 false 则点遮罩不响应。 */
dismissable?: boolean;
}) {
useBodyScrollLock(open);
const { mounted, show } = useOverlayTransition(open, onCancel);
if (!mounted) return null;
// 挂到 body:脱离 .content(z-index:1)层叠上下文,遮罩才能盖住头部/侧栏
return createPortal(
<div className={`modal-bg${show ? " show" : ""}`} onClick={onCancel}>
<div className={`modal-bg${show ? " show" : ""}`} onClick={dismissable ? onCancel : undefined}>
<div className="modal" onClick={(event) => event.stopPropagation()}>
<span className="corner-tr">+</span><span className="corner-bl">+</span>
<div className="modal-h"><div className="ic-m">{icon ?? <Shield size={16} />}</div><div className="ti">{title}<span>{subtitle}</span></div></div>