fix:sample/plate 之前的开发

This commit is contained in:
彭帅
2026-05-28 11:56:17 +08:00
parent fc36bc83e3
commit 8b65de36b8
367 changed files with 57752 additions and 947 deletions

View File

@@ -0,0 +1,67 @@
# 01 Core - crop 表录入说明
来源:`docs/requirements/01-core-data-entry-requirements.md`
## 录入目标
`crop` 记录项目涉及的作物范围,是 Core 上下文的起点。后续 program、trial、study、germplasm、observation_variable、genome_map 等数据都需要回到作物维度筛选和解释。
## 前置依赖和下游引用
| 类型 | 内容 |
| --- | --- |
| 表 | `crop` |
| 前置依赖 | 无 |
| 下游引用 | `program``location``trial``study``germplasm``observation_variable``genome_map` |
## 页面入口
| 页面 | 录入要求 |
| --- | --- |
| Crop 列表页 | 支持关键词查询、新增、编辑、查看详情、停用 |
| Crop 新增/编辑页 | 轻量表单,重点录入作物名称 |
| Crop 详情页 | 展示该作物下的项目、试验、研究、种质、图谱入口 |
列表页表格字段:`crop_name`、下游 program 数、下游 study 数、状态。
## 字段录入
| 字段 | 类型 | 控件 | 录入说明 | 校验/来源 |
| --- | --- | --- | --- | --- |
| `id` | varchar(255) | 隐藏/只读 | 作物主键,新增时系统生成,也可导入时指定 | 必填、唯一 |
| `auth_user_id` | varchar(255) | 隐藏 | 数据所属用户 | 登录上下文自动写入 |
| `crop_name` | varchar(255) | 文本框 | 作物名称,用于所有下拉选择展示 | 必填、建议唯一 |
## 校验规则
1. `crop_name` 必填。
2. `crop_name` 建议唯一,新增和编辑时需要做重复提示。
3. 已被下游引用的作物不能物理删除,只能停用或提示引用关系。
## 接口能力
| 接口 | 用途 |
| --- | --- |
| `GET /crops` | crop 分页查询 |
| `POST /crops` | 新增 crop |
| `GET /crops/{id}` | crop 详情 |
| `PUT /crops/{id}` | 编辑 crop |
| `DELETE /crops/{id}` | 删除或停用 crop需做引用检查 |
| `GET /selectors/crops` | crop 搜索下拉,参数 `keyword` |
## 导入导出
1. 支持通过 Core 导入流程导入 `crop`
2. 模板列名使用数据库字段名。
3. 可按 `id` 幂等更新;无 `id` 时新增。
4. 列表页支持导出当前筛选结果,导出文件应包含 ID 和展示名称。
## 删除/停用
`crop` 已被 `program``location``trial``study``germplasm``observation_variable``genome_map` 引用时,不允许物理删除。后端需要返回引用对象类型和数量,前端弹窗展示后引导用户停用。
## 验收点
1. Crop 列表页支持分页、关键词搜索和基础筛选。
2. 外键选择器展示作物名称,提交保存 `crop.id`
3. 被引用的 crop 删除失败时,前端展示引用详情。

View File

@@ -0,0 +1,76 @@
# 01 Core - person 表录入说明
来源:`docs/requirements/01-core-data-entry-requirements.md`
## 录入目标
`person` 记录项目负责人、trial 联系人、study 联系人和 list owner。它支撑责任追踪、联系人展示、权限和通知。
## 前置依赖和下游引用
| 类型 | 内容 |
| --- | --- |
| 表 | `person` |
| 前置依赖 | 无 |
| 下游引用 | `program.lead_person_id``trial_contact``study_contact``list.list_owner_person_id` |
## 页面入口
| 页面 | 录入要求 |
| --- | --- |
| Person 列表页 | 支持姓名、邮箱、机构筛选;新增、编辑、查看详情、停用 |
| Person 新增/编辑页 | 使用联系人表单维护人员信息 |
| Person 详情页 | 展示负责的 program、参与的 trial/study、拥有的 list |
列表页表格字段:姓名、邮箱、电话、机构、负责项目数、参与 study 数。
## 字段录入
| 字段 | 类型 | 控件 | 录入说明 | 校验/来源 |
| --- | --- | --- | --- | --- |
| `id` | varchar(255) | 隐藏/只读 | 人员主键 | 必填、唯一 |
| `auth_user_id` | varchar(255) | 隐藏 | 数据所属用户 | 登录上下文自动写入 |
| `description` | varchar(255) | 多行文本 | 人员说明、职责补充 | 可选 |
| `email_address` | varchar(255) | 邮箱输入框 | 邮箱地址 | 邮箱格式校验,建议唯一 |
| `first_name` | varchar(255) | 文本框 | 名 | 与 `last_name` 至少填写一个 |
| `institute_name` | varchar(255) | 文本框/选择器 | 所属机构 | 可选 |
| `last_name` | varchar(255) | 文本框 | 姓 | 与 `first_name` 至少填写一个 |
| `mailing_address` | varchar(255) | 多行文本 | 通讯地址 | 可选 |
| `middle_name` | varchar(255) | 文本框 | 中间名 | 可选 |
| `phone_number` | varchar(255) | 电话输入框 | 联系电话 | 可选,格式提示 |
| `userid` | varchar(255) | 文本框 | 外部用户 ID 或登录名 | 可选,建议唯一 |
## 校验规则
1. 姓名必填,`first_name``last_name` 至少填写一个。
2. `email_address` 需要校验邮箱格式。
3. 同一邮箱不建议重复录入。
4. 作为负责人或联系人被引用时,不允许物理删除。
## 接口能力
| 接口 | 用途 |
| --- | --- |
| `GET /persons` | person 分页查询 |
| `POST /persons` | 新增 person |
| `GET /persons/{id}` | person 详情 |
| `PUT /persons/{id}` | 编辑 person |
| `DELETE /persons/{id}` | 删除或停用 person需做引用检查 |
| `GET /selectors/persons` | person 搜索下拉,参数 `keyword``instituteName` |
## 导入导出
1. 支持通过 Core 导入流程导入 `person`
2. 模板列名使用数据库字段名。
3. 可按 `id` 幂等更新;无 `id` 时新增。
4. 列表页支持导出当前筛选结果,导出文件应包含 ID 和展示名称。
## 删除/停用
`person` 已作为 program 负责人、trial 联系人、study 联系人或 list owner 时,不允许物理删除。后端需要返回引用对象类型和数量,前端展示后引导用户停用。
## 验收点
1. Person 列表页支持分页、关键词搜索和机构筛选。
2. 邮箱格式错误时不能提交。
3. 作为负责人或联系人被引用的 person 删除失败时,前端展示引用详情。

View File

@@ -0,0 +1,77 @@
# 01 Core - program 表录入说明
来源:`docs/requirements/01-core-data-entry-requirements.md`
## 录入目标
`program` 表示长期育种项目,是多个 trial、study、材料、样本和结果的聚合维度。创建 program 时必须明确所属 crop可选负责人。
## 前置依赖和下游引用
| 类型 | 内容 |
| --- | --- |
| 表 | `program` |
| 前置依赖 | `crop`,可选 `person` |
| 下游引用 | `trial``study``location``crossing_project``seed_lot``plate``sample` |
## 页面入口
| 页面 | 录入要求 |
| --- | --- |
| Program 列表页 | 支持 crop、负责人、program_type、关键词筛选新增、编辑、查看详情、停用 |
| Program 新增/编辑页 | 分为“基本信息”和“负责人/作物”两组 |
| Program 详情页 | Tab 展示 trial、study、location、seed lot、sample |
列表页表格字段:`name``abbreviation`、crop、负责人、trial 数、study 数。
## 字段录入
| 字段 | 类型 | 控件 | 录入说明 | 校验/来源 |
| --- | --- | --- | --- | --- |
| `id` | varchar(255) | 隐藏/只读 | 项目主键 | 必填、唯一 |
| `auth_user_id` | varchar(255) | 隐藏 | 数据所属用户 | 登录上下文自动写入 |
| `abbreviation` | varchar(255) | 文本框 | 项目缩写 | 可选 |
| `documentationurl` | varchar(255) | URL 输入框 | 项目文档链接 | URL 格式校验 |
| `funding_information` | varchar(255) | 多行文本 | 经费来源说明 | 可选 |
| `name` | varchar(255) | 文本框 | 项目名称 | 必填 |
| `objective` | varchar(255) | 多行文本 | 项目目标 | 可选 |
| `program_type` | integer | 下拉框 | 项目类型枚举 | 可选,按 BrAPI 枚举 |
| `crop_id` | varchar(255) | 作物选择器 | 所属作物 | 必选,来源 `crop.id` |
| `lead_person_id` | varchar(255) | 人员选择器 | 项目负责人 | 可选,来源 `person.id` |
## 校验规则
1. `name` 必填。
2. `crop_id` 必选,且必须引用已存在的 `crop.id`
3. 选择负责人时,`lead_person_id` 必须引用已存在的 `person.id`
4. `documentationurl` 需要做 URL 格式校验。
## 接口能力
| 接口 | 用途 |
| --- | --- |
| `GET /programs` | program 分页查询 |
| `POST /programs` | 新增 program |
| `GET /programs/{id}` | program 详情 |
| `PUT /programs/{id}` | 编辑 program |
| `DELETE /programs/{id}` | 删除或停用 program需做引用检查 |
| `GET /programs/{id}/trials` | 查询 program 下 trial |
| `GET /programs/{id}/studies` | 查询 program 下 study |
| `GET /selectors/programs` | program 搜索下拉,参数 `keyword``cropId` |
## 导入导出
1. 支持通过 Core 导入流程导入 `program`
2. 外键列支持填写 ID可额外支持名称匹配但名称重复时必须报错。
3. 可按 `id` 幂等更新;无 `id` 时新增。
4. 列表页支持导出当前筛选结果,导出文件应包含 ID 和展示名称。
## 删除/停用
`program` 已有关联 `trial``study``location``crossing_project``seed_lot``plate``sample` 时,不允许物理删除。后端需要返回引用对象类型和数量,前端展示后引导用户停用。
## 验收点
1. 创建 program 时必须选择 crop。
2. 负责人选择器只能保存已存在的 person ID。
3. Program 详情页能进入该项目下的 trial 和 study。

View File

@@ -0,0 +1,86 @@
# 01 Core - location 表录入说明
来源:`docs/requirements/01-core-data-entry-requirements.md`
## 录入目标
`location` 记录试验实施地点,可作为公共地点,也可绑定 program 和 crop。study 创建时必须选择实施地点。
## 前置依赖和下游引用
| 类型 | 内容 |
| --- | --- |
| 表 | `location` |
| 前置依赖 | 可选 `crop``program`、父级 `location`、坐标 |
| 下游引用 | `study``seed_lot` |
## 页面入口
| 页面 | 录入要求 |
| --- | --- |
| Location 列表页 | 支持 crop、program、location_type、country、关键词筛选新增、编辑、查看详情、停用、地图查看 |
| Location 新增/编辑页 | 包含基本信息、行政区、坐标、父级地点 |
| Location 详情页 | 展示该地点下的 study 和 seed lot |
列表页支持地图/表格两种视图。列表页表格字段:`location_name`、location_type、country、program、crop、父级地点。
## 字段录入
| 字段 | 类型 | 控件 | 录入说明 | 校验/来源 |
| --- | --- | --- | --- | --- |
| `id` | varchar(255) | 隐藏/只读 | 地点主键 | 必填、唯一 |
| `auth_user_id` | varchar(255) | 隐藏 | 数据所属用户 | 登录上下文自动写入 |
| `abbreviation` | varchar(255) | 文本框 | 地点缩写 | 可选 |
| `coordinate_description` | varchar(255) | 多行文本 | 坐标描述 | 可选 |
| `coordinate_uncertainty` | varchar(255) | 文本框 | 坐标不确定性 | 可选 |
| `country_code` | varchar(255) | 国家代码选择器 | 国家代码 | 可选,建议 ISO 代码 |
| `country_name` | varchar(255) | 文本框 | 国家名称 | 可选,可由国家代码带出 |
| `documentationurl` | varchar(255) | URL 输入框 | 地点文档链接 | URL 格式校验 |
| `environment_type` | varchar(255) | 下拉框/文本框 | 环境类型 | 可选 |
| `exposure` | varchar(255) | 文本框 | 暴露条件 | 可选 |
| `institute_address` | varchar(255) | 多行文本 | 机构地址 | 可选 |
| `institute_name` | varchar(255) | 文本框 | 机构名称 | 可选 |
| `location_name` | varchar(255) | 文本框 | 地点名称 | 必填 |
| `location_type` | varchar(255) | 下拉框 | 地点类型,如 field、greenhouse、storage | 可选 |
| `site_status` | varchar(255) | 下拉框 | 地点状态 | 可选 |
| `slope` | varchar(255) | 文本框 | 坡度 | 可选 |
| `topography` | varchar(255) | 文本框 | 地形 | 可选 |
| `coordinates_id` | varchar(255) | 坐标选择器/地图取点 | 坐标对象 | 可选,来源 `geojson/coordinate` |
| `crop_id` | varchar(255) | 作物选择器 | 关联作物 | 可选,来源 `crop.id` |
| `parent_location_id` | varchar(255) | 地点选择器 | 父级地点 | 可选,不能选择自己 |
| `program_id` | varchar(255) | 项目选择器 | 所属项目 | 可选,来源 `program.id` |
## 校验规则
1. `location_name` 必填。
2. 坐标字段格式合法。
3. `parent_location_id` 不能选择自己。
4. 选择 program 后可自动带出 crop但允许地点作为公共地点不绑定 program。
5. `documentationurl` 需要做 URL 格式校验。
## 接口能力
| 接口 | 用途 |
| --- | --- |
| `GET /locations` | location 分页查询 |
| `POST /locations` | 新增 location |
| `GET /locations/{id}` | location 详情 |
| `PUT /locations/{id}` | 编辑 location |
| `GET /selectors/locations` | location 搜索下拉,参数 `keyword``programId``cropId``locationType` |
## 导入导出
1. 支持通过 Core 导入流程导入 `location`
2. 导入时如果 `parent_location_id` 指向自己,应报错并指出行号。
3. 外键列支持填写 ID可额外支持名称匹配但名称重复时必须报错。
4. 列表页支持导出当前筛选结果,导出文件应包含 ID 和展示名称。
## 删除/停用
`location` 已被 `study``seed_lot` 引用时,不允许物理删除。后端需要返回引用对象类型和数量,前端展示后引导用户停用。
## 验收点
1. Location 列表页支持表格视图和地图查看。
2. 父级地点不能选择自己。
3. Study 新增时 location 选择器可按 program/crop 过滤。

View File

@@ -0,0 +1,78 @@
# 01 Core - trial 表录入说明
来源:`docs/requirements/01-core-data-entry-requirements.md`
## 录入目标
`trial` 表示某一批试验、区域试验或年度试验,位于 program 与 study 之间。创建 trial 时选择 program并自动带出或校验 crop。
## 前置依赖和下游引用
| 类型 | 内容 |
| --- | --- |
| 表 | `trial` |
| 前置依赖 | `program``crop` |
| 下游引用 | `study``observation_unit``observation``plate``sample` |
## 页面入口
| 页面 | 录入要求 |
| --- | --- |
| Trial 列表页 | 支持 crop、program、active、起止日期、关键词筛选新增、编辑、查看详情、停用 |
| Trial 新增/编辑页 | 包含基本信息、项目作物、联系人、出版物四个区域 |
| Trial 详情页 | 展示 study 列表和 phenotyping/genotyping 入口 |
列表页表格字段:`trial_name`、program、crop、`start_date``end_date`、active。
## 字段录入
| 字段 | 类型 | 控件 | 录入说明 | 校验/来源 |
| --- | --- | --- | --- | --- |
| `id` | varchar(255) | 隐藏/只读 | 试验主键 | 必填、唯一 |
| `auth_user_id` | varchar(255) | 隐藏 | 数据所属用户 | 登录上下文自动写入 |
| `active` | boolean | 开关 | 是否启用 | 默认启用 |
| `documentationurl` | varchar(255) | URL 输入框 | 试验文档链接 | URL 格式校验 |
| `end_date` | timestamp | 日期选择器 | 结束日期 | 不早于 `start_date` |
| `start_date` | timestamp | 日期选择器 | 开始日期 | 可选 |
| `trial_description` | varchar(255) | 多行文本 | 试验描述 | 可选 |
| `trial_name` | varchar(255) | 文本框 | 试验名称 | 必填 |
| `trialpui` | varchar(255) | 文本框 | 试验永久标识 | 可选,建议唯一 |
| `crop_id` | varchar(255) | 作物选择器 | 所属作物 | 必选,来源 `crop.id` |
| `program_id` | varchar(255) | 项目选择器 | 所属项目 | 必选,来源 `program.id` |
## 校验规则
1. `trial_name` 必填。
2. `program_id` 必选且必须存在。
3. `crop_id` 必选且必须与 `program.crop_id` 一致。
4. `end_date` 不能早于 `start_date`
5. `documentationurl` 需要做 URL 格式校验。
## 接口能力
| 接口 | 用途 |
| --- | --- |
| `GET /trials` | trial 分页查询 |
| `POST /trials` | 新增 trial |
| `GET /trials/{id}` | trial 详情 |
| `PUT /trials/{id}` | 编辑 trial |
| `DELETE /trials/{id}` | 删除或停用 trial需检查 study 引用 |
| `GET /trials/{id}/studies` | 查询 trial 下 study |
| `GET /selectors/trials` | trial 搜索下拉,参数 `keyword``programId``cropId``active` |
## 导入导出
1. 支持通过 Core 导入流程导入 `trial`
2. 外键列支持填写 ID可额外支持名称匹配但名称重复时必须报错。
3. 导入时必须校验 trial 的 crop 与 program 的 crop 一致。
4. 列表页支持导出当前筛选结果,导出文件应包含 ID 和展示名称。
## 删除/停用
`trial` 已被 `study``observation_unit``observation``plate``sample` 引用时,不允许物理删除。后端需要返回引用对象类型和数量,前端展示后引导用户停用。
## 验收点
1. 创建 trial 时,选择 program 后自动带出 crop。
2. Trial 列表页支持按 crop、program、active、日期筛选。
3. 已被 study 引用的 trial 不能直接删除。

View File

@@ -0,0 +1,66 @@
# 01 Core - season 表录入说明
来源:`docs/requirements/01-core-data-entry-requirements.md`
## 录入目标
`season` 记录年度和季节,用于 study 的季节绑定,以及部分 observation 的季节维度统计。
## 前置依赖和下游引用
| 类型 | 内容 |
| --- | --- |
| 表 | `season` |
| 前置依赖 | 无 |
| 下游引用 | `study_season`、部分 `observation` |
## 页面入口
| 页面 | 录入要求 |
| --- | --- |
| Season 列表页 | 支持 year、season 筛选;新增、编辑、查看详情、停用 |
| Season 新增/编辑页 | 简单表单 |
| Season 详情页 | 展示关联 study |
列表页表格字段:`year``season`、关联 study 数。
## 字段录入
| 字段 | 类型 | 控件 | 录入说明 | 校验/来源 |
| --- | --- | --- | --- | --- |
| `id` | varchar(255) | 隐藏/只读 | 季节主键 | 必填、唯一 |
| `auth_user_id` | varchar(255) | 隐藏 | 数据所属用户 | 登录上下文自动写入 |
| `season` | varchar(255) | 文本框/下拉框 | 季节名称,如 Spring、Summer | 必填 |
| `year` | integer | 年份选择器 | 年份 | 必填,四位年份 |
## 校验规则
1. `season` 必填。
2. `year` 必填,使用四位年份。
3. 同一年份内 season 名称不建议重复。
## 接口能力
| 接口 | 用途 |
| --- | --- |
| `GET /seasons` | season 查询 |
| `POST /seasons` | 新增 season |
| `PUT /seasons/{id}` | 编辑 season |
| `GET /selectors/seasons` | season 搜索下拉,参数 `year``keyword` |
## 导入导出
1. 支持通过 Core 导入流程导入 `season`
2. 模板列名使用数据库字段名。
3. 可按 `id` 幂等更新;无 `id` 时新增。
4. 列表页支持导出当前筛选结果,导出文件应包含 ID 和展示名称。
## 删除/停用
`season` 已被 `study_season``observation` 引用时,不允许物理删除。后端需要返回引用对象类型和数量,前端展示后引导用户停用。
## 验收点
1. Season 列表页支持按 year 和 season 筛选。
2. 同一年份内重复季节名称需要提示。
3. Study 新增/编辑页可以多选 season。

View File

@@ -0,0 +1,103 @@
# 01 Core - study 表录入说明
来源:`docs/requirements/01-core-data-entry-requirements.md`
## 录入目标
`study` 是一次真正落地执行的试验,是 Core 模块最关键的上下文单元。后续 observation_unit、event、observation、plate、sample、variantset 都会直接或间接挂到 study 上。
## 前置依赖和下游引用
| 类型 | 内容 |
| --- | --- |
| 表 | `study` |
| 前置依赖 | `crop``program``trial``location`,可选 `season` |
| 下游引用 | `observation_unit``event``observation``plate``sample``variantset` |
## 页面入口
| 页面 | 录入要求 |
| --- | --- |
| Study 列表页 | 支持 crop、program、trial、location、season、active、study_type、关键词筛选新增、编辑、查看详情、停用 |
| Study 新增/编辑页 | 分组表单:基本信息、上下文、地点季节、实验设计、联系人 |
| Study 工作台 | 点击 study 名称或“进入工作台”后进入,展示下游业务入口和聚合数量 |
Study 列表页表格字段:`study_name``study_code`、program、trial、location、`start_date``end_date`、active。
## 字段录入
| 字段 | 类型 | 控件 | 录入说明 | 校验/来源 |
| --- | --- | --- | --- | --- |
| `id` | varchar(255) | 隐藏/只读 | study 主键 | 必填、唯一 |
| `auth_user_id` | varchar(255) | 隐藏 | 数据所属用户 | 登录上下文自动写入 |
| `active` | boolean | 开关 | 是否启用 | 默认启用 |
| `cultural_practices` | varchar(255) | 多行文本 | 栽培管理说明 | 可选 |
| `documentationurl` | varchar(255) | URL 输入框 | study 文档链接 | URL 格式校验 |
| `end_date` | timestamp | 日期选择器 | 结束日期 | 不早于 `start_date` |
| `license` | varchar(255) | 文本框 | 数据许可证 | 可选 |
| `observation_units_description` | varchar(255) | 多行文本 | 观测单元说明 | 可选 |
| `start_date` | timestamp | 日期选择器 | 开始日期 | 可选 |
| `study_code` | varchar(255) | 文本框 | study 编码 | 可选,建议同项目内唯一 |
| `study_description` | varchar(255) | 多行文本 | study 描述 | 可选 |
| `study_name` | varchar(255) | 文本框 | study 名称 | 必填 |
| `studypui` | varchar(255) | 文本框 | study 永久标识 | 可选,建议唯一 |
| `study_type` | varchar(255) | 下拉框 | study 类型 | 可选 |
| `crop_id` | varchar(255) | 作物选择器 | 所属作物 | 必选,来源 `crop.id` |
| `location_id` | varchar(255) | 地点选择器 | 实施地点 | 必选,来源 `location.id` |
| `program_id` | varchar(255) | 项目选择器 | 所属项目 | 必选,来源 `program.id` |
| `trial_id` | varchar(255) | 试验选择器 | 所属 trial | 必选,来源 `trial.id` |
## 新增/编辑分区
| 区域 | 字段/功能 | 要求 |
| --- | --- | --- |
| 基本信息 | study_name、study_code、study_type、active、start_date、end_date | study_name 必填;结束日期不早于开始日期 |
| 上下文 | crop、program、trial、location、season | program、trial、crop、location 必选program -> trial 联动 |
| 说明信息 | study_description、cultural_practices、observation_units_description、license、documentationurl | URL 格式校验 |
| 联系人 | study_contact | 多选 person可增删 |
| 季节 | study_season | 可多选 season |
| 提交后 | 保存成功进入 Study 工作台 | 新建成功后自动跳转 |
## 校验规则
1. `study_name` 必填。
2. `program_id``trial_id``crop_id``location_id` 必选且必须存在。
3. `trial_id` 必须属于所选 `program_id`
4. 选择 program 后过滤 trial选择 trial 后自动带出 crop。
5. `end_date` 不能早于 `start_date`
6. 编辑 study 时,如果已有 observation_unit、sample、observation变更 program/trial/crop/location 前必须二次确认并检查一致性。
7. study 是下游核心引用,删除必须强提示。
## 接口能力
| 接口 | 用途 |
| --- | --- |
| `GET /studies` | study 分页查询 |
| `POST /studies` | 新增 study |
| `GET /studies/{id}` | study 详情 |
| `PUT /studies/{id}` | 编辑 study |
| `DELETE /studies/{id}` | 删除或停用 study需检查下游引用 |
| `GET /studies/{id}/workbench` | Study 工作台聚合信息 |
| `GET /studies/{id}/contacts` | study 联系人 |
| `GET /studies/{id}/seasons` | study 季节 |
| `GET /selectors/studies` | study 搜索下拉,参数 `keyword``programId``trialId``locationId``active` |
## 导入导出
1. 支持通过 Core 导入流程导入 `study`
2. 导入时必须校验字段完整性、必填、格式、外键是否存在、联动关系是否一致。
3. 如果 trial 不属于 program应报错并指出行号。
4. study 导出应支持工作台摘要包括联系人、season、下游数据数量。
5. 大数据量导出时应走异步任务。
## 删除/停用
`study` 已被 `observation_unit``event``observation``plate``sample``variantset` 引用时,不允许物理删除。后端需要返回引用对象类型和数量,前端弹窗展示后引导用户停用。
## 验收点
1. Study 列表页支持按 crop、program、trial、location、season、active 筛选。
2. 点击 study 名称或“进入工作台”按钮后进入 Study 工作台。
3. Study 工作台可以看到观测单元、表型、样本、基因型入口。
4. study 创建成功后自动进入 Study 工作台。
5. 已被 observation_unit、sample、observation 引用的 study 不能直接删除。

View File

@@ -0,0 +1,73 @@
# 01 Core - list 表录入说明
来源:`docs/requirements/01-core-data-entry-requirements.md`
## 录入目标
`list` 是通用分组列表的主表,用于维护一组业务对象或文本项。`list` 负责列表基本信息,`list_item` 负责列表明细。
## 前置依赖和下游引用
| 类型 | 内容 |
| --- | --- |
| 表 | `list` |
| 前置依赖 | 可选 `person` |
| 下游引用 | `list_item`、业务查询和分组 |
## 页面入口
| 页面 | 录入要求 |
| --- | --- |
| List 列表页 | 展示 list支持查询、新增、编辑 |
| List 详情页 | 顶部展示 list 基本信息,下方内嵌 list_item 表格 |
List 详情页支持新增 item、批量导入 item、删除 item、排序。同一 list 内 item 不重复。
## 字段录入
| 字段 | 类型 | 控件 | 录入说明 | 校验/来源 |
| --- | --- | --- | --- | --- |
| `id` | varchar(255) | 隐藏/只读 | 列表主键 | 必填、唯一 |
| `auth_user_id` | varchar(255) | 隐藏 | 数据所属用户 | 登录上下文自动写入 |
| `date_created` | timestamp | 只读日期时间 | 创建时间 | 系统自动写入 |
| `date_modified` | timestamp | 只读日期时间 | 修改时间 | 系统自动更新 |
| `description` | varchar(255) | 多行文本 | 列表描述 | 可选 |
| `list_name` | varchar(255) | 文本框 | 列表名称 | 必填 |
| `list_owner_name` | varchar(255) | 文本框 | 列表 owner 名称 | 可选,可由 owner person 带出 |
| `list_source` | varchar(255) | 文本框 | 列表来源 | 可选 |
| `list_type` | integer | 下拉框 | 列表类型 | 必填,按 BrAPI 枚举 |
| `list_owner_person_id` | varchar(255) | 人员选择器 | 列表 owner | 可选,来源 `person.id` |
## 校验规则
1. `list_name` 必填。
2. `list_type` 必填,按 BrAPI 枚举选择。
3. 如果绑定 owner`list_owner_person_id` 必须引用已存在的 `person.id`
4. `date_created``date_modified` 由系统维护,前端只读。
## 接口能力
| 接口 | 用途 |
| --- | --- |
| `GET /lists` | list 查询 |
| `POST /lists` | 新增 list |
| `PUT /lists/{id}` | 编辑 list |
| `POST /lists/{id}/items` | 给 list 添加 item |
| `DELETE /lists/{id}/items/{itemId}` | 删除 list item |
## 导入导出
1. 支持通过 Core 导入流程导入 `list`
2. 模板列名使用数据库字段名。
3. 外键列支持填写 `list_owner_person_id`;可额外支持名称匹配,但名称重复时必须报错。
4. 列表页支持导出当前筛选结果,导出文件应包含 ID 和展示名称。
## 删除/停用
`list` 已有 `list_item` 时,删除前必须提示。可以先清空明细再删除 list。
## 验收点
1. List 详情页顶部展示 list 基本信息,下方展示 list_item 表格。
2. 同一 list 内 item 不重复。
3. 绑定 owner 时只能保存已存在的 person ID。

View File

@@ -0,0 +1,62 @@
# 01 Core - list_item 表录入说明
来源:`docs/requirements/01-core-data-entry-requirements.md`
## 录入目标
`list_item` 是 list 的明细项,是“给 list 添加成员”这个动作留下的记录。它可以保存目标对象 ID 或文本值,用于业务查询和分组。
## 前置依赖和下游引用
| 类型 | 内容 |
| --- | --- |
| 表 | `list_item` |
| 前置依赖 | `list` |
| 下游引用 | 业务查询和分组 |
## 页面入口
| 页面 | 录入要求 |
| --- | --- |
| List 详情页 | 在 list 基本信息下方内嵌 list_item 表格 |
| 批量导入 | 支持给指定 list 批量导入 item |
新增 item 时可选择目标类型,例如 germplasm、study、sample。
## 字段录入
| 字段 | 类型 | 控件 | 录入说明 | 校验/来源 |
| --- | --- | --- | --- | --- |
| `id` | varchar(255) | 隐藏/只读 | 列表项主键 | 必填、唯一 |
| `item` | varchar(255) | 文本框/对象选择器 | 列表项值,可存目标对象 ID 或文本 | 必填,同一 list 内不重复 |
| `list_id` | varchar(255) | List 选择器 | 所属列表 | 必选,来源 `list.id` |
## 校验规则
1. `list_id` 必选,且必须引用已存在的 `list.id`
2. `item` 必填。
3. 同一 `list_id``item` 不应重复。
## 接口能力
| 接口 | 用途 |
| --- | --- |
| `POST /lists/{id}/items` | 给 list 添加 item |
| `DELETE /lists/{id}/items/{itemId}` | 删除 list item |
## 导入导出
1. 支持通过 Core 导入流程导入 `list_item`
2. 导入时需要校验 `list_id` 是否存在。
3. 导入时需要校验同一 list 内 item 是否重复。
4. 错误报告返回行号、字段名、错误原因、建议修正方式。
## 删除/停用
`list_item` 是明细记录,可从 List 详情页删除。删除前需要确认,删除后不影响 list 基本信息。
## 验收点
1. List 详情页可新增 item、批量导入 item、删除 item、排序。
2. 同一 list 内重复 item 不能提交。
3. 批量导入错误能定位到行号和字段名。

View File

@@ -0,0 +1,57 @@
# 01 Core - trial_contact 表录入说明
来源:`docs/requirements/01-core-data-entry-requirements.md`
## 录入目标
`trial_contact` 是给 trial 添加联系人的关系表,不是独立主数据。它记录 trial 与 person 的多对多关系,用于试验责任追踪、联系人展示、权限和通知。
## 前置依赖和下游引用
| 类型 | 内容 |
| --- | --- |
| 表 | `trial_contact` |
| 前置依赖 | `trial``person` |
| 下游引用 | trial 联系人展示、权限和通知 |
## 页面入口
| 页面 | 录入要求 |
| --- | --- |
| Trial 新增/编辑页 | 联系人区域使用可增删表格选择 `person` |
| Trial 详情页 | 展示 trial 联系人 |
| 批量导入 | 支持通过 Core 导入流程导入 trial 联系人关系 |
## 字段录入
| 字段 | 类型 | 控件 | 录入说明 | 校验/来源 |
| --- | --- | --- | --- | --- |
| `trial_db_id` | varchar(255) | Trial 选择器 | 所属 trial | 必选,来源 `trial.id` |
| `person_db_id` | varchar(255) | 人员选择器 | 联系人 | 必选,来源 `person.id` |
## 校验规则
1. `trial_db_id` 必选,且必须引用已存在的 `trial.id`
2. `person_db_id` 必选,且必须引用已存在的 `person.id`
3. 同一 trial 下不建议重复添加同一个 person。
## 接口能力
本文档原始需求未强制限定 trial_contact 的独立 URL。实现时可以随 trial 新增/编辑一起保存,也可以提供 trial 联系人子资源接口;前端需要具备新增、删除、查询 trial 联系人的能力。
## 导入导出
1. 支持通过 Core 导入流程导入 `trial_contact`
2. 外键列支持填写 ID可额外支持名称匹配但名称重复时必须报错。
3. 导入时需要校验 trial 和 person 是否存在。
4. 错误报告返回行号、字段名、错误原因、建议修正方式。
## 删除/停用
`trial_contact` 是关系记录,可在 Trial 新增/编辑页或详情页移除。删除关系不应删除 `trial``person` 主数据。
## 验收点
1. Trial 新增/编辑页可增删联系人。
2. 联系人选择器展示 person 名称,提交保存 `person.id`
3. 删除 trial_contact 后person 主数据仍保留。

View File

@@ -0,0 +1,56 @@
# 01 Core - trial_publication 表录入说明
来源:`docs/requirements/01-core-data-entry-requirements.md`
## 录入目标
`trial_publication` 是给 trial 记录出版物、报告或文献引用的痕迹表。它挂在 trial 下,用于说明试验相关的外部文献和永久标识。
## 前置依赖和下游引用
| 类型 | 内容 |
| --- | --- |
| 表 | `trial_publication` |
| 前置依赖 | `trial` |
| 下游引用 | trial 出版物/报告展示 |
## 页面入口
| 页面 | 录入要求 |
| --- | --- |
| Trial 新增/编辑页 | 出版物区域可增删 publication 记录 |
| Trial 详情页 | 展示 trial 的出版物、报告或引用 |
## 字段录入
| 字段 | 类型 | 控件 | 录入说明 | 校验/来源 |
| --- | --- | --- | --- | --- |
| `id` | varchar(255) | 隐藏/只读 | 出版物记录主键 | 必填、唯一 |
| `publicationpui` | varchar(255) | 文本框 | 出版物 PUI | 可选 |
| `publication_reference` | varchar(255) | 文本框/URL | 出版物引用 | 可选 |
| `trial_id` | varchar(255) | Trial 选择器 | 所属 trial | 必选,来源 `trial.id` |
## 校验规则
1. `id` 必填且唯一,新增时可由系统生成。
2. `trial_id` 必选,且必须引用已存在的 `trial.id`
3. `publication_reference` 如果录入 URL需要做 URL 格式校验。
4. `publicationpui` 建议唯一。
## 接口能力
本文档原始需求未强制限定 trial_publication 的独立 URL。实现时可以随 trial 新增/编辑一起保存,也可以提供 trial 出版物子资源接口;前端需要具备新增、删除、查询 trial 出版物的能力。
## 导入导出
原始导入对象清单未单独列出 `trial_publication`,但字段需求中包含该表。若纳入 Core 导入,应遵循通用导入流程:模板列名使用数据库字段名,外键校验 `trial_id`,错误报告返回行号、字段名和错误原因。
## 删除/停用
`trial_publication` 是 trial 的明细记录,可在 Trial 新增/编辑页或详情页移除。删除 publication 记录不应删除 `trial` 主数据。
## 验收点
1. Trial 新增/编辑页可维护出版物记录。
2. `trial_id` 不存在时不能提交。
3. 删除 publication 记录后trial 主数据仍保留。

View File

@@ -0,0 +1,61 @@
# 01 Core - study_contact 表录入说明
来源:`docs/requirements/01-core-data-entry-requirements.md`
## 录入目标
`study_contact` 是给 study 添加联系人的关系表,不是独立主数据。它记录 study 与 person 的多对多关系,用于 Study 工作台联系人展示、责任追踪、权限和通知。
## 前置依赖和下游引用
| 类型 | 内容 |
| --- | --- |
| 表 | `study_contact` |
| 前置依赖 | `study``person` |
| 下游引用 | Study 工作台联系人展示、权限和通知 |
## 页面入口
| 页面 | 录入要求 |
| --- | --- |
| Study 新增/编辑页 | 联系人区域多选 person可增删 |
| Study 工作台 | 展示 study 联系人 |
| 批量导入 | 支持通过 Core 导入流程导入 study 联系人关系 |
## 字段录入
| 字段 | 类型 | 控件 | 录入说明 | 校验/来源 |
| --- | --- | --- | --- | --- |
| `study_db_id` | varchar(255) | Study 选择器 | 所属 study | 必选,来源 `study.id` |
| `person_db_id` | varchar(255) | 人员选择器 | 联系人 | 必选,来源 `person.id` |
## 校验规则
1. `study_db_id` 必选,且必须引用已存在的 `study.id`
2. `person_db_id` 必选,且必须引用已存在的 `person.id`
3. 同一 study 下不建议重复添加同一个 person。
## 接口能力
| 接口 | 用途 |
| --- | --- |
| `GET /studies/{id}/contacts` | study 联系人,返回 person 列表 |
本文档原始需求未强制限定 study_contact 的写入 URL。实现时可以随 study 新增/编辑一起保存,也可以提供 study 联系人子资源接口;前端需要具备新增、删除、查询 study 联系人的能力。
## 导入导出
1. 支持通过 Core 导入流程导入 `study_contact`
2. 外键列支持填写 ID可额外支持名称匹配但名称重复时必须报错。
3. 导入时需要校验 study 和 person 是否存在。
4. 错误报告返回行号、字段名、错误原因、建议修正方式。
## 删除/停用
`study_contact` 是关系记录,可在 Study 新增/编辑页或工作台移除。删除关系不应删除 `study``person` 主数据。
## 验收点
1. Study 新增/编辑页可增删联系人。
2. Study 工作台能展示联系人列表。
3. 删除 study_contact 后person 主数据仍保留。

View File

@@ -0,0 +1,61 @@
# 01 Core - study_season 表录入说明
来源:`docs/requirements/01-core-data-entry-requirements.md`
## 录入目标
`study_season` 是给 study 绑定 season 的关系表。一个 study 可以关联多个 season用于多季节筛选、统计和 Study 工作台上下文展示。
## 前置依赖和下游引用
| 类型 | 内容 |
| --- | --- |
| 表 | `study_season` |
| 前置依赖 | `study``season` |
| 下游引用 | Study 工作台季节展示、多季节筛选和统计 |
## 页面入口
| 页面 | 录入要求 |
| --- | --- |
| Study 新增/编辑页 | 季节区域多选 season |
| Study 工作台 | 展示 study 关联 season |
| 批量导入 | 支持通过 Core 导入流程导入 study 与 season 关系 |
## 字段录入
| 字段 | 类型 | 控件 | 录入说明 | 校验/来源 |
| --- | --- | --- | --- | --- |
| `study_db_id` | varchar(255) | Study 选择器 | 所属 study | 必选,来源 `study.id` |
| `season_db_id` | varchar(255) | Season 选择器 | 关联季节 | 必选,来源 `season.id` |
## 校验规则
1. `study_db_id` 必选,且必须引用已存在的 `study.id`
2. `season_db_id` 必选,且必须引用已存在的 `season.id`
3. 同一 study 下不建议重复绑定同一个 season。
## 接口能力
| 接口 | 用途 |
| --- | --- |
| `GET /studies/{id}/seasons` | study 季节,返回 season 列表 |
本文档原始需求未强制限定 study_season 的写入 URL。实现时可以随 study 新增/编辑一起保存,也可以提供 study season 子资源接口;前端需要具备新增、删除、查询 study season 的能力。
## 导入导出
1. 支持通过 Core 导入流程导入 `study_season`
2. 外键列支持填写 ID可额外支持名称匹配但名称重复时必须报错。
3. 导入时需要校验 study 和 season 是否存在。
4. 错误报告返回行号、字段名、错误原因、建议修正方式。
## 删除/停用
`study_season` 是关系记录,可在 Study 新增/编辑页或工作台移除。删除关系不应删除 `study``season` 主数据。
## 验收点
1. Study 新增/编辑页可多选 season。
2. Study 工作台能展示关联 season。
3. 删除 study_season 后season 主数据仍保留。

View File

@@ -0,0 +1,26 @@
# 02 Germplasm / Seed - breeding_method 表录入说明
来源:`docs/requirements/02-germplasm-seed-entry-requirements.md`
## 录入目标
`breeding_method` 是育种方法字典,用来说明某个 germplasm 是通过什么方式形成的,例如杂交选育、回交、自交系选育、诱变、转基因、克隆选择等。它不是一次具体杂交动作,而是材料来源方法的分类。
## 字段录入
| 字段 | 业务意义 | 录入方式 | 控件建议 | 校验规则 |
| -------------- | -------------------------------------------- | -------------------------------- | --------- | -------------------------------- |
| `id` | 育种方法主键,系统内部唯一标识 | 新增时系统生成;导入时可允许指定 | 隐藏/只读 | 必填、唯一;编辑时不允许修改 |
| `auth_user_id` | 数据所属用户或租户 | 登录上下文自动写入 | 隐藏 | 不允许前端手填 |
| `abbreviation` | 方法缩写,如 MB、BC、DH | 用户录入 | 文本框 | 可选;建议同一用户下唯一 |
| `description` | 方法解释,如“回交用于恢复目标基因” | 用户录入 | 多行文本 | 可选,限制长度 |
| `name` | 方法名称,如 Male Backcross、Doubled Haploid | 用户录入 | 文本框 | 必填;建议唯一;作为下拉展示名称 |
## 页面与交互
- 列表页展示:方法名称、缩写、描述、使用材料数量。
- 新增页为简单字典表单。
- 删除前检查是否被 `germplasm.breeding_method_id` 引用;已引用时不允许物理删除,只允许停用。
---

View File

@@ -0,0 +1,54 @@
# 02 Germplasm / Seed - germplasm 表录入说明
来源:`docs/requirements/02-germplasm-seed-entry-requirements.md`
## 录入目标
`germplasm` 是材料身份证,描述一个品种、品系、亲本、后代材料、遗传资源或研究材料“是谁”。它不表示库存数量,库存数量由 `seed_lot` 表达。
## 字段录入
| 字段 | 业务意义 | 录入方式 | 控件建议 | 校验规则 |
| ------------------------------------- | ------------------------------------------------------------ | -------------------------------------- | ----------------- | --------------------------------------------------------- |
| `id` | 种质主键,系统内部唯一标识 | 系统生成;导入可指定 | 隐藏/只读 | 必填、唯一;编辑不可随意修改 |
| `auth_user_id` | 数据所属用户或租户 | 登录上下文自动写入 | 隐藏 | 不允许手填 |
| `accession_number` | 材料在种质库/机构内的 accession 编号,如 PI 113869 | 用户录入或导入 | 文本框 | 可选;建议同一 crop / institution 下唯一 |
| `acquisition_date` | 材料进入本系统或本机构的获取日期 | 用户录入 | 日期选择器 | 可选;不得晚于当前日期太多,导入时允许缺月/缺日需统一规则 |
| `acquisition_source_code` | 获取来源编码,如采集、引进、交换、繁殖等 | 用户选择 | 下拉框 | 可选;值来自 BrAPI/MCPD 枚举或系统字典 |
| `biological_status_of_accession_code` | 材料生物状态,如野生、地方品种、育种材料、改良品种、突变体等 | 用户选择 | 下拉框 | 可选;使用受控枚举,不建议自由输入 |
| `collection` | 材料所属集合、群体、panel 或 collection | 用户录入/选择 | 文本框/选择器 | 可选;可用于分组筛选 |
| `country_of_origin_code` | 原产国或育成/选育国家代码 | 用户选择 | 国家代码选择器 | 可选;建议使用 ISO 3166-1 三字母代码 |
| `default_display_name` | 系统默认展示名,给下拉框、表格、详情标题使用 | 用户录入,可由 germplasm_name 自动带出 | 文本框 | 与 `germplasm_name` 至少填一个;建议必填 |
| `documentationurl` | 材料说明文档、外部数据库页面或 DOI 链接 | 用户录入 | URL 输入框 | 可选;校验 URL 格式 |
| `genus` | 属名,如 Oryza、Triticum | 用户录入/字典选择 | 文本框/物种选择器 | 可选;建议首字母大写 |
| `germplasm_name` | 材料名称,可以是品种名、品系名、后代编号 | 用户录入 | 文本框 | 与 `default_display_name` 至少填一个;不强制全局唯一 |
| `germplasmpui` | 永久唯一标识,通常是 DOI、URI 或全局唯一编码 | 用户录入/外部导入 | 文本框/URL 输入框 | 可选;若填写必须唯一;建议用于跨系统交换 |
| `germplasm_preprocessing` | 材料用于试验前的统一处理说明,如消毒、催芽、低温处理 | 用户录入 | 文本框/多行文本 | 可选 |
| `mls_status` | 多边系统 MLS 状态,涉及植物遗传资源交换协议 | 用户选择 | 下拉框 | 可选;普通业务可隐藏到高级信息 |
| `seed_source` | 材料来源标识,如来源机构+accession或亲本组合描述 | 用户录入 | 文本框 | 可选;注意它不是库存批次,不等于 seed_lot |
| `seed_source_description` | 材料来源详细说明 | 用户录入 | 多行文本 | 可选 |
| `species` | 种名,如 sativa、aestivum | 用户录入/物种字典 | 文本框 | 可选;建议小写 |
| `species_authority` | 种名命名权威,如 L. | 用户录入 | 文本框 | 可选 |
| `subtaxa` | 亚种、变种、品种群、line 等更细分类 | 用户录入 | 文本框 | 可选 |
| `subtaxa_authority` | 亚种/变种命名权威 | 用户录入 | 文本框 | 可选 |
| `breeding_method_id` | 该材料形成所使用的育种方法 | 从 breeding_method 选择 | 搜索选择器 | 可选;必须引用存在的 breeding_method |
| `crop_id` | 所属作物 | 从 crop 选择 | 作物选择器 | 必填;后续 trial/study/attribute 应尽量同 crop |
## 录入建议
- 新建材料时,第一屏只放核心字段:`crop_id``germplasm_name``default_display_name``germplasmpui``accession_number``breeding_method_id`
- 分类与来源信息放在“高级信息”或“来源信息”分组。
- `germplasmpui``accession_number``germplasm_name` 三者不要混为一谈:
- `germplasm_name` 是人看的名字;
- `accession_number` 是机构内编号;
- `germplasmpui` 是跨系统长期唯一标识。
## 验收点
1. 新增 germplasm 时,必须选择 crop。
2. `germplasm_name``default_display_name` 至少填写一个。
3. 下拉选择材料时展示 `default_display_name`,辅助展示 accession number / PUI。
4. 如果 germplasm 已被 seed lot、cross parent、observation unit 引用,不允许物理删除。
---

View File

@@ -0,0 +1,48 @@
# 02 Germplasm / Seed - germplasm_attribute_definition 表录入说明
来源:`docs/requirements/02-germplasm-seed-entry-requirements.md`
## 录入目标
属性定义描述“材料可以有哪些稳定属性”。这些属性通常不是环境依赖的田间观测值,而是材料自身特征,例如籽粒颜色、抗病基因、硬度、熟期类型、特定 QTL、分子标记结果等。
## 字段录入
| 字段 | 业务意义 | 录入方式 | 控件建议 | 校验规则 |
| ---------------------- | ------------------------------------------------------------ | ---------------------------- | ----------------- | ------------------------------------- |
| `id` | 属性定义主键 | 系统生成 | 隐藏/只读 | 必填、唯一 |
| `auth_user_id` | 数据所属用户或租户 | 登录上下文自动写入 | 隐藏 | 不允许手填 |
| `default_value` | 属性默认值 | 用户录入 | 动态输入框 | 可选;按 datatype / scale 校验 |
| `documentationurl` | 属性说明文档链接 | 用户录入 | URL 输入框 | 可选;校验 URL |
| `growth_stage` | 属性适用生长阶段,如 flowering | 用户录入/选择 | 下拉框/文本框 | 可选 |
| `institution` | 提交或维护该属性定义的机构 | 用户录入 | 文本框 | 可选 |
| `language` | 定义语言,如 zh、en | 用户选择 | 下拉框 | 可选;建议 ISO 639-1 |
| `scientist` | 提交该属性定义的科学家或负责人 | 用户录入/人员选择 | 文本框/人员选择器 | 可选 |
| `status` | 属性状态,如 recommended、obsolete、legacy | 用户选择 | 下拉框 | 可选;推荐使用枚举 |
| `submission_timestamp` | 属性定义提交时间 | 系统默认当前时间,可手动调整 | 日期时间选择器 | 可选;新增默认当前时间 |
| `crop_id` | 适用作物 | 从 crop 选择 | 作物选择器 | 可选;若填写,下游材料应同 crop |
| `method_id` | 属性测定方法 | 从 method 选择 | 方法选择器 | 可选;若填写,属性值录入按该方法解释 |
| `ontology_id` | 所属本体 | 从 ontology 选择 | 本体选择器 | 可选 |
| `scale_id` | 值标尺/单位/有效值范围 | 从 scale 选择 | 标尺选择器 | 可选;若填写,属性值必须按 scale 校验 |
| `trait_id` | 关联性状 | 从 trait 选择 | 性状选择器 | 可选 |
| `attribute_category` | 属性分类,如 Morphological、Genetic、Quality | 用户选择/录入 | 下拉框/文本框 | 可选;建议字典化 |
| `code` | 属性代码,便于导入导出 | 用户录入 | 文本框 | 可选;建议唯一 |
| `datatype` | 属性值数据类型,如 text、numeric、date、boolean、categorical | 用户选择 | 下拉框 | 必填 |
| `description` | 属性解释 | 用户录入 | 多行文本 | 可选 |
| `name` | 属性名称 | 用户录入 | 文本框 | 必填;作为属性选择器展示名称 |
| `pui` | 属性永久标识 | 用户录入 | 文本框/URL 输入框 | 可选;建议唯一 |
| `uri` | 属性 URI | 用户录入 | URL 输入框 | 可选;校验 URL |
## 录入建议
- 属性定义页面本质是“属性字典配置”。
- 前端应根据 `datatype` 动态决定属性值录入控件:
- numeric数字输入框
- categorical下拉框
- date日期选择器
- boolean开关
- text文本框。
- 若绑定了 `scale_id`,则优先按 scale 的单位、上下限、有效分类值校验。
---

View File

@@ -0,0 +1,27 @@
# 02 Germplasm / Seed - germplasm_attribute_value 表录入说明
来源:`docs/requirements/02-germplasm-seed-entry-requirements.md`
## 录入目标
属性值是“某个 germplasm 在某个属性上的实际取值”。它不是属性定义,也不是 observation。它适合记录材料相对稳定、不强依赖环境的特征。
## 字段录入
| 字段 | 业务意义 | 录入方式 | 控件建议 | 校验规则 |
| ----------------- | ------------------------------ | -------------------------------------- | ---------- | ---------------------------------------- |
| `id` | 属性值主键 | 系统生成 | 隐藏/只读 | 必填、唯一 |
| `auth_user_id` | 数据所属用户或租户 | 登录上下文自动写入 | 隐藏 | 不允许手填 |
| `determined_date` | 属性值被测定或确认的日期 | 用户录入 | 日期选择器 | 可选;多次测定时必须填写以区分记录 |
| `value` | 某个材料在某个属性上的实际取值 | 用户录入 | 动态控件 | 必填;按 attribute datatype / scale 校验 |
| `attribute_id` | 属性定义 | 从 germplasm_attribute_definition 选择 | 属性选择器 | 必选;必须存在 |
| `germplasm_id` | 所属材料 | 从 germplasm 选择 | 材料选择器 | 必选;必须存在 |
## 录入建议
- 推荐嵌入 Germplasm 详情页的“属性值”Tab。
- 支持批量导入,模板列建议为:`germplasm_id/germplasm_name``attribute_code/attribute_name``value``determined_date`
- 同一个 germplasm + attribute 可以允许多次测定,但页面必须显示测定日期、来源和最新值标记。
---

View File

@@ -0,0 +1,25 @@
# 02 Germplasm / Seed - crossing_project 表录入说明
来源:`docs/requirements/02-germplasm-seed-entry-requirements.md`
## 录入目标
`crossing_project` 是某个育种项目下的一组杂交任务集合。它不是一次杂交而是一个杂交工作台例如“2026 抗倒伏杂交项目”。
## 字段录入
| 字段 | 业务意义 | 录入方式 | 控件建议 | 校验规则 |
| -------------- | ------------------ | ------------------ | ---------- | ----------------------------- |
| `id` | 杂交项目主键 | 系统生成 | 隐藏/只读 | 必填、唯一 |
| `auth_user_id` | 数据所属用户或租户 | 登录上下文自动写入 | 隐藏 | 不允许手填 |
| `description` | 杂交项目说明 | 用户录入 | 多行文本 | 可选 |
| `name` | 杂交项目名称 | 用户录入 | 文本框 | 必填;同一 program 下建议唯一 |
| `program_id` | 所属育种项目 | 从 program 选择 | 项目选择器 | 必选;必须存在 |
## 页面与交互
- 详情页应展示计划杂交、实际杂交、潜在亲本、后代材料、产生的 seed lot。
- 创建 cross 时应自动带入 crossing_project_id。
---

View File

@@ -0,0 +1,30 @@
# 02 Germplasm / Seed - cross_entity 表录入说明
来源:`docs/requirements/02-germplasm-seed-entry-requirements.md`
## 录入目标
`cross_entity` 统一承载计划杂交和实际杂交。通过 `planned` 字段区分计划与实际,通过 `planned_cross_id` 指向来源计划。
## 字段录入
| 字段 | 业务意义 | 录入方式 | 控件建议 | 校验规则 |
| --------------------- | ------------------------------------------- | ------------------------ | -------------- | --------------------------------------- |
| `id` | cross 主键 | 系统生成 | 隐藏/只读 | 必填、唯一 |
| `auth_user_id` | 数据所属用户或租户 | 登录上下文自动写入 | 隐藏 | 不允许手填 |
| `cross_type` | 杂交类型,如 biparental、self、backcross 等 | 用户选择 | 下拉框 | 可选;值来自枚举字典 |
| `name` | cross 名称,如 A × B、A/B、Cross-2026-001 | 用户录入或自动生成 | 文本框 | 必填;同一 crossing project 下建议唯一 |
| `planned` | 是否为计划杂交 | 页面根据入口自动设置 | 开关/分段控件 | 必填;计划杂交为 true实际杂交为 false |
| `status` | 状态,如 TODO、DONE、SKIPPED、FAILED | 用户选择/系统更新 | 下拉框 | 可选;计划杂交常用 TODO/DONE/SKIPPED |
| `crossing_project_id` | 所属杂交项目 | 从 crossing_project 选择 | 杂交项目选择器 | 必选 |
| `planned_cross_id` | 实际杂交来源的计划杂交 | 从 cross_entity 选择 | Cross 选择器 | 可选;不能选择自己;实际杂交建议填写 |
## 录入建议
- 页面上分成“计划杂交”和“实际杂交”两个入口,但后端都保存到 `cross_entity`
- 创建计划杂交时:`planned=true``planned_cross_id=null`
- 完成实际杂交时:`planned=false``planned_cross_id=原计划杂交 id`
- 亲本不要直接塞在 cross 主表字段中,应通过 `cross_parent` 维护,便于支持多亲本和 observation_unit 亲本来源。
---

View File

@@ -0,0 +1,26 @@
# 02 Germplasm / Seed - cross_parent 表录入说明
来源:`docs/requirements/02-germplasm-seed-entry-requirements.md`
## 录入目标
`cross_parent` 表示某个 cross 的亲本。亲本可以来自 `germplasm`,也可以来自某个 `observation_unit`,例如田间某一株实际被选作父本/母本。
## 字段录入
| 字段 | 业务意义 | 录入方式 | 控件建议 | 校验规则 |
| --------------------- | --------------------------------------------------- | ---------------------------------- | ----------------- | ------------------------------------- |
| `id` | 亲本记录主键 | 系统生成 | 隐藏/只读 | 必填、唯一 |
| `parent_type` | 亲本角色,如 MALE、FEMALE、SELF、POPULATION、CLONAL | 用户选择 | 下拉框 | 必填;使用枚举 |
| `cross_id` | 所属 cross | 从 cross_entity 选择或由详情页带入 | Cross 选择器/隐藏 | 必选 |
| `crossing_project_id` | 所属 crossing project | 由 cross 自动带出 | 只读/隐藏 | 可选;如填写必须与 cross 一致 |
| `germplasm_id` | 亲本材料 | 从 germplasm 选择 | 材料选择器 | 与 `observation_unit_id` 至少一个必填 |
| `observation_unit_id` | 亲本观测单元 | 从 observation_unit 选择 | 观测单元选择器 | 与 `germplasm_id` 至少一个必填 |
## 录入建议
- 在 Cross 详情页内嵌“亲本列表”。
- 常见快捷录入Parent1 / Parent2。
- 对于田间选株杂交,优先记录 observation_unit_id同时可带出 germplasm_id保证可追溯到具体植株。
---

View File

@@ -0,0 +1,28 @@
# 02 Germplasm / Seed - pedigree_node 表录入说明
来源:`docs/requirements/02-germplasm-seed-entry-requirements.md`
## 录入目标
`pedigree_node` 是系谱图中的节点,通常对应一个 germplasm。它用于描述材料在系谱树中的位置不等同于一次杂交记录。
## 字段录入
| 字段 | 业务意义 | 录入方式 | 控件建议 | 校验规则 |
| --------------------- | --------------------- | ------------------------ | -------------- | ----------------------------------------- |
| `id` | 系谱节点主键 | 系统生成 | 隐藏/只读 | 必填、唯一 |
| `auth_user_id` | 数据所属用户或租户 | 登录上下文自动写入 | 隐藏 | 不允许手填 |
| `crossing_year` | 亲本最初杂交年份 | 用户录入 | 年份选择器 | 可选;四位年份 |
| `family_code` | 家系编号 | 用户录入 | 文本框 | 可选;同一 crossing_project 下建议唯一 |
| `pedigree_string` | 系谱字符串,如 A/B//C | 用户录入/系统生成 | 文本框 | 可选;建议支持 Purdy notation |
| `crossing_project_id` | 产生该节点的杂交项目 | 从 crossing_project 选择 | 杂交项目选择器 | 可选 |
| `germplasm_id` | 该系谱节点对应的材料 | 从 germplasm 选择 | 材料选择器 | 建议必填;同一 germplasm 不建议重复建节点 |
## 录入建议
- Germplasm 详情页提供“系谱”Tab。
- 支持两种维护方式:树图拖拽维护、表格维护节点和边。
- 如果 cross 完成后产生后代 germplasm应自动或半自动创建 pedigree_node。
---

View File

@@ -0,0 +1,27 @@
# 02 Germplasm / Seed - pedigree_edge 表录入说明
来源:`docs/requirements/02-germplasm-seed-entry-requirements.md`
## 录入目标
`pedigree_edge` 是系谱图中的边,描述节点之间的父子、同胞等关系。
## 字段录入
| 字段 | 业务意义 | 录入方式 | 控件建议 | 校验规则 |
| ------------------- | ------------------------------------------ | --------------------- | ---------- | ------------------------------------ |
| `id` | 系谱边主键 | 系统生成 | 隐藏/只读 | 必填、唯一 |
| `auth_user_id` | 数据所属用户或租户 | 登录上下文自动写入 | 隐藏 | 不允许手填 |
| `edge_type` | 边类型,如 parent、child、sibling | 用户选择 | 下拉框 | 必填 |
| `parent_type` | 如果是亲本关系,标识 MALE、FEMALE、SELF 等 | 用户选择 | 下拉框 | 可选;当 edge_type=parent 时建议必填 |
| `connceted_node_id` | 被连接节点 | 从 pedigree_node 选择 | 节点选择器 | 必选 |
| `this_node_id` | 当前节点 | 从 pedigree_node 选择 | 节点选择器 | 必选;不能等于 connected node |
## 录入建议
- 前端展示时不要暴露“this_node_id / connected_node_id”这种技术词应该显示为“当前材料”和“关联材料”。
- 添加父本/母本时,系统自动创建 edge_type=parent。
- 需要避免明显循环,例如 A 是 B 的父本,同时 B 又是 A 的父本。
---

View File

@@ -0,0 +1,33 @@
# 02 Germplasm / Seed - seed_lot 表录入说明
来源:`docs/requirements/02-germplasm-seed-entry-requirements.md`
## 录入目标
`seed_lot` 是实物库存批次,描述某一批种子当前有多少、放在哪里、属于哪个项目。它不是 germplasm 身份;同一个 germplasm 可以有多个 seed_lot。
## 字段录入
| 字段 | 业务意义 | 录入方式 | 控件建议 | 校验规则 |
| ------------------- | ---------------------------------------------------- | --------------------- | ------------------- | ----------------------------- |
| `id` | SeedLot 主键 | 系统生成 | 隐藏/只读 | 必填、唯一 |
| `auth_user_id` | 数据所属用户或租户 | 登录上下文自动写入 | 隐藏 | 不允许手填 |
| `amount` | 当前库存数量,可以是粒数、重量、株数等 | 用户录入/交易自动更新 | 数字输入框 | 必填;非负;交易后自动更新 |
| `created_date` | 批次创建时间 | 系统默认,可导入 | 日期时间选择器/只读 | 默认当前时间 |
| `description` | 批次说明 | 用户录入 | 多行文本 | 可选 |
| `last_updated` | 最后更新时间,包含交易变化 | 系统自动更新 | 只读 | 不允许手动改 |
| `name` | 批次名称,如 华占-2026-荆门-扩繁批 | 用户录入或自动生成 | 文本框 | 必填;同一 program 下建议唯一 |
| `source_collection` | 原始来源 collection如野外采集、nursery、种质库集合 | 用户录入 | 文本框 | 可选 |
| `storage_location` | 具体库位描述,如 冰箱A-2层-盒03 | 用户录入 | 文本框 | 可选 |
| `units` | 数量单位,如 seeds、g、kg、plants | 用户选择 | 下拉框/文本框 | 必填;交易单位需一致或可换算 |
| `location_id` | 库存所在地点 | 从 location 选择 | 地点选择器 | 可选 |
| `program_id` | 所属项目 | 从 program 选择 | 项目选择器 | 可选;用于项目库存筛选 |
## 录入建议
- 创建 seed_lot 后必须进入“批次组成”Tab至少录入一条 `seed_lot_content_mixture`
- 普通用户不要直接编辑 amountamount 应通过入库、出库、转移、分装等交易动作更新。
- 支持库存状态:充足、低库存、耗尽,可由 amount 和阈值计算。
---

View File

@@ -0,0 +1,26 @@
# 02 Germplasm / Seed - seed_lot_content_mixture 表录入说明
来源:`docs/requirements/02-germplasm-seed-entry-requirements.md`
## 录入目标
`seed_lot_content_mixture` 描述一个 seed_lot 由哪些材料或 cross 组成。单一材料批次也需要有一条组成记录,比例为 100%。混合批次则多条记录占比合计为 100%。
## 字段录入
| 字段 | 业务意义 | 录入方式 | 控件建议 | 校验规则 |
| -------------------- | ----------------------------- | -------------------- | ------------------- | ---------------------------------------- |
| `id` | 批次组成主键 | 系统生成 | 隐藏/只读 | 必填、唯一 |
| `mixture_percentage` | 该材料或 cross 在批次中的占比 | 用户录入 | 百分比输入框 | 0 到 100同一 seed lot 总和建议等于 100 |
| `cross_id` | 来源 cross | 从 cross_entity 选择 | Cross 选择器 | 与 `germplasm_id` 至少一个必填 |
| `germplasm_id` | 来源 germplasm | 从 germplasm 选择 | 材料选择器 | 与 `cross_id` 至少一个必填 |
| `seed_lot_id` | 所属 seed lot | 由详情页带入或选择 | SeedLot 选择器/隐藏 | 必选 |
## 录入建议
- 新建 seed_lot 时,如果用户选择了单个 germplasm系统自动生成一条 mixture`germplasm_id=所选材料``mixture_percentage=100`
- 如果来源是某次杂交产生的种子,优先填写 `cross_id`
- 如果既能追溯 cross 又能追溯 germplasm可按系统设计决定是否允许同时填写若允许同时展示“来源杂交”和“当前材料身份”。
---

View File

@@ -0,0 +1,42 @@
# 02 Germplasm / Seed - seed_lot_transaction 表录入说明
来源:`docs/requirements/02-germplasm-seed-entry-requirements.md`
## 录入目标
`seed_lot_transaction` 记录库存变化。它不应该由用户像普通表单一样手动维护,而应该由“入库、出库、转移、分装、合并、消耗”等业务动作自动生成。
## 字段录入
| 字段 | 业务意义 | 录入方式 | 控件建议 | 校验规则 |
| ------------------ | -------------------------------------------- | ----------------------- | ------------------- | ------------------------------------------------- |
| `id` | 流转记录主键 | 系统生成 | 隐藏/只读 | 必填、唯一 |
| `auth_user_id` | 数据所属用户或租户 | 登录上下文自动写入 | 隐藏 | 不允许手填 |
| `amount` | 流转数量 | 用户在业务动作中录入 | 数字输入框 | 必填;大于 0 |
| `description` | 流转说明,如用于某 study、分装原因、报废原因 | 用户录入 | 多行文本 | 可选;出库/报废建议必填 |
| `timestamp` | 流转发生时间 | 默认当前时间,可调整 | 日期时间选择器 | 必填 |
| `units` | 流转单位 | 默认继承 seed_lot.units | 下拉框/只读 | 必填;需与 seed_lot 单位一致或有换算关系 |
| `from_seed_lot_id` | 来源批次 | 按动作自动设置 | SeedLot 选择器/隐藏 | 与 `to_seed_lot_id` 至少一个存在 |
| `to_seed_lot_id` | 目标批次 | 按动作自动设置 | SeedLot 选择器/隐藏 | 与 `from_seed_lot_id` 至少一个存在;不能等于 from |
## 业务动作映射
| 动作 | from_seed_lot_id | to_seed_lot_id | amount 对库存影响 |
| --------- | ---------------- | -------------- | -------------------------------------------- |
| 入库 | 空 | 目标批次 | 目标批次增加 |
| 出库 | 来源批次 | 空 | 来源批次减少 |
| 转移 | 来源批次 | 目标批次 | 来源减少,目标增加 |
| 分装 | 原批次 | 新批次 | 原批次减少,新批次增加 |
| 合并 | 多个来源批次 | 目标批次 | 来源减少,目标增加;可能生成多条 transaction |
| 消耗/报废 | 来源批次 | 空 | 来源减少,并记录原因 |
## 验收点
1. amount 必须大于 0。
2. 出库/消耗时amount 不得超过来源批次当前库存。
3. from 和 to 不能相同。
4. transaction 创建后应自动更新 seed_lot.amount 和 last_updated。
5. 已生成的 transaction 原则上不允许随意修改;如需纠错,应通过反向交易或更正记录处理。
---

View File

@@ -0,0 +1,48 @@
# 03 Genotyping - plate 表录入说明
来源:`docs/architecture/03-genotyping-data-flow.md`
## 录入目标
`plate` 表示样本板,是批量送检和测序前的样本组织单元。一个 plate 可以包含多个 `sample`,也可以关联 vendor submission。
## 上下游关系
| 类型 | 内容 |
| --- | --- |
| 表 | `plate` |
| Java 实体 | `PlateEntity` |
| 前置依赖 | `program``trial``study`,可选 `plate_submission` |
| 下游引用 | `sample` |
| API | `/brapi/v2/plates` |
## 字段录入
| 字段 | 业务意义 | 录入方式 | 校验规则 |
| --- | --- | --- | --- |
| `id` | plate 主键 | 系统生成;导入时可指定 | 必填、唯一 |
| `auth_user_id` | 数据所属用户 | 登录上下文自动写入 | 不允许前端手填 |
| `plate_name` | 样本板名称 | 用户录入 | 建议必填,同一 study 下建议唯一 |
| `plate_barcode` | 样本板条码 | 扫码/手填 | 建议唯一 |
| `client_plate_db_id` | 客户侧 plate ID | 用户录入/导入 | 可选 |
| `client_plate_barcode` | 客户侧 plate 条码 | 用户录入/导入 | 可选 |
| `plate_format` | plate 规格,如 96/384 孔板 | 枚举选择 | 可选;与样本孔位校验联动 |
| `sample_type` | plate 中样本类型 | 枚举选择 | 可选 |
| `sample_submission_format` | 提交给 vendor 的样本板格式 | 枚举选择 | 可选 |
| `status_time_stamp` | 状态时间 | 系统写入或导入 | 可选 |
| `program_id` | 所属项目 | 项目选择器 | 可选;若填需存在 |
| `trial_id` | 所属 trial | Trial 选择器 | 可选;若填需存在 |
| `study_id` | 所属 study | Study 选择器 | 可选;若填需存在 |
| `submission_id` | vendor plate submission | Vendor submission 选择器 | 可选 |
## 页面与交互
- Plate 列表页支持按 program、trial、study、barcode、plateName 查询。
- 详情页展示 plate 基本信息和下属 sample 列表。
- 新增 sample 时如果从 plate 详情进入,默认带出 `plate_id`
## 关键校验
1. 如果录入 `program_id/trial_id/study_id`,需要校验 Core 上下文一致性。
2. 如果使用 `plate_format`,样本 `plate_row/plate_column/well` 不能超出规格。
3. 已有关联 `sample` 的 plate 删除前必须提示,通常只允许停用或先迁移样本。

View File

@@ -0,0 +1,56 @@
# 03 Genotyping - sample 表录入说明
来源:`docs/architecture/03-genotyping-data-flow.md`
## 录入目标
`sample` 是 Genotyping 流程的样本入口,表示送检样本或测序样本。它可以挂到 `plate`,也可以直接关联 `observation_unit`,并冗余保存 program/trial/study 方便查询。
## 上下游关系
| 类型 | 内容 |
| --- | --- |
| 表 | `sample` |
| Java 实体 | `SampleEntity` |
| 前置依赖 | `plate``observation_unit``program``trial``study`,可选 `germplasm_taxon` |
| 下游引用 | `callset` |
| API | `/brapi/v2/samples` |
## 字段录入
| 字段 | 业务意义 | 录入方式 | 校验规则 |
| --- | --- | --- | --- |
| `id` | sample 主键 | 系统生成;导入时可指定 | 必填、唯一 |
| `auth_user_id` | 数据所属用户 | 登录上下文自动写入 | 不允许前端手填 |
| `sample_name` | 样本名称 | 用户录入/批量导入 | 建议必填 |
| `sample_barcode` | 样本条码 | 扫码/手填 | 建议唯一 |
| `samplepui` | 样本永久标识 | 用户录入/导入 | 可选,建议唯一 |
| `sample_description` | 样本说明 | 用户录入 | 可选 |
| `sample_type` | 样本类型 | 下拉/文本 | 可选 |
| `tissue_type` | 组织类型 | 下拉/文本 | 可选 |
| `sample_timestamp` | 取样时间 | 日期时间选择器 | 可选 |
| `taken_by` | 取样人 | 文本/人员选择 | 可选 |
| `sample_group_db_id` | 样本分组 ID | 文本/导入 | 可选 |
| `concentration` | 样本浓度 | 文本/数值 | 可选,建议带单位 |
| `volume` | 样本体积 | 文本/数值 | 可选,建议带单位 |
| `plate_id` | 所在样本板 | Plate 选择器 | 可选,若填需存在 |
| `plate_row` | 板行 | 文本 | 与 plate format 联动校验 |
| `plate_column` | 板列 | 数字输入 | 与 plate format 联动校验 |
| `well` | 孔位,如 A01 | 文本/自动生成 | 同一 plate 内建议唯一 |
| `observation_unit_id` | 对应观测单元 | ObservationUnit 选择器 | 可选,若填需存在 |
| `program_id` | 所属项目 | 项目选择器 | 可选,若填需存在 |
| `trial_id` | 所属 trial | Trial 选择器 | 可选,若填需存在 |
| `study_id` | 所属 study | Study 选择器 | 可选,若填需存在 |
| `taxon_id_id` | germplasm taxon | Taxon 选择器 | 可选 |
## 页面与交互
- Sample 列表页支持按 sampleName、barcode、plate、study、trial、program、observationUnit 查询。
- 从 Study 工作台创建 sample 时默认继承 `study_id/trial_id/program_id`
- 从 ObservationUnit 详情创建 sample 时默认带出 `observation_unit_id`
## 关键校验
1. `sample` 若关联 `observation_unit`,需要检查 observation unit 所属 study 与 sample 的 study 一致。
2. 同一 plate 内 `well` 不应重复。
3. 删除 sample 前必须检查是否已有 `callset`

View File

@@ -0,0 +1,44 @@
# 03 Genotyping - reference_set 表录入说明
来源:`docs/architecture/03-genotyping-data-flow.md`
## 录入目标
`reference_set` 表示参考基因组集合,是 reference、variantset、variant 的参考侧上游。它可以关联来源 germplasm。
## 上下游关系
| 类型 | 内容 |
| --- | --- |
| 表 | `reference_set` |
| Java 实体 | `ReferenceSetEntity` |
| 前置依赖 | 可选 `germplasm` |
| 下游引用 | `reference``variantset``variant` |
| API | `/brapi/v2/referencesets` |
## 字段录入
| 字段 | 业务意义 | 录入方式 | 校验规则 |
| --- | --- | --- | --- |
| `id` | reference set 主键 | 系统生成;导入时可指定 | 必填、唯一 |
| `auth_user_id` | 数据所属用户 | 登录上下文自动写入 | 不允许前端手填 |
| `reference_set_name` | 参考集合名称 | 用户录入 | 建议必填 |
| `assemblypui` | assembly 永久标识 | 用户录入/导入 | 可选,建议唯一 |
| `description` | 参考集合说明 | 多行文本 | 可选 |
| `is_derived` | 是否派生参考 | 开关 | 可选 |
| `md5checksum` | 校验值 | 文本 | 可选,格式提示 |
| `sourceuri` | 来源 URI | URL 输入 | 可选URL 格式校验 |
| `species_ontology_term` | 物种本体 term | 文本/本体选择器 | 可选 |
| `species_ontology_termuri` | 物种本体 URI | URL 输入 | 可选URL 格式校验 |
| `source_germplasm_id` | 来源 germplasm | Germplasm 选择器 | 可选,若填需存在 |
## 页面与交互
- 列表页展示 referenceSetName、assemblyPUI、species、sourceGermplasm、reference 数、variantset 数。
- 详情页展示 reference、variantset、variant 入口。
## 关键校验
1. 删除 reference_set 前检查 `reference``variantset``variant` 引用。
2. 若填写 `source_germplasm_id`,必须引用已存在 germplasm。
3. md5 checksum 建议做格式提示,不强行阻断历史数据。

View File

@@ -0,0 +1,40 @@
# 03 Genotyping - reference 表录入说明
来源:`docs/architecture/03-genotyping-data-flow.md`
## 录入目标
`reference` 表示具体参考序列,例如 chromosome、contig 或 scaffold。它属于一个 `reference_set`,下游可以分页保存序列片段。
## 上下游关系
| 类型 | 内容 |
| --- | --- |
| 表 | `reference` |
| Java 实体 | `ReferenceEntity` |
| 前置依赖 | `reference_set` |
| 下游引用 | `reference_bases` |
| API | `/brapi/v2/references` |
## 字段录入
| 字段 | 业务意义 | 录入方式 | 校验规则 |
| --- | --- | --- | --- |
| `id` | reference 主键 | 系统生成;导入时可指定 | 必填、唯一 |
| `auth_user_id` | 数据所属用户 | 登录上下文自动写入 | 不允许前端手填 |
| `reference_name` | 参考序列名称 | 用户录入 | 建议必填 |
| `reference_set_id` | 所属 reference_set | ReferenceSet 选择器 | 必选,必须存在 |
| `length` | 序列长度 | 数字输入/导入 | 可选,非负 |
| `md5checksum` | 序列校验值 | 文本 | 可选 |
| `source_divergence` | 与来源差异度 | 数字输入 | 可选 |
## 页面与交互
- Reference 列表页支持按 referenceSet、referenceName 查询。
- Reference 详情页展示 reference_bases 分页和长度、checksum 信息。
## 关键校验
1. `reference_set_id` 必须存在。
2. 删除 reference 前检查 `reference_bases`
3. 若维护 `reference_bases`,建议校验分页总长度与 `length` 的一致性。

View File

@@ -0,0 +1,37 @@
# 03 Genotyping - reference_bases 表录入说明
来源:`docs/architecture/03-genotyping-data-flow.md`
## 录入目标
`reference_bases` 保存 reference 的序列片段或分页内容。它是参考序列的明细表,通常通过导入或后端任务写入。
## 上下游关系
| 类型 | 内容 |
| --- | --- |
| 表 | `reference_bases` |
| Java 实体 | `ReferenceBasesPageEntity` |
| 前置依赖 | `reference` |
| 下游引用 | 无 |
## 字段录入
| 字段 | 业务意义 | 录入方式 | 校验规则 |
| --- | --- | --- | --- |
| `id` | reference bases 主键 | 系统生成;导入时可指定 | 必填、唯一 |
| `auth_user_id` | 数据所属用户 | 登录上下文自动写入 | 不允许前端手填 |
| `reference_id` | 所属 reference | Reference 选择器/导入 | 必选,必须存在 |
| `page_number` | 分页序号 | 数字输入/导入 | 同一 reference 内建议唯一 |
| `bases` | 碱基序列片段 | 文本/文件导入 | 最大 2048 字符;建议仅允许 A/C/G/T/N 等字符 |
## 页面与交互
- 一般不单独提供复杂 CRUD可在 Reference 详情页查看或导入。
- 长序列建议走文件导入或异步任务,不建议手工逐页录入。
## 关键校验
1. `reference_id` 必须存在。
2. `bases` 长度不能超过数据库字段限制。
3. 同一 reference 下 `page_number` 不应重复。

View File

@@ -0,0 +1,39 @@
# 03 Genotyping - variantset 表录入说明
来源:`docs/architecture/03-genotyping-data-flow.md`
## 录入目标
`variantset` 表示一批 variant 的集合通常对应一次测序、芯片、DArTSeq 或某个 study 下的位点集合。
## 上下游关系
| 类型 | 内容 |
| --- | --- |
| 表 | `variantset` |
| Java 实体 | `VariantSetEntity` |
| 前置依赖 | `reference_set``study` |
| 下游引用 | `variant``callset_variant_sets``variantset_analysis``variantset_format` |
| API | `/brapi/v2/variantsets` |
## 字段录入
| 字段 | 业务意义 | 录入方式 | 校验规则 |
| --- | --- | --- | --- |
| `id` | variantset 主键 | 系统生成;导入时可指定 | 必填、唯一 |
| `auth_user_id` | 数据所属用户 | 登录上下文自动写入 | 不允许前端手填 |
| `variant_set_name` | 变异集合名称 | 用户录入/导入 | 建议必填 |
| `reference_set_id` | 参考基因组集合 | ReferenceSet 选择器 | 建议必选,若填需存在 |
| `study_id` | 所属 study | Study 选择器 | 可选,若填需存在 |
## 页面与交互
- VariantSet 列表页支持按 referenceSet、study、variantSetName 查询。
- 详情页展示 variants、callsets、analysis、available formats。
- 从 Study 工作台创建时默认带出 `study_id`
## 关键校验
1. `reference_set_id` 与下属 `variant.reference_set_id` 应保持一致。
2. 删除 variantset 前检查 `variant``callset_variant_sets``variantset_analysis``variantset_format`
3. 导入大型 variantset 时建议先建 variantset再异步导入 variants 和 calls。

View File

@@ -0,0 +1,57 @@
# 03 Genotyping - variant 表录入说明
来源:`docs/architecture/03-genotyping-data-flow.md`
## 录入目标
`variant` 表示具体变异位点,例如 SNP、Indel 或结构变异。它是位点定义,不是某个样本的结果;样本上的 genotype 结果写入 `allele_call`
## 上下游关系
| 类型 | 内容 |
| --- | --- |
| 表 | `variant` |
| Java 实体 | `VariantEntity` |
| 前置依赖 | `reference_set``variantset` |
| 下游引用 | `allele_call``marker_position` |
| API | `/brapi/v2/variants` |
## 字段录入
| 字段 | 业务意义 | 录入方式 | 校验规则 |
| --- | --- | --- | --- |
| `id` | variant 主键 | 系统生成;导入时可指定 | 必填、唯一 |
| `auth_user_id` | 数据所属用户 | 登录上下文自动写入 | 不允许前端手填 |
| `variant_name` | 位点名称/marker 名称 | 用户录入/导入 | 建议必填 |
| `variant_type` | 位点类型,如 SNP/INDEL/SV | 下拉/导入 | 可选,建议枚举 |
| `reference_set_id` | 参考集合 | ReferenceSet 选择器 | 可选,若填需存在 |
| `variant_set_id` | 所属 variantset | VariantSet 选择器 | 建议必选,若填需存在 |
| `reference_bases` | 参考碱基 | 文本/导入 | 可选 |
| `variant_start` | 起始位置 | 数字输入/导入 | 可选,非负 |
| `variant_end` | 结束位置 | 数字输入/导入 | 可选,不能小于 start |
| `svlen` | 结构变异长度 | 数字输入/导入 | 可选 |
| `filters_applied` | 是否做过过滤 | 开关/导入 | 可选 |
| `filters_passed` | 是否通过过滤 | 开关/导入 | 可选 |
| `created` | 创建时间 | 系统写入/导入 | 可选 |
| `updated` | 更新时间 | 系统写入/导入 | 可选 |
## 附属集合字段
| 附属表 | 内容 |
| --- | --- |
| `variant_entity_alternate_bases` | alternateBases 列表 |
| `variant_entity_ciend` | CIEND 区间 |
| `variant_entity_cipos` | CIPOS 区间 |
| `variant_entity_filters_failed` | 未通过的 filter 列表 |
## 页面与交互
- Variant 列表页支持按 variantSet、referenceSet、variantName、variantType 查询。
- 大批量位点建议通过文件导入,不建议普通表单逐条录入。
- 详情页展示 allele_call 数量和 marker_position 入口。
## 关键校验
1. `variant` 是位点定义,不能把样本 genotype 写在本表。
2. `variant_set_id``reference_set_id` 应与所属 variantset 保持一致。
3. 删除 variant 前检查 `allele_call``marker_position` 引用。

View File

@@ -0,0 +1,40 @@
# 03 Genotyping - callset 表录入说明
来源:`docs/architecture/03-genotyping-data-flow.md`
## 录入目标
`callset` 表示某个 sample 的一组 genotype calls通常对应一个样本在一个或多个 variantset 上的调用集合。
## 上下游关系
| 类型 | 内容 |
| --- | --- |
| 表 | `callset` |
| Java 实体 | `CallSetEntity` |
| 前置依赖 | `sample` |
| 下游引用 | `allele_call``callset_variant_sets` |
| API | `/brapi/v2/callsets` |
## 字段录入
| 字段 | 业务意义 | 录入方式 | 校验规则 |
| --- | --- | --- | --- |
| `id` | callset 主键 | 系统生成;导入时可指定 | 必填、唯一 |
| `auth_user_id` | 数据所属用户 | 登录上下文自动写入 | 不允许前端手填 |
| `call_set_name` | 调用集合名称 | 用户录入/导入 | 建议必填,同一 sample 下建议唯一 |
| `sample_id` | 所属 sample | Sample 选择器/导入 | 必选,必须存在 |
| `created` | 创建时间 | 系统写入/导入 | 可选 |
| `updated` | 更新时间 | 系统写入/导入 | 可选 |
## 页面与交互
- CallSet 列表页支持按 sample、variantSet、callSetName 查询。
- 从 Sample 详情创建时默认带出 `sample_id`
- 需要通过 `callset_variant_sets` 绑定参与的 variantset。
## 关键校验
1. `sample_id` 必须存在。
2. 删除 callset 前检查 `allele_call``callset_variant_sets`
3. 如果 callset 绑定多个 variantset查询和导出时要明确当前 variantset 范围。

View File

@@ -0,0 +1,42 @@
# 03 Genotyping - allele_call 表录入说明
来源:`docs/architecture/03-genotyping-data-flow.md`
## 录入目标
`allele_call` 是最终 genotype 调用结果。业务上它就是 Call一条记录表示某个 sample/callset 在某个 variant 上的 genotype、read depth、likelihood 等结果。
## 上下游关系
| 类型 | 内容 |
| --- | --- |
| 表 | `allele_call` |
| Java 实体 | `CallEntity` |
| 前置依赖 | `callset``variant` |
| 下游引用 | 无 |
| API | `/brapi/v2/calls` |
## 字段录入
| 字段 | 业务意义 | 录入方式 | 校验规则 |
| --- | --- | --- | --- |
| `id` | call 主键 | 系统生成;导入时可指定 | 必填、唯一 |
| `auth_user_id` | 数据所属用户 | 登录上下文自动写入 | 不允许前端手填 |
| `call_set_id` | 所属 callset | CallSet 选择器/导入 | 必选,必须存在 |
| `variant_id` | 对应 variant | Variant 选择器/导入 | 必选,必须存在 |
| `genotype` | genotype 值,如 0/1、A/T | 文本/导入 | 建议必填 |
| `read_depth` | 测序深度 | 数字输入/导入 | 可选,非负 |
| `genotype_likelihood` | genotype likelihood | 数字输入/导入 | 可选 |
| `phase_set` | phase set | 文本/导入 | 可选 |
## 页面与交互
- 通常不做逐条手工录入,主要通过 VCF/HapMap/矩阵文件导入。
- 列表页支持按 callset、sample、variantset、variant 查询。
- 在 Variant 详情页可查看该位点下的 calls在 Sample/CallSet 详情页可查看该样本的 calls。
## 关键校验
1. `call_set_id``variant_id` 必须存在。
2. 同一 callset 对同一 variant 不应重复。
3. `allele_call` 不应直接承担 variant 定义字段;位点信息应来自 `variant`

View File

@@ -0,0 +1,45 @@
# 03 Genotyping - genome_map 表录入说明
来源:`docs/architecture/03-genotyping-data-flow.md`
## 录入目标
`genome_map` 表示遗传图谱,用于组织 linkage group并通过 marker_position 将 variant 放到图谱坐标上。
## 上下游关系
| 类型 | 内容 |
| --- | --- |
| 表 | `genome_map` |
| Java 实体 | `GenomeMapEntity` |
| 前置依赖 | `crop`,可关联 `study` |
| 下游引用 | `linkageGroup` / `linkage_group` |
| API | `/brapi/v2/maps` |
## 字段录入
| 字段 | 业务意义 | 录入方式 | 校验规则 |
| --- | --- | --- | --- |
| `id` | map 主键 | 系统生成;导入时可指定 | 必填、唯一 |
| `auth_user_id` | 数据所属用户 | 登录上下文自动写入 | 不允许前端手填 |
| `map_name` | 图谱名称 | 用户录入 | 建议必填 |
| `mappui` | map 永久标识 | 用户录入/导入 | 可选,建议唯一 |
| `crop_id` | 所属作物 | Crop 选择器 | 可选,若填需存在 |
| `scientific_name` | 学名 | 文本 | 可选 |
| `type` | 图谱类型 | 下拉/文本 | 可选 |
| `unit` | 图谱单位,如 cM | 文本/下拉 | 可选 |
| `published_date` | 发表日期 | 日期选择器 | 可选 |
| `documentationurl` | 文档链接 | URL 输入 | 可选URL 格式校验 |
| `comments` | 备注 | 多行文本 | 可选 |
## 页面与交互
- GenomeMap 列表页支持按 crop、mapName、type 查询。
- 详情页展示 linkage groups 和 marker positions。
- 可通过图谱详情批量导入 linkage group 与 marker position。
## 关键校验
1. 删除 genome_map 前检查 linkage group 引用。
2. 若关联 study应检查 study 的 crop 与 map 的 crop 一致。
3. `unit` 应与 marker_position 的 position 语义保持一致。

View File

@@ -0,0 +1,42 @@
# 03 Genotyping - linkageGroup / linkage_group 表录入说明
来源:`docs/architecture/03-genotyping-data-flow.md`
## 命名注意
架构文档标注 `LinkageGroupEntity` 对应表名是驼峰 `linkageGroup`。当前初始 schema DDL 中实际表名为 `linkage_group`。做 Atlas/Flyway 迁移时,必须先确认目标数据库中的真实表名,避免生成大小写或命名不一致的重复表。
## 录入目标
连锁群是 genome_map 下的分组,例如 chromosome 或 linkage group。`marker_position` 会把 variant 放到具体 linkage group 的位置上。
## 上下游关系
| 类型 | 内容 |
| --- | --- |
| Java 实体 | `LinkageGroupEntity` |
| 表 | 架构文档:`linkageGroup`;当前 DDL`linkage_group` |
| 前置依赖 | `genome_map` |
| 下游引用 | `marker_position` |
## 字段录入
| 字段 | 业务意义 | 录入方式 | 校验规则 |
| --- | --- | --- | --- |
| `id` | linkage group 主键 | 系统生成;导入时可指定 | 必填、唯一 |
| `auth_user_id` | 数据所属用户 | 登录上下文自动写入 | 不允许前端手填 |
| `genome_map_id` | 所属 genome_map | GenomeMap 选择器 | 必选,必须存在 |
| `linkage_group_name` | 连锁群名称 | 用户录入/导入 | 建议必填,同一 map 下唯一 |
| `max_marker_position` | 最大 marker 位置 | 数字输入/导入 | 可选,非负 |
## 页面与交互
- 通常作为 GenomeMap 详情页的子表维护。
- 支持批量导入 linkage group。
- 详情页展示该 linkage group 下的 marker_position 列表。
## 关键校验
1. `genome_map_id` 必须存在。
2. 同一 genome_map 下 `linkage_group_name` 不应重复。
3. 删除 linkage group 前检查 `marker_position` 引用。

View File

@@ -0,0 +1,39 @@
# 03 Genotyping - marker_position 表录入说明
来源:`docs/architecture/03-genotyping-data-flow.md`
## 录入目标
`marker_position` 记录 marker/variant 在 linkage group 上的位置,是遗传图谱定位侧与 variant 位点侧的连接表。
## 上下游关系
| 类型 | 内容 |
| --- | --- |
| 表 | `marker_position` |
| Java 实体 | `MarkerPositionEntity` |
| 前置依赖 | `linkageGroup` / `linkage_group``variant` |
| 下游引用 | 无 |
| API | `/brapi/v2/markerpositions` |
## 字段录入
| 字段 | 业务意义 | 录入方式 | 校验规则 |
| --- | --- | --- | --- |
| `id` | marker position 主键 | 系统生成;导入时可指定 | 必填、唯一 |
| `auth_user_id` | 数据所属用户 | 登录上下文自动写入 | 不允许前端手填 |
| `linkage_group_id` | 所属 linkage group | LinkageGroup 选择器/导入 | 必选,必须存在 |
| `variant_id` | 对应 variant | Variant 选择器/导入 | 必选,必须存在 |
| `position` | 图谱位置 | 数字输入/导入 | 必填,非负 |
## 页面与交互
- 可在 GenomeMap/LinkageGroup 详情页批量维护。
- 列表页支持按 map、linkageGroup、variant 查询。
- Variant 详情页可展示 marker_position 信息。
## 关键校验
1. `linkage_group_id``variant_id` 必须存在。
2. 同一 linkage group 下同一 variant 不应重复。
3. `position` 不应超过 linkage group 的 `max_marker_position`

View File

@@ -0,0 +1,34 @@
# 03 Genotyping - callset_variant_sets 表录入说明
来源:`docs/architecture/03-genotyping-data-flow.md`
## 录入目标
`callset_variant_sets``callset``variantset` 的多对多关系表,表示某个样本调用集合覆盖了哪些 variantset。
## 上下游关系
| 类型 | 内容 |
| --- | --- |
| 表 | `callset_variant_sets` |
| 前置依赖 | `callset``variantset` |
| 下游引用 | 查询、导出和 allele matrix 范围过滤 |
## 字段录入
| 字段 | 业务意义 | 录入方式 | 校验规则 |
| --- | --- | --- | --- |
| `call_sets_id` | callset 主键 | CallSet 选择器/导入 | 必选,必须存在 |
| `variant_sets_id` | variantset 主键 | VariantSet 选择器/导入 | 必选,必须存在 |
## 页面与交互
- 通常在 CallSet 详情页或 VariantSet 详情页维护,不建议独立做主菜单。
- 创建 callset 后可选择一个或多个 variantset。
- 大批量导入 calls 时可以由导入任务自动创建关系。
## 关键校验
1. `call_sets_id``variant_sets_id` 必须存在。
2. 同一 callset 与 variantset 关系不应重复。
3. 删除关系不应删除 callset 或 variantset 主数据。

View File

@@ -0,0 +1,45 @@
# 03 Genotyping - variantset_analysis 表录入说明
来源:`docs/architecture/03-genotyping-data-flow.md`
## 录入目标
`variantset_analysis` 记录 variantset 的分析或 QC 信息,例如分析名称、软件、类型、描述和时间。它是 variantset 的附属明细表。
## 上下游关系
| 类型 | 内容 |
| --- | --- |
| 表 | `variantset_analysis` |
| Java 实体 | `VariantSetAnalysisEntity` |
| 前置依赖 | `variantset` |
| 下游引用 | 分析信息展示 |
## 字段录入
| 字段 | 业务意义 | 录入方式 | 校验规则 |
| --- | --- | --- | --- |
| `id` | analysis 主键 | 系统生成;导入时可指定 | 必填、唯一 |
| `variant_set_id` | 所属 variantset | VariantSet 选择器/导入 | 必选,必须存在 |
| `analysis_name` | 分析名称 | 用户录入 | 建议必填 |
| `description` | 分析说明 | 多行文本 | 可选 |
| `type` | 分析类型,如 QC | 下拉/文本 | 可选 |
| `created` | 创建时间 | 日期时间 | 可选 |
| `updated` | 更新时间 | 日期时间 | 可选 |
## 附属集合字段
| 附属表 | 内容 |
| --- | --- |
| `variant_set_analysis_entity_software` | software 列表,如软件名称、版本或 URL |
## 页面与交互
- 在 VariantSet 详情页以 Analysis Tab 维护。
- 支持添加多条分析记录,每条可维护多个 software。
## 关键校验
1. `variant_set_id` 必须存在。
2. 删除 variantset 时需要先处理或级联处理 analysis。
3. `software` 如果是 URL前端可做 URL 格式提示。

View File

@@ -0,0 +1,42 @@
# 03 Genotyping - variantset_format 表录入说明
来源:`docs/architecture/03-genotyping-data-flow.md`
## 录入目标
`variantset_format` 记录 variantset 可用的数据格式和文件地址,例如 allele matrix、VCF、HapMap 或 CSV。它用于下载、导出和矩阵读取。
## 上下游关系
| 类型 | 内容 |
| --- | --- |
| 表 | `variantset_format` |
| Java 实体 | `VariantSetAvailableFormatEntity` |
| 前置依赖 | `variantset` |
| 下游引用 | 文件下载、allele matrix 展示、导出 |
## 字段录入
| 字段 | 业务意义 | 录入方式 | 校验规则 |
| --- | --- | --- | --- |
| `id` | format 主键 | 系统生成;导入时可指定 | 必填、唯一 |
| `variant_set_id` | 所属 variantset | VariantSet 选择器/导入 | 必选,必须存在 |
| `data_format` | 数据格式,如 VCF/HapMap/矩阵 | 枚举选择 | 建议必填 |
| `file_format` | MIME/文件格式 | 枚举选择 | 建议必填 |
| `fileurl` | 文件 URL | URL 输入/导入 | 可选URL 格式校验 |
| `expand_homozygotes` | 是否展开纯合位点 | 开关 | 可选 |
| `sep_phased` | phased genotype 分隔符 | 文本 | 可选 |
| `sep_unphased` | unphased genotype 分隔符 | 文本 | 可选 |
| `unknown_string` | 缺失值字符串 | 文本 | 可选 |
## 页面与交互
- 在 VariantSet 详情页以 Formats Tab 维护。
- 支持一组 variantset 配置多个可下载格式。
- 点击 `fileurl` 可下载或预览,对 allele matrix URL 可进入矩阵查看。
## 关键校验
1. `variant_set_id` 必须存在。
2. `fileurl` 如填写需通过 URL 格式校验。
3. 对矩阵格式,`sep_phased/sep_unphased/unknown_string` 会影响解析,应在导入预览时展示。

View File

@@ -0,0 +1,45 @@
# 03 Genotyping 开发录入说明
来源:`docs/architecture/03-genotyping-data-flow.md`
本目录按 Genotyping 模块的数据录入顺序拆分开发说明。主线是:
```text
Core/Phenotyping 上游数据 -> plate / sample
reference_set -> reference -> reference_bases
reference_set + study -> variantset -> variant
sample -> callset
callset + variantset -> callset_variant_sets
callset + variant -> allele_call
genome_map -> linkageGroup/linkage_group -> marker_position -> variant
```
## 文档清单
| 顺序 | 文档 | 表 | 作用 |
| --- | --- | --- | --- |
| 01 | `01-plate.md` | `plate` | 样本板 |
| 02 | `02-sample.md` | `sample` | 送检样本/测序样本 |
| 03 | `03-reference_set.md` | `reference_set` | 参考基因组集合 |
| 04 | `04-reference.md` | `reference` | 参考序列 |
| 05 | `05-reference_bases.md` | `reference_bases` | 参考序列片段/分页 |
| 06 | `06-variantset.md` | `variantset` | 变异集合 |
| 07 | `07-variant.md` | `variant` | 变异位点 |
| 08 | `08-callset.md` | `callset` | 样本调用集合 |
| 09 | `09-allele_call.md` | `allele_call` | genotype 调用结果 |
| 10 | `10-genome_map.md` | `genome_map` | 遗传图谱 |
| 11 | `11-linkage_group.md` | `linkageGroup` / `linkage_group` | 连锁群 |
| 12 | `12-marker_position.md` | `marker_position` | marker/variant 图谱位置 |
| 13 | `13-callset_variant_sets.md` | `callset_variant_sets` | callset 与 variantset 关系 |
| 14 | `14-variantset_analysis.md` | `variantset_analysis` | variantset 分析信息 |
| 15 | `15-variantset_format.md` | `variantset_format` | variantset 可用文件/矩阵格式 |
## 全局注意点
1. `CallEntity` 对应真实业务表是 `allele_call`,不要新建 `call` 表。
2. `CallSetEntity` 对应 `callset`,不是 `call_set`
3. `VariantSetEntity` 对应 `variantset`,不是 `variant_set`
4. 架构文档标注 `LinkageGroupEntity` 的表名为 `linkageGroup`;当前初始 DDL 中表名为 `linkage_group`。做迁移前必须以实际数据库 catalog 为准。
5. `sample` 是 Genotyping 样本入口,向上关联 `plate/observation_unit/study/trial/program`
6. `variant` 是位点定义,`allele_call` 是某个样本/callset 在位点上的结果。
7. `reference_set/reference/reference_bases` 是参考基因组侧;`variantset/variant/callset/allele_call` 是变异和结果侧。

View File

@@ -0,0 +1,37 @@
# 04 Germplasm / Seed - breeding_method 表录入说明
来源:`docs/architecture/04-germplasm-seed-data-flow.md`
## 录入目标
`breeding_method` 是育种方法字典,用来说明 germplasm 是通过什么方式形成的例如杂交选育、回交、自交系选育、诱变、DH、克隆选择等。
## 上下游关系
| 类型 | 内容 |
| --- | --- |
| 表 | `breeding_method` |
| Java 实体 | `BreedingMethodEntity` |
| 前置依赖 | 无 |
| 下游引用 | `germplasm.breeding_method_id` |
| API | `/brapi/v2/breedingmethods` |
## 字段录入
| 字段 | 业务意义 | 录入方式 | 校验规则 |
| --- | --- | --- | --- |
| `id` | 育种方法主键 | 系统生成;导入可指定 | 必填、唯一 |
| `auth_user_id` | 数据所属用户 | 登录上下文自动写入 | 不允许前端手填 |
| `name` | 方法名称 | 用户录入 | 必填,建议唯一 |
| `abbreviation` | 方法缩写 | 用户录入 | 可选,建议唯一 |
| `description` | 方法说明 | 多行文本 | 可选 |
## 页面与交互
- 列表页展示 name、abbreviation、description、引用 germplasm 数。
- 新增/编辑页为简单字典表单。
## 关键校验
1. `name` 必填。
2. 已被 `germplasm` 引用时不允许物理删除,只允许停用或提示引用关系。

View File

@@ -0,0 +1,68 @@
# 04 Germplasm / Seed - germplasm 表录入说明
来源:`docs/architecture/04-germplasm-seed-data-flow.md`
## 录入目标
`germplasm` 是种质主表,保存 accession、PUI、分类、采集、来源、育种方法和展示名称等身份信息。它不是库存批次库存批次由 `seed_lot` 表达。
## 上下游关系
| 类型 | 内容 |
| --- | --- |
| 表 | `germplasm` |
| Java 实体 | `GermplasmEntity` |
| 前置依赖 | `crop`,可选 `breeding_method` |
| 下游引用 | `germplasm_attribute_value``germplasm_donor``germplasm_institute``germplasm_origin``germplasm_synonym``germplasm_taxon``pedigree_node``cross_parent``seed_lot_content_mixture` |
| API | `/brapi/v2/germplasm` |
## 字段录入
| 字段 | 业务意义 | 录入方式 | 校验规则 |
| --- | --- | --- | --- |
| `id` | germplasm 主键 | 系统生成;导入可指定 | 必填、唯一 |
| `auth_user_id` | 数据所属用户 | 登录上下文自动写入 | 不允许前端手填 |
| `germplasm_name` | 种质名称 | 用户录入/导入 | 建议必填 |
| `default_display_name` | 默认展示名称 | 用户录入/自动生成 | 可选,缺省用 germplasm_name |
| `germplasmpui` | 种质永久标识 | 用户录入/导入 | 可选,建议唯一 |
| `accession_number` | accession 编号 | 用户录入/导入 | 可选,建议唯一 |
| `crop_id` | 所属作物 | Crop 选择器 | 建议必选,若填需存在 |
| `breeding_method_id` | 育种方法 | BreedingMethod 选择器 | 可选,若填需存在 |
| `genus` | 属 | 用户录入 | 可选 |
| `species` | 种 | 用户录入 | 可选 |
| `species_authority` | 种命名人 | 用户录入 | 可选 |
| `subtaxa` | 亚种/变种 | 用户录入 | 可选 |
| `subtaxa_authority` | 亚种命名人 | 用户录入 | 可选 |
| `country_of_origin_code` | 来源国家代码 | 国家选择器 | 可选 |
| `collection` | collection | 用户录入 | 可选 |
| `acquisition_date` | 获取日期 | 日期选择器 | 可选 |
| `acquisition_source_code` | 获取来源编码 | 枚举选择 | 可选 |
| `biological_status_of_accession_code` | 生物状态编码 | 枚举选择 | 可选 |
| `mls_status` | MLS 状态 | 枚举选择 | 可选 |
| `germplasm_preprocessing` | 种质预处理说明 | 文本 | 可选 |
| `seed_source` | 种子来源描述字段 | 文本 | 可选,不等于 seed_lot |
| `seed_source_description` | 种子来源补充说明 | 多行文本 | 可选 |
| `documentationurl` | 文档链接 | URL 输入 | 可选URL 格式校验 |
## 附属信息
| 附属表 | 内容 |
| --- | --- |
| `germplasm_donor` | donor accession、donor institute |
| `germplasm_institute` | host、donor、breeding、collecting、redundant 等机构 |
| `germplasm_origin` | 来源坐标和坐标不确定性 |
| `germplasm_synonym` | 别名及别名类型 |
| `germplasm_taxon` | taxon 来源和值 |
| `germplasm_entity_type_of_germplasm_storage_code` | storage type code 列表 |
## 页面与交互
- Germplasm 列表页支持按 crop、germplasmName、accessionNumber、PUI、synonym 查询。
- 详情页以 Tab 展示 attributes、donors、institutes、origin、synonyms、taxon、pedigree、seed lots、cross parent 记录。
- 从 Study/ObservationUnit 或 SeedLot 进入时应能回到 germplasm 详情。
## 关键校验
1. `germplasm_name` 建议必填,`accession_number``germplasmpui` 建议唯一。
2. 删除 germplasm 前必须检查属性值、seed lot 组成、cross parent、pedigree、sample/taxon 等引用。
3. 不要用 `seed_source` 表达库存;库存必须走 `seed_lot`

View File

@@ -0,0 +1,39 @@
# 04 Germplasm / Seed - germplasm_donor 表录入说明
来源:`docs/architecture/04-germplasm-seed-data-flow.md`
## 录入目标
`germplasm_donor` 记录某个 germplasm 的 donor accession 和 donor institute 信息,是 germplasm 的附属明细。
## 上下游关系
| 类型 | 内容 |
| --- | --- |
| 表 | `germplasm_donor` |
| Java 实体 | `DonorEntity` |
| 前置依赖 | `germplasm` |
| 下游引用 | MCPD 展示、来源追踪 |
## 字段录入
| 字段 | 业务意义 | 录入方式 | 校验规则 |
| --- | --- | --- | --- |
| `id` | donor 记录主键 | 系统生成;导入可指定 | 必填、唯一 |
| `auth_user_id` | 数据所属用户 | 登录上下文自动写入 | 不允许前端手填 |
| `germplasm_id` | 所属 germplasm | Germplasm 选择器/详情页带出 | 必选,必须存在 |
| `donor_accession_number` | donor accession 编号 | 用户录入 | 可选 |
| `donor_institute_code` | donor 机构代码 | 用户录入/选择 | 可选 |
| `donor_institute_name` | donor 机构名称 | 用户录入/选择 | 可选 |
| `germplasmpui` | donor germplasm PUI | 用户录入 | 可选 |
## 页面与交互
- 在 Germplasm 详情页 Donor Tab 内维护。
- 支持一条 germplasm 维护多个 donor 记录。
## 关键校验
1. `germplasm_id` 必须存在。
2. 同一 germplasm 下 donor accession + institute code 不建议重复。
3. 删除 donor 记录不应删除 germplasm 主数据。

View File

@@ -0,0 +1,38 @@
# 04 Germplasm / Seed - germplasm_institute 表录入说明
来源:`docs/architecture/04-germplasm-seed-data-flow.md`
## 录入目标
`germplasm_institute` 记录 germplasm 相关机构,包括 host、donor、breeding、collecting、redundant 等类型。
## 上下游关系
| 类型 | 内容 |
| --- | --- |
| 表 | `germplasm_institute` |
| Java 实体 | `GermplasmInstituteEntity` |
| 前置依赖 | `germplasm` |
| 下游引用 | Germplasm MCPD、机构筛选 |
## 字段录入
| 字段 | 业务意义 | 录入方式 | 校验规则 |
| --- | --- | --- | --- |
| `id` | 机构记录主键 | 系统生成 | 必填、唯一 |
| `germplasm_id` | 所属 germplasm | Germplasm 选择器/详情页带出 | 必选,必须存在 |
| `institute_type` | 机构类型 | 枚举选择 | HOST、DONOR、BREEDING、COLLECTING、REDUNDANT |
| `institute_code` | 机构代码 | 用户录入 | 可选 |
| `institute_name` | 机构名称 | 用户录入 | 建议必填 |
| `institute_address` | 机构地址 | 多行文本 | 可选 |
## 页面与交互
- 在 Germplasm 详情页 Institute Tab 内维护。
- 可把 HOST institute 作为 germplasm 主信息摘要展示。
## 关键校验
1. `germplasm_id` 必须存在。
2. 同一 germplasm 下同类型、同 code 的机构不建议重复。
3. 删除 institute 记录不应删除 germplasm 主数据。

View File

@@ -0,0 +1,36 @@
# 04 Germplasm / Seed - germplasm_origin 表录入说明
来源:`docs/architecture/04-germplasm-seed-data-flow.md`
## 录入目标
`germplasm_origin` 记录 germplasm 的来源地坐标和坐标不确定性,适合表达采集地点或原产地的空间信息。
## 上下游关系
| 类型 | 内容 |
| --- | --- |
| 表 | `germplasm_origin` |
| Java 实体 | `GermplasmOriginEntity` |
| 前置依赖 | `germplasm`,可选 `geojson` |
| 下游引用 | 地理来源展示、MCPD |
## 字段录入
| 字段 | 业务意义 | 录入方式 | 校验规则 |
| --- | --- | --- | --- |
| `id` | origin 记录主键 | 系统生成 | 必填、唯一 |
| `germplasm_id` | 所属 germplasm | Germplasm 选择器/详情页带出 | 必选,必须存在 |
| `coordinate_uncertainty` | 坐标不确定性 | 文本/数字 | 可选 |
| `coordinates_id` | GeoJSON 坐标对象 | 地图取点/GeoJSON 导入 | 可选,若填需存在 |
## 页面与交互
- 在 Germplasm 详情页 Origin Tab 内维护。
- 支持地图取点和 GeoJSON 查看。
## 关键校验
1. `germplasm_id` 必须存在。
2. 坐标格式需要合法。
3. 删除 origin 记录不应删除 germplasm 主数据。

View File

@@ -0,0 +1,36 @@
# 04 Germplasm / Seed - germplasm_synonym 表录入说明
来源:`docs/architecture/04-germplasm-seed-data-flow.md`
## 录入目标
`germplasm_synonym` 记录 germplasm 的别名、旧名、商品名或本地名,用于检索和展示。
## 上下游关系
| 类型 | 内容 |
| --- | --- |
| 表 | `germplasm_synonym` |
| Java 实体 | `GermplasmSynonymEntity` |
| 前置依赖 | `germplasm` |
| 下游引用 | Germplasm 搜索、详情展示 |
## 字段录入
| 字段 | 业务意义 | 录入方式 | 校验规则 |
| --- | --- | --- | --- |
| `id` | synonym 记录主键 | 系统生成 | 必填、唯一 |
| `germplasm_id` | 所属 germplasm | Germplasm 选择器/详情页带出 | 必选,必须存在 |
| `synonym` | 别名 | 用户录入 | 必填 |
| `type` | 别名类型 | 下拉/文本 | 可选,如 local、commercial、old name |
## 页面与交互
- 在 Germplasm 详情页 Synonym Tab 内维护。
- Germplasm 列表搜索应支持 synonym 命中。
## 关键校验
1. `germplasm_id` 必须存在。
2. 同一 germplasm 下同一个 synonym 不应重复。
3. 删除 synonym 不应删除 germplasm 主数据。

View File

@@ -0,0 +1,36 @@
# 04 Germplasm / Seed - germplasm_taxon 表录入说明
来源:`docs/architecture/04-germplasm-seed-data-flow.md`
## 录入目标
`germplasm_taxon` 记录外部 taxon 标识和来源,用于把 germplasm 连接到分类数据库或外部生物分类体系。该表由 `TaxonEntity` 映射。
## 上下游关系
| 类型 | 内容 |
| --- | --- |
| 表 | `germplasm_taxon` |
| Java 实体 | `TaxonEntity` |
| 前置依赖 | `germplasm` |
| 下游引用 | `sample.taxon_id_id`、分类展示 |
## 字段录入
| 字段 | 业务意义 | 录入方式 | 校验规则 |
| --- | --- | --- | --- |
| `id` | taxon 记录主键 | 系统生成 | 必填、唯一 |
| `germplasm_id` | 所属 germplasm | Germplasm 选择器/详情页带出 | 必选,必须存在 |
| `source_name` | taxon 来源名称 | 文本/下拉 | 可选,如 NCBI Taxonomy |
| `taxon_id` | taxon 标识 | 用户录入 | 必填 |
## 页面与交互
- 在 Germplasm 详情页 Taxon Tab 内维护。
- Sample 表可引用 taxon 记录。
## 关键校验
1. `germplasm_id` 必须存在。
2. 同一 source 下 taxon_id 不建议重复。
3. 删除 taxon 前检查 sample 引用。

View File

@@ -0,0 +1,55 @@
# 04 Germplasm / Seed - germplasm_attribute_definition 表录入说明
来源:`docs/architecture/04-germplasm-seed-data-flow.md`
## 录入目标
`germplasm_attribute_definition` 定义 germplasm 可维护的属性。它继承变量定义体系,可关联 crop、trait、method、scale、ontology。
## 上下游关系
| 类型 | 内容 |
| --- | --- |
| 表 | `germplasm_attribute_definition` |
| Java 实体 | `GermplasmAttributeDefinitionEntity` |
| 前置依赖 | `crop``trait``method``scale``ontology` |
| 下游引用 | `germplasm_attribute_value` |
| API | `/brapi/v2/attributes` |
## 字段录入
| 字段 | 业务意义 | 录入方式 | 校验规则 |
| --- | --- | --- | --- |
| `id` | 属性定义主键 | 系统生成;导入可指定 | 必填、唯一 |
| `auth_user_id` | 数据所属用户 | 登录上下文自动写入 | 不允许前端手填 |
| `name` | 属性名称 | 用户录入 | 必填 |
| `code` | 属性编码 | 用户录入 | 可选,建议唯一 |
| `pui` | 永久标识 | 用户录入 | 可选,建议唯一 |
| `attribute_category` | 属性分类 | 下拉/文本 | 可选 |
| `datatype` | 数据类型 | 下拉 | 建议必填 |
| `description` | 属性说明 | 多行文本 | 可选 |
| `uri` | 外部 URI | URL 输入 | 可选URL 格式校验 |
| `crop_id` | 作物 | Crop 选择器 | 可选 |
| `trait_id` | 性状 | Trait 选择器 | 可选 |
| `method_id` | 方法 | Method 选择器 | 可选 |
| `scale_id` | 标尺 | Scale 选择器 | 可选 |
| `ontology_id` | 本体 | Ontology 选择器 | 可选 |
| `documentationurl` | 文档链接 | URL 输入 | 可选 |
| `status` | 状态 | 下拉/文本 | 可选 |
| `default_value` | 默认值 | 文本 | 可选 |
| `growth_stage` | 生育期 | 文本 | 可选 |
| `institution` | 机构 | 文本 | 可选 |
| `language` | 语言 | 文本 | 可选 |
| `scientist` | 科学家/维护人 | 文本 | 可选 |
| `submission_timestamp` | 提交时间 | 日期时间 | 可选 |
## 页面与交互
- Attribute Definition 列表页支持按 crop、category、datatype、keyword 查询。
- 创建 attribute value 前必须先有 definition。
## 关键校验
1. `name` 必填。
2. 已被 `germplasm_attribute_value` 引用时不允许物理删除。
3. `datatype` 要与 value 输入控件联动。

View File

@@ -0,0 +1,39 @@
# 04 Germplasm / Seed - germplasm_attribute_value 表录入说明
来源:`docs/architecture/04-germplasm-seed-data-flow.md`
## 录入目标
`germplasm_attribute_value` 保存某个 germplasm 在某个属性定义上的实际取值。
## 上下游关系
| 类型 | 内容 |
| --- | --- |
| 表 | `germplasm_attribute_value` |
| Java 实体 | `GermplasmAttributeValueEntity` |
| 前置依赖 | `germplasm``germplasm_attribute_definition` |
| 下游引用 | 属性查询、详情展示 |
| API | `/brapi/v2/attributevalues` |
## 字段录入
| 字段 | 业务意义 | 录入方式 | 校验规则 |
| --- | --- | --- | --- |
| `id` | 属性值主键 | 系统生成;导入可指定 | 必填、唯一 |
| `auth_user_id` | 数据所属用户 | 登录上下文自动写入 | 不允许前端手填 |
| `germplasm_id` | 所属 germplasm | Germplasm 选择器/详情页带出 | 必选,必须存在 |
| `attribute_id` | 属性定义 | Attribute 选择器 | 必选,必须存在 |
| `value` | 属性值 | 根据 definition.datatype 选择控件 | 必填或按业务要求 |
| `determined_date` | 测定日期 | 日期选择器 | 可选 |
## 页面与交互
- 在 Germplasm 详情页 Attributes Tab 维护。
- 批量导入时按 germplasm + attribute 组成矩阵录入更高效。
## 关键校验
1. `germplasm_id``attribute_id` 必须存在。
2. 同一 germplasm 下同一 attribute 不建议重复,若允许多次测定,需要用 determined_date 区分。
3. `value` 必须符合 attribute definition 的 datatype。

View File

@@ -0,0 +1,38 @@
# 04 Germplasm / Seed - crossing_project 表录入说明
来源:`docs/architecture/04-germplasm-seed-data-flow.md`
## 录入目标
`crossing_project` 表示杂交项目,是 cross、planned cross、cross parent 和 pedigree node 的上游组织维度,通常挂在 Core 的 `program` 下。
## 上下游关系
| 类型 | 内容 |
| --- | --- |
| 表 | `crossing_project` |
| Java 实体 | `CrossingProjectEntity` |
| 前置依赖 | `program` |
| 下游引用 | `cross_entity``cross_parent``pedigree_node` |
| API | `/brapi/v2/crossingprojects` |
## 字段录入
| 字段 | 业务意义 | 录入方式 | 校验规则 |
| --- | --- | --- | --- |
| `id` | crossing project 主键 | 系统生成;导入可指定 | 必填、唯一 |
| `auth_user_id` | 数据所属用户 | 登录上下文自动写入 | 不允许前端手填 |
| `name` | 杂交项目名称 | 用户录入 | 必填,建议同一 program 下唯一 |
| `description` | 项目说明 | 多行文本 | 可选 |
| `program_id` | 所属 program | Program 选择器 | 必选,必须存在 |
## 页面与交互
- 列表页支持按 program、keyword 查询。
- 详情页展示 crosses、planned crosses、potential parents、pedigree nodes。
## 关键校验
1. `program_id` 必须存在。
2. 删除 crossing_project 前检查 cross、cross_parent、pedigree_node 引用。
3. 如果 program 有 crop创建 cross 时亲本 germplasm 建议与 program crop 一致。

View File

@@ -0,0 +1,50 @@
# 04 Germplasm / Seed - cross_entity 表录入说明
来源:`docs/architecture/04-germplasm-seed-data-flow.md`
## 录入目标
`cross_entity` 是 Cross 和 PlannedCross 的统一落库表。`plannedcross` 不是独立数据库表,计划杂交通过 `planned=true` 表达;实际杂交可以通过 `planned_cross_id` 关联计划杂交。
## 上下游关系
| 类型 | 内容 |
| --- | --- |
| 表 | `cross_entity` |
| Java 实体 | `CrossEntity` |
| 前置依赖 | `crossing_project`,可选自关联 `cross_entity` |
| 下游引用 | `cross_parent``cross_pollination_event``seed_lot_content_mixture` |
| API | `/brapi/v2/crosses``/brapi/v2/plannedcrosses` |
## 字段录入
| 字段 | 业务意义 | 录入方式 | 校验规则 |
| --- | --- | --- | --- |
| `id` | cross 主键 | 系统生成;导入可指定 | 必填、唯一 |
| `auth_user_id` | 数据所属用户 | 登录上下文自动写入 | 不允许前端手填 |
| `name` | cross 名称 | 用户录入/自动生成 | 建议必填 |
| `cross_type` | 杂交类型 | 枚举选择 | 可选 |
| `crossing_project_id` | 所属 crossing project | CrossingProject 选择器 | 建议必选,若填需存在 |
| `status` | planned cross 状态 | 枚举选择 | 计划杂交常用 |
| `planned` | 是否为计划杂交 | 开关 | 必填,默认 false |
| `planned_cross_id` | 关联计划杂交 | Cross 选择器 | 可选,必须指向 `planned=true` 的 cross |
## 附属集合字段
| 附属表 | 内容 |
| --- | --- |
| `cross_entity_cross_attributes` | crossAttributes 列表 |
| `cross_parent` | cross 的亲本 |
| `cross_pollination_event` | 授粉事件 |
## 页面与交互
- Cross 列表页展示实际杂交PlannedCross 列表页展示 `planned=true` 数据。
- 新建实际 cross 时可选择 planned cross并继承 planned cross 的亲本作为初始值。
- 详情页展示 parents、pollination events 和 seed lot 组成入口。
## 关键校验
1. `plannedcross` 不新建表,所有 planned cross 走 `cross_entity`
2. `planned_cross_id` 不能指向自己。
3. 删除 cross 前检查 `cross_parent``cross_pollination_event``seed_lot_content_mixture` 引用。

View File

@@ -0,0 +1,39 @@
# 04 Germplasm / Seed - cross_parent 表录入说明
来源:`docs/architecture/04-germplasm-seed-data-flow.md`
## 录入目标
`cross_parent` 连接 cross 与亲本来源。亲本可以是 germplasm也可以是 observation_unit用来表达实际田间单株或 plot 来源。
## 上下游关系
| 类型 | 内容 |
| --- | --- |
| 表 | `cross_parent` |
| Java 实体 | `CrossParentEntity` |
| 前置依赖 | `cross_entity``crossing_project``germplasm``observation_unit` |
| 下游引用 | 杂交亲本展示和校验 |
## 字段录入
| 字段 | 业务意义 | 录入方式 | 校验规则 |
| --- | --- | --- | --- |
| `id` | cross parent 主键 | 系统生成 | 必填、唯一 |
| `cross_id` | 所属 cross | Cross 选择器/详情页带出 | 必选,必须存在 |
| `crossing_project_id` | 所属 crossing project | 自动带出/选择器 | 建议与 cross 一致 |
| `germplasm_id` | 亲本 germplasm | Germplasm 选择器 | 与 observation_unit 至少填一个 |
| `observation_unit_id` | 亲本 observation unit | ObservationUnit 选择器 | 与 germplasm 至少填一个 |
| `parent_type` | 亲本类型 | 枚举选择 | FEMALE、MALE、SELF、POPULATION、CLONAL 等 |
## 页面与交互
- 在 Cross 或 PlannedCross 详情页 Parents Tab 内维护。
- 创建 cross 时至少添加一个亲本;常见杂交需要 FEMALE 和 MALE。
## 关键校验
1. `cross_id` 必须存在。
2. `germplasm_id``observation_unit_id` 至少填写一个,不建议同时为空。
3. 同一 cross 下相同 parentType + germplasm/observationUnit 不应重复。
4. 如果填 `crossing_project_id`,应与 `cross.crossing_project_id` 一致。

View File

@@ -0,0 +1,37 @@
# 04 Germplasm / Seed - cross_pollination_event 表录入说明
来源:`docs/architecture/04-germplasm-seed-data-flow.md`
## 录入目标
`cross_pollination_event` 记录实际杂交过程中的授粉事件,包括授粉编号、时间和是否成功。
## 上下游关系
| 类型 | 内容 |
| --- | --- |
| 表 | `cross_pollination_event` |
| Java 实体 | `CrossPollinationEventEntity` |
| 前置依赖 | `cross_entity` |
| 下游引用 | Cross 过程追踪 |
## 字段录入
| 字段 | 业务意义 | 录入方式 | 校验规则 |
| --- | --- | --- | --- |
| `id` | 授粉事件主键 | 系统生成 | 必填、唯一 |
| `cross_id` | 所属 cross | Cross 选择器/详情页带出 | 必选,必须存在 |
| `pollination_number` | 授粉编号 | 用户录入/自动生成 | 可选,建议同一 cross 下唯一 |
| `pollination_successful` | 是否授粉成功 | 开关 | 可选 |
| `pollination_time_stamp` | 授粉时间 | 日期时间选择器 | 可选 |
## 页面与交互
- 在 Cross 详情页 Pollination Events Tab 内维护。
- 可以按授粉时间排序展示。
## 关键校验
1. `cross_id` 必须存在。
2. 同一 cross 下 `pollination_number` 不建议重复。
3. 删除授粉事件不应删除 cross 主数据。

View File

@@ -0,0 +1,40 @@
# 04 Germplasm / Seed - pedigree_node 表录入说明
来源:`docs/architecture/04-germplasm-seed-data-flow.md`
## 录入目标
`pedigree_node` 表示系谱中的一个节点,一个节点通常关联一个 germplasm并可归属 crossing_project。节点之间的 parent/child/sibling 关系由 `pedigree_edge` 记录。
## 上下游关系
| 类型 | 内容 |
| --- | --- |
| 表 | `pedigree_node` |
| Java 实体 | `PedigreeNodeEntity` |
| 前置依赖 | `germplasm`、可选 `crossing_project` |
| 下游引用 | `pedigree_edge` |
| API | `/brapi/v2/pedigree` |
## 字段录入
| 字段 | 业务意义 | 录入方式 | 校验规则 |
| --- | --- | --- | --- |
| `id` | pedigree node 主键 | 系统生成;导入可指定 | 必填、唯一 |
| `auth_user_id` | 数据所属用户 | 登录上下文自动写入 | 不允许前端手填 |
| `germplasm_id` | 对应 germplasm | Germplasm 选择器 | 建议必选,若填需存在 |
| `crossing_project_id` | 所属 crossing project | CrossingProject 选择器 | 可选 |
| `crossing_year` | 杂交年份 | 年份输入 | 可选 |
| `family_code` | 家系编号 | 文本 | 可选 |
| `pedigree_string` | 系谱字符串 | 文本 | 可选 |
## 页面与交互
- 可从 Germplasm 详情页进入 Pedigree Tab。
- 支持图谱视图和表格视图。
## 关键校验
1. 同一 germplasm 通常只应有一个 pedigree node。
2. 删除 pedigree_node 前检查 `pedigree_edge` 中 this_node 和 connceted_node 引用。
3. 导入 pedigree 时需要先创建所有节点,再创建边。

View File

@@ -0,0 +1,43 @@
# 04 Germplasm / Seed - pedigree_edge 表录入说明
来源:`docs/architecture/04-germplasm-seed-data-flow.md`
## 录入目标
`pedigree_edge` 描述两个 pedigree_node 之间的 parent、child 或 sibling 关系,并标注亲本类型。
## 上下游关系
| 类型 | 内容 |
| --- | --- |
| 表 | `pedigree_edge` |
| Java 实体 | `PedigreeEdgeEntity` |
| 前置依赖 | `pedigree_node` |
| 下游引用 | 系谱查询、亲本/后代展示 |
| API | `/brapi/v2/pedigree` |
## 字段录入
| 字段 | 业务意义 | 录入方式 | 校验规则 |
| --- | --- | --- | --- |
| `id` | pedigree edge 主键 | 系统生成;导入可指定 | 必填、唯一 |
| `auth_user_id` | 数据所属用户 | 登录上下文自动写入 | 不允许前端手填 |
| `this_node_id` | 当前节点 | PedigreeNode 选择器 | 必选,必须存在 |
| `connceted_node_id` | 关联节点 | PedigreeNode 选择器 | 必选,必须存在 |
| `edge_type` | 关系类型 | 枚举选择 | parent、child、sibling |
| `parent_type` | 亲本类型 | 枚举选择 | 可选,如 FEMALE、MALE |
## 命名注意
实体字段是 `conncetedNode`,拼写与 `connected` 不同;开发 DTO、SQL、迁移时要留意当前代码和数据库列名。
## 页面与交互
- 在 Germplasm/Pedigree 图谱视图中维护。
- 创建 parent 关系时可自动补齐反向 child 关系,具体以业务实现为准。
## 关键校验
1. `this_node_id``connceted_node_id` 必须存在。
2. 两个节点不能相同。
3. 同一节点之间同一种 edge_type 不应重复。

View File

@@ -0,0 +1,46 @@
# 04 Germplasm / Seed - seed_lot 表录入说明
来源:`docs/architecture/04-germplasm-seed-data-flow.md`
## 录入目标
`seed_lot` 是真实库存批次,描述某一批种子当前数量、单位、库位和项目归属。同一个 germplasm 可以有多个 seed lot。
## 上下游关系
| 类型 | 内容 |
| --- | --- |
| 表 | `seed_lot` |
| Java 实体 | `SeedLotEntity` |
| 前置依赖 | 可选 `location``program` |
| 下游引用 | `seed_lot_content_mixture``seed_lot_transaction` |
| API | `/brapi/v2/seedlots` |
## 字段录入
| 字段 | 业务意义 | 录入方式 | 校验规则 |
| --- | --- | --- | --- |
| `id` | seed lot 主键 | 系统生成;导入可指定 | 必填、唯一 |
| `auth_user_id` | 数据所属用户 | 登录上下文自动写入 | 不允许前端手填 |
| `name` | 批次名称 | 用户录入/自动生成 | 必填,建议同一 program 下唯一 |
| `amount` | 当前库存数量 | 交易自动更新/用户录入初始值 | 非负 |
| `units` | 数量单位 | 下拉/文本 | 建议必填 |
| `created_date` | 创建时间 | 系统写入/导入 | 可选 |
| `last_updated` | 最后更新时间 | 系统更新 | 不建议手填 |
| `description` | 批次说明 | 多行文本 | 可选 |
| `source_collection` | 来源 collection | 文本 | 可选 |
| `storage_location` | 具体库位 | 文本 | 可选 |
| `location_id` | 所在地点/库位 | Location 选择器 | 可选,若填需存在 |
| `program_id` | 所属项目 | Program 选择器 | 可选,若填需存在 |
## 页面与交互
- SeedLot 列表页支持按 program、location、name、库存状态查询。
- 详情页展示 content mixture 和 transactions。
- 创建 seed lot 后建议至少维护一条 `seed_lot_content_mixture`
## 关键校验
1. `amount` 不允许为负。
2. 普通用户不应直接编辑 amount库存变化应通过 `seed_lot_transaction`
3. 删除 seed lot 前检查组成明细和交易引用。

View File

@@ -0,0 +1,38 @@
# 04 Germplasm / Seed - seed_lot_content_mixture 表录入说明
来源:`docs/architecture/04-germplasm-seed-data-flow.md`
## 录入目标
`seed_lot_content_mixture` 表示 seed lot 的组成明细。它可以把 seed lot 连接到 germplasm也可以连接到 cross_entity适合表达混合批次或杂交产生的批次。
## 上下游关系
| 类型 | 内容 |
| --- | --- |
| 表 | `seed_lot_content_mixture` |
| Java 实体 | `SeedLotContentMixtureEntity` |
| 前置依赖 | `seed_lot`、可选 `germplasm`、可选 `cross_entity` |
| 下游引用 | Seed lot 组成展示 |
## 字段录入
| 字段 | 业务意义 | 录入方式 | 校验规则 |
| --- | --- | --- | --- |
| `id` | 组成明细主键 | 系统生成 | 必填、唯一 |
| `seed_lot_id` | 所属 seed lot | SeedLot 选择器/详情页带出 | 必选,必须存在 |
| `germplasm_id` | 组成 germplasm | Germplasm 选择器 | 与 cross_id 至少填一个 |
| `cross_id` | 组成来源 cross | Cross 选择器 | 与 germplasm_id 至少填一个 |
| `mixture_percentage` | 组成比例 | 数字输入 | 0-100 |
## 页面与交互
- 在 SeedLot 详情页 Content Mixture Tab 内维护。
- 支持多个组成明细,合计比例可展示为进度或校验提示。
## 关键校验
1. `seed_lot_id` 必须存在。
2. `germplasm_id``cross_id` 至少填写一个。
3. 同一 seed lot 下 mixture_percentage 合计建议为 100。
4. 删除组成明细不应删除 seed lot、germplasm 或 cross 主数据。

View File

@@ -0,0 +1,43 @@
# 04 Germplasm / Seed - seed_lot_transaction 表录入说明
来源:`docs/architecture/04-germplasm-seed-data-flow.md`
## 录入目标
`seed_lot_transaction` 记录 seed lot 之间的库存流转,例如入库、出库、转移、分装、合并或消耗。它表达 from seed lot 到 to seed lot 的数量变化。
## 上下游关系
| 类型 | 内容 |
| --- | --- |
| 表 | `seed_lot_transaction` |
| Java 实体 | `SeedLotTransactionEntity` |
| 前置依赖 | `from_seed_lot``to_seed_lot` |
| 下游引用 | 库存追踪、库存数量更新 |
| API | `/brapi/v2/seedlots/transactions``/brapi/v2/seedlots/{seedLotDbId}/transactions` |
## 字段录入
| 字段 | 业务意义 | 录入方式 | 校验规则 |
| --- | --- | --- | --- |
| `id` | transaction 主键 | 系统生成;导入可指定 | 必填、唯一 |
| `auth_user_id` | 数据所属用户 | 登录上下文自动写入 | 不允许前端手填 |
| `from_seed_lot_id` | 来源 seed lot | SeedLot 选择器 | 入库场景可为空,若填需存在 |
| `to_seed_lot_id` | 目标 seed lot | SeedLot 选择器 | 出库/消耗场景可为空,若填需存在 |
| `amount` | 流转数量 | 数字输入 | 必填,正数 |
| `units` | 数量单位 | 下拉/文本 | 必填,应与批次单位一致或可换算 |
| `timestamp` | 流转时间 | 日期时间选择器 | 默认当前时间 |
| `description` | 流转说明 | 多行文本 | 可选 |
## 页面与交互
- 在 SeedLot 详情页 Transactions Tab 展示相关流转。
- 新增交易后应更新 from/to seed lot 的 amount 和 last_updated。
- 支持按时间、from/to seed lot、program、location 查询。
## 关键校验
1. `from_seed_lot_id``to_seed_lot_id` 至少填写一个。
2. `from_seed_lot_id` 不能等于 `to_seed_lot_id`
3. 出库或转移时,来源批次数量不能被扣成负数。
4. transaction 是业务动作痕迹,原则上不允许随意物理删除。

View File

@@ -0,0 +1,46 @@
# 04 Germplasm / Seed 开发录入说明
来源:`docs/architecture/04-germplasm-seed-data-flow.md`
本目录按 Germplasm / Seed 模块的数据录入顺序拆分开发说明。主线是:
```text
breeding_method -> germplasm
germplasm_attribute_definition -> germplasm_attribute_value
program -> crossing_project -> cross_entity -> cross_parent
germplasm / cross_entity -> seed_lot_content_mixture -> seed_lot
seed_lot -> seed_lot_transaction
germplasm -> pedigree_node -> pedigree_edge
```
## 文档清单
| 顺序 | 文档 | 表 | 作用 |
| --- | --- | --- | --- |
| 01 | `01-breeding_method.md` | `breeding_method` | 育种方法字典 |
| 02 | `02-germplasm.md` | `germplasm` | 种质主表 |
| 03 | `03-germplasm_donor.md` | `germplasm_donor` | donor 信息 |
| 04 | `04-germplasm_institute.md` | `germplasm_institute` | 机构信息 |
| 05 | `05-germplasm_origin.md` | `germplasm_origin` | 来源地/坐标 |
| 06 | `06-germplasm_synonym.md` | `germplasm_synonym` | 别名 |
| 07 | `07-germplasm_taxon.md` | `germplasm_taxon` | taxon 标识 |
| 08 | `08-germplasm_attribute_definition.md` | `germplasm_attribute_definition` | 属性定义 |
| 09 | `09-germplasm_attribute_value.md` | `germplasm_attribute_value` | 属性值 |
| 10 | `10-crossing_project.md` | `crossing_project` | 杂交项目 |
| 11 | `11-cross_entity.md` | `cross_entity` | Cross / PlannedCross |
| 12 | `12-cross_parent.md` | `cross_parent` | 杂交亲本 |
| 13 | `13-cross_pollination_event.md` | `cross_pollination_event` | 授粉事件 |
| 14 | `14-pedigree_node.md` | `pedigree_node` | 系谱节点 |
| 15 | `15-pedigree_edge.md` | `pedigree_edge` | 系谱边 |
| 16 | `16-seed_lot.md` | `seed_lot` | 种子库存批次 |
| 17 | `17-seed_lot_content_mixture.md` | `seed_lot_content_mixture` | 批次组成 |
| 18 | `18-seed_lot_transaction.md` | `seed_lot_transaction` | 批次流转 |
## 全局注意点
1. `plannedcross` 没有独立数据库表,统一落在 `cross_entity`,通过 `planned``planned_cross_id` 自关联表达。
2. `germplasm.seedSource` / `seedSourceDescription` 是种质来源描述,不等于真实库存批次。
3. 真正表达库存的是 `seed_lot`,批次与种质或杂交来源的关系在 `seed_lot_content_mixture`
4. `seed_lot_transaction` 表达 seed lot 到 seed lot 的流转,不直接表达 seed lot 到 germplasm。
5. 属性定义和值要分开:`germplasm_attribute_definition` 定义“可填什么”,`germplasm_attribute_value` 记录“某个 germplasm 填了什么”。
6. 系谱关系用 `pedigree_node` / `pedigree_edge`;杂交流程用 `cross_entity` / `cross_parent`,两条线都可以回到 `germplasm`

533
docs/dev/backend/auth.md Normal file
View File

@@ -0,0 +1,533 @@
# 后端登录注册接口说明
本文档描述 `common-br-api` 项目中用户认证注册、登录、Token 校验)的后端实现,便于前后端联调与部署排查。
---
## 1. 总览
| 项目 | 说明 |
|------|------|
| 路由前缀 | `/auth` |
| 框架 | FastAPI |
| 用户表 | `sys_users` |
| 会话表 | `user_sessions` |
| 密码算法 | PBKDF2-HMAC-SHA256210000 次迭代) |
| Token 形式 | 自实现 JWT 风格 Bearer TokenHS256 签名) |
| 默认有效期 | 24 小时1440 分钟) |
**当前已实现的 HTTP 接口:**
| 方法 | 路径 | 说明 |
|------|------|------|
| `POST` | `/auth/register` | 注册并自动登录 |
| `POST` | `/auth/login` | 账号密码登录 |
**尚未实现的接口(前端 UI 可能已预留):**
- `/auth/logout`(登出 / 服务端吊销会话)
- `/auth/refresh`(刷新 Token
- 手机号 / 短信验证码登录
---
## 2. 代码结构
```
app/
├── api/
│ └── auth.py # 注册、登录、get_current_user 依赖
├── core/
│ └── security.py # 密码哈希、Token 签发、Token 哈希
├── models/
│ └── auth.py # User、UserSession ORM 模型
├── config/
│ └── settings.py # JWT 密钥、过期时间等配置
└── main.py # 挂载 auth 路由
migrations/versions/
└── 7c91a64f2b2e_create_auth_tables.py # 建表迁移
```
路由挂载(`app/main.py`
```python
app.include_router(auth_router) # 无前缀叠加router 自身 prefix="/auth"
```
因此完整 URL 为:
```text
http://<host>:8000/auth/register
http://<host>:8000/auth/login
```
经 Next.js 代理后(开发环境)也可访问:
```text
http://localhost:3000/auth/register
http://localhost:3000/auth/login
```
---
## 3. 认证流程
### 3.1 注册 / 登录发 Token
```mermaid
sequenceDiagram
participant Client as 客户端
participant API as /auth/*
participant DB as PostgreSQL
Client->>API: POST /auth/register 或 /auth/login
API->>DB: 查重 / 校验密码
API->>API: create_access_token(sub, account, jti)
API->>DB: INSERT user_sessions(jti, token_hash, expires_at)
API-->>Client: TokenResponse(access_token, expires_at, user)
```
### 3.2 受保护接口校验 Token
```mermaid
sequenceDiagram
participant Client as 客户端
participant API as 业务接口
participant DB as PostgreSQL
Client->>API: Authorization: Bearer <token>
API->>API: 校验 JWT 签名与 exp
API->>DB: JOIN sys_users + user_sessions<br/>匹配 user_id, jti, token_hash
alt 会话有效
API-->>Client: 200 + 业务数据
else 无效或过期
API-->>Client: 401 / 403
end
```
**要点:**
1. Token 不仅校验 JWT 签名和过期时间,还必须在 `user_sessions` 表中有对应且未吊销的记录。
2. 数据库存的是 Token 的 **SHA256 哈希**,不是明文 Token。
3. 每个 Token 有唯一 `jti`JWT ID用于会话追踪。
---
## 4. 数据库设计
### 4.1 `sys_users`
| 字段 | 类型 | 约束 | 说明 |
|------|------|------|------|
| `id` | UUID | PK | 用户 ID |
| `account` | VARCHAR(100) | UNIQUE, NOT NULL | 登录账号 |
| `password_hash` | TEXT | NOT NULL | PBKDF2 哈希串 |
| `name` | VARCHAR(100) | NOT NULL | 显示名称 |
| `email` | VARCHAR(255) | UNIQUE, NOT NULL | 邮箱(注册时转小写) |
| `phone` | VARCHAR(50) | NULL | 手机号(可选) |
| `created_at` | TIMESTAMPTZ | NOT NULL | 创建时间 |
| `updated_at` | TIMESTAMPTZ | NOT NULL | 更新时间 |
索引:
- `ux_users_account`account 唯一)
- `ux_users_email`email 唯一)
### 4.2 `user_sessions`
| 字段 | 类型 | 约束 | 说明 |
|------|------|------|------|
| `id` | UUID | PK | 会话记录 ID |
| `user_id` | UUID | FK → sys_users.id, CASCADE | 所属用户 |
| `jti` | VARCHAR(64) | UNIQUE, NOT NULL | Token 会话 ID |
| `token_hash` | TEXT | NOT NULL | SHA256(access_token) |
| `expires_at` | TIMESTAMPTZ | NOT NULL | 过期时间 |
| `revoked_at` | TIMESTAMPTZ | NULL | 吊销时间(预留,当前无 logout 接口写入) |
| `created_at` | TIMESTAMPTZ | NOT NULL | 创建时间 |
| `updated_at` | TIMESTAMPTZ | NOT NULL | 更新时间 |
---
## 5. 环境配置
配置类:`app/config/settings.py`
| 环境变量 | 默认值 | 说明 |
|----------|--------|------|
| `JWT_SECRET_KEY` | `change-me-in-production` | HMAC 签名密钥,**生产必须修改** |
| `JWT_ALGORITHM` | `HS256` | 写入 JWT Header实际签名为 HMAC-SHA256 |
| `ACCESS_TOKEN_EXPIRE_MINUTES` | `1440`24h | Token 有效期(分钟) |
| `DATABASE_URL` | 见 `.env.example` | PostgreSQL 连接串 |
示例(`.env`
```env
JWT_SECRET_KEY=your-long-random-secret
DATABASE_URL=postgresql+asyncpg://user:pass@postgres:5432/brapi-python
```
---
## 6. 密码安全
实现文件:`app/core/security.py`
### 6.1 哈希格式
```
pbkdf2_sha256$210000$<salt_hex>$<digest_hex>
```
- 算法:`PBKDF2-HMAC-SHA256`
- 迭代次数:`210000`
- Salt16 字节随机 hex`secrets.token_hex(16)`
### 6.2 注册时
```python
password_hash=hash_password(payload.password)
```
### 6.3 登录时
```python
verify_password(payload.password, user.password_hash)
```
校验失败统一返回 `401 Invalid account or password`,不区分「账号不存在」与「密码错误」。
---
## 7. Access Token 结构
Token 由 `create_access_token()` 生成,格式为三段式 Base64URL
```text
<base64url(header)>.<base64url(payload)>.<base64url(signature)>
```
### 7.1 Header
```json
{"alg": "HS256", "typ": "JWT"}
```
### 7.2 Payload
```json
{
"sub": "<user_uuid>",
"account": "<login_account>",
"jti": "<32_hex_chars>",
"iat": 1710000000,
"exp": 1710086400
}
```
| Claim | 含义 |
|-------|------|
| `sub` | 用户 UUID 字符串 |
| `account` | 登录账号 |
| `jti` | 会话唯一 ID |
| `iat` | 签发时间Unix 秒) |
| `exp` | 过期时间Unix 秒) |
### 7.3 签名
```python
HMAC-SHA256(key=JWT_SECRET_KEY, msg=f"{header_b64}.{payload_b64}")
```
> 注意:项目使用**自实现**的 JWT 编解码(`app/api/auth.py` + `app/core/security.py`),未依赖 PyJWT 库。
---
## 8. HTTP 接口详情
### 8.1 注册 `POST /auth/register`
**请求体 `RegisterRequest`**
| 字段 | 类型 | 必填 | 校验 |
|------|------|------|------|
| `account` | string | 是 | 长度 3100 |
| `password` | string | 是 | 长度 6128 |
| `name` | string | 是 | 长度 1100 |
| `email` | string | 是 | 长度 3255入库前转小写 |
| `phone` | string | 否 | 最大 50 |
**业务逻辑:**
1. `account``email` 去空格 / 小写处理
2. 查询 `sys_users`,若 `account``email` 已存在 → `409 Conflict`
3. 创建用户并 `flush`
4. 调用 `_issue_token()` 写入 `user_sessions` 并返回 Token
**成功响应:** `201 Created`Body 为 `TokenResponse`
**curl 示例:**
```bash
curl -X POST http://127.0.0.1:8000/auth/register \
-H "Content-Type: application/json" \
-d '{
"account": "demo_user",
"password": "demo123456",
"name": "演示用户",
"email": "demo@example.com",
"phone": "13800138000"
}'
```
---
### 8.2 登录 `POST /auth/login`
**请求体 `LoginRequest`**
| 字段 | 类型 | 必填 | 校验 |
|------|------|------|------|
| `account` | string | 是 | 长度 1100 |
| `password` | string | 是 | 长度 1128 |
**业务逻辑:**
1.`account` 查用户
2. `verify_password` 失败 → `401 Unauthorized`
3. 成功则 `_issue_token()` 并返回
**成功响应:** `200 OK`Body 为 `TokenResponse`
**curl 示例:**
```bash
curl -X POST http://127.0.0.1:8000/auth/login \
-H "Content-Type: application/json" \
-d '{
"account": "demo_user",
"password": "demo123456"
}'
```
---
### 8.3 统一成功响应 `TokenResponse`
```json
{
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9....",
"token_type": "bearer",
"expires_at": "2026-05-27T10:00:00+00:00",
"user": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"account": "demo_user",
"name": "演示用户",
"email": "demo@example.com",
"phone": "13800138000"
}
}
```
| 字段 | 说明 |
|------|------|
| `access_token` | Bearer Token 字符串 |
| `token_type` | 固定 `"bearer"` |
| `expires_at` | ISO8601 UTC 过期时间 |
| `user` | 当前用户公开信息(不含密码) |
---
### 8.4 错误响应格式
认证相关错误通过 `ApiError` 抛出,由 `app/main.py` 统一处理:
```json
{
"message": "错误摘要",
"detail": "错误摘要或详细信息"
}
```
| HTTP 状态码 | 场景 | message 示例 |
|-------------|------|----------------|
| `401` | 登录失败 | `Invalid account or password` |
| `401` | 缺少 Token | `Missing bearer token` |
| `401` | Token 无效 | `Invalid token signature` / `Session invalid or expired` |
| `403` | Token 过期 | `Token expired` |
| `409` | 注册冲突 | `Account or email already exists` |
| `422` | 参数校验失败 | `Validation failed`detail 为字段错误列表) |
---
## 9. 受保护接口:`get_current_user`
定义位置:`app/api/auth.py`
```python
async def get_current_user(
credentials: HTTPAuthorizationCredentials | None = Depends(bearer_scheme),
session: AsyncSession = Depends(get_db_session),
) -> User:
...
```
### 9.1 客户端如何携带 Token
```http
Authorization: Bearer <access_token>
```
### 9.2 校验步骤
1. 检查 `Authorization` 头是否存在且 scheme 为 `bearer`
2. `_decode_access_token()`验证格式、HMAC 签名、`exp` 未过期
3. 从 payload 读取 `sub`user_id`jti`
4. 数据库查询:
```sql
SELECT sys_users.*
FROM sys_users
JOIN user_sessions ON user_sessions.user_id = sys_users.id
WHERE sys_users.id = :user_id
AND user_sessions.jti = :jti
AND user_sessions.token_hash = sha256(:token)
AND user_sessions.revoked_at IS NULL
AND user_sessions.expires_at > now()
```
5. 查不到用户 → `401 Session invalid or expired`
### 9.3 哪些接口使用了 `get_current_user`
#### `/auth` 模块
register/login 本身不需要 Token
#### `/api/dictionaries` 模块(`app/api/dictionaries.py`
| 接口 | 是否需要登录 |
|------|-------------|
| `GET /api/dictionaries/crops` | 否 |
| `POST /api/dictionaries/crops` | **是** |
| `GET /api/dictionaries/persons` | 否 |
| `POST /api/dictionaries/persons` | 否 |
| `POST /api/dictionaries/countries` | **是** |
| `PUT /api/dictionaries/countries/{code}` | **是** |
#### `/brapi/v2` 模块(`app/api/router.py`
- 多数 **GET** 接口:接收 `Authorization` 头但**不强制校验**BrAPI 兼容占位)
- 多数 **POST / PUT / DELETE** 写操作:通过 `Depends(get_current_user)` **强制登录**
写操作成功后会将 `current_user.id` 写入业务表的 `auth_user_id` 字段,用于记录数据创建者。
> 上传接口 `POST /brapi/v2/upload/image` 当前**未**接入 `get_current_user`,前端可选择性携带 Token。
---
## 10. `_issue_token` 内部流程
```python
async def _issue_token(session: AsyncSession, user: User) -> TokenResponse:
jti = uuid4().hex
token, expires_at = create_access_token(
subject=str(user.id),
account=user.account,
jti=jti,
)
session.add(UserSession(
user_id=user.id,
jti=jti,
token_hash=hash_token(token),
expires_at=expires_at,
))
await session.commit()
return TokenResponse(...)
```
每次登录/注册都会**新增一条** `user_sessions` 记录;旧会话不会自动吊销(除非手动清理数据库或未来实现 logout
---
## 11. 前端对接(简要)
| 文件 | 作用 |
|------|------|
| `frontend/src/services/authService.ts` | 封装 `loginWithPassword``registerAccount` |
| `frontend/src/lib/api/sdk.gen.ts` | OpenAPI 生成的 `/auth/login``/auth/register` 客户端 |
| `frontend/src/stores/modules/auth.ts` | Zustand 持久化 Token 与用户信息 |
| `frontend/src/utils/token.ts` | 从 `localStorage` 读取 `auth_token` |
| `frontend/src/lib/client.ts` | 请求拦截器自动附加 `Authorization: Bearer ...` |
登录成功后前端会:
1. 调用 `setSession(session)` 写入 Zustand + `localStorage.auth_token`
2. 跳转到 `/central-config/user/employee``redirect` 参数指定页
登出:仅前端 `logout()` 清除本地存储,**不会**通知后端吊销会话。
---
## 12. 本地调试
### 12.1 启动后端
```bash
uv run uvicorn app.main:app --host 127.0.0.1 --port 8000 --reload
```
### 12.2 Swagger 文档
```text
http://127.0.0.1:8000/docs
```
在 Swagger 中可找到 `auth` 分组下的 `register``login`
### 12.3 用 Token 访问受保护接口
```bash
TOKEN="<access_token>"
curl http://127.0.0.1:8000/api/dictionaries/crops \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"crop_name": "maize"}'
```
---
## 13. 部署注意事项
1. **必须修改** `JWT_SECRET_KEY`,不要使用默认值 `change-me-in-production`
2. 首次部署需执行数据库迁移:`uv run alembic upgrade head`(包含 `sys_users``user_sessions` 建表)。
3. Docker / K8s 环境中,容器内 `API_BASE_URL=http://127.0.0.1:8000` 供 Next.js 代理;客户端浏览器仍通过同源 `/auth/*` 访问。
4. 当前无服务端 logoutToken 在过期前始终有效(只要 `user_sessions` 记录存在)。如需强制下线,需扩展 logout 接口并设置 `revoked_at`
---
## 14. 后续可扩展项
| 功能 | 建议实现 |
|------|----------|
| 登出 | `POST /auth/logout`,将当前 `jti``revoked_at` 设为 now |
| 刷新 Token | `POST /auth/refresh`,验证旧 Token 后签发新 Token |
| 当前用户 | `GET /auth/me`,返回 `UserResponse` |
| 修改密码 | `POST /auth/change-password` |
| 手机号登录 | 独立短信验证码表 + 新 login 分支 |
| 上传鉴权 | `upload.py` 增加 `Depends(get_current_user)` |
---
## 15. 相关源码索引
| 内容 | 路径 |
|------|------|
| 路由与 DTO | `app/api/auth.py` |
| 密码 / Token 工具 | `app/core/security.py` |
| ORM 模型 | `app/models/auth.py` |
| 配置 | `app/config/settings.py` |
| 建表迁移 | `migrations/versions/7c91a64f2b2e_create_auth_tables.py` |
| 应用入口 | `app/main.py` |
| 前端封装 | `frontend/src/services/authService.ts` |