You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
13 KiB
13 KiB
四维能力测评 API 设计文档(V36 设计锁定版)
状态:设计已锁定,待编码。功能版本 V36。题库为自研工作情境题;本版不接入候选评分引擎、不向企业开放结果。题目统计质量门槛保留为后续试测工作,不阻塞本版功能实现。
0. 产品来源摘要(func.xlsx,已确认)
- 功能名:能力测评(4维度) = 逻辑 / 沟通 / 执行 / 学习 能力四维测评(
功能详细清单 D24/F24、求职端功能详情 B24/C24、企业端功能详情)。 - 目标:了解自己目前的能力短板在哪里(G24)。
- 结果展示:四维能力测试 → 能力雷达图 + 短板提示(F24)。
- 限时:测评限时 30 分钟,超时强制提交(G24)。
- 完成率:测评完成率 ≥ 70%(H24,中途退出保存进度的判定)。
- 质量:测评区分度 ≥ 0.4(H24/H52,为非功能质量门槛)。
- 能力测评评分(F1.2):基于四维得分 → 能力综合分,「让企业看到我的能力测评结果」;未测评显示「待测评」(G52)。
- 成长信号:学习能力/成长速度潜力分(F55/G55)。
1. 功能范围与非目标
范围内(第一版 V36):
- 四维能力测评的题型目录、创建答卷、答题保存、进度恢复、提交、结果查询。
- 结果含四维分、综合分、最低维度短板提示、雷达图数据、题目解析与有效期状态。
非目标(V36 默认不做,除非负责人确认):
- 不接入 Candidate Scoring / 不写
candidate_dimension_scores(ABILITY 保持 PENDING)。 - 不提供企业查看学生能力测评结果的接口。
- 不做岗位推荐、AI 路径建议、开放题或 AI 自动评分。
- 不做定时器批量改写结果有效期;结果是否过期在读取或新建答卷时由后端按
valid_until动态判断。
2. 四个能力维度的正式名称与编码
| 编码(Code) | 名称 | 说明 |
|---|---|---|
| LOGIC | 逻辑能力 | 逻辑/推理/分析 |
| COMMUNICATION | 沟通能力 | 表达/协作/共情 |
| EXECUTION | 执行能力 | 行动/落地/结果导向 |
| LEARNING | 学习能力 | 学习/成长/适应 |
编码和结果字段按上表锁定。
3. 题库来源、题目数量、题目版本
- 题目来源:自研(
SELF_AUTHORED),不复制商用量表。 - 锁定题库文件:
docs/ability-question-bank-v0.1.json。迁移种子、题库测试和题目版本必须以该文件为唯一权威来源,禁止在 SQL 或 Java 中自行改写题干、选项、答案键、分值或解析。 - 题库总量:每维 12 题,共 48 题;每次答卷从每个维度分层随机抽取 6 题,共 24 题。
- 题型:单选题、情境判断题、排序题;允许选项部分得分,不采用开放题。
- 题目版本:
ability-v0.1。每题必须保留difficulty、discrimination、version字段;前两项允许在首版种子数据中为空,试测后回填。
4. 是否固定题目或分层随机抽题
- 采用分层随机抽题:从每维 ACTIVE 题库随机抽取 6 题,并把题目集合、顺序、题目版本和题目快照持久化;刷新、恢复和重复读取均不得重新抽题。
- 新建或重测答卷均重新抽取本次 24 题;不得向前端返回内部维度、答案键、评分规则或题目版本。
5. 单次答题数量与完成条件
- 单次题量固定为 4 维 × 6 = 24 题。
- 必须回答 24/24 才能提交;任何未完成答卷均返回
ABILITY_INCOMPLETE,不得依据 70% 生成正式结果。 - 产品“完成率 ≥ 70%”仅用于过程进度展示,不构成提交门槛。
6. 题型与计分规则
- 每题均为后端判分的工作情境题。每个选项对应 0、1、2 或 4 分;选项及其得分、标准答案键、评分规则和解析均只保存在后端。
- 每维原始分为该维 6 题得分之和,维度百分制分数为
rawScore / 24 × 100;保留两位小数,使用HALF_UP。 - 综合分为四维百分制得分的等权平均;只有四维均完成 6 题时才生成综合分。
- 短板取最低维度;若最低分并列,返回全部并列维度。结果页同时返回每道题解析,但仅限答卷提交后由本人读取。
7. 中途保存和恢复规则
- 保存答案对 (attempt, question) upsert;同请求内同题重复 → 校验拒绝。
- 获取答卷恢复:固定题目顺序 + 已答值;刷新不重抽题。
- 未答完可退出,下次 GET 恢复;与 RIASEC 一致(active 答卷阻塞重测)。
8. 答卷状态机
锁定状态机:
DRAFT → IN_PROGRESS → COMPLETED
IN_PROGRESS --(超过 expires_at 且未提交)--> EXPIRED
- 创建答卷仅进入
DRAFT,不开始计时。 - 第一次成功保存答案时,后端一次性设置
started_at=now、expires_at=started_at+30分钟,并转为IN_PROGRESS。 - 后续保存、读取、提交均由后端校验
expires_at;超时未答完 24 题时,原子标记为EXPIRED,不生成结果、不可继续答题或提交。 DRAFT没有倒计时;同一学生同一类型始终至多存在一份DRAFT/IN_PROGRESS活跃答卷。
9. 重测和历史保留规则
- 历史答卷和结果永久保留,不删除。
- 完成时写入
valid_until = completed_at + 7天。在valid_until前为当前有效结果;到期后结果仍可查询,但validityStatus=EXPIRED且仅作为历史结果。 - 不设置“历史最高分”。当前结果只取最近一次已完成且仍有效的结果,避免用户通过反复答题刷取最高分。
- 有效结果存在期间禁止重测;结果到期后方可创建下一份答卷。
- 每名学生滚动 90 天内最多完成 3 次测评;未完成而超时的
EXPIRED答卷不计入该完成次数。
10. 提交幂等与并发策略
- 唯一键:
(student_user_id, idempotency_key)幂等;active_key(学生+类型+ACTIVE)保证同类型最多 1 份活跃答卷(复用 V35 已验证方案)。 - 提交原子化:
DRAFT/IN_PROGRESS → COMPLETED的批量更新返回行数;仅行数=1 者生成结果+写审计;并发只产生 1 条 result + 1 条提交审计;重复提交幂等返回原结果。 - 提交并发无 500(沿用 V35 REQUIRES_NEW + READ_COMMITTED 修复)。
- 创建时先校验当前有效结果是否存在,再校验 90 天完成次数;两类限制须有对应错误码,不能误报为活跃答卷冲突。
11. 权限矩阵
| 接口 | 未登录 | STUDENT | COMPANY | ADMIN |
|---|---|---|---|---|
| 类型列表 | 401 | 200 | 200 | 200 |
| 创建 / 答卷 / 保存 / 提交 / 结果 / 历史 | 401 | 仅本人 | 403/2002 | 403/2002 |
- 身份一律 JWT/SecurityContext,不接受 userId 参数。
- 第一版不提供企业查看能力结果接口;能力综合分写入评分引擎与企业侧结果展示均为后续独立评审事项。
12. 错误码
- V35 RIASEC 已占用
9701–9709(97xx)。V36 使用独立区间9801–9811(能力测评),避免复用冲突:9801 ABILITY_TYPE_NOT_FOUND、9802 ABILITY_ATTEMPT_NOT_FOUND、9803 ABILITY_ATTEMPT_INVALID_STATE、9805 ABILITY_ANSWER_INVALID、9806 ABILITY_INCOMPLETE、9807 ABILITY_CONCURRENT_UPDATE、9808 ABILITY_DUPLICATE_ACTIVE、9809 ABILITY_IDEMPOTENCY_CONFLICT。
9810 ABILITY_RETAKE_COOLDOWN(409):当前仍存在有效完成结果,尚不可重测。9811 ABILITY_RETAKE_LIMIT(429):滚动 90 天内已完成 3 次。- 复用
1001/2001/2002;超时答卷读取、保存或提交统一按9803 ABILITY_ATTEMPT_INVALID_STATE处理。
13. DTO 与接口字段
接口采用独立 /abilities/** 命名空间(最终 7 个接口):
GET /abilities/types
POST /abilities/attempts
GET /abilities/attempts/{attemptId}
PATCH /abilities/attempts/{attemptId}/answers
POST /abilities/attempts/{attemptId}/submit
GET /abilities/attempts/{attemptId}/result
GET /abilities/me?page&size
V36 不提供 GET /abilities/{type}/questions;题目只在创建答卷后通过 GET /abilities/attempts/{attemptId} 返回。
- 题目响应隐藏
dimension/questionCode/competencyTag/source/reverseScored/questionVersion/answerKey/scoringRule(不泄露能力维度语义与计分内部字段)。 - 结果响应(白名单):
attemptId/typeCode/status/validityStatus/validUntil/dimensionScores[{code,score,answeredCount}]/overallScore/weaknesses/radar/answeredCount/completionRate/questionFeedback[{questionId,selectedOption,explanation}]/disclaimer。不含答案键、选项得分、studentUserId、phone、email、password。
14. 数据库表、索引、唯一约束、外键
采用独立 ability_* 六表,避免与 V35 RIASEC 的题型、判分方式和生命周期耦合:
ability_definitions type_code UNIQUE; status; scale_type; question_count; attempt_question_count; min_per_dimension; question_set_version; rules_version
ability_questions UNIQUE(definition_id, question_code), UNIQUE(definition_id, position), CHECK(dimension IN LOGIC/COMMUNICATION/EXECUTION/LEARNING), item_type/options_json/answer_key_json/scoring_rule_json/explanation/difficulty/discrimination/version
ability_attempts UNIQUE(student_user_id, idempotency_key), UNIQUE(active_key), @Version, CHECK(status IN DRAFT/IN_PROGRESS/COMPLETED/EXPIRED)
ability_attempt_questions UNIQUE(attempt_id, question_id), UNIQUE(attempt_id, position), question_version/question_snapshot_json
ability_answers UNIQUE(attempt_id, question_id), selected_option/awarded_score/answered_at
ability_results UNIQUE(attempt_id)(幂等)
- 外键:attempt→definitions/users(CASCADE)、attempt_question/answer→attempt(CASCADE)+question、result→attempt(CASCADE)。题目快照用于保证题库后续修订或停用后,历史答卷和提交后的解析仍按当时版本展示与计分。
- 索引:
(student_user_id, created_at)、active_key唯一、status等。 - 时间相关字段:
started_at/expires_at/submitted_at/completed_at;结果含valid_until。active_key仅在DRAFT/IN_PROGRESS非空,进入COMPLETED/EXPIRED后置空。
15. 脱敏要求
- 题目响应不泄露维度与内部编码;结果不返回原始答案、手机号、邮箱、password、JWT、他人信息。
- 不保存不必要的题面;审计不含题面/答案/PII。
16. 审计要求
- 写入
ABILITY_ATTEMPT_CREATED/ABILITY_ATTEMPT_SUBMITTED。 - details 仅允许
attemptId/typeCode/status/answeredCount/questionSetVersion/rulesVersion/requestId/timestamp;禁止题面、答案、手机号、邮箱、JWT。
17. 是否写入 candidate_dimension_scores
- V36 第一版不写
candidate_dimension_scores,ABILITY 维度维持PENDING;不提供企业端能力测评结果接口。 - 将能力综合分写入评分引擎、企业端查看结果均为后续独立评审事项。
18. OpenAPI 增量
- 基线 134 paths / 168 operations。
- 固定 +7 paths / +7 operations(
/abilities/**7 端点:类型/创建/详情/保存/提交/结果/我的历史)→ 141 paths / 175 operations;V36 不提供GET /abilities/{type}/questions。运行时 OpenAPI 必须与静态一致。
19. MockMvc、集成测试和 MySQL 黑盒验收方案
- 测试类(镜像 RIASEC):
AbilityAssessmentCatalogTest、AbilityAssessmentResultComputerTest、AbilityAssessmentAttemptServiceTest、AbilityAssessmentControllerTest、AbilityAssessmentPersistenceIntegrationTest(含并发创建/并发提交)、种子/迁移测试。
- 覆盖:创建、幂等重放、同 key 同/异请求、活跃重复、有效结果冷却、90 天完成上限、中途保存、首次保存起算、恢复同一题、30 分钟超时、非法/跨答卷题 ID、未答完提交、重复提交、并发创建/提交、STUDENT/COMPANY/ADMIN/匿名权限、结果和题目解析脱敏、业务表无异常写入、Flyway、外键/唯一约束。
- MySQL 黑盒:健康 200、Flyway 最新成功、运行时/静态 OpenAPI 一致、表/约束/数据核验、并发无 500、审计脱敏、队列归零、
candidate_dimension_scores行数不变、V31–V35 回归。
20. 回滚与兼容方案
- 不修改 V1–V35 表与语义;V36 迁移为附加新表
V35__ability_assessment.sql(当前最新 Flyway 为 V34,下一编号为 V35;功能版本仍标 V36)。 - 回滚:删除 V36 迁移即可,不影响 V35 及既有数据。
- 使用独立
/abilities/**命名空间与独立ability_*表,回滚不会影响 V35 RIASEC。
21. 试测与上线声明
- 首版 48 题必须在后续试测中统计难度、选项分布与区分度;区分度低于 0.4 或存在明显歧义的题目应修改、停用或替换。
- 当前未定义试测样本量和正式上线统计门槛,因此本版不得宣称题库已完成心理测量学验证。
- 结果页必须声明:本测评反映当前工作情境答题表现,用于自我了解和能力提升参考;不构成职业资格、正式招聘结论或永久能力标签。
本设计已由负责人确认,可进入 V36 编码;试测统计口径为后续运营与题库质量治理工作,不阻塞本版实现。