fix(qa): 第五轮系统性质量保障缺陷修复 + 单元/集成测试
安全/鉴权:登出清服务端 httpOnly 令牌、登录 IP 限流前置 bcrypt、停用账号 令牌在 6 个内联 role handler 失效、admin/items 存在性 oracle 认证前置、 同意偏好 sanitize fail-closed、api-crypto 按 HTTP 方法判体。 CMS:workflow 状态更新+审计收进交互式 $transaction(失败即回滚)、编辑器 richtext 走 textarea 防换行损毁、array/object 子字段按作用域读写防污染、 about/contact/erp-upgrade 补 ISR revalidate 与路由映射。 UI/a11y:AnimatedCounter 入视口前显起点、CLS 累计上报、MetricCard 动画入 effect 并卸载取消 rAF、后台状态四态映射/搜索防抖+序号守卫/媒体单 input/ 吞错改横幅/表单 label-aria 关联。 新增对应判别性单测与 pagination/rate-limit/client-ip/sanitize/validate-content-data 等模块及 tests-integration 真库集成层。
This commit is contained in:
+31
-97
@@ -25,6 +25,11 @@ body {
|
||||
--color-brand-light: #E04A68;
|
||||
--color-brand-soft: rgba(196, 30, 58, 0.12);
|
||||
--color-brand-bg: #FEF2F4;
|
||||
/* Tailwind 无法对「任意值形式的裸 var()」套用 /NN 透明度修饰符(bg-[var(--color-brand-bg)] 再加 /50
|
||||
编译后 0 条规则,静默失效),故底色通道也要提供 rgb 三元组,配合 tailwind.config.js 的
|
||||
brand.bg = rgb(var(--color-brand-bg-rgb) / <alpha-value>) 让 bg-brand-bg/50 正确生成。
|
||||
254 242 244 = #FEF2F4,alpha 默认 1 时与裸 var() 同色,无视觉漂移。 */
|
||||
--color-brand-bg-rgb: 254 242 244;
|
||||
--color-brand-rgb: 196 30 58;
|
||||
/* 品牌「文字墨色」专用通道(text-brand-ink)。
|
||||
与 --color-brand-rgb 分离的原因:--color-brand-rgb 同时服务 bg-brand / border-brand,
|
||||
@@ -33,6 +38,10 @@ body {
|
||||
深色下取 #F87171(248 113 113):于 #0A0E14/#0F1419/#151B23 分别 6.99/6.69/6.26,全达 AA。 */
|
||||
--color-brand-ink: #C41E3A;
|
||||
--color-brand-ink-rgb: 196 30 58;
|
||||
/* 品牌红文字通道的 hover 档:与 --color-brand-hover(底色通道)分离,
|
||||
暗色下必须提亮,否则 #A01830 压在 #0A0E14 上仅 2.06:1(验收 A-12 残留项)。 */
|
||||
--color-brand-ink-hover: #A01830;
|
||||
--color-brand-ink-hover-rgb: 160 24 48;
|
||||
/* 详情页 Hero badge 的 accent 文字色(accentColor 由各页 hero-themes 传入,
|
||||
经 --badge-accent 自定义属性注入)。浅色 = 原色;深色 = 45% accent + 55% 白的提亮变体
|
||||
—— accentColor 多为深色系(#1e3a5f 等),直接用作深底文字仅 1.65:1 */
|
||||
@@ -76,6 +85,10 @@ body {
|
||||
--color-bg-secondary-rgb: 248 250 252;
|
||||
--color-bg-tertiary: #F1F5F9;
|
||||
--color-bg-section: #F8FAFC;
|
||||
/* 同 --color-brand-bg-rgb 的理由:bg-[var(--color-bg-section)] 再加 /60 这类写法编译后 0 条规则。
|
||||
与 --color-bg-secondary-rgb 当前同值但语义不同(section ≠ secondary),故独立建三元组,
|
||||
避免任一 token 调整时静默串色。248 250 252 = #F8FAFC。 */
|
||||
--color-bg-section-rgb: 248 250 252;
|
||||
--color-bg-hover: #F1F5F9;
|
||||
--color-bg-elevated: #FFFFFF;
|
||||
--color-bg-primary-rgb: 255 255 255;
|
||||
@@ -268,12 +281,14 @@ body {
|
||||
/* ease-out 别名:默认使用水墨曲线(Porsche 风格:快速开始,缓慢结束) */
|
||||
--ease-out: cubic-bezier(0.22, 1, 0.36, 1);
|
||||
|
||||
/* 动效延迟序列(错落动效用) */
|
||||
--stagger-xs: 30ms;
|
||||
--stagger-sm: 60ms;
|
||||
--stagger-md: 100ms;
|
||||
--stagger-lg: 150ms;
|
||||
--stagger-xl: 200ms;
|
||||
/* 动效延迟序列(错落动效用)—— 已删除:--stagger-xs…xl 此前零消费者。
|
||||
全站 stagger 全部由 framer-motion 以「秒」为单位的数值驱动
|
||||
(transition.delay / variants.staggerChildren),CSS 自定义属性无法被
|
||||
transition.delay 读取(除非物质化 getComputedStyle),故令牌在此形同虚设。
|
||||
唯一事实来源改为 JS:src/components/ui/scroll-reveal.tsx(StaggerReveal
|
||||
默认 staggerDelay = 0.05)与 page-transition.tsx。
|
||||
取值区间按 CONTEXT.md「动效设计四原则」4:子元素 stagger 30–60ms、
|
||||
Section 间 stagger 100–150ms。 */
|
||||
|
||||
/* 容器宽度 */
|
||||
--container-max: 1360px;
|
||||
@@ -369,15 +384,6 @@ body {
|
||||
--accordion-trigger-height: 3rem;
|
||||
--accordion-trigger-padding-x: 1rem;
|
||||
|
||||
/* Skeleton 骨架屏 */
|
||||
--skeleton-radius: var(--radius-sm);
|
||||
--skeleton-bg: var(--color-bg-tertiary);
|
||||
|
||||
/* Stats Bar 数据条 */
|
||||
--stats-bar-gap: var(--spacing-2xl);
|
||||
--stats-number-size: var(--font-size-4xl);
|
||||
--stats-label-size: var(--font-size-xs);
|
||||
|
||||
/* === 12 列网格系统(Grid System)=== */
|
||||
--grid-columns: 12;
|
||||
--grid-gap-xs: 0.5rem;
|
||||
@@ -419,6 +425,8 @@ html[data-theme='dark'] {
|
||||
--color-bg-secondary-rgb: 15 20 25;
|
||||
--color-bg-tertiary: #151B23;
|
||||
--color-bg-section: #0F1419;
|
||||
/* 与 :root 的 --color-bg-section-rgb 成对覆写,否则深色下 bg-bg-section/NN 会退回浅色值 */
|
||||
--color-bg-section-rgb: 15 20 25;
|
||||
--color-bg-hover: #151B23;
|
||||
--color-bg-elevated: #151B23;
|
||||
|
||||
@@ -470,7 +478,11 @@ html[data-theme='dark'] {
|
||||
此前只翻了 error-bg,导致深色下白字压浅粉底仅 1.04:1(首页「首批客户共创计划」卡)。 */
|
||||
--color-brand-ink: #F87171;
|
||||
--color-brand-ink-rgb: 248 113 113;
|
||||
--color-brand-ink-hover: #FCA5A5;
|
||||
--color-brand-ink-hover-rgb: 252 165 165;
|
||||
--color-brand-bg: #2A1418;
|
||||
/* 42 20 24 = #2A1418;与上方 --color-brand-bg 同步翻转,否则 bg-brand-bg/NN 在深色下仍是浅粉 */
|
||||
--color-brand-bg-rgb: 42 20 24;
|
||||
|
||||
/* hero 徽章文字:accentColor 直用作深底文字不可读(如 #1e3a5f 于 #0B1119 仅 1.65:1),
|
||||
深色下按 accent 45% + 白 55% 提亮;--badge-accent 未注入时回退到反色墨字。 */
|
||||
@@ -1312,16 +1324,13 @@ p, li, span {
|
||||
/* WCAG 2.5.5 (AAA): 44×44px 触控目标仅作用于移动端导航/页眉/页脚交互元素。
|
||||
原全局选择器会撑大正文行内链接,破坏排版节奏与组件自有的尺寸控制。 */
|
||||
@media (max-width: 768px) {
|
||||
/* MobileTabBar 是 fixed bottom-0 高度 64px,需给 main 与 footer 都留出安全区
|
||||
防止正文/页脚被遮挡("联系我们"等页脚内链接被截问题)。
|
||||
使用 calc + env(safe-area-inset-bottom) 兼容刘海屏/小白条。
|
||||
全站单一 <main>(ClientLayout,2026-09-19 polish 三重 main 收敛后)。 */
|
||||
/* MobileTabBar 是 fixed bottom-0 高度 64px(含 env 安全区),需给页面底部留出等高的避让。
|
||||
全站单一 <main>(ClientLayout)且 <Footer> 就在 main 内,因此这条 padding 是唯一的避让点:
|
||||
此前 main 与 footer 各加一次,safe-area 被算了两遍(验收 R-1,iPhone SE 上底部空 128px+2×inset)。
|
||||
使用 calc + env(safe-area-inset-bottom) 兼容刘海屏/小白条。 */
|
||||
main {
|
||||
padding-bottom: calc(64px + env(safe-area-inset-bottom, 0px));
|
||||
}
|
||||
footer {
|
||||
padding-bottom: calc(64px + env(safe-area-inset-bottom, 0px));
|
||||
}
|
||||
nav a,
|
||||
nav button,
|
||||
header a,
|
||||
@@ -1456,78 +1465,3 @@ p, li, span {
|
||||
.glow-border:hover {
|
||||
animation-play-state: running;
|
||||
}
|
||||
|
||||
/* === CMS RichTextEditor (TipTap) 样式 === */
|
||||
/* 仅用于 CMS Studio 暗色主题,选择器限定在 .rich-text-editor-content */
|
||||
.rich-text-editor-content {
|
||||
min-height: 120px;
|
||||
padding: 0.75rem;
|
||||
color: white;
|
||||
font-size: 0.875rem;
|
||||
line-height: 1.6;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.rich-text-editor-content:empty::before {
|
||||
content: attr(data-placeholder);
|
||||
color: rgba(255, 255, 255, 0.3);
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.rich-text-editor-content h2 {
|
||||
font-size: 1.125rem;
|
||||
font-weight: 600;
|
||||
margin: 0.75rem 0 0.5rem;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.rich-text-editor-content h3 {
|
||||
font-size: 1rem;
|
||||
font-weight: 600;
|
||||
margin: 0.5rem 0 0.375rem;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.rich-text-editor-content p {
|
||||
margin: 0.375rem 0;
|
||||
}
|
||||
|
||||
.rich-text-editor-content ul,
|
||||
.rich-text-editor-content ol {
|
||||
padding-left: 1.25rem;
|
||||
margin: 0.5rem 0;
|
||||
}
|
||||
|
||||
.rich-text-editor-content ul {
|
||||
list-style: disc;
|
||||
}
|
||||
|
||||
.rich-text-editor-content ol {
|
||||
list-style: decimal;
|
||||
}
|
||||
|
||||
.rich-text-editor-content li {
|
||||
margin: 0.25rem 0;
|
||||
}
|
||||
|
||||
.rich-text-editor-content blockquote {
|
||||
border-left: 3px solid var(--color-brand);
|
||||
padding-left: 0.75rem;
|
||||
margin: 0.5rem 0;
|
||||
color: rgba(255, 255, 255, 0.7);
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.rich-text-editor-content a {
|
||||
color: var(--color-brand);
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.rich-text-editor-content strong {
|
||||
font-weight: 600;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.rich-text-editor-content em {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user