有关志愿通的代码仓库
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.
 
 
 
 
 

18 KiB

志愿通 P0 后端建设蓝图

1 结论

现有系统已经完成全国院校主档、2025 年各省招录数据、来源追溯和人工审核台,适合作为志愿通的内部数据治理底座。下一阶段不应重写现有审核系统,而应在同一个 Spring Boot 工程中逐步建设面向考生的业务模块,并在原始业务表与公开查询接口之间增加标准化、审核发布和查询读模型。

P0 的首要闭环是:考生输入省份、科类或选科、分数和位次,系统完成报考资格过滤,给出可解释的冲稳保候选院校,用户可以查看院校和专业信息、收藏并进行多校对比。

当前只有 2025 年全国快照,第一版推荐结果应称为“风险分层”或“冲稳保建议”,不能展示为统计意义上的录取概率。补齐至少三个招生年度的数据后,再引入趋势稳定性和概率模型。

2 当前工程与数据盘点

2.1 已有工程

  • 后端:Spring Boot 3.5.7、Java 17、Spring JDBC、MySQL。
  • 前端:Vue 3、Vite、Element Plus。
  • 当前产品形态:内部数据审核台,不是考生端应用。
  • 当前后端结构:一个通用数据控制器和一个动态 SQL 服务,支持分页筛选、数据详情、审核状态和审核历史。
  • 当前接口前缀:/api,主要服务内部审核前端。
  • 当前测试:只有基础占位测试,尚无数据库、接口和推荐规则测试。

2.2 实库数据快照

以下数字来自当前运行中的审核后台:

数据集 2025 年记录数 说明
全国院校主档 2,952 教育部十位代码作为稳定标识
院校专业组 193,564 其中约 91.88% 已匹配院校稳定 ID
专业招生计划 866,917 各省字段完整度差异较大
专业录取线 432,005 约 97.51% 已匹配院校稳定 ID
院校或专业组投档线 68,567 约 97.14% 已匹配院校稳定 ID
一分一段 28,010 西藏仍无可用记录
控制线 159 山西、青海当前覆盖缺失

31 个省级地区均已建立 2025 采集范围,其中 27 个标记为已采集,4 个标记为部分采集。当前公开快照还存在这些明确缺口:

  • 山西:专业录取线、普通类控制线缺失。
  • 青海:院校投档线、专业录取线、普通类控制线缺失。
  • 西藏:一分一段缺失。
  • 招生计划来源中,科类、专业组、专业代码和计划人数存在大量空缺或未标注值。
  • 科类维度同时存在“物理类”“物理科目组合”“理科”“理工类”等来源值,需要按省份、年份和考试模式标准化,不能直接用字符串判断报考资格。
  • 约 160 万条记录仍处于待审核状态,公开接口不能默认把全部记录视为可信数据。

2.3 已有表可以继续使用

  • 数据来源与导入:data_sources、ingestion_runs、各类 stg_* 表。
  • 院校主档:schools、school_names、school_external_codes、school_campuses。
  • 招录事实数据:admission_groups、admission_major_plans、admission_cutoff_lines、admission_major_lines、score_rank_points、control_score_lines。
  • 数据治理:dataset_coverage、collection_scopes、review_records、review_audit_logs。

这些表继续承担采集、追溯和审核职责。面向考生的高频查询不应直接拼接这些表和 review_records。

3 目标架构

P0 采用模块化单体,不拆微服务。保持一次部署和一个数据库,通过包边界、应用服务和只读查询模型控制复杂度。

采集文件和官方来源
        |
        v
暂存表 stg_* -> 规范化业务表 -> 人工审核 -> 发布版本
                                           |
                                           v
                                    公共查询读模型
                                           |
                  +------------------------+------------------------+
                  |                        |                        |
              院校查询                 推荐引擎                 用户与志愿表
                  |                        |                        |
                  +------------------------+------------------------+
                                           |
                                      REST API v1

3.1 包结构

保留现有 cn.zhiyuantong.review,新增以下顶层业务包:

cn.zhiyuantong
  common
    api
    error
    security
    persistence
  review
    现有审核台代码
  publishing
    数据标准化 发布版本 质量门禁
  catalog
    院校 校区 城市 排名 学科 专业
  admission
    招生规则 计划 投档线 专业录取线 一分一段
  recommendation
    资格过滤 风险分层 推荐解释
  comparison
    多校对比 对比导出
  account
    登录 考生档案 收藏
  volunteer
    志愿方案 志愿项 排序

每个业务包内部按 controller、application、domain、repository 分层。P0 不强制使用完整领域驱动设计,但禁止控制器直接拼 SQL。

3.2 接口隔离

  • 现有审核接口暂时保持 /api/**,避免破坏审核前端。
  • 新增考生端接口统一使用 /api/v1/**。
  • 后续再把审核接口迁移为 /api/admin/v1/**,迁移期间保留兼容路由。
  • 考生端只能读取已发布版本,不能直接查询待审核记录。

4 数据发布与标准化层

4.1 必须新增的发布表

dataset_publications

记录一次可供考生端使用的数据发布。

关键字段:

  • publication_id
  • province_name
  • admission_year
  • dataset_name
  • version_no
  • status:draft、validating、published、withdrawn
  • source_record_count
  • published_record_count
  • quality_grade
  • published_at
  • published_by

data_quality_issues

保存缺失字段、院校未匹配、维度无法识别、数值异常和跨表冲突。

关键字段:

  • issue_id
  • entity_type
  • entity_key
  • issue_code
  • severity
  • field_name
  • issue_message
  • resolution_status
  • detected_at
  • resolved_at

admission_dimension_mappings

把来源中的科类、批次、招生类别和培养层次映射为稳定代码。

关键字段:

  • dimension_type
  • province_name
  • admission_year
  • source_value
  • canonical_code
  • canonical_name
  • verification_status

必须结合省份和年份映射,不能把全国来源值做成一张无上下文的同义词表。

4.2 公共读模型

建议通过普通表维护公开快照,不使用复杂实时视图:

  • public_school_profiles
  • public_school_admission_stats
  • public_major_admission_stats
  • public_score_rank_points

发布操作在事务内生成新版本,校验完成后切换当前版本。上一版本至少保留一份,以支持快速回滚。

4.3 发布质量门禁

任一省份数据发布前至少满足:

  1. 来源文件可追溯且哈希存在。
  2. 省份、年份、科类和批次已映射为标准维度。
  3. 一分一段分数顺序、累计人数和位次区间单调有效。
  4. 分数、位次、计划数不存在明显越界。
  5. 推荐所用记录必须匹配稳定院校 ID。
  6. 未通过审核的数据不进入公开快照。
  7. 缺失数据要转化为质量等级和用户可见说明,不能静默补零。

5 P0 核心业务表

5.1 考试模式与选科规则

province_exam_configs

保存某省某年的考试模式、总分和科类结构。

  • province_name
  • exam_year
  • exam_mode:traditional、three_plus_one_plus_two、three_plus_three
  • total_score
  • rank_basis
  • effective_from
  • effective_to

subject_requirement_rules

把来源中的选科要求解析为机器可判定规则。

  • rule_id
  • raw_requirement
  • rule_type:all、any、first_choice、unlimited
  • required_subjects_json
  • excluded_subjects_json
  • verification_status

5.2 专业标准库

当前系统只有招生记录里的 major_name,缺少稳定专业实体。需要新增:

majors

  • major_id
  • major_code
  • major_name
  • degree_level
  • discipline_category
  • major_category
  • degree_type
  • status

major_aliases

  • major_alias_id
  • major_id
  • alias_name
  • alias_type
  • valid_from_year
  • valid_to_year

admission_major_mappings

将省级招生计划和录取线中的专业名称映射到标准专业;专业类、大类招生和方向不能强制映射为单一专业。

5.3 院校内容与标签

school_tags

保存 985、211、双一流、办学层次、特色类型等带来源和有效期的标签。

school_rankings

按排名机构、年份、榜单类型保存名次,禁止在 schools 主表上放一个没有口径的 ranking 字段。

school_disciplines

保存学科评估、一流学科和优势学科,并记录评估轮次和来源。

school_statistics

保存保研率、升学率、就业率、师生规模等年度指标。

campus_facilities 与 campus_media

分别保存宿舍、食堂、图书馆、体育设施等结构化属性,以及图片、版权、来源和审核状态。

city_profiles

保存城市气候、生活成本、交通、产业和就业特征。所有数值字段必须包含统计年份和来源。

5.4 用户、收藏与志愿方案

user_accounts

保存系统用户和账号状态。手机号使用加密列和单独的检索哈希,不保存明文日志。

user_identities

保存微信 OpenID、UnionID 或手机号身份,一个用户可以绑定多个登录方式。

candidate_profiles

  • user_id
  • exam_year
  • province_name
  • admission_category
  • subject_combination_json
  • score
  • rank_value
  • target_education_level
  • preferred_regions_json

school_favorites

用户与院校唯一关联,支持收藏时间和备注。

volunteer_plans 与 volunteer_items

保存一个考生的多套方案,以及方案内院校专业组、专业、顺序、是否服从调剂和风险等级。

5.5 推荐记录

recommendation_runs

保存用户输入、使用的数据版本、规则版本和运行时间,使推荐结果可复现。

recommendation_items

保存候选院校或专业组、风险等级、位次差、命中规则、排除原因和数据质量等级。

推荐结果不能只保存一个总分。前端需要展示“为什么推荐”和“为什么被排除”。

6 推荐引擎 V1

6.1 输入

  • 考试省份和年份
  • 招生类别
  • 科类或选科组合
  • 分数与位次,至少一个必填
  • 目标培养层次
  • 可选地区、学校性质、专业偏好

6.2 计算流程

  1. 使用当年一分一段完成分数和位次互换。
  2. 按省份、年份、招生类别、培养层次和批次筛选记录。
  3. 使用结构化选科规则执行资格过滤。
  4. 剔除未发布、院校未匹配、关键位次缺失或质量等级过低的数据。
  5. 以考生位次和院校或专业组最低位次计算位次差与位次差比例。
  6. 使用可配置阈值划分冲、稳、保。
  7. 根据地区、学校属性、专业偏好和数据质量排序。
  8. 为每个结果生成解释和风险提示。

6.3 单年数据下的风险定义

V1 默认使用配置化阈值,阈值按省份和考试模式分别设置。例如:

  • 冲:考生位次略低于上一年最低位次。
  • 稳:考生位次优于上一年最低位次,且处于合理缓冲区。
  • 保:考生位次明显优于上一年最低位次。

实际阈值必须通过样本回测后确定,不把示例比例写死在业务代码中。响应中必须返回:

  • riskLevel
  • rankGap
  • rankGapRatio
  • dataYear
  • dataQualityGrade
  • reasons
  • warnings

6.4 升级到多年度模型

补齐历史数据后增加:

  • 同位分或等位分换算。
  • 三年最低位次中位数、波动范围和趋势。
  • 招生计划变化率。
  • 异常年份降权。
  • 录取概率校准和历史回测报告。

7 第一批接口

7.1 无需登录即可使用

方法 路径 用途
GET /api/v1/meta/admission-contexts 返回省份、年份、考试模式、可选科类和数据可用性
GET /api/v1/score-ranks/convert 分数与位次互换
GET /api/v1/schools 院校搜索与条件筛选
GET /api/v1/schools/{schoolId} 院校综合详情
GET /api/v1/schools/{schoolId}/admissions 指定生源省份下的计划和录取数据
GET /api/v1/schools/{schoolId}/campuses 校区、住宿、交通和设施
GET /api/v1/majors 标准专业搜索与分类筛选
GET /api/v1/majors/{majorId} 专业课程、选科、就业和相近专业
POST /api/v1/recommendations/schools 生成院校或专业组冲稳保结果
GET /api/v1/recommendations/{runId} 查询可复现的推荐结果
POST /api/v1/comparisons/schools 对比 2 至 4 所院校

GET /api/v1/meta/admission-contexts 必须先实现。前端不能自己猜某省有哪些科类、批次或数据是否齐全。

7.2 登录用户接口

方法 路径 用途
POST /api/v1/auth/wechat/login 微信登录或绑定
POST /api/v1/auth/sms/send 发送短信验证码
POST /api/v1/auth/sms/login 手机号验证码登录
GET /api/v1/me/profile 获取考生档案
PUT /api/v1/me/profile 更新考生档案
GET /api/v1/me/favorites/schools 收藏院校列表
PUT /api/v1/me/favorites/schools/{schoolId} 收藏院校
DELETE /api/v1/me/favorites/schools/{schoolId} 取消收藏
POST /api/v1/me/volunteer-plans 新建志愿方案
PUT /api/v1/me/volunteer-plans/{planId} 修改方案和排序
GET /api/v1/me/volunteer-plans/{planId} 查询志愿方案

短信和微信接口先定义应用层端口,第三方供应商实现放在基础设施层,避免业务代码绑定具体厂商。

7.3 内部管理接口

第一阶段继续复用现有审核接口,新增:

方法 路径 用途
POST /api/admin/v1/publications/validate 执行发布前质量检查
POST /api/admin/v1/publications 创建数据发布版本
POST /api/admin/v1/publications/{id}/publish 切换公开版本
POST /api/admin/v1/publications/{id}/withdraw 撤回有问题的版本
GET /api/admin/v1/quality/issues 查询质量问题
PUT /api/admin/v1/dimension-mappings/{id} 修正维度映射

8 实施顺序

P0 A 数据可发布

  1. 新增发布版本、质量问题和维度映射表。
  2. 标准化省份、招生类别、科类、考试模式、培养层次和批次。
  3. 为一分一段和招录数据增加自动质量校验。
  4. 建立公共读模型,只发布已通过的数据。
  5. 为现有数据审核接口补集成测试。

验收标准:指定省份可以生成一个可回滚的 2025 公开数据版本,且所有公开记录都有来源与质量等级。

P0 B 能查能筛

  1. 实现 admission-contexts 元数据接口。
  2. 实现分数位次转换。
  3. 实现院校列表、院校详情和招生详情。
  4. 建立标准专业库和专业映射最小版本。
  5. 增加 Redis 缓存前先通过 MySQL 索引和查询计划验证性能。

验收标准:用户可按省份、科类、分数或位次查询真实可用的院校和专业数据,缺失省份明确提示。

P0 C 能推荐能解释

  1. 实现资格过滤。
  2. 实现配置化冲稳保规则。
  3. 保存推荐运行与推荐明细。
  4. 返回推荐原因、排除原因和数据风险。
  5. 使用 2025 数据构造回放测试集。

验收标准:同一输入和同一数据版本得到稳定结果,任一推荐项都可以解释来源和风险等级。

P0 D 能收藏能对比

  1. 实现用户、身份与考生档案。
  2. 实现收藏和志愿方案。
  3. 实现 2 至 4 校对比。
  4. 逐步补充校区、宿舍、城市、排名和学科内容。

验收标准:用户可以保存多套方案,并基于同一口径对比院校。

9 暂不进入第一轮开发

  • 短视频播放、上传和转码。
  • 社区发帖、评论、点赞和学长认证。
  • VIP 付费与课程。
  • 直播、创作者激励和院校 B 端后台。
  • Elasticsearch。院校和专业基础搜索先使用规范化字段、索引和 MySQL 全文或前缀检索验证需求。
  • 机器学习录取概率。历史数据和回测体系未建立前只做规则化风险分层。

为减少后续重构,可预留统一内容审核抽象,但不在 P0 A 至 P0 C 实现内容生态业务。

10 第一轮开发任务

第一轮 P0 A 基础代码已完成:

  1. 已创建数据库迁移 008_create_publication_and_dimension_tables.sql。
  2. 已为科类和培养层次建立第一版标准代码与映射。
  3. 已新增 /api/v1/meta/admission-contexts。
  4. 已新增 /api/v1/score-ranks/convert。
  5. 已实现 publishing 发布前质量门禁和只读校验接口。
  6. 已增加科类归一化、公共接口、发布校验服务和 HTTP 路由测试。
  7. 已在本地 zhiyuantong 实库执行 008 迁移并写入 14 条初始维度映射。
  8. 已完成河北 2025 实库联调:上下文、分数转位次、位次转分数和发布门禁均通过。

第二轮 P0 A 已完成:

  1. 已新增 011_create_versioned_public_read_models.sql,建立五类不可变公共快照表和当前版本指针。
  2. 已实现创建快照、发布切换、撤回和把历史版本重新切换为当前版本的管理接口。
  3. 公共招录上下文和分数位次转换只读取当前已发布版本,不再直接读取待审核业务表。
  4. 已按教育部及省级招考部门资料核验并录入 2025 年 31 个省级地区考试模式:6 个 3+3、23 个 3+1+2、2 个传统文理科。
  5. 已发布考试模式版本 2025.exam-mode.v1,每个省份保留独立当前版本指针与来源快照。
  6. 已增加公共读模型 SQL 核验脚本和服务、HTTP 测试。

下一项 P0 A 工作是增加基于独立测试数据库的迁移和 SQL 集成测试;当前实库迁移和接口联调已经通过。