Files
freedakgmail c670b9e454 外包风险评估系统:领域引擎+前端+服务端持久化与生产部署
- 确定性领域引擎(分类/评分/分级/红线/费用/裁决)+LLM(通义千问)语言理解
- 6步评估向导、服务端草稿持久化(跨设备/编辑草稿保护)
- 工作流(草稿→风控→管理层)、RBAC、报告导出、校准、客户/费率/红线/最低工资管理
- 专业图标体系替换全部emoji、看板美化
- 生产化:API_BASE可配置(同源反代)、auth密钥惰性读取修复RBAC
- 444单测+204前端测试+51 e2e
2026-06-13 01:06:39 +08:00

1263 lines
62 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Design Document
## Overview
本设计文档描述**外包项目风险评估 AI 智能体**(System)的技术方案,覆盖 25 条需求(含 Req 19-25 的统一设计系统、数据可视化、便捷评估流程、响应式适配、可访问性、操作反馈与角色化默认视图等 UI/前端需求)。System 是一个 Web 应用,由三部分构成:结构化评分表单、对话式自适应追问、风险评估报告生成与导出,并对评估结果进行持久化存档。
设计的核心原则是**指标体系与评分引擎解耦**:风险模型(维度 / 指标 / 权重 / 评分规则 / 红线)以结构化配置存储,Scoring_Engine 是一台"通用计算器"——读取任意合法配置即可完成评分、归一化、分级与红线校验,新增维度或指标只是一次配置操作,无需改动代码(Req 4、11、14)。
设计目标分解:
- **可配置**:管理员统一维护风险模型,评估者只用不改,配置变更留痕审计(Req 11、12)。
- **可量化**:在定性分级之外输出具体金额的费用/定价测算(Req 8)。
- **可解释**:每个评分项可追溯到维度、指标、评分规则、数据点取值、来源与置信度(Req 18)。
- **可扩展**:分行业知识库分区、可插拔外部数据适配层、地域参数化合规规则集(Req 14、15、16)。
- **可验证**:评分 / 归一化 / 分级 / 红线 / 排序等纯算法逻辑以正确性属性约束,支撑属性化测试。
### Research Notes
设计涉及的关键领域均为系统内部确定性逻辑,研究集中在三处:
1. **线性归一化映射**:需求 4.3 规定当全部纳入计算的指标 Risk_Level 同取 1 时 Risk_Score=0、同取 5 时=100。由于评分项得分 = Risk_Level × 权重,且同级权重归一化后和为 1,加权汇总后的原始分天然落在区间 [1, 5]。因此归一化公式为 `Risk_Score = round((weightedRaw - 1) / (5 - 1) × 100)`。该公式与权重无关地满足端点约束,是设计的基础不变式。
2. **分级区间互斥与完备**:需求 5 定义四个区间 [0,25]、(25,50]、(50,75]、(75,100],采用"左开右闭 + 首段闭"的边界约定,保证任意 0-100 整数恰好落入一级(互斥且完备)。
3. **中国大陆合规规则**:劳务派遣用工比例上限 10%、经济补偿 N 与 N+1、社保缴费基数下限、当地最低工资标准(Req 16)。这些以 Compliance_Rule_Set 配置项形式落地,按 Region 加载,跨境通过新增规则集扩展而不改判定引擎。来源为《劳务派遣暂行规定》《劳动合同法》既有规则(内容用于建模规则结构,不作法律意见)。
## Architecture
System 采用分层架构:表现层(角色化视图)、应用编排层(评估流程编排)、领域引擎层(分类 / 追问 / 评分 / 费用 / 策略 / 报告)、配置与知识层(配置中心 / 知识库 / 合规规则集)、适配层(外部数据)、持久化层。
```mermaid
graph TB
subgraph Presentation[表现层 - 角色化视图]
SalesView[商务/销售视图]
RiskView[风控视图]
MgmtView[管理层看板/组合看板]
ConfigUI[管理员配置界面]
end
subgraph App[应用编排层]
Orchestrator[Assessment Orchestrator 评估流程编排]
AuthZ[角色权限控制 RBAC]
end
subgraph Engines[领域引擎层]
Classifier[Classifier 业务类型/行业识别]
QEngine[Question_Engine 自适应追问]
SEngine[Scoring_Engine 评分/归一化/分级/红线]
CEngine[Cost_Engine 费用测算]
StratEngine[Strategy_Engine 应对策略]
Report[Report_Generator 报告生成/导出]
end
subgraph ConfigLayer[配置与知识层]
ConfigCenter[Config_Center 模型配置中心]
KB[Knowledge_Base 分行业知识库]
Compliance[Compliance_Rule_Set 地域合规规则集]
end
subgraph Adapters[适配层]
ExtAdapter[External_Data_Adapter 可插拔外部数据]
end
subgraph Persistence[持久化层]
AssessmentStore[(Assessment 存储)]
ConfigStore[(配置/模板存储)]
AuditLog[(配置变更审计日志)]
end
Presentation --> AuthZ --> Orchestrator
Orchestrator --> Classifier
Orchestrator --> QEngine
Orchestrator --> SEngine
Orchestrator --> CEngine
Orchestrator --> StratEngine
Orchestrator --> Report
Classifier --> KB
QEngine --> KB
SEngine --> ConfigCenter
SEngine --> Compliance
CEngine --> Compliance
QEngine --> ExtAdapter
ConfigCenter --> ConfigStore
ConfigCenter --> AuditLog
KB --> ConfigStore
Orchestrator --> AssessmentStore
ConfigUI --> AuthZ
```
### 评估流程编排(端到端)
```mermaid
sequenceDiagram
participant U as 评估者
participant O as Orchestrator
participant C as Classifier
participant KB as Knowledge_Base
participant Q as Question_Engine
participant E as External_Data_Adapter
participant S as Scoring_Engine
participant Cost as Cost_Engine
participant St as Strategy_Engine
participant R as Report_Generator
participant DB as Assessment Store
U->>O: 提交项目描述 (+可选 Region)
O->>C: 识别业务类型/行业
C-->>O: 类型/行业 + Confidence
alt Confidence < 0.6
O->>U: 展示 Top3 候选请确认
U-->>O: 确认选择
end
O->>KB: 按 类型×行业 加载 Template
KB-->>O: Template (含继承解析)
O->>O: 实例化 Risk_Model (校验权重/必填)
loop 信息缺口 (≤ 最大追问轮次)
O->>Q: 识别缺口/生成追问
Q->>E: 尝试外部数据取值
E-->>Q: 命中/降级回退
Q->>U: 追问问题
U-->>Q: 回答
end
Q->>Q: 缺口达上限→行业默认值(标注"智能体假设")
O->>S: 评分/归一化/分级/红线
S-->>O: Risk_Score/Risk_Grade/Redline 结果
O->>Cost: 费用测算
O->>St: 可接受性结论 + 应对策略
O->>R: 生成报告
O->>DB: 持久化 Assessment
```
### 关键架构决策
| 决策 | 理由 | 关联需求 |
|------|------|----------|
| 配置驱动的通用评分引擎 | 新增维度/指标/行业零代码改动 | Req 4、11、14 |
| 红线校验独立于分值通道 | 一票否决须优先于分级,且不受 Risk_Score 高低影响 | Req 6 |
| Data_Provenance 三态贯穿全链路 | 可解释性与降级回退的统一载体 | Req 15、18 |
| Region 参数化合规规则集 | 中国先行,跨境靠新增规则集扩展 | Req 16 |
| 适配层接口化 + 超时降级 | 外部源不可用不阻断评估 | Req 15 |
| 前端单一 Design_System 驱动 | 组件/排版/配色/间距/图标全局一致,新增页面零样式漂移 | Req 19 |
| 配色与主题以 Color_Token 抽象 | 风险等级语义化配色单一来源,主题切换仅切换令牌取值 | Req 19、20、23 |
| 视图层与领域引擎严格解耦 | UI 仅消费 Orchestrator/各引擎输出,纯算法属性不受 UI 影响 | Req 13、19-25 |
### 前端架构与设计系统(表现层细化)
表现层采用与既有技术栈一致的 **TypeScript** 实现,建议技术选型如下(均为成熟生态、不自研基础设施):
| 关注点 | 选型建议 | 理由 / 关联需求 |
|--------|----------|------------------|
| 组件化前端框架 | React + TypeScript | 组件化、状态可测、生态成熟;便于组件测试与可视化回归 (Req 19、21) |
| 设计系统载体 | 设计令牌(Design Tokens+ 组件库(如基于 Radix/Headless 模式封装) | Color_Token / 排版 / 间距 / 图标单一来源 (Req 19) |
| 数据可视化 | 图表库(如 ECharts 或 Recharts/Visx) | 热力图、仪表盘、对比图等专业图表,支持图例/标签/图案编码 (Req 20、23) |
| 主题方案 | CSS 自定义属性(CSS Variables)承载 Color_Token,按 Theme 切换变量集 | Light/Dark 切换不重渲染数据状态 (Req 19.6、19.7) |
| 路由与角色导航 | 客户端路由 + 角色守卫(RBAC route guard) | 角色化默认视图与无角色拦截 (Req 25) |
| 表单与草稿 | 受控表单 + 本地/服务端 Draft 持久化 | 断点续评、切换录入方式不丢数据 (Req 21) |
| 可访问性 | 语义化 HTML + ARIA + 自动化检查(axe | WCAG 2.1 AA (Req 23) |
#### 前端分层
```mermaid
graph TB
subgraph DS[Design_System 设计系统层]
Tokens[Design Tokens<br/>Color_Token / 排版 / 间距(4px) / 图标]
ThemeProvider[Theme Provider<br/>Light / Dark]
Primitives[基础组件<br/>Button/Input/Table/Card/Dialog/Nav/Toast]
end
subgraph Viz[可视化组件层 Charts]
Heatmap[风险热力图]
Gauge[风险总分仪表盘]
Badge[Risk_Badge]
TopN[Top N 关键风险图]
CostChart[费用拆解/报价对比图]
Portfolio[组合对比图]
end
subgraph Flow[流程与视图层]
WizardC[Wizard 向导]
FormDlg[表单/对话式录入]
GapPanel[缺口提示面板]
RoleViews[角色化视图: 商务/风控/管理层]
end
subgraph State[前端状态层]
UIStore[UI 状态: 操作态/Loading/Empty]
DraftStore[Draft 草稿状态]
ViewportSvc[Viewport/断点服务]
end
Tokens --> Primitives
ThemeProvider --> Tokens
Primitives --> Viz
Primitives --> Flow
Tokens --> Viz
Viz --> RoleViews
Flow --> UIStore
Flow --> DraftStore
ViewportSvc --> Flow
RoleViews -->|消费输出| AppLayer[应用编排层/领域引擎]
```
#### 风险等级语义化配色映射
Design_System 为四级 Risk_Grade 各定义唯一且稳定的 Color_Token(每个 Theme 下各有取值,但令牌名稳定)。UI 在 Risk_Badge、风险热力图、Top N 关键风险图等所有等级相关呈现中,对同一 Risk_Grade 一律引用同名 Color_Token,禁止内联硬编码颜色(Req 19.3)。
| Risk_Grade | Color_Token(令牌名) | 语义 | 非颜色编码(Req 23.6 |
|------------|----------------------|------|------------------------|
| 低 | `color.risk.low` | 安全/可接受 | 文本标签"低" + 实心图案 |
| 中 | `color.risk.medium` | 关注 | 文本标签"中" + 斜纹图案 |
| 高 | `color.risk.high` | 警示/有条件 | 文本标签"高" + 网格图案 |
| 极高 | `color.risk.critical` | 否决/不可接受 | 文本标签"极高" + 实心粗边图案 |
热力图的 Risk_Level(1-5)严重度同样映射到一组稳定的顺序色令牌(`color.heat.1..5`),并辅以数值标签,确保不依赖颜色即可识别(Req 20、23.6)。
## Components and Interfaces
下列接口以语言无关的伪签名描述,标注其核心契约与关联需求。
### Classifier(业务类型与行业识别)
```
classify(description: string): ClassificationResult
// 前置:description 有效字符数 ≥ 10 且非纯空白,否则抛 InsufficientInputError (Req 1.6)
// 返回 businessType + industry + 各自 Confidence(0-1, 两位小数) (Req 1.1-1.3)
// businessType 为五类中 Confidence 最高的唯一项
// industry 无法判定时取 "未识别"
ClassificationResult {
businessType: BusinessType // 唯一最高置信
businessTypeCandidates: Candidate[] // 按 Confidence 降序,≤3 项
businessTypeConfidence: number
industry: string // 或 "未识别"
industryCandidates: Candidate[]
industryConfidence: number
needsBusinessTypeConfirm: boolean // businessTypeConfidence < 0.6 (Req 1.4)
needsIndustryConfirm: boolean // industryConfidence < 0.6 且 industry≠"未识别" (Req 1.5)
}
confirmClassification(assessmentId, businessType, industry): void
// 评估者修改后以确认值为后续加载模板依据 (Req 1.7)
```
### Config_Center(模型配置中心)
```
loadTemplate(businessType, industry): Template // 精确匹配;回退默认 (Req 2.1-2.2, 2.6)
resolveInheritance(template): Template // 父→子逐项覆盖;环/层级>5 报错 (Req 2.5, 2.7)
instantiateRiskModel(template): RiskModel // 校验必填+权重和=100% (Req 2.4)
saveConfig(actor, config): SaveResult // 仅 Administrator;校验后保存 (Req 11.6-11.8)
normalizeWeights(siblings): Weight[] // 按比例归一化,和=100%,两位小数 (Req 11.2)
saveAsTemplate(actor, config): Template // 另存/派生 (Req 11.5)
```
权限边界:所有写操作前置 `requireRole(Administrator)`;非管理员(含 Assessor、未认证)写操作一律拒绝并审计(Req 12.1、12.3、12.5)。
### Question_Engine(自适应追问引擎)
```
identifyGaps(riskModel, knownData): Indicator[] // 启用且信息不足判定 Risk_Level 的指标 (Req 3.1)
generateQuestions(gaps): Question[] // 按 Indicator 权重降序,同权按 Dimension 权重降序 (Req 3.2)
answerQuestion(indicatorId, answer): UpdateResult // 空/不满足证据→保留缺口 (Req 3.3-3.4)
applyDefaultsOnExhaust(indicator): void // 达最大轮次(默认3,可配)→行业默认值+标注"智能体假设" (Req 3.5-3.6)
// 不变式:Data_Provenance 一旦为"智能体假设",永久保留 (Req 3.7)
Question { id, dimensionId, indicatorId, prompt, round } // 关联维度与指标 (Req 3.8)
```
### Scoring_Engine(评分引擎)
```
scoreIndicator(indicator): number // Risk_Level(1-5) × 权重 (Req 4.1)
scoreDimension(dimension): number // 启用指标评分项加权求和 (Req 4.2)
computeRiskScore(riskModel): number // 线性映射归一化→0-100 整数 (Req 4.3-4.4)
// 仅纳入启用的 Dimension/Indicator;无启用项→ScoringError (Req 4.5)
classifyGrade(riskScore): RiskGrade // 四级互斥完备 (Req 5)
checkRedlines(assessment): RedlineResult[] // 独立于分值;缺数据/假设→"待核实"不计命中 (Req 6)
buildHeatmap(riskModel): HeatmapCell[] // 维度×指标×Risk_Level (Req 7.1)
topKeyRisks(riskModel, n): RiskItem[] // 得分降序 Top N,确定性消歧 (Req 7.2-7.5)
explain(scoringItem): Explanation // 判定依据/影响/建议非空 (Req 18.1-18.3)
```
归一化公式(核心):
```
weightedRaw = Σ_dim ( dimWeight × Σ_ind ( indWeight × riskLevel ) )
// dimWeight、indWeight 已归一化(同级和=1),故 weightedRaw ∈ [1,5]
riskScore = round( (weightedRaw - 1) / 4 × 100 ) // ∈ [0,100]
```
排序消歧(Top N):主键评分项得分降序 → 次键所属 Dimension 权重降序 → 三键 Indicator 权重降序 → 末键 Indicator 稳定标识升序,保证确定性(Req 7.3、7.5)。
### Cost_Engine(费用测算引擎)
```
estimate(assessment, costInputs): CostEstimate
// 前置:评分已完成,否则 ScoringNotCompleteError (Req 8.5)
// 缺成本输入→行业默认值+标注"智能体假设" (Req 8.4)
CostEstimate {
riskPremiumRange: Range // 金额或百分比区间,依 Risk_Grade+评分 (Req 8.1)
advanceInterest: Money // 垫资利息
insuranceCost: Money // 保险费用
compensationReserve: Money // 补偿准备金
badDebtReserve: Money // 坏账准备金
baselineQuote: Money // 基准报价
riskAdjustedQuote: Money // 风险调整后报价
breakdown: CostLineItem[] // 每项标注依据输入项+费率/参数来源 (Req 8.2,8.3,8.6)
}
```
### Strategy_Engine(应对策略推荐引擎)
```
decide(riskGrade, redlineHit): Acceptability // 可接受/有条件接受/不可接受
// 决策表见下;红线命中或极高→不可接受 (Req 9.6-9.8)
managementMeasures(...): Measure[] // 合同条款/用工合规整改/退场预案/过程监控 各≥1 (Req 9.3)
costMeasures(...): Measure[] // 风险溢价/预付保证金/保险转移/账期成本/准备金计提 各≥1 (Req 9.4)
acceptanceConditions(...): Condition[] // 有条件接受时,每条件关联≥1 关键风险 + 成本影响 (Req 9.2,9.5)
```
可接受性决策表:
| 红线命中 | Risk_Grade | 可接受性结论 | 关联需求 |
|----------|-----------|--------------|----------|
| 是 | 任意 | 不可接受 | 6.2、9.8 |
| 否 | 低 | 可接受 | 9.6 |
| 否 | 中 | 可接受 | 9.6 |
| 否 | 高 | 有条件接受 | 9.7 |
| 否 | 极高 | 不可接受 | 9.8 |
### External_Data_Adapter(外部数据适配层)
```
interface DataSourceAdapter { // 可插拔,新增源不改 Scoring_Engine (Req 15.5)
fetch(query): DataPoint[] // 单次请求 10 秒超时 (Req 15.1)
}
// 成功:标注 Data_Provenance="外部数据" + Confidence(0-1) (Req 15.2)
// 失败/超时/错误:回退用户输入,标注"用户输入" (Req 15.3)
// 回退后仍缺失:标注"智能体假设",不中断 (Req 15.4)
```
### Report_Generator(报告生成与导出)
```
generate(assessment): Report
// 前置:评分+红线+费用+可接受性结论均完成,否则 FlowNotCompleteError (Req 10.4)
// 含项目概要/总分分级/热力图/维度明细/Top风险+红线结果/结论/应对/假设缺口 (Req 10.1)
// 未命中红线亦明确标注"无红线命中" (Req 10.1)
export(report, format): DownloadFile
// 请求后 30 秒内导出完整自包含文件 (Req 10.2)
// 失败→中止,保留报告不变,返回错误 (Req 10.5)
```
### 角色权限与视图层(RBAC + Views
```
requireRole(role): void // 鉴权
renderView(role, assessment): View // 角色化视图 (Req 13.1-13.3)
// 商务/销售:结论+接受条件+风险调整后报价
// 风控:评分明细(Risk_Level/依据/Provenance)+红线+缺口尽调
// 管理层:Grade+热力图+TopN+利润vs风险看板
renderPortfolio(assessmentIds): PortfolioView // 跨项目组合看板;空集→空看板提示 (Req 13.4,13.6)
// 无角色→拒绝展示并提示分配角色 (Req 13.5)
```
### 评估持久化层
```
save(assessment): SaveResult // 完成即持久化输入/评分/报告/元数据 (Req 17.1)
// 失败→保留会话数据+返回错误 (Req 17.2)
reassess(assessmentId): Assessment // 基于原输入创建新评估,原评估不变 (Req 17.3-17.4)
compare(assessmentIds): ComparisonResult // ≥2 个;否则拒绝 (Req 17.5-17.6)
search(filters): Assessment[] // 按类型/行业/Grade/时间;无匹配→空集 (Req 17.7)
```
### Design_System(设计系统与主题)
```
interface DesignSystem {
typography: TypographyScale // ≥4 级具名层级,各含固定字号与行高 (Req 19.2)
spacing: SpacingScale // 4px 基数标度,取值均为 4 的整数倍 (Req 19.4)
icons: IconSet // 单一来源图标集 (Req 19.5)
components: ComponentLibrary // Button/Input/Table/Card/Dialog/Nav/Toast 等 (Req 19.1)
}
resolveColorToken(token: ColorToken, theme: Theme): ColorValue
// 对任意令牌名与主题,确定性返回该主题下取值 (Req 19.6)
riskGradeColorToken(grade: RiskGrade): ColorToken
// 四级各映射唯一稳定令牌名,全 UI 共用 (Req 19.3)
contrastRatio(fg: ColorValue, bg: ColorValue): number
// 计算 WCAG 相对对比度,用于达标校验 (Req 23.3)
setTheme(theme: Theme): void
// 切换 Light/Dark:仅替换 Color_Token 取值,保留页面已录入数据 (Req 19.6, 19.7)
TypographyScale { levels: TypographyLevel[≥4] } // 每级: name, fontSize, lineHeight
SpacingScale { base: 4, steps: number[] } // 每个 step % 4 == 0
Theme = Light | Dark
```
### 数据可视化组件(Charts
```
renderChart(spec: ChartSpec): ChartView
// 通用契约:
// - data 为空 → 呈现 Empty_State 并提示无可展示数据 (Req 20.4)
// - data 处于请求/计算中 → 呈现 Loading_State (Req 20.5)
// - 系列/类别 ≥2 → 提供图例,图例标签与数据元素一致 (Req 20.2)
// - 坐标轴/数据点/分区提供文本标签 (Req 20.3)
// - 类别以"文本标签或图案"在颜色之外区分 (Req 23.6)
ChartView 变体:
Heatmap // Dimension×Indicator×Risk_Level,单元格附数值标签 (Req 20.1)
ScoreGauge // 同时呈现 Risk_Score 数值 + 对应 Risk_Grade (Req 20.6)
RiskBadge // 语义化 Color_Token + 文字标签呈现 Risk_Grade (Req 20.1)
TopNRiskChart // Top N 关键风险条形图 (Req 20.1)
CostBreakdown // 费用拆解图 (Req 20.1)
QuoteCompare // 基准报价/风险调整后报价/差额三值并呈,差额=风险调整后-基准 (Req 20.7)
PortfolioCompare // 跨项目组合对比图 (Req 20.1)
ChartSpec { type, series: Series[], status: ready|loading|empty, legend, labels }
```
### Wizard(向导式评估流程)
```
WizardState {
steps: Step[] // 有序步骤
currentIndex: number // 当前步骤序号
total: number // 步骤总数
completed: boolean[] // 已完成步骤进度 (Req 21.1)
}
progress(state): { current, total, completedCount } // 进度指示 (Req 21.1)
advance(state): WizardState // 推进;进度 completedCount 单调非减 (Req 21.1)
switchInputMode(state, mode: 对话式|表单): WizardState
// 切换录入方式保留切换前已录入数据 (Req 21.2)
listGaps(assessment): GapItem[] // 信息缺口/待补充项
renderGaps(gaps): GapPanel
// 以醒目样式呈现全部缺口项 + 提供定位至录入位置入口 (Req 21.3)
quickActions(): { submit, saveDraft, exportReport } // 各一键入口 (Req 21.4)
saveDraft(assessment): Draft // 持久化为 Draft,保留全部录入数据 (Req 21.5)
openDraft(draftId): { assessment, wizardStep }
// 恢复全部录入数据并定位至保存时步骤 (Req 21.6)
confirmLeaveIfDirty(state): LeaveDecision
// 存在未保存修改时提示并请求确认 (Req 21.7)
```
### 响应式布局服务(Viewport
```
selectLayout(viewportWidth: number): Layout
// 确定性断点映射 (Req 22.1, 22.2, 22.3, 22.4):
// width ≥ 1280 → DesktopLayout(全部功能)
// 768 ≤ width ≤ 1279 → CompactLayout(无横向滚动条,内容完整可见)
// width < 768 → MobileLayout(看板保留 Risk_Score/Risk_Grade/Top N
onViewportChange(prevState, newWidth): UIState
// 跨断点切换应用匹配布局且不丢失已录入数据 (Req 22.4)
Layout = DesktopLayout | CompactLayout | MobileLayout
```
### 可访问性(Accessibility, WCAG 2.1 AA
```
// 交互控件:可键盘聚焦并触发,聚焦时呈现可见焦点指示 (Req 23.1, 23.2)
// 对比度:正文 ≥ 4.5:1、大号文本 ≥ 3:1,由 contrastRatio 校验 (Req 23.3)
// 表单:每个输入控件关联可被辅助技术识别的文本标签 (Req 23.4)
associateLabel(input): { controlId, labelId, accessibleName } // 非空可达 (Req 23.4)
renderFieldError(input, validation): AccessibleError
// 校验失败为每个未通过控件呈现可被辅助技术识别的错误提示 (Req 23.5)
// 图表:颜色之外以文本标签/图案区分类别 (Req 23.6)
```
### 操作反馈与状态(Feedback & States
```
OperationState = idle | loading | success | error
runOperation(op): OperationState
// 进行中 → Loading_State (Req 24.1)
// 成功 → 成功反馈 (Req 24.2)
// 失败 → 可读错误信息(说明原因)+ 指向修正路径的操作入口 (Req 24.3)
exportWithProgress(report): ExportResult
// 导出执行中呈现进度反馈,30 秒内呈现完成或失败结果 (Req 24.4)
```
### 角色化默认视图与导航(Role-based Default Views
```
defaultRoute(role: Role): Route
// 确定性映射 (Req 25.1-25.3):
// 商务/销售 → SalesView
// 风控 → RiskView
// 管理层 → ManagementDashboard
// 无角色 → AssignRolePrompt(不呈现评估数据) (Req 25.5)
renderDefaultView(role): View
// 角色匹配的功能入口呈现于无需额外导航即可见的位置 (Req 25.4)
```
## Data Models
```mermaid
erDiagram
RiskModel ||--o{ Dimension : contains
Dimension ||--o{ Indicator : contains
Indicator ||--|{ ScoringRule : defines
RiskModel ||--o{ Redline : has
Template ||--o| Template : inherits
Template ||--|| RiskModel : instantiates
Assessment ||--|| RiskModel : uses
Assessment ||--o{ ScoringItem : produces
Assessment ||--|| Region : adopts
Region ||--|| ComplianceRuleSet : maps
ScoringItem ||--|| DataProvenance : annotated
KnowledgeBase ||--o{ Template : stores
```
### 核心实体
```
RiskModel {
id, name, businessType,
dimensions: Dimension[],
redlines: Redline[]
}
Dimension {
id, name,
weight: number, // 0-100,同级启用项归一化后和=100%
enabled: boolean, // 停用保留配置但不计分 (Req 11.1)
indicators: Indicator[]
}
Indicator {
id, name,
weight: number, // 0-100,同级启用项归一化后和=100%
enabled: boolean,
scoringRules: ScoringRule[5], // 覆盖 Risk_Level 1-5 (Req 11.3)
evidenceRequired: string,
askPrompt: string
}
ScoringRule { level: 1..5, label, description } // 判定标准
Redline {
id, // 唯一标识 (Req 11.4)
triggerCondition, // 触发条件(独立于分值)
consequence, // 一票否决后果
enabled: boolean
}
Template {
id, name, businessType, industry,
parentTemplateId?, // 继承;环或层级>5 非法 (Req 2.5,2.7)
isDefault: boolean, // 业务类型默认模板 (Req 2.2)
riskModelConfig
}
```
### 评估与可解释性实体
```
Assessment {
id, projectDescription,
businessType, industry,
region: Region, // 默认 CN,记录所采用 Region (Req 16.4-16.5)
riskModel: RiskModel, // 实例化快照
scoringItems: ScoringItem[],
riskScore: 0..100,
riskGrade: 低|中|高|极高,
redlineResults: RedlineResult[],
costEstimate: CostEstimate,
acceptability: 可接受|有条件接受|不可接受,
report: Report,
metadata: { businessType, industry, region, riskScore, riskGrade, createdAt, assessorId }, // (Req 17.1)
createdAt, assessorId
}
ScoringItem {
dimensionId, indicatorId,
riskLevel: 1..5,
score: number, // riskLevel × indicatorWeight
provenance: 用户输入|外部数据|智能体假设, // (Req 18.4)
confidence: 0..1, // 两位小数
rationale: string, // 非空,引用 Dimension/Indicator/ScoringRule/数据点 (Req 18.1)
riskImpact: string, // 非空 (Req 18.2)
recommendation: string // 非空 (Req 18.3)
}
RedlineResult {
redlineId,
status: 命中|未命中|待核实, // 缺数据/假设→待核实,不计命中 (Req 6.5)
triggeredCondition, evidenceData
}
DataProvenance = 用户输入 | 外部数据 | 智能体假设 // 三态
```
### 合规与地域实体
```
Region { code, name } // 首版 CN=中国大陆
ComplianceRuleSet {
region,
socialInsuranceBase: { lowerBound }, // 社保缴费基数下限
economicCompensation: { nRule, nPlusOneRule }, // N / N+1
dispatchRatioCap: 0.10, // 劳务派遣比例上限 10%
minimumWage: { byLocality } // 当地最低工资标准
}
// Region 无对应规则集→拒绝合规判定/费用测算+提示暂不支持 (Req 16.6)
```
### 知识库实体
```
KnowledgeBase {
partitions: IndustryPartition[] // 按行业分区 (Req 14.1)
}
IndustryPartition {
industryId,
indicators, weightTemplates, redlines, cases, askPrompts // 五类必备 (Req 14.1,14.4)
}
// 缺任一类→拒绝创建分区+指明缺失类别 (Req 14.4)
// 无匹配行业分区→默认分区+标注未匹配 (Req 14.5)
```
### 审计日志实体
```
ConfigAuditEntry {
actorId, timestamp, // 精确到秒
action: 变更提交|变更拒绝,
changedConfigKeys: string[], // 成功时记录变更项 (Req 12.4)
reason // 拒绝时记录 (Req 12.5)
}
```
### UI 与设计系统实体
```
ColorToken = string // 具名稳定令牌,如 color.risk.low (Req 19.3)
Theme = Light | Dark
DesignTokens {
colors: Map<ColorToken, { light: ColorValue, dark: ColorValue }>, // 每令牌双主题取值 (Req 19.6)
typography: TypographyLevel[], // ≥4 级,各具名 + 固定字号 + 固定行高 (Req 19.2)
spacing: number[], // 均为 4 的整数倍 (Req 19.4)
icons: IconRef[] // 单一来源 (Req 19.5)
}
TypographyLevel { name, fontSize, lineHeight }
RiskGradeColorMap { // 四级 → 唯一稳定令牌 (Req 19.3)
低: color.risk.low, 中: color.risk.medium, 高: color.risk.high, 极高: color.risk.critical
}
Draft { // 断点续评中间状态 (Req 21.5,21.6)
id, baseAssessmentId?,
enteredData, // 全部已录入数据快照
wizardStep: number, // 保存时所处步骤
inputMode: 对话式|表单,
savedAt
}
GapItem { indicatorId, dimensionId, label, locateAnchor } // 缺口定位 (Req 21.3)
ChartViewModel {
type, status: ready|loading|empty, // 驱动 Empty_State/Loading_State (Req 20.4,20.5)
series: Series[], legend?: LegendItem[], // ≥2 系列必有图例 (Req 20.2)
labels: Label[], // 轴/点/分区文本标签 (Req 20.3)
categoryEncoding: { colorToken, textLabel, pattern } // 非纯颜色编码 (Req 23.6)
}
OperationFeedback { state: idle|loading|success|error, message?, correctiveAction? } // (Req 24)
Role = 商务/销售 | 风控 | 管理层 | 无角色
RouteMap { 商务/销售: SalesView, 风控: RiskView, 管理层: ManagementDashboard, 无角色: AssignRolePrompt } // (Req 25)
Breakpoint = Desktop(≥1280) | Compact(768-1279) | Mobile(<768) // (Req 22)
```
## Correctness Properties
*A property is a characteristic or behavior that should hold true across all valid executions of a system—essentially, a formal statement about what the system should do. Properties serve as the bridge between human-readable specifications and machine-verifiable correctness guarantees.*
下列属性由需求验收标准经可测试性分析(prework)转化而来,并经冗余消解(互斥完备性蕴含、决策表合并、多级排序合并、可解释性三要素合并、来源标注合并等)。每条均为全称量化("对任意…"),用于属性化测试。非属性类标准(语义识别、外部 IO、导出时延、架构解耦等)由示例测试与集成测试覆盖,见 Testing Strategy。
### Property 1: 业务类型判定唯一且取最高置信
*对任意*有效项目描述产生的业务类型置信分布,Classifier 输出的 businessType *必为*五类业务类型中 Confidence 最高的*唯一*一项。
**Validates: Requirements 1.1**
### Property 2: 置信度恒在有效值域内
*对任意*分类结果,业务类型 Confidence 与行业 Confidence *均*落在区间 [0, 1] 内且保留两位小数。
**Validates: Requirements 1.3**
### Property 3: 低置信触发候选确认
*对任意*分类结果,当某判定的 Confidence 低于 0.6(行业判定附加条件:行业标记不为"未识别")时,System *必*返回按 Confidence 降序排列、数量至多 3 项的候选列表并置确认标志为真;否则不触发确认。
**Validates: Requirements 1.4, 1.5**
### Property 4: 描述信息不足必被拒绝
*对任意*为空、仅含空白字符或有效字符数少于 10 的项目描述,System *必*拒绝执行业务类型与行业判定并返回信息不足错误;而任意有效字符数不少于 10 的非空白描述*不会*因长度被拒。
**Validates: Requirements 1.6**
### Property 5: 确认值驱动后续加载
*对任意*评估者确认或修改后的(业务类型, 行业),System 后续加载模板*必*以该确认值为依据。
**Validates: Requirements 1.7**
### Property 6: 模板匹配与回退确定性
*对任意*知识库与(业务类型, 行业)组合:若存在精确匹配模板则*必*选中该精确模板;若无精确匹配但存在该业务类型默认模板,则*必*选中默认模板并标注"未匹配行业专用模板";若两者皆无则*必*终止并返回无可用模板提示。
**Validates: Requirements 2.1, 2.2, 2.6, 14.3, 14.5**
### Property 7: 模板实例化结构保持
*对任意*合法模板,实例化为 Risk_Model 后*必*完整保留其全部 Dimension、Indicator、权重、Scoring_Rule、Redline、追问话术及各项启用/停用状态,无丢失无篡改。
**Validates: Requirements 2.3**
### Property 8: 非法模板必被拒绝实例化
*对任意*缺失必填组成项、或同级 Dimension 权重之和/同级 Indicator 权重之和不等于 100% 的模板,System *必*不实例化、终止评估并返回模板数据错误。
**Validates: Requirements 2.4**
### Property 9: 模板继承逐项覆盖
*对任意*父子模板对,继承解析结果*必*等于"应用父模板全部组成项后,以子模板中存在差异的组成项逐项覆盖"。
**Validates: Requirements 2.5**
### Property 10: 继承链环与深度防护
*对任意*模板继承图,若存在循环引用或继承层级超过 5 层,System *必*终止并返回继承错误;任意无环且层级不超过 5 的合法链*必*成功解析。
**Validates: Requirements 2.7**
### Property 11: 信息缺口识别准确
*对任意*已知信息集与实例化模型,被标记为信息缺口的指标集合*恰为*{启用 ∧ 依据其 Scoring_Rule 无法判定 Risk_Level} 的指标集合。
**Validates: Requirements 3.1**
### Property 12: 追问仅针对缺口且排序确定
*对任意*缺口指标集合,Question_Engine 生成的问题*仅*覆盖缺口指标,且按 Indicator 权重降序排列、Indicator 权重相同时按所属 Dimension 权重降序消歧;每个问题*必*关联非空且真实存在的 Dimension 与 Indicator。
**Validates: Requirements 3.2, 3.8**
### Property 13: 有效回答移出缺口
*对任意*缺口指标,给出满足证据要求的回答后,该指标*必*从缺口集合移除并更新已知信息。
**Validates: Requirements 3.3**
### Property 14: 无效回答保留缺口
*对任意*空回答或不满足证据要求的回答,对应指标的信息缺口标记*必*保留,并返回需补充信息的提示。
**Validates: Requirements 3.4**
### Property 15: 追问轮次不超上限并触发兜底
*对任意*可配置的最大追问轮次(正整数,默认 3)与任意追问序列,单个指标的追问轮次*恒*不超过该上限;当轮次达上限仍缺失时,该指标*必*采用行业默认值且 Data_Provenance 被标注为"智能体假设"。
**Validates: Requirements 3.5, 3.6**
### Property 16: 智能体假设标注单调永久
*对任意*已被标注为"智能体假设"的数据点,施加任意后续补充、更新或重算操作序列后,其 Data_Provenance *恒*保持"智能体假设",不被改回其他取值。
**Validates: Requirements 3.7**
### Property 17: 评分项得分公式
*对任意*启用指标,其评分项得分*恒*等于该指标 Risk_Level(1 至 5)乘以其权重;维度得分*恒*等于其下各启用指标评分项得分的加权求和。
**Validates: Requirements 4.1, 4.2**
### Property 18: 归一化端点与值域
*对任意*启用指标集合:当全部纳入计算的指标 Risk_Level 同取最小值 1 时 Risk_Score *必*为 0、同取最大值 5 时 *必*为 100;且*对任意* Risk_Level 组合,Risk_Score *恒*为 [0, 100] 内的整数(四舍五入取整)。
**Validates: Requirements 4.3**
### Property 19: 停用项不影响评分
*对任意*风险模型,改动任何停用 Dimension 或停用 Indicator 的 Risk_Level 或权重,*均不*改变 Risk_Score(汇总仅纳入启用项)。
**Validates: Requirements 4.4**
### Property 20: 无启用项必报错
*对任意*不存在任何启用 Indicator 或启用 Dimension 的评估,Scoring_Engine *必*终止评分、不产生 Risk_Score 并返回评分数据不足错误。
**Validates: Requirements 4.5**
### Property 21: 评分项来源与置信标注
*对任意*评分项,*必*记录 Data_Provenance(取值为 用户输入 / 外部数据 / 智能体假设 之一)与落在 [0, 1] 内的 Confidence。
**Validates: Requirements 4.6, 18.4**
### Property 22: 分级区间互斥且完备
*对任意* [0, 100] 内整数 Risk_ScoreScoring_Engine *必*输出且仅输出一个 Risk_Grade,且其取值严格遵循区间 [0,25]→低、(25,50]→中、(50,75]→高、(75,100]→极高。
**Validates: Requirements 5.1, 5.2, 5.3, 5.4, 5.5**
### Property 23: 红线校验正确且独立于分值
*对任意*评估与启用红线集合,满足触发条件的红线*恰被*标记为命中、不满足的*不被*标记;且*对任意*改变其他评分项使 Risk_Score/Risk_Grade 变化但不改变红线相关数据点的操作,红线命中结果*恒*不变。
**Validates: Requirements 6.1, 6.4**
### Property 24: 红线数据不足标待核实
*对任意*启用红线,若其触发条件所需数据缺失或 Data_Provenance 为"智能体假设"以致无法确定是否命中,该红线*必*被标记为"待核实"且*不*计为命中。
**Validates: Requirements 6.5**
### Property 25: 命中红线列入报告
*对任意*命中红线的评估,报告*必*列出每个被命中红线及其被触发的条件与对应判定依据数据。
**Validates: Requirements 6.3**
### Property 26: 可接受性决策表完备且红线最高优先
*对任意*(红线是否命中, Risk_Grade)组合,Strategy_Engine 输出的可接受性结论*必*为唯一确定值:命中任一红线时*恒*为"不可接受"(优先于 Grade);未命中时,Grade 为低或中→"可接受"、高→"有条件接受"、极高→"不可接受"。
**Validates: Requirements 6.2, 6.6, 9.1, 9.6, 9.7, 9.8**
### Property 27: 应对措施类别全覆盖
*对任意*结论为"可接受"或"有条件接受"的评估,管理层面措施*必*在合同条款、用工合规整改、退场预案、过程监控四类中各输出至少一项,费用层面措施*必*在风险溢价定价、预付/保证金、保险转移、账期成本、准备金计提五类中各输出至少一项。
**Validates: Requirements 9.3, 9.4**
### Property 28: 有条件接受的条件关联与成本影响
*对任意*结论为"有条件接受"的评估,接受条件清单中每个条件*必*关联至少一个关键风险清单中的风险项,且*必*输出取值为具体金额或金额区间的成本影响测算。
**Validates: Requirements 9.2, 9.5**
### Property 29: 热力图覆盖全部启用指标
*对任意*风险模型,热力图数据*必*为每个启用 Indicator 提供一个以其所属 Dimension 为行、Indicator 为列、Risk_Level1 至 5)为严重度的单元格。
**Validates: Requirements 7.1**
### Property 30: Top N 确定性排序
*对任意*评分项集合与可配置 N(1 至 50,默认 10),关键风险清单*必*为按评分项得分降序、同分时先按所属 Dimension 权重降序再按 Indicator 权重降序消歧的确定性排序结果;当启用评分项数量少于 N 时输出全部启用项,否则输出前 N 项;同一输入*恒*产生同一输出顺序。清单中每项*必*提供其 Dimension、Indicator、得分与判定依据。
**Validates: Requirements 7.2, 7.3, 7.4, 7.5**
### Property 31: 风险溢价区间合法且随分级单调
*对任意* Risk_Grade 与风险评分,风险溢价加价区间的下界*恒*不大于上界;且更高 Risk_Grade 对应的溢价*恒*不低于更低 Risk_Grade 对应的溢价。
**Validates: Requirements 8.1**
### Property 32: 费用项非负且标注依据
*对任意*成本输入,垫资利息、保险费用、补偿准备金、坏账准备金各项金额*恒*非负,且每一项测算金额*必*标注其所依据的输入项与所采用的费率或参数来源。
**Validates: Requirements 8.2, 8.6**
### Property 33: 风险调整后报价不低于基准且拆解一致
*对任意*成本输入,风险调整后报价*恒*不低于基准报价,且各项成本拆解之和*与*报价口径一致。
**Validates: Requirements 8.3**
### Property 34: 缺失成本输入兜底为假设
*对任意*缺失的成本输入项,Cost_Engine *必*采用行业默认值并将该输入项的 Data_Provenance 标注为"智能体假设"。
**Validates: Requirements 8.4**
### Property 35: 评分未完成拒绝费用测算
*对任意*风险评分尚未完成的状态,Cost_Engine *必*拒绝执行费用测算并返回评分未完成提示。
**Validates: Requirements 8.5**
### Property 36: 报告章节完备
*对任意*风险评分、红线校验、费用测算与可接受性结论均已完成的评估,生成的报告*必*包含全部规定章节(项目概要与业务类型判定、风险总分与分级、风险热力图、各维度风险明细、Top 关键风险与红线校验结果、可接受性结论、应对方案、假设与信息缺口说明),且未命中任一红线时红线校验结果*必*明确标注为"无红线命中"。
**Validates: Requirements 10.1**
### Property 37: 维度明细字段齐备
*对任意*报告,各维度风险明细中每个评分项*必*展示评分、判定依据、风险影响、Data_Provenance 与 Confidence。
**Validates: Requirements 10.3**
### Property 38: 流程未完成拒绝报告
*对任意*评估流程尚未完成的状态,请求生成或导出报告*必*被拒绝并返回流程尚未完成提示。
**Validates: Requirements 10.4**
### Property 39: 停用项保留但不计分
*对任意*被管理员停用的 Dimension 或 Indicator,其配置数据*必*保留,且*不*纳入评分计算。
**Validates: Requirements 11.1**
### Property 40: 权重归一化保比例且同级和为 100%
*对任意*非全零的同级权重向量(取值 0 至 100),保存时归一化后同级启用项权重之和*恒*等于 100%(保留两位小数),且任意两项归一化前后的比例*恒*保持不变。
**Validates: Requirements 11.2**
### Property 41: 评分规则与红线配置校验
*对任意*自定义 Scoring_Rule,未覆盖 Risk_Level 1 至 5 全部级别者*必*被拒绝;*对任意* Redline 配置,缺少唯一标识、触发条件或一票否决后果,或标识重复者*必*被拒绝。
**Validates: Requirements 11.3, 11.4**
### Property 42: 配置另存为模板可往返
*对任意*合法配置,将其另存为模板再加载实例化所得配置*必*与原配置等价(round-trip)。
**Validates: Requirements 11.5**
### Property 43: 校验失败保留上次有效配置
*对任意*未通过校验的配置保存请求,存储中的配置*必*保持为上次有效配置不变,并返回指明失败项的校验错误。
**Validates: Requirements 11.6, 11.7**
### Property 44: 同级权重全零拒绝归一化
*对任意*同级启用项权重之和为 0 的向量,Config_Center *必*拒绝保存并返回权重校验错误。
**Validates: Requirements 11.8**
### Property 45: 非管理员配置修改一律拒绝且配置不变
*对任意*非 Administrator 角色(含 Assessor、未认证、未授权)发起的 Risk_Model 配置修改请求,System *必*拒绝该请求、保持当前配置不变并返回权限不足错误。
**Validates: Requirements 12.1, 12.3**
### Property 46: 配置变更与拒绝均留痕审计
*对任意*成功提交的配置变更,审计日志*必*记录操作者身份、精确到秒的变更时间与发生变更的配置项标识;*对任意*被拒绝的配置修改请求,审计日志*必*记录操作者身份与精确到秒的请求时间。
**Validates: Requirements 12.4, 12.5**
### Property 47: 角色化视图内容映射
*对任意*已完成评估:商务/销售视图*必*包含可接受性结论、接受条件清单与风险调整后报价;风控视图*必*包含评分项明细(含 Risk_Level、判定依据、Data_Provenance)、红线校验结果与信息缺口尽调事项;管理层视图*必*包含 Risk_Grade、风险热力图、Top N 关键风险与利润对风险对比。
**Validates: Requirements 13.1, 13.2, 13.3**
### Property 48: 组合看板汇总与空集处理
*对任意* Assessment 集合,管理层组合看板*必*汇总集合中全部评估;当集合为空时*必*展示空组合看板并提示无可汇总的评估。
**Validates: Requirements 13.4, 13.6**
### Property 49: 无角色拒绝展示
*对任意*未分配商务/销售、风控或管理层任一角色的用户,System *必*拒绝展示评估视图并提示需分配角色。
**Validates: Requirements 13.5**
### Property 50: 行业分区内容完备性校验
*对任意*行业分区,合法分区*必*包含 Indicator、权重模板、Redline、典型案例、追问话术全部五类内容;*对任意*缺少其中任一类内容的新增分区请求,System *必*拒绝创建、返回指明缺失内容类别的校验错误,并保持已有分区不变。
**Validates: Requirements 14.1, 14.4**
### Property 51: 外部数据点来源与置信标注
*对任意*成功获取的外部数据点,其 Data_Provenance *必*为"外部数据"且 Confidence 落在 [0, 1] 内。
**Validates: Requirements 15.2**
### Property 52: 外部数据失败降级回退
*对任意*外部数据源连接失败、超过 10 秒未返回或返回错误响应的情形,受影响数据点*必*回退到用户输入并标注 Data_Provenance 为"用户输入";若回退后用户输入仍不完整,则*必*标注为"智能体假设"并继续执行评估、不中断流程。
**Validates: Requirements 15.3, 15.4**
### Property 53: 合规判定覆盖与计量标注
*对任意* Region 为中国大陆(CN)的评估,合规判定*必*覆盖社保缴费基数、经济补偿 N 与 N+1、劳务派遣用工比例上限 10%、当地最低工资标准四项;且经济补偿金额、社保缴费金额与相关合规费用*必*依规则项计算并标注其所依据的规则项与输入项。
**Validates: Requirements 16.1, 16.2**
### Property 54: 合规不满足项标注
*对任意*合规判定中存在不满足项(社保缴费基数低于法定下限、劳务派遣用工比例超过 10% 或约定薪酬低于当地最低工资标准)的评估,System *必*将该项标注为合规不通过并在报告中列出对应规则项与判定依据。
**Validates: Requirements 16.3**
### Property 55: Region 记录与默认
*对任意*创建的 Assessment*必*记录其所采用的 Region;当请求未指定 Region 时,*必*采用中国大陆(CN)并标注该 Region 为系统默认值。
**Validates: Requirements 16.4, 16.5**
### Property 56: 无规则集地域拒绝合规处理
*对任意*当前无对应 Compliance_Rule_Set 的 RegionSystem *必*拒绝该 Region 的合规判定与费用测算、不生成合规结论,并返回该地域暂不支持的提示。
**Validates: Requirements 16.6**
### Property 57: 评估持久化往返
*对任意*完成的 Assessment,持久化存储后再读取*必*得到等价记录,且其元数据*必*至少包含业务类型、行业、Region、Risk_Score、Risk_Grade、创建时间与评估者身份。
**Validates: Requirements 17.1**
### Property 58: 复评保留原评估
*对任意*历史 Assessment,复评*必*基于其输入创建一个新 Assessment(新标识)且原 Assessment 保持不变;*对任意*引用不存在历史 Assessment 的复评请求,*必*被拒绝并返回该评估不存在提示。
**Validates: Requirements 17.3, 17.4**
### Property 59: 跨项目对比的数量约束与内容
*对任意*被选中的 Assessment 集合:当数量不少于 2 时*必*返回每个被选中 Assessment 的 Risk_Grade、Risk_Score 与关键风险对比数据;当数量少于 2 时*必*拒绝对比并提示至少需选择 2 个评估。
**Validates: Requirements 17.5, 17.6**
### Property 60: 检索结果满足过滤条件
*对任意*历史数据集与按业务类型、行业、Risk_Grade 或创建时间范围的检索条件,返回的全部 Assessment *均*满足该检索条件,且无匹配时返回空结果集。
**Validates: Requirements 17.7**
### Property 61: 评分项可解释三要素非空
*对任意*评分项,*必*输出非空的判定依据(引用其所属 Dimension、Indicator、Scoring_Rule 及导致该 Risk_Level 的数据点取值)、非空的风险影响说明与非空的建议。
**Validates: Requirements 18.1, 18.2, 18.3**
### Property 62: 假设项进入缺口说明并附尽调建议
*对任意* Data_Provenance 为"智能体假设"的评分项,报告的信息缺口说明中*必*列出该项,并为其输出关联对应 Indicator 的补充尽调建议。
**Validates: Requirements 18.5, 18.6**
> 以下为针对 UI/前端需求(Req 19-25)经 prework 可测试性分析与冗余消解后补充的属性,编号续接。纯视觉/主观、键盘可达性、时延与可达位置等标准不强行属性化,改由组件测试、可视化回归、自动化可访问性检查(axe)与人工审查覆盖,详见 Testing Strategy。
### Property 63: 排版层级完备且文本取自层级
*对任意* UI 文本元素,其排版样式*必*解析到 Design_System 已定义的某个具名 Typography 层级;且已定义层级*恒*不少于 4 级,每级具有固定字号与固定行高。
**Validates: Requirements 19.2**
### Property 64: Risk_Grade 配色令牌一致且唯一
*对任意* Risk_GradeUI 在 Risk_Badge、风险热力图与 Top N 关键风险图等所有等级相关呈现中取得的 Color_Token *必*为同一稳定令牌名;且四级(低、中、高、极高)对应的 Color_Token *互不相同*
**Validates: Requirements 19.3**
### Property 65: 间距为 4 像素整数倍
*对任意* Design_System 间距标度取值与任意组件间距,其像素值*恒*为 4 的非负整数倍。
**Validates: Requirements 19.4**
### Property 66: 主题配色令牌解析正确
*对任意* Color_Token 与任意 ThemeLight 或 Dark),`resolveColorToken` *必*返回该令牌在所选 Theme 下定义的取值;切换 Theme 后,页面所有引用该令牌处*必*一致地反映所选 Theme 的取值。
**Validates: Requirements 19.6**
### Property 67: UI 状态转换保留已录入数据
*对任意*已录入数据的页面状态,执行切换 Theme、在对话式追问与表单录入之间切换、或因 Viewport 宽度跨越布局断点而变更布局等任一 UI 状态转换后,已录入数据*恒*保持不变(无丢失、无篡改)。
**Validates: Requirements 19.7, 21.2, 22.4**
### Property 68: 图表图例与数据系列一致
*对任意*含两个及以上数据系列或类别的 Chart,其图例*必*存在,且图例标签集合*恒*与该 Chart 中对应数据元素的标签集合相等。
**Validates: Requirements 20.2**
### Property 69: 图表文本标签齐备
*对任意* Chart,其每个坐标轴、数据点或分区*必*具有非空的文本标签。
**Validates: Requirements 20.3**
### Property 70: 图表空态与加载态呈现
*对任意* Chart:当其对应数据为空时*必*呈现 Empty_State 并提示无可展示数据;当其对应数据正在请求或计算中时*必*呈现 Loading_State。
**Validates: Requirements 20.4, 20.5**
### Property 71: 仪表盘同时呈现总分与分级
*对任意* Risk_Score,风险总分仪表盘*必*同时呈现该 Risk_Score 数值与其按分级规则对应的 Risk_Grade,且所呈现 Risk_Grade *恒*与分级函数输出一致。
**Validates: Requirements 20.6**
### Property 72: 费用对比图三值并呈且差额一致
*对任意*基准报价与风险调整后报价对,费用对比图*必*同时呈现基准报价金额、风险调整后报价金额与二者差额,且所呈现差额*恒*等于风险调整后报价减基准报价。
**Validates: Requirements 20.7**
### Property 73: Wizard 进度正确且单调
*对任意* Wizard 步骤序列,进度指示*必*正确呈现当前步骤序号、步骤总数与已完成步骤数(已完成数不超过总数);且*对任意*推进操作序列,已完成步骤数*恒*单调非减。
**Validates: Requirements 21.1**
### Property 74: 缺口项醒目呈现并可定位
*对任意*存在信息缺口或待补充项的 Assessment,缺口面板*必*以区别于常规文本的醒目样式呈现*全部*该类项,且每一项*必*提供定位至其对应录入位置的入口。
**Validates: Requirements 21.3**
### Property 75: Draft 往返保真
*对任意* Assessment 录入状态,将其保存为 Draft 后再打开该 Draft,所恢复的已录入数据*必*与保存前等价,且恢复后所处的 Wizard 步骤*必*等于保存时所处步骤。
**Validates: Requirements 21.5, 21.6**
### Property 76: 断点布局映射确定性
*对任意* Viewport 宽度,`selectLayout` *必*返回唯一确定的布局:宽度不小于 1280 → 桌面布局;768 至 1279 → 紧凑布局;小于 768 → 移动布局;且移动布局的看板视图*必*保留 Risk_Score、Risk_Grade 与 Top N 关键风险清单的呈现。同一宽度*恒*映射到同一布局。
**Validates: Requirements 22.1, 22.2, 22.3**
### Property 77: 文本对比度达标
*对任意* Theme 下任意正文文本与其背景的 Color_Token 对,二者计算所得相对对比度*恒*不低于 4.5:1;*对任意*大号文本与其背景的 Color_Token 对,对比度*恒*不低于 3:1。
**Validates: Requirements 23.3**
### Property 78: 表单可访问标注与错误提示
*对任意*表单输入控件,*必*关联一个非空、可被辅助技术识别的文本标签;且*对任意*校验失败的输入控件,*必*为其呈现可被辅助技术识别的非空错误提示文本。
**Validates: Requirements 23.4, 23.5**
### Property 79: 图表非纯颜色编码
*对任意* Chart 中的数据类别,*必*存在颜色之外的区分编码(文本标签或图案),使该类别在不依赖颜色的情况下仍可识别。
**Validates: Requirements 23.6**
### Property 80: 操作状态反馈映射
*对任意*用户触发的操作及其生命周期,UI 呈现的状态*必*确定性映射为:处理中→Loading_State、成功→成功反馈、失败→可读错误信息;且失败时该错误信息*必*非空地说明失败原因并提供指向修正路径的操作入口。
**Validates: Requirements 24.1, 24.2, 24.3**
### Property 81: 角色默认路由确定性
*对任意*登录用户角色,`defaultRoute` *必*返回唯一确定的默认视图:商务/销售→商务/销售视图、风控→风控视图、管理层→管理层看板;*对任意*未分配上述任一角色的用户,*必*返回需分配角色的提示视图且不呈现任何评估数据。
**Validates: Requirements 25.1, 25.2, 25.3, 25.5**
## Error Handling
错误处理遵循统一原则:**输入校验前置、错误可解释、失败不破坏既有状态、降级不中断主流程**。
| 错误场景 | 处理策略 | 关联需求 |
|----------|----------|----------|
| 项目描述信息不足(空/纯空白/<10 有效字符) | 拒绝分类,返回信息不足错误 | 1.6 |
| 无可用模板(无精确且无默认) | 终止评估,返回无可用模板提示 | 2.6 |
| 模板数据非法(缺必填/权重和≠100%) | 不实例化,终止,返回模板数据错误并指明问题项 | 2.4 |
| 模板继承环或层级>5 | 终止,返回继承错误 | 2.7 |
| 追问无效回答 | 保留缺口标记,返回需补充信息提示 | 3.4 |
| 追问轮次耗尽仍缺失 | 降级:行业默认值 + 标注"智能体假设",继续流程 | 3.6 |
| 无任何启用指标/维度 | 终止评分,返回评分数据不足错误 | 4.5 |
| 红线数据缺失/为假设 | 标"待核实",不计命中,报告说明原因 | 6.5 |
| 评分未完成请求费用测算 | 拒绝,返回评分未完成提示 | 8.5 |
| 流程未完成请求生成/导出报告 | 拒绝,返回流程未完成提示 | 10.4 |
| 报告导出失败 | 中止导出,保留已生成报告不变,返回导出失败错误 | 10.5 |
| 配置校验失败 | 拒绝保存,保留上次有效配置,返回失败项 | 11.7 |
| 同级权重和为 0 | 拒绝保存,返回权重校验错误 | 11.8 |
| 非授权角色修改配置 | 拒绝,配置不变,返回权限不足错误,写审计 | 12.1, 12.3, 12.5 |
| 用户无角色 | 拒绝展示视图,提示分配角色 | 13.5 |
| 行业分区内容缺类 | 拒绝创建,指明缺失类别,已有分区不变 | 14.4 |
| 外部数据失败/超时/错误 | 降级回退用户输入→(仍缺)智能体假设,不中断 | 15.3, 15.4 |
| Region 无对应规则集 | 拒绝合规判定/费用测算,提示地域暂不支持 | 16.6 |
| 持久化失败 | 保留会话数据,返回存储失败错误 | 17.2 |
| 复评引用不存在评估 | 拒绝,返回评估不存在提示 | 17.4 |
| 对比选中<2 个评估 | 拒绝,提示至少需 2 个 | 17.6 |
| 存在未保存修改时离开评估流程 | 弹出确认提示,未确认则不离开,保留当前数据 | 21.7 |
| 图表数据为空 | 呈现 Empty_State 并提示无可展示数据,不抛错 | 20.4 |
| 图表数据加载中 | 呈现 Loading_State,不阻塞页面其余部分 | 20.5 |
| 用户操作失败 | 呈现可读错误信息(说明原因)+ 指向修正路径的操作入口 | 24.3 |
| 报告导出执行中 | 呈现进度反馈,30 秒内给出完成或失败终态 | 24.4 |
| 请求的 Region/数据缺失致图表无数据 | 图表降级为 Empty_State,主视图其余部分照常呈现 | 20.4 |
| 登录用户无角色 | 呈现需分配角色提示视图,不呈现评估数据 | 25.5 |
错误响应统一携带:错误码、面向用户的可读消息、关联的需求/配置项标识(便于定位)。降级类错误(追问耗尽、外部数据失败)不向用户报错而是以 Data_Provenance 标注体现,保证主流程不中断(Req 3.6、15.4)。
## Testing Strategy
采用**单元测试 + 属性化测试 + 集成测试**三层互补策略。属性化测试覆盖纯算法与不变式逻辑(评分、归一化、分级、红线、排序、权重归一化、决策表、来源标注等),单元测试覆盖具体示例与边界,集成测试覆盖外部 IO、导出、持久化失败与架构解耦。
### 属性化测试(Property-Based Testing
适用范围:本特性的核心评分/分级/红线/排序/费用/配置/合规/持久化逻辑均为确定性纯函数或具备清晰输入输出的状态转移,高度适合 PBT。
约束:
- 选用目标语言的成熟 PBT 库(如 TypeScript 的 fast-check、Python 的 Hypothesis、JVM 的 jqwik),**不自行实现** PBT 框架。
- 每个属性测试*至少运行 100 次迭代*。
- 每个属性测试以注释标注其对应设计属性,标签格式:
`Feature: outsourcing-risk-assessment, Property {number}: {property_text}`
- 每条 Correctness Property 由*单个*属性测试实现,共 81 条属性(含 Req 19-25 的 UI 可属性化标准 19 条:Property 63-81)。
生成器要点:
- 随机生成合法/非法风险模型(维度、指标、权重向量、启停状态、评分规则、红线)。
- 边界覆盖:纯空白与 <10 字符描述、权重全零、Risk_Level 同取 1/5、Risk_Score 区间边界 0/25/50/75/100、继承深度 5/6 与含环图、N=1/50 与启用项少于 N、空 Assessment 集合、<2 项对比集合。
- 三态 Data_Provenance 与 Confidence 边界(0、1)覆盖。
- UI 属性生成器:随机 ThemeLight/Dark)、随机 Viewport 宽度(覆盖 <768 / 768-1279 / ≥1280 及断点边界 767/768/1279/1280)、随机已录入数据快照、随机图表数据(空集/单系列/多系列/多类别)、随机 Wizard 步骤序列与推进操作、随机 Color_Token 文本/背景对、随机角色(含无角色)。
### 前端 UI 测试(组件测试 + 可视化回归 + 自动化可访问性)
对纯视觉/主观、键盘可达性、可见位置与时延等不适合属性化的 UI 标准,采用以下互补手段覆盖:
- **组件测试**:验证 Design_System 同类组件在各页面外观/行为一致(19.1)、单一图标集引用(19.5)、一键操作入口存在(21.4)、默认视图首屏含角色匹配功能入口(25.4)、未保存离开确认(21.7)、规定全套图表组件可渲染(20.1)。
- **可视化回归测试**:对关键页面与图表(含 Light/Dark 双主题、各断点布局)建立基线快照,验证排版/配色/间距视觉一致与图表标签不被遮挡(19.1、20.3)。
- **自动化可访问性检查(axe)**:对全部页面运行 axe 规则集,验证键盘可聚焦与可见焦点指示(23.1、23.2)、标签关联与 ARIA 正确性(23.4、23.5),作为属性化对比度校验(Property 77)之外的补充。
- **性能/时延检查**:主题切换 1 秒内生效(19.7)、报告导出 30 秒内给出终态(24.4)以性能与集成测试度量,不纳入属性化。
- **人工审查**:"专业一致的视觉体验"等主观目标由设计评审与可用性走查保证。
### 单元测试(示例与边界)
- 行业语义识别(1.2):代表性描述验证可识别行业与"未识别"分支。
- Assessor 可执行评估(12.2):示例验证允许路径。
- 具体合规算例:给定社保基数、派遣比例、最低工资的代表性数值,验证 N/N+1 与社保金额计算正确(配合属性 53/54)。
- 各错误分支的代表性触发与消息内容。
- UI 示例:图表全套组件渲染(20.1)、一键入口存在(21.4)、单一图标集引用(19.5)、默认视图首屏角色入口可见(25.4)、未保存离开确认弹窗(21.7)的代表性用例。
### 集成测试(外部依赖与架构解耦,1-3 例)
- 报告导出(10.2、10.5):验证导出文件自包含且含全部章节、耗时 < 30 秒;注入导出失败验证报告内容不变。
- 外部数据适配(15.1、15.5):mock 数据源验证成功取数路径;注册新适配器验证无需改 Scoring_Engine 源码即可使用。
- 知识库行业分区扩展(14.2):运行时新增分区后验证其 Template 可被加载,无需重编译。
- 持久化失败(17.2):注入存储失败,验证会话数据保留并返回错误。
### 追溯性
每条属性、单元用例与集成用例均标注其验证的需求编号,确保 25 条需求的可测试验收标准全部被覆盖;非可测试标准(如 UI 主观体验、纯架构组织约束、键盘可达性、时延与可见位置)以设计审查、可视化回归与自动化可访问性检查保证。