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:
@@ -112,7 +112,7 @@ const FALLBACK_FOUNDER_QUOTE = {
|
||||
// 排版约束:3 行均势(17 / 18 / 13 字),避开"量。"孤儿字。
|
||||
// 配合 blockquote 的 whitespace-pre-line 渲染换行。
|
||||
text: '我们相信,数字化不是一次性项目,\n而是持续迭代的能力建设。\n每一份投入,都应当经得起衡量。',
|
||||
name: 'Novalon 创始团队',
|
||||
name: '睿新致远创始团队',
|
||||
role: '技术咨询 · 数字化转型同行者',
|
||||
};
|
||||
|
||||
@@ -255,7 +255,7 @@ function HeroSection({ heroData }: {
|
||||
className={`group inline-flex items-center gap-2 text-sm font-medium transition-colors duration-200 py-4 ${dark ? 'text-white/70 hover:text-white' : 'text-text-secondary hover:text-ink'}`}
|
||||
>
|
||||
{secondaryCtaLabel}
|
||||
<ArrowRight className="w-4 h-4 transition-transform duration-300 group-hover:translate-x-1" />
|
||||
<ArrowRight className="w-4 h-4 transition-transform duration-normal group-hover:translate-x-1" />
|
||||
</a>
|
||||
)}
|
||||
</motion.div>
|
||||
@@ -394,7 +394,7 @@ function NarrativeSection({ pageCopy }: { pageCopy?: HomePageCopy | null }) {
|
||||
<div className="grid md:grid-cols-3 gap-px bg-border-primary">
|
||||
{NARRATIVE_ACTS_CMS.map((act) => (
|
||||
<StaggerReveal key={act.number} staggerDelay={0.05}>
|
||||
<div className="group relative h-full bg-bg-primary p-8 sm:p-10 md:p-12 transition-colors duration-300 hover:bg-bg-secondary">
|
||||
<div className="group relative h-full bg-bg-primary p-8 sm:p-10 md:p-12 transition-colors duration-normal hover:bg-bg-secondary">
|
||||
<div className="flex items-start justify-between mb-8">
|
||||
<span
|
||||
aria-hidden="true"
|
||||
@@ -403,7 +403,7 @@ function NarrativeSection({ pageCopy }: { pageCopy?: HomePageCopy | null }) {
|
||||
{act.number}
|
||||
</span>
|
||||
</div>
|
||||
<h3 className="text-xl lg:text-2xl font-bold text-ink mb-4 group-hover:text-brand-ink transition-colors duration-300">
|
||||
<h3 className="text-xl lg:text-2xl font-bold text-ink mb-4 group-hover:text-brand-ink transition-colors duration-normal">
|
||||
{act.title}
|
||||
</h3>
|
||||
<p className="text-text-secondary leading-relaxed mb-8 text-sm">
|
||||
@@ -415,7 +415,7 @@ function NarrativeSection({ pageCopy }: { pageCopy?: HomePageCopy | null }) {
|
||||
className="group/link inline-flex items-center min-h-6 gap-2 text-sm font-semibold text-text-secondary group-hover:text-brand-ink transition-colors"
|
||||
>
|
||||
<span>{act.cta}</span>
|
||||
<ArrowRight className="w-4 h-4 transition-transform duration-300 group-hover/link:translate-x-1" />
|
||||
<ArrowRight className="w-4 h-4 transition-transform duration-normal group-hover/link:translate-x-1" />
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
@@ -464,7 +464,7 @@ function InsightsSection({ pageCopy }: { pageCopy?: HomePageCopy | null }) {
|
||||
className="group inline-flex items-center min-h-6 gap-3 text-ink font-semibold text-sm"
|
||||
>
|
||||
查看全部洞察
|
||||
<ArrowRight className="w-4 h-5 transition-transform duration-300 group-hover:translate-x-2 text-text-secondary group-hover:text-brand-ink" />
|
||||
<ArrowRight className="w-4 h-5 transition-transform duration-normal group-hover:translate-x-2 text-text-secondary group-hover:text-brand-ink" />
|
||||
</StaticLink>
|
||||
</ScrollReveal>
|
||||
</div>
|
||||
@@ -474,7 +474,7 @@ function InsightsSection({ pageCopy }: { pageCopy?: HomePageCopy | null }) {
|
||||
<StaggerReveal key={i} staggerDelay={0.05}>
|
||||
<a
|
||||
href={insight.href}
|
||||
className="group flex flex-col h-full bg-bg-primary p-8 sm:p-10 md:p-12 transition-colors duration-300 hover:bg-bg-secondary"
|
||||
className="group flex flex-col h-full bg-bg-primary p-8 sm:p-10 md:p-12 transition-colors duration-normal hover:bg-bg-secondary"
|
||||
>
|
||||
<div className="flex items-center justify-between mb-8">
|
||||
<span className="text-[13px] tracking-[0.12em] font-semibold text-brand-ink">
|
||||
@@ -484,7 +484,7 @@ function InsightsSection({ pageCopy }: { pageCopy?: HomePageCopy | null }) {
|
||||
<span className="text-xs text-text-muted tabular-nums">{insight.date}</span>
|
||||
)}
|
||||
</div>
|
||||
<h3 className="text-xl lg:text-2xl font-bold text-ink mb-4 leading-[1.25] group-hover:text-brand-ink transition-colors duration-300">
|
||||
<h3 className="text-xl lg:text-2xl font-bold text-ink mb-4 leading-[1.25] group-hover:text-brand-ink transition-colors duration-normal">
|
||||
{insight.title}
|
||||
</h3>
|
||||
<p className="text-text-secondary leading-relaxed mb-8 text-sm flex-1">
|
||||
@@ -493,7 +493,7 @@ function InsightsSection({ pageCopy }: { pageCopy?: HomePageCopy | null }) {
|
||||
<div className="pt-6 border-t border-border-primary">
|
||||
<span className="inline-flex items-center gap-2 text-sm font-semibold text-text-secondary group-hover:text-brand-ink transition-colors">
|
||||
了解详情
|
||||
<ArrowRight className="w-4 h-4 transition-transform duration-300 group-hover:translate-x-1" />
|
||||
<ArrowRight className="w-4 h-4 transition-transform duration-normal group-hover:translate-x-1" />
|
||||
</span>
|
||||
</div>
|
||||
</a>
|
||||
@@ -543,7 +543,7 @@ function ServicesSection({ services, pageCopy }: { services?: Record<string, any
|
||||
</div>
|
||||
<p className="text-text-secondary leading-relaxed mb-8 text-sm">{service.desc}</p>
|
||||
<div className="flex flex-wrap gap-2 mb-8">
|
||||
{service.highlights.map((h: string, j: number) => (
|
||||
{(Array.isArray(service.highlights) ? service.highlights : []).map((h: string, j: number) => (
|
||||
<span key={j} className="px-3 py-1.5 text-xs text-text-muted border border-border-primary font-medium">
|
||||
{h}
|
||||
</span>
|
||||
@@ -565,7 +565,7 @@ function ServicesSection({ services, pageCopy }: { services?: Record<string, any
|
||||
<div className="mt-auto pt-2">
|
||||
<div className="inline-flex items-center gap-2 text-sm font-semibold text-text-secondary group-hover:text-brand-ink transition-colors">
|
||||
<span>了解详情</span>
|
||||
<ArrowRight className="w-4 h-4 transition-transform duration-300 group-hover:translate-x-1" />
|
||||
<ArrowRight className="w-4 h-4 transition-transform duration-normal group-hover:translate-x-1" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -728,7 +728,7 @@ function CasesSection({ cases, pageCopy }: { cases?: Record<string, any>[]; page
|
||||
className="group inline-flex items-center min-h-6 gap-3 text-ink font-semibold text-sm"
|
||||
>
|
||||
查看全部案例
|
||||
<ArrowRight className="w-4 h-5 transition-transform duration-300 group-hover:translate-x-2 text-text-secondary group-hover:text-brand-ink" />
|
||||
<ArrowRight className="w-4 h-5 transition-transform duration-normal group-hover:translate-x-2 text-text-secondary group-hover:text-brand-ink" />
|
||||
</StaticLink>
|
||||
</ScrollReveal>
|
||||
</div>
|
||||
@@ -780,7 +780,7 @@ function CasesSection({ cases, pageCopy }: { cases?: Record<string, any>[]; page
|
||||
<div className="mt-auto pt-6 border-t border-white/10 flex items-center justify-between gap-6 flex-wrap">
|
||||
<span className="inline-flex items-center gap-2 text-sm font-semibold text-white group-hover:text-brand-light transition-colors">
|
||||
查看完整案例
|
||||
<ArrowRight className="w-4 h-4 transition-transform duration-300 group-hover:translate-x-1" />
|
||||
<ArrowRight className="w-4 h-4 transition-transform duration-normal group-hover:translate-x-1" />
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
@@ -825,7 +825,7 @@ function CasesSection({ cases, pageCopy }: { cases?: Record<string, any>[]; page
|
||||
</h3>
|
||||
|
||||
<div className="grid grid-cols-3 gap-4 mb-8">
|
||||
{caseItem.metrics.slice(0, 3).map((metric: Record<string, any>, j: number) => (
|
||||
{(Array.isArray(caseItem.metrics) ? caseItem.metrics : []).slice(0, 3).map((metric: Record<string, any>, j: number) => (
|
||||
<div key={j}>
|
||||
<div className={cn(
|
||||
'text-xl sm:text-2xl font-black leading-none mb-2',
|
||||
@@ -843,7 +843,7 @@ function CasesSection({ cases, pageCopy }: { cases?: Record<string, any>[]; page
|
||||
<div className="mt-auto pt-4 border-t border-border-primary">
|
||||
<div className="inline-flex items-center gap-2 text-sm font-semibold text-text-secondary group-hover:text-brand-ink transition-colors">
|
||||
<span>了解详情</span>
|
||||
<ArrowRight className="w-4 h-4 transition-transform duration-300 group-hover:translate-x-1" />
|
||||
<ArrowRight className="w-4 h-4 transition-transform duration-normal group-hover:translate-x-1" />
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
@@ -884,7 +884,7 @@ function NewsSection({ news, pageCopy }: { news?: NewsItem[]; pageCopy?: HomePag
|
||||
className="group inline-flex items-center min-h-6 gap-3 text-ink font-semibold text-sm"
|
||||
>
|
||||
{ctaLabel}
|
||||
<ArrowRight className="w-4 h-5 transition-transform duration-300 group-hover:translate-x-2 text-text-secondary group-hover:text-brand-ink" />
|
||||
<ArrowRight className="w-4 h-5 transition-transform duration-normal group-hover:translate-x-2 text-text-secondary group-hover:text-brand-ink" />
|
||||
</StaticLink>
|
||||
</ScrollReveal>
|
||||
</div>
|
||||
@@ -905,7 +905,7 @@ function NewsSection({ news, pageCopy }: { news?: NewsItem[]; pageCopy?: HomePag
|
||||
{item.date}
|
||||
</span>
|
||||
</div>
|
||||
<h3 className="text-lg lg:text-xl font-bold text-ink mb-4 leading-[1.3] line-clamp-2 group-hover:text-brand-ink transition-colors duration-300">
|
||||
<h3 className="text-lg lg:text-xl font-bold text-ink mb-4 leading-[1.3] line-clamp-2 group-hover:text-brand-ink transition-colors duration-normal">
|
||||
{item.title}
|
||||
</h3>
|
||||
<p className="text-sm text-text-secondary leading-relaxed mb-6 line-clamp-2 flex-1">
|
||||
@@ -914,7 +914,7 @@ function NewsSection({ news, pageCopy }: { news?: NewsItem[]; pageCopy?: HomePag
|
||||
<div className="pt-4 border-t border-border-primary">
|
||||
<span className="inline-flex items-center gap-2 text-sm font-semibold text-text-secondary group-hover:text-brand-ink transition-colors">
|
||||
阅读全文
|
||||
<ArrowRight className="w-4 h-4 transition-transform duration-300 group-hover:translate-x-1" />
|
||||
<ArrowRight className="w-4 h-4 transition-transform duration-normal group-hover:translate-x-1" />
|
||||
</span>
|
||||
</div>
|
||||
</StaticLink>
|
||||
|
||||
Reference in New Issue
Block a user