feat(review): 全站统一「审核盾」徽章 + 灰盾点击手动提交兜底
火山人像审核状态此前三处文案各异(已审核/通过/审核✓…)。统一成一个共享 ReviewBadge: 全色填充盾(无对勾叉)+ 文案 + hover 气泡说明,4 态: 🟢已过审(active) / 🔴未过审(failed) / 🟠审核中(processing,橙盾光扫动画) / ⚪待审核(空) 灰盾(未送审)可点 → 提交审核(兜底,不加固定按钮):后端新增 POST /api/assets/{id}/submit-review/ (团队级,仅送审三类),前端点击乐观置 processing。气泡组件顺带成为全站首个统一 tooltip。 - 后端 submit-review 端点 + 单测(送审类 200 / 非送审类 400) - 共享 components/review-badge.{tsx,css}(盾用 SVG 蒙版填色 + 橙态 rv-sweep 光扫) - 资产库详情弹窗 / 商品详情素材组弹窗 / 视频流程基础资产 三处全换成它(各自接 onSubmit) 验收:assets 16 测绿;tsc+build 绿;无头核对四态(灰可点+气泡/绿已过审/橙审核中不可点)、0 console error Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,84 @@
|
||||
/* 火山人像审核盾 · 全站统一徽章 · 仅用 design token */
|
||||
.review-badge {
|
||||
position: relative;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
height: 22px;
|
||||
padding: 0 8px;
|
||||
border-radius: var(--r-pill);
|
||||
border: 1px solid transparent;
|
||||
font-size: 11.5px;
|
||||
font-weight: 500;
|
||||
letter-spacing: .02em;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
/* 盾形:用 SVG 蒙版裁出盾,background 填当前态颜色(全色填充,无对勾/叉) */
|
||||
.review-badge .rv-shield {
|
||||
width: 12px;
|
||||
height: 13px;
|
||||
flex-shrink: 0;
|
||||
background: currentColor;
|
||||
-webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10Z'/%3E%3C/svg%3E") center / contain no-repeat;
|
||||
mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10Z'/%3E%3C/svg%3E") center / contain no-repeat;
|
||||
}
|
||||
|
||||
.review-badge.rv-pass { color: var(--accent-forest); background: var(--forest-bg); border-color: var(--forest-bd); }
|
||||
.review-badge.rv-fail { color: var(--accent-crimson); background: var(--crimson-bg); border-color: var(--crimson-bd); }
|
||||
.review-badge.rv-proc { color: var(--heat); background: var(--heat-12); border-color: var(--heat-20); }
|
||||
.review-badge.rv-idle { color: var(--black-alpha-56); background: var(--black-alpha-4); border-color: var(--border-faint); }
|
||||
|
||||
/* 审核中:橙盾上一道亮光从左扫到右(蒙版只让盾发亮,柔和不闪) */
|
||||
.review-badge.rv-proc .rv-shield {
|
||||
background: linear-gradient(100deg, var(--heat) 38%, #ffe0c2 50%, var(--heat) 62%);
|
||||
background-size: 250% 100%;
|
||||
animation: rv-sweep 1.5s linear infinite;
|
||||
}
|
||||
@keyframes rv-sweep { from { background-position: 150% 0; } to { background-position: -150% 0; } }
|
||||
|
||||
/* 灰盾可点 → 提交审核 */
|
||||
.review-badge.clickable { cursor: pointer; }
|
||||
.review-badge.clickable:hover { border-color: var(--black-alpha-24); color: var(--accent-black); }
|
||||
|
||||
/* hover 气泡说明(全站统一气泡) */
|
||||
.review-pop {
|
||||
position: absolute;
|
||||
bottom: calc(100% + 8px);
|
||||
left: 50%;
|
||||
transform: translateX(-50%) translateY(4px);
|
||||
width: max-content;
|
||||
max-width: 240px;
|
||||
padding: 8px 10px;
|
||||
background: var(--surface);
|
||||
border: 1px solid var(--border-faint);
|
||||
border-radius: var(--r-md);
|
||||
box-shadow: 0 12px 32px rgba(0, 0, 0, .14);
|
||||
font-size: 12px;
|
||||
font-weight: 400;
|
||||
line-height: 1.5;
|
||||
color: var(--accent-black);
|
||||
letter-spacing: 0;
|
||||
white-space: normal;
|
||||
text-align: left;
|
||||
opacity: 0;
|
||||
visibility: hidden;
|
||||
transition: opacity var(--t-base, .15s), transform var(--t-base, .15s), visibility var(--t-base, .15s);
|
||||
pointer-events: none;
|
||||
z-index: 60;
|
||||
}
|
||||
.review-pop::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 100%;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
border: 5px solid transparent;
|
||||
border-top-color: var(--surface);
|
||||
}
|
||||
.review-badge:hover .review-pop,
|
||||
.review-badge:focus-within .review-pop {
|
||||
opacity: 1;
|
||||
visibility: visible;
|
||||
transform: translateX(-50%) translateY(0);
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
import "./review-badge.css";
|
||||
|
||||
// 火山人像合规审核盾(全站统一):全绿=已过审 / 全红=未过审 / 橙光扫=审核中 / 全灰=待审核。
|
||||
// 灰盾(未送审)可点 → 提交审核(兜底,火山很快)。只在送审类(角色/三视图/分镜)上用。
|
||||
export type ReviewStatus = "active" | "failed" | "processing" | "" | undefined;
|
||||
|
||||
const META: Record<string, { label: string; cls: string }> = {
|
||||
active: { label: "已过审", cls: "rv-pass" },
|
||||
failed: { label: "未过审", cls: "rv-fail" },
|
||||
processing: { label: "审核中", cls: "rv-proc" },
|
||||
"": { label: "待审核", cls: "rv-idle" }
|
||||
};
|
||||
|
||||
export function ReviewBadge({ status, onSubmit, error, busy }: {
|
||||
status: ReviewStatus;
|
||||
onSubmit?: () => void; // 仅灰盾(待审核)时点击触发提交
|
||||
error?: string; // 未过审原因(气泡里显)
|
||||
busy?: boolean; // 提交中
|
||||
}) {
|
||||
const key = status || "";
|
||||
const meta = META[key] || META[""];
|
||||
const clickable = key === "" && !!onSubmit && !busy;
|
||||
const hint =
|
||||
key === "active" ? "火山人像合规审核 · 已通过,可安全用于视频生成"
|
||||
: key === "failed" ? `火山人像合规审核 · 未通过${error ? " · " + error : ",建议改提示词重新生成"}`
|
||||
: key === "processing" ? "火山人像合规审核 · 审核中,通常很快"
|
||||
: clickable ? "尚未送审 · 点击立即提交火山人像审核"
|
||||
: "尚未送审 · 含人脸的视频素材需过火山人像审核";
|
||||
return (
|
||||
<span
|
||||
className={`review-badge ${meta.cls}${clickable ? " clickable" : ""}`}
|
||||
role={clickable ? "button" : undefined}
|
||||
tabIndex={clickable ? 0 : undefined}
|
||||
onClick={clickable ? (e) => { e.stopPropagation(); onSubmit!(); } : undefined}
|
||||
onKeyDown={clickable ? (e) => { if (e.key === "Enter" || e.key === " ") { e.preventDefault(); e.stopPropagation(); onSubmit!(); } } : undefined}
|
||||
>
|
||||
<span className="rv-shield" aria-hidden="true" />
|
||||
<span className="rv-label">{busy ? "提交中…" : meta.label}</span>
|
||||
<span className="review-pop" role="tooltip">{hint}</span>
|
||||
</span>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user