779 lines
49 KiB
Markdown
779 lines
49 KiB
Markdown
# Phenotyping 模块专业数据录入需求文档 V2
|
||
|
||
## 1. 文档目的
|
||
|
||
本文档用于指导 Phenotyping 表型模块的前端页面、后端接口、字段校验、数据导入和测试验收设计。本文档不只描述表关系,而是从真实育种表型采集业务出发,解释每个对象和字段的业务意义、录入方式、控件建议、校验规则和上下游影响。
|
||
|
||
## 2. 模块定位
|
||
|
||
Phenotyping 模块用于管理田间、温室、实验室或高通量设备采集到的表型数据。它的核心不是“录一张 observation 表”,而是完整描述:
|
||
|
||
```text
|
||
在哪个 study 里
|
||
对哪个 observation_unit
|
||
按照哪个 observation_variable
|
||
在什么时间、由谁、用什么方法
|
||
采集到了什么 value
|
||
并能关联事件、图片、坐标和上下文
|
||
```
|
||
|
||
## 3. 核心业务概念
|
||
|
||
| 概念 | 业务含义 | 关键表 |
|
||
| ---------------------------- | ---------------------------------------------------------- | ------------------------------------------------- |
|
||
| Ontology 本体 | 性状、方法、标尺、变量的术语来源,可以是本地本体或公开本体 | `ontology` |
|
||
| Trait 性状 | 测什么。例如株高、穗长、病害等级、籽粒颜色 | `trait` |
|
||
| Method 方法 | 怎么测。例如尺测、人工评分、无人机图像分析、实验室检测 | `method` |
|
||
| Scale 标尺 | 用什么单位或尺度表达。例如 cm、kg、0-5 等级、文本、布尔值 | `scale`、`scale_valid_value_category` |
|
||
| ObservationVariable 观测变量 | Trait + Method + Scale 的组合,表示一个可采集指标 | `observation_variable` |
|
||
| StudyVariable 研究采集指标 | 某个 study 计划采集哪些 observation variable | `study_variable` |
|
||
| ObservationUnit 观测单元 | 被观测对象。通常是 plot、plant、block、field、sample | `observation_unit` |
|
||
| Event 事件 | 管理动作或环境事件,如施肥、灌溉、打药、移栽、极端天气 | `event`、`event_param`、`event_observation_units` |
|
||
| Image 图像 | 田间图片、无人机图片、病害图片、长势图像等 | `image`、`image_observations` |
|
||
| Observation 观测值 | 某个观测单元在某个变量上的一次实际测量结果 | `observation` |
|
||
|
||
## 4. 推荐业务流程
|
||
|
||
```text
|
||
1. 准备 Core 上下文:crop、program、trial、study、location、season
|
||
2. 维护或导入本体 ontology
|
||
3. 定义 trait / method / scale
|
||
4. 组合 observation_variable
|
||
5. 把 observation_variable 绑定到 study_variable,形成本 study 的采集指标清单
|
||
6. 根据田间设计生成 observation_unit,例如 block / plot / plant
|
||
7. 给 observation_unit 绑定材料来源:germplasm / seed_lot / cross
|
||
8. 记录 event,例如播种、移栽、施肥、灌溉、打药、采样、极端天气
|
||
9. 通过矩阵方式批量录入 observation
|
||
10. 上传 image,并关联 observation_unit 或 observation
|
||
11. 做数据质控:缺失值、异常值、重复采集、单位和分类值校验
|
||
```
|
||
|
||
## 5. 推荐页面形态
|
||
|
||
### 5.1 Study 表型工作台
|
||
|
||
```text
|
||
Study 表型工作台
|
||
├─ 试验上下文:study / trial / program / crop / location / season
|
||
├─ 指标清单:study_variable
|
||
├─ 田间设计:observation_unit 层级、block、plot、plant、row、column
|
||
├─ 材料布置:germplasm、seed_lot、cross
|
||
├─ 表型矩阵:observation_unit × observation_variable
|
||
├─ 田间事件:event + event_param + event_observation_units
|
||
├─ 图片证据:image + image_observations
|
||
├─ 数据质控:缺失值、异常值、重复值、单位校验、分类值校验
|
||
└─ 导入导出:观测单元模板、表型采集模板、图片元数据模板
|
||
```
|
||
|
||
### 5.2 表型矩阵录入
|
||
|
||
真实采集时不应只提供单条 observation 表单,而应支持矩阵录入:
|
||
|
||
| observation_unit | germplasm | 株高 cm | 穗长 cm | 倒伏等级 | 备注 |
|
||
| ---------------- | --------- | ------: | ------: | -------: | ---------- |
|
||
| Plot-001 | 华占 | 112.5 | 24.1 | 1 | 正常 |
|
||
| Plot-002 | 抗倒伏A | 98.3 | 22.8 | 0 | 正常 |
|
||
| Plot-003 | F2-001 | 101.6 | 23.0 | 4 | 台风后倒伏 |
|
||
|
||
保存时,系统按每个非空单元格生成一条 `observation`,每一列对应一个 `observation_variable`。
|
||
|
||
---
|
||
|
||
# 6. 字段级专业录入需求
|
||
|
||
## 6.1 ontology 本体
|
||
|
||
### 业务说明
|
||
|
||
`ontology` 表示术语体系来源,用来说明 trait、method、scale、observation_variable 的定义来自哪里。它可以是本地维护的术语库,也可以是公开 Crop Ontology、Trait Ontology 或机构内部标准。
|
||
|
||
### 字段说明
|
||
|
||
| 字段 | 业务意义 | 录入方式 | 控件建议 | 校验规则 |
|
||
| ------------------ | ----------------------------------------- | -------------------------------- | --------------- | -------------------------------- |
|
||
| `id` | 本体主键,系统内部唯一标识 | 新增时系统生成;导入时可允许指定 | 隐藏/只读 | 必填、唯一;编辑时不可修改 |
|
||
| `auth_user_id` | 数据所属用户或租户 | 登录上下文自动写入 | 隐藏 | 不允许前端手填 |
|
||
| `authors` | 本体作者或维护者 | 用户录入 | 文本框 | 可选;多个作者可用分号或数组扩展 |
|
||
| `copyright` | 本体版权说明 | 用户录入 | 文本框/多行文本 | 可选 |
|
||
| `description` | 本体用途说明 | 用户录入 | 多行文本 | 可选,建议填写 |
|
||
| `documentationurl` | 本体文档链接 | 用户录入 | URL 输入框 | 可选;若填写必须是合法 URL |
|
||
| `licence` | 本体许可证,例如 CC-BY、MIT、机构内部许可 | 用户录入/选择 | 文本框/下拉框 | 可选 |
|
||
| `ontology_name` | 本体名称,例如 Rice Trait Ontology | 用户录入 | 文本框 | 必填;同一用户下建议唯一 |
|
||
| `version` | 本体版本,例如 2024.1、v2.0 | 用户录入 | 文本框 | 可选;建议与外部本体版本一致 |
|
||
|
||
### 录入建议
|
||
|
||
- 若系统只是内部使用,可先创建一个“默认本体”或“本地表型本体”。
|
||
- 若对接 Crop Ontology,建议保存 ontology 名称、版本、文档 URL。
|
||
- 本体删除前必须检查是否被 trait、method、scale、observation_variable 引用。
|
||
|
||
---
|
||
|
||
## 6.2 trait 性状
|
||
|
||
### 业务说明
|
||
|
||
`trait` 描述“测什么”。例如株高、叶长、穗长、倒伏等级、病害严重度、籽粒颜色。专业上 trait 可以拆成 `entity` 和 `attribute`:
|
||
|
||
```text
|
||
Trait = Entity + Attribute
|
||
例如:grain colour
|
||
entity = grain
|
||
attribute = colour
|
||
```
|
||
|
||
### 字段说明
|
||
|
||
| 字段 | 业务意义 | 录入方式 | 控件建议 | 校验规则 |
|
||
| ------------------- | ----------------------------------------------------- | -------------------- | ----------------- | ---------------------------------------- |
|
||
| `id` | 性状主键,系统内部唯一标识 | 系统生成;导入可指定 | 隐藏/只读 | 必填、唯一 |
|
||
| `auth_user_id` | 数据所属用户或租户 | 登录上下文自动写入 | 隐藏 | 不允许手填 |
|
||
| `attribute` | 性状属性,即被观察的特征,如 height、colour、severity | 用户录入/本体选择 | 文本框/本体选择器 | 可选;若填写 PUI,建议同步填写 attribute |
|
||
| `attributepui` | 属性永久唯一标识,通常是 URI | 用户录入/本体带出 | 文本框/URL 输入框 | 可选;若填写建议唯一 |
|
||
| `entity` | 性状实体,即观察对象部位,如 plant、leaf、grain、root | 用户录入/本体选择 | 文本框/本体选择器 | 可选 |
|
||
| `entitypui` | 实体永久唯一标识,通常是 URI | 用户录入/本体带出 | 文本框/URL 输入框 | 可选;若填写建议唯一 |
|
||
| `main_abbreviation` | 性状主缩写,如 PH、GY、DTH | 用户录入 | 文本框 | 可选;同一 ontology 下建议唯一 |
|
||
| `status` | 性状状态,如 recommended、obsolete、legacy | 用户选择 | 下拉框 | 可选;推荐使用枚举 |
|
||
| `trait_class` | 性状分类,如 phenology、morphology、disease、quality | 用户选择/录入 | 下拉框/文本框 | 可选;建议字典化 |
|
||
| `trait_description` | 性状定义和说明 | 用户录入 | 多行文本 | 可选,但专业使用强烈建议填写 |
|
||
| `trait_name` | 性状名称,给用户看的名称 | 用户录入 | 文本框 | 必填;作为下拉展示名称 |
|
||
| `traitpui` | 性状永久唯一标识 | 用户录入/本体带出 | 文本框/URL 输入框 | 可选;若填写必须唯一 |
|
||
| `ontology_id` | 所属本体 | 从 ontology 选择 | 本体选择器 | 可选;必须引用存在的 ontology |
|
||
|
||
### 录入建议
|
||
|
||
- 简单业务可只填:`trait_name`、`trait_description`、`trait_class`。
|
||
- 专业数据交换场景建议填写:`entity`、`attribute`、`traitpui`、`ontology_id`。
|
||
- 不要把单位写进 trait。比如“株高 cm”不应该作为 trait,正确拆分是 trait=株高,scale=cm。
|
||
|
||
---
|
||
|
||
## 6.3 method 方法
|
||
|
||
### 业务说明
|
||
|
||
`method` 描述“怎么测”。同一个 trait 用不同方法测,会形成不同 observation_variable。例如:
|
||
|
||
```text
|
||
Trait: plant height
|
||
Method 1: tape measure
|
||
Method 2: drone image processing
|
||
Scale: cm
|
||
```
|
||
|
||
这两个变量不能混为一谈,因为它们的数据来源、误差和可比性不同。
|
||
|
||
### 字段说明
|
||
|
||
| 字段 | 业务意义 | 录入方式 | 控件建议 | 校验规则 |
|
||
| -------------- | ------------------------------------------------------------ | ------------------ | ----------------- | -------------------------------- |
|
||
| `id` | 方法主键 | 系统生成 | 隐藏/只读 | 必填、唯一 |
|
||
| `auth_user_id` | 数据所属用户或租户 | 登录上下文自动写入 | 隐藏 | 不允许手填 |
|
||
| `description` | 方法说明,如测量位置、工具、采样规则 | 用户录入 | 多行文本 | 可选;建议必填 |
|
||
| `formula` | 如果该方法通过计算得到结果,填写公式 | 用户录入 | 文本框/公式编辑器 | 可选;需要格式提示 |
|
||
| `method_class` | 方法分类,如 measurement、estimation、computed、image_analysis | 用户选择/录入 | 下拉框/文本框 | 可选;建议字典化 |
|
||
| `methodpui` | 方法永久唯一标识 | 用户录入/本体带出 | 文本框/URL 输入框 | 可选;若填写建议唯一 |
|
||
| `name` | 方法名称 | 用户录入 | 文本框 | 必填;同一 ontology 下不建议重复 |
|
||
| `reference` | 方法参考文献、SOP、标准链接 | 用户录入 | 文本框/URL 输入框 | 可选;若为 URL 需校验格式 |
|
||
| `ontology_id` | 所属本体 | 从 ontology 选择 | 本体选择器 | 可选;必须引用存在的 ontology |
|
||
|
||
### 录入建议
|
||
|
||
- 方法页面应重点让用户说明“测量步骤”,否则后续数据不可复现。
|
||
- 对于人工评分,必须在 description 中说明评分标准,并通过 scale 配置有效分类值。
|
||
- 对于高通量图像方法,reference 建议填写算法版本、模型版本或 SOP 链接。
|
||
|
||
---
|
||
|
||
## 6.4 scale 标尺
|
||
|
||
### 业务说明
|
||
|
||
`scale` 描述“用什么尺度表达结果”。它决定 observation.value 的合法值、单位、数据类型、小数位和分类值。常见类型:
|
||
|
||
```text
|
||
Numerical: 株高 cm、产量 kg/ha
|
||
Ordinal: 倒伏等级 0-5、病害等级 1-9
|
||
Categorical: 籽粒颜色 red/yellow/white
|
||
Text: 描述性备注
|
||
Boolean: 是否开花、是否倒伏
|
||
Date: 开花日期
|
||
```
|
||
|
||
### 字段说明
|
||
|
||
| 字段 | 业务意义 | 录入方式 | 控件建议 | 校验规则 |
|
||
| ----------------- | ----------------------------------------------------- | ------------------ | ----------------- | --------------------------------- |
|
||
| `id` | 标尺主键 | 系统生成 | 隐藏/只读 | 必填、唯一 |
|
||
| `auth_user_id` | 数据所属用户或租户 | 登录上下文自动写入 | 隐藏 | 不允许手填 |
|
||
| `data_type` | 数据类型,决定 observation.value 的输入控件和校验方式 | 用户选择 | 下拉框 | 必填;使用系统枚举 |
|
||
| `decimal_places` | 小数位数 | 用户录入 | 数字输入框 | 数值型可填;必须为非负整数 |
|
||
| `scale_name` | 标尺名称,如 cm、0-5 lodging score、disease score 1-9 | 用户录入 | 文本框 | 必填;同一 ontology 下建议唯一 |
|
||
| `scalepui` | 标尺永久唯一标识 | 用户录入/本体带出 | 文本框/URL 输入框 | 可选;若填写建议唯一 |
|
||
| `units` | 单位,如 cm、mm、kg/ha、days | 用户选择/录入 | 单位选择器/文本框 | 数值型建议必填;分类型可为空 |
|
||
| `valid_value_max` | 最大有效值 | 用户录入 | 数字输入框/文本框 | 数值/等级型校验;必须大于等于 min |
|
||
| `valid_value_min` | 最小有效值 | 用户录入 | 数字输入框/文本框 | 数值/等级型校验;必须小于等于 max |
|
||
| `ontology_id` | 所属本体 | 从 ontology 选择 | 本体选择器 | 可选;必须引用存在 ontology |
|
||
|
||
### 录入建议
|
||
|
||
- `data_type` 是动态表单核心字段。前端要根据它渲染 observation.value:
|
||
- Numerical:数字输入框,按 min/max/decimal_places 校验;
|
||
- Ordinal:数字或下拉,通常有 min/max;
|
||
- Categorical:下拉框,选项来自 `scale_valid_value_category`;
|
||
- Text:文本框;
|
||
- Boolean:开关/单选;
|
||
- Date:日期选择器。
|
||
- 如果 data_type 是分类型,必须至少配置一个 `scale_valid_value_category`。
|
||
- 如果 data_type 是数值型,建议填写单位和有效范围。
|
||
|
||
---
|
||
|
||
## 6.5 scale_valid_value_category 分类有效值
|
||
|
||
### 业务说明
|
||
|
||
`scale_valid_value_category` 是分类型或等级型 scale 的合法取值表。例如倒伏等级 0-5、病害等级 1-9、颜色 red/yellow/white。
|
||
|
||
### 字段说明
|
||
|
||
| 字段 | 业务意义 | 录入方式 | 控件建议 | 校验规则 |
|
||
| ---------- | --------------------------------- | --------------------------- | ----------------- | ------------------------ |
|
||
| `id` | 分类值主键 | 系统生成 | 隐藏/只读 | 必填、唯一 |
|
||
| `label` | 用户界面展示文案,如 “0 - 不倒伏” | 用户录入 | 文本框 | 必填 |
|
||
| `value` | 实际保存值,如 0、1、red | 用户录入 | 文本框 | 必填;同一 scale 内唯一 |
|
||
| `scale_id` | 所属 scale | 从 scale 选择或由详情页带出 | Scale 选择器/隐藏 | 必选;必须引用存在 scale |
|
||
|
||
### 录入建议
|
||
|
||
- 在 scale 详情页中以内嵌表格维护。
|
||
- 保存 observation 时,如果 scale 是分类型,value 必须在该表中存在。
|
||
- label 可以给用户看,value 用于保存和导出,二者可以不同。
|
||
|
||
---
|
||
|
||
## 6.6 observation_variable 观测变量
|
||
|
||
### 业务说明
|
||
|
||
`observation_variable` 是真正进入采集模板的指标。它由 trait、method、scale 组合而成。
|
||
|
||
```text
|
||
observation_variable = trait + method + scale
|
||
例如:株高 + 尺子测量 + cm = 株高-尺测法-cm
|
||
```
|
||
|
||
它不是观测结果,而是“可以被测的一列数据”。
|
||
|
||
### 字段说明
|
||
|
||
| 字段 | 业务意义 | 录入方式 | 控件建议 | 校验规则 |
|
||
| ---------------------- | ------------------------------------------ | ------------------------ | ----------------- | ---------------------------------------- |
|
||
| `id` | 观测变量主键 | 系统生成 | 隐藏/只读 | 必填、唯一 |
|
||
| `auth_user_id` | 数据所属用户或租户 | 登录上下文自动写入 | 隐藏 | 不允许手填 |
|
||
| `default_value` | 默认观测值,例如默认等级、默认文本 | 用户录入 | 动态控件 | 可选;按 scale 校验 |
|
||
| `documentationurl` | 变量说明文档链接 | 用户录入 | URL 输入框 | 可选;若填写必须合法 URL |
|
||
| `growth_stage` | 建议采集生育期,如 flowering、maturity | 用户录入/选择 | 下拉框/文本框 | 可选;建议字典化 |
|
||
| `institution` | 定义该变量的机构 | 用户录入 | 文本框 | 可选 |
|
||
| `language` | 变量语言,如 zh、en | 用户选择 | 下拉框 | 可选;建议 ISO 639-1 |
|
||
| `scientist` | 提交或维护该变量的科学家/负责人 | 用户录入/人员选择 | 文本框/选择器 | 可选 |
|
||
| `status` | 变量状态,如 recommended、obsolete、legacy | 用户选择 | 下拉框 | 可选;obsolete 不建议用于新 study |
|
||
| `submission_timestamp` | 变量提交时间 | 系统默认当前时间,可调整 | 日期时间选择器 | 可选;新增默认当前时间 |
|
||
| `crop_id` | 适用作物 | 从 crop 选择 | 作物选择器 | 可选;如果填写,下游 study 应尽量同 crop |
|
||
| `method_id` | 测定方法 | 从 method 选择 | 方法选择器 | 必选 |
|
||
| `ontology_id` | 所属本体 | 从 ontology 选择 | 本体选择器 | 可选 |
|
||
| `scale_id` | 标尺 | 从 scale 选择 | 标尺选择器 | 必选 |
|
||
| `trait_id` | 被测性状 | 从 trait 选择 | 性状选择器 | 必选 |
|
||
| `name` | 变量名称,采集矩阵列名 | 自动生成后允许修改 | 文本框 | 必填;同一 crop/ontology 下建议唯一 |
|
||
| `pui` | 变量永久唯一标识 | 用户录入/本体带出 | 文本框/URL 输入框 | 可选;若填写建议唯一 |
|
||
|
||
### 录入建议
|
||
|
||
- 新建变量采用“三段式选择”:先选 trait,再选 method,再选 scale。
|
||
- 系统自动生成 name,例如:`trait_name + method_name + scale_name`,用户可修改。
|
||
- 变量详情页应展示:被哪些 study 使用、已有多少 observation、是否仍推荐使用。
|
||
- 如果变量已经产生 observation,不建议修改 trait/method/scale,只能停用旧变量并创建新变量。
|
||
|
||
---
|
||
|
||
## 6.7 study_variable 研究采集指标
|
||
|
||
### 业务说明
|
||
|
||
`study_variable` 是 study 和 observation_variable 的多对多关系,表示某个 study 计划采集哪些指标。它是“配置采集模板”的动作痕迹。
|
||
|
||
### 字段说明
|
||
|
||
| 字段 | 业务意义 | 录入方式 | 控件建议 | 校验规则 |
|
||
| ---------------- | --------------------- | ---------------------------- | ----------------- | --------------------------- |
|
||
| `study_db_id` | 所属 study | 从 study 选择或由工作台带出 | Study 选择器/隐藏 | 必选;必须引用存在 study |
|
||
| `variable_db_id` | 该 study 要采集的变量 | 从 observation_variable 选择 | 变量多选器 | 必选;必须引用存在 variable |
|
||
|
||
### 录入建议
|
||
|
||
- 在 Study 表型工作台的“指标清单”Tab 中维护。
|
||
- 支持批量选择变量和从历史 study 复制变量清单。
|
||
- 若某变量已有 observation,不允许从 study_variable 中直接移除,除非先处理已有观测数据。
|
||
|
||
---
|
||
|
||
## 6.8 observation_unit 观测单元
|
||
|
||
### 业务说明
|
||
|
||
`observation_unit` 是“被观测对象”。通常是 plot 或 plant,也可以是 field、block、sub-plot、sample 等。它连接了 Core 上下文和材料来源,是表型数据的入口,也可以成为后续 genotyping sample 的来源。
|
||
|
||
### 字段说明
|
||
|
||
| 字段 | 业务意义 | 录入方式 | 控件建议 | 校验规则 |
|
||
| ----------------------- | ------------------------------------ | ------------------------- | ----------------- | -------------------------------------------------- |
|
||
| `id` | 观测单元主键 | 系统生成;导入可指定 | 隐藏/只读 | 必填、唯一 |
|
||
| `auth_user_id` | 数据所属用户或租户 | 登录上下文自动写入 | 隐藏 | 不允许手填 |
|
||
| `observation_unit_name` | 观测单元名称,如 Plot-001、Plant-003 | 用户录入/批量生成 | 文本框 | 必填;同一 study 内建议唯一 |
|
||
| `observation_unitpui` | 观测单元永久唯一标识 | 用户录入/系统生成 | 文本框/URL 输入框 | 可选;若填写建议唯一 |
|
||
| `crop_id` | 作物 | 由 study 自动带出,可只读 | 作物选择器/只读 | 可选但建议有;需与 study.crop 一致 |
|
||
| `cross_id` | 材料来源 cross | 从 cross_entity 选择 | Cross 选择器 | 可选;与 germplasm/seed_lot 至少建议选一个材料来源 |
|
||
| `germplasm_id` | 材料来源 germplasm | 从 germplasm 选择 | 材料选择器 | 可选;常用字段 |
|
||
| `program_id` | 项目 | 由 study 自动带出 | 项目选择器/只读 | 可选但建议有;需与 study.program 一致 |
|
||
| `seed_lot_id` | 种子批次来源 | 从 seed_lot 选择 | SeedLot 选择器 | 可选;田间播种建议填写 |
|
||
| `study_id` | 所属 study | 从 study 选择或工作台带出 | Study 选择器/隐藏 | 必选 |
|
||
| `trial_id` | 所属 trial | 由 study 自动带出 | Trial 选择器/只读 | 可选但建议有;需与 study.trial 一致 |
|
||
|
||
### 录入建议
|
||
|
||
- 推荐从 Study 表型工作台批量生成,不建议逐条手工建。
|
||
- 必须支持田间布局字段:field、block、rep、plot、row、column、plant。若当前表没有这些字段,应通过 position/level 附属表或 additional_info 保存。
|
||
- `germplasm_id` 代表材料身份;`seed_lot_id` 代表实际播种批次;二者建议都保留。
|
||
- 选择 seed_lot 时可自动带出 germplasm,但不应强行覆盖用户选择。
|
||
|
||
### 观测层级建议
|
||
|
||
| 层级 | 含义 | 例子 |
|
||
| ------ | -------------- | ---------- |
|
||
| field | 田块或试验场 | Field-01 |
|
||
| block | 区组 | Block-01 |
|
||
| rep | 重复 | Rep-01 |
|
||
| plot | 小区 | Plot-001 |
|
||
| plant | 单株 | Plant-001 |
|
||
| sample | 样本级观测对象 | Sample-001 |
|
||
|
||
---
|
||
|
||
## 6.9 event 事件
|
||
|
||
### 业务说明
|
||
|
||
`event` 记录发生在 study 或 observation_unit 上的离散事件。它既可以是处理的一部分,也可以是影响结果的外部背景。例如播种、移栽、施肥、灌溉、打药、收获、采样、暴雨、台风、病害暴发等。
|
||
|
||
### 字段说明
|
||
|
||
| 字段 | 业务意义 | 录入方式 | 控件建议 | 校验规则 |
|
||
| ------------------- | ---------------------------------------------------------- | ------------------------- | ----------------- | -------------------------- |
|
||
| `id` | 事件主键 | 系统生成 | 隐藏/只读 | 必填、唯一 |
|
||
| `auth_user_id` | 数据所属用户或租户 | 登录上下文自动写入 | 隐藏 | 不允许手填 |
|
||
| `event_description` | 事件说明,如“台风后倒伏严重” | 用户录入 | 多行文本 | 可选;异常事件建议必填 |
|
||
| `event_type` | 事件类型名称,如 fertilizer、irrigation、planting、harvest | 用户选择/录入 | 下拉框/文本框 | 必填;建议使用事件类型字典 |
|
||
| `event_type_db_id` | 事件类型 ID,可引用标准事件类型字典 | 用户选择/系统带出 | 选择器/隐藏 | 可选 |
|
||
| `study_id` | 事件所属 study | 从 study 选择或工作台带出 | Study 选择器/隐藏 | 必选 |
|
||
|
||
### 录入建议
|
||
|
||
- 在 Study 表型工作台的“事件”Tab 中维护。
|
||
- 新增事件时先选择作用范围:整个 study 或部分 observation_unit。
|
||
- 如果只作用于部分 plot/plant,必须通过 `event_observation_units` 记录范围。
|
||
- 事件发生时间字段在你当前表结构中未显式列出,但业务上非常重要;如果数据库已有 event_date/time 字段,应强制录入;如果没有,建议补字段或放入 additional_info。
|
||
|
||
---
|
||
|
||
## 6.10 event_param 事件参数
|
||
|
||
### 业务说明
|
||
|
||
`event_param` 是事件的参数明细。例如施肥事件可以有肥料类型、剂量、单位;灌溉事件可以有水量、持续时间;打药事件可以有药剂名称、浓度、剂量。
|
||
|
||
### 字段说明
|
||
|
||
| 字段 | 业务意义 | 录入方式 | 控件建议 | 校验规则 |
|
||
| ------------------- | ------------------------------------- | ----------------- | ----------------- | ------------------------- |
|
||
| `id` | 事件参数主键 | 系统生成 | 隐藏/只读 | 必填、唯一 |
|
||
| `code` | 参数代码,如 N_RATE、IRR_VOL | 用户录入/字典带出 | 文本框 | 可选;同一事件内建议唯一 |
|
||
| `description` | 参数解释 | 用户录入 | 多行文本 | 可选 |
|
||
| `key` | 参数键,如 fertilizerType、dose、unit | 用户录入/字典选择 | 文本框 | 必填;同一事件内不应重复 |
|
||
| `name` | 参数名称,如 氮肥施用量 | 用户录入 | 文本框 | 可选 |
|
||
| `rdf_value` | RDF 或本体语义值 | 用户录入/系统带出 | 文本框 | 可选;普通业务可隐藏 |
|
||
| `units` | 参数单位,如 kg/ha、mm、L | 用户选择/录入 | 单位选择器 | 可选;数值参数建议必填 |
|
||
| `value` | 参数值 | 用户录入 | 动态控件 | 可选;若 key 需要值则必填 |
|
||
| `value_description` | 参数值说明 | 用户录入 | 多行文本 | 可选 |
|
||
| `event_id` | 所属事件 | 由事件详情页带出 | Event 选择器/隐藏 | 必选 |
|
||
|
||
### 录入建议
|
||
|
||
- 前端以键值表格方式维护。
|
||
- 可以为常用事件类型配置参数模板,例如 fertilizer 事件默认出现 fertilizerType、amount、units。
|
||
- 参数值是否必填取决于事件类型配置。
|
||
|
||
---
|
||
|
||
## 6.11 event_observation_units 事件作用范围
|
||
|
||
### 业务说明
|
||
|
||
`event_observation_units` 记录事件作用到哪些 observation_unit。比如一次施肥作用于整个 study,则可以不逐个绑定;如果某个处理只作用于部分 plot,则必须明确绑定。
|
||
|
||
### 字段说明
|
||
|
||
| 字段 | 业务意义 | 录入方式 | 控件建议 | 校验规则 |
|
||
| ---------------------- | ------------ | --------------------------------------- | ----------------- | ------------------------ |
|
||
| `event_entity_id` | 事件 | 由事件详情页带出 | Event 选择器/隐藏 | 必选 |
|
||
| `observation_units_id` | 事件作用对象 | 从当前 study 的 observation_unit 中选择 | 多选器/表格 | 必选;必须属于同一 study |
|
||
|
||
### 录入建议
|
||
|
||
- 支持按 block、rep、plot 范围批量选择。
|
||
- 如果事件作用于整个 study,可以在 event 上记录 scope=study,不必生成大量关系记录。
|
||
- 如果 event_observation_units 有记录,所有 observation_units 必须属于 event.study_id。
|
||
|
||
---
|
||
|
||
## 6.12 image 图像
|
||
|
||
### 业务说明
|
||
|
||
`image` 用于保存图片或图片元数据。图片可以是人工拍摄、无人机、固定相机、显微图、病害图片等。图片可以直接关联 observation_unit,也可以通过 `image_observations` 关联具体 observation。
|
||
|
||
### 字段说明
|
||
|
||
| 字段 | 业务意义 | 录入方式 | 控件建议 | 校验规则 |
|
||
| --------------------- | ------------------------------------- | ------------------------ | ------------------- | -------------------------------------- |
|
||
| `id` | 图片主键 | 系统生成 | 隐藏/只读 | 必填、唯一 |
|
||
| `auth_user_id` | 数据所属用户或租户 | 登录上下文自动写入 | 隐藏 | 不允许手填 |
|
||
| `copyright` | 图片版权或授权说明 | 用户录入 | 文本框 | 可选 |
|
||
| `description` | 图片说明,如“Plot-003 台风后倒伏照片” | 用户录入 | 多行文本 | 可选,建议填写 |
|
||
| `image_data` | 图片二进制内容 | 用户上传 | 文件上传 | 与 `imageurl` 至少一个;限制大小和格式 |
|
||
| `image_file_name` | 图片文件名 | 上传时自动填充 | 只读/文本框 | 可选;上传时自动生成 |
|
||
| `image_file_size` | 文件大小 | 上传时自动识别 | 只读 | 可选;应限制最大大小 |
|
||
| `image_height` | 图片高度 | 上传后自动识别 | 只读/数字框 | 可选;必须为非负整数 |
|
||
| `imagemimetype` | MIME 类型,如 image/jpeg、image/png | 上传后自动识别 | 只读/下拉框 | 可选;只允许图片 MIME 类型 |
|
||
| `imageurl` | 外部图片 URL 或对象存储 URL | 用户填写/上传后生成 | URL 输入框 | 与 `image_data` 至少一个;URL 格式校验 |
|
||
| `image_width` | 图片宽度 | 上传后自动识别 | 只读/数字框 | 可选;必须为非负整数 |
|
||
| `name` | 图片名称 | 用户录入/文件名带出 | 文本框 | 必填 |
|
||
| `time_stamp` | 拍摄或上传时间 | 用户录入/系统默认 | 日期时间选择器 | 可选;建议填写拍摄时间 |
|
||
| `coordinates_id` | 图片坐标 | 地图取点/坐标对象选择 | 地图控件/坐标选择器 | 可选;建议支持 Point/Polygon |
|
||
| `observation_unit_id` | 所属观测单元 | 从 observation_unit 选择 | 观测单元选择器 | 可选;若填写应属于同一 study 上下文 |
|
||
|
||
### 录入建议
|
||
|
||
- 推荐图片文件存对象存储,数据库只存 URL 和元数据,避免 bytea 过大。
|
||
- 手机拍照或无人机导入时,应自动提取文件名、大小、宽高、MIME、拍摄时间和 GPS 信息。
|
||
- 对无人机俯拍图,可保存图像中心点,也可保存图像覆盖范围 Polygon。
|
||
|
||
---
|
||
|
||
## 6.13 image_observations 图片与观测值关系
|
||
|
||
### 业务说明
|
||
|
||
`image_observations` 表示某张图片支持或关联哪些 observation。比如一张倒伏照片可以关联一个 plot 的倒伏等级 observation。
|
||
|
||
### 字段说明
|
||
|
||
| 字段 | 业务意义 | 录入方式 | 控件建议 | 校验规则 |
|
||
| ----------------- | ---------- | ------------------- | ------------------ | ---------------------------------------- |
|
||
| `image_entity_id` | 图片 | 由图片详情页带出 | Image 选择器/隐藏 | 必选 |
|
||
| `observations_id` | 关联观测值 | 从 observation 选择 | Observation 选择器 | 必选;建议与图片的 observation_unit 一致 |
|
||
|
||
### 录入建议
|
||
|
||
- 图片详情页支持关联多个 observation。
|
||
- observation 详情页也支持反向查看相关图片。
|
||
- 如果图片已绑定 observation_unit,则关联 observation 时应过滤为同一 observation_unit 下的 observation。
|
||
|
||
---
|
||
|
||
## 6.14 observation 观测值
|
||
|
||
### 业务说明
|
||
|
||
`observation` 是 Phenotyping 模块最核心的事实表。它表示“某个 observation_unit 在某个 observation_variable 上的一次实际采集结果”。
|
||
|
||
```text
|
||
observation_unit = Plot-003
|
||
observation_variable = 株高-尺测法-cm
|
||
value = 112.5
|
||
observation_time_stamp = 2026-07-12 09:30
|
||
```
|
||
|
||
### 字段说明
|
||
|
||
| 字段 | 业务意义 | 录入方式 | 控件建议 | 校验规则 |
|
||
| ------------------------- | ------------------ | ---------------------------------------- | ------------------- | ------------------------------------------ |
|
||
| `id` | 观测值主键 | 系统生成;导入可指定 | 隐藏/只读 | 必填、唯一 |
|
||
| `auth_user_id` | 数据所属用户或租户 | 登录上下文自动写入 | 隐藏 | 不允许手填 |
|
||
| `collector` | 采集人 | 用户选择/登录用户带出 | 人员选择器/文本框 | 可选;人工采集建议填写 |
|
||
| `observation_time_stamp` | 观测时间 | 用户录入/采集设备带出 | 日期时间选择器 | 建议必填;按 ISO 8601 保存 |
|
||
| `uploaded_by` | 上传人 | 登录用户自动写入 | 只读 | 可选;批量导入时自动填 |
|
||
| `value` | 实际观测值 | 用户录入/导入/设备上传 | 动态控件 | 必填;按 variable.scale 校验 |
|
||
| `crop_id` | 作物上下文 | 由 observation_unit 或 study 自动带出 | 只读/隐藏 | 可选但建议保存;需与 observation_unit 一致 |
|
||
| `geo_coordinates_id` | 观测发生坐标 | 地图取点/设备 GPS | 地图控件/坐标选择器 | 可选;坐标需合法 |
|
||
| `observation_unit_id` | 被观测对象 | 从 observation_unit 选择或矩阵行带出 | 观测单元选择器/隐藏 | 必选 |
|
||
| `observation_variable_id` | 观测变量 | 从 observation_variable 选择或矩阵列带出 | 变量选择器/隐藏 | 必选 |
|
||
| `program_id` | 项目上下文 | 由 observation_unit/study 自动带出 | 只读/隐藏 | 可选但建议保存 |
|
||
| `season_id` | 季节 | 从 study season 或用户选择 | Season 选择器 | 可选;多季节 study 建议填写 |
|
||
| `study_id` | 所属 study | 由 observation_unit 自动带出 | 只读/隐藏 | 必选;需与 observation_unit.study 一致 |
|
||
| `trial_id` | 所属 trial | 由 observation_unit/study 自动带出 | 只读/隐藏 | 可选但建议保存 |
|
||
|
||
### 录入建议
|
||
|
||
- 普通录入优先走矩阵:行是 observation_unit,列是 observation_variable。
|
||
- 单条表单只用于补录、纠错、详情编辑。
|
||
- value 必须使用 observation_variable.scale 决定控件和校验:
|
||
- 数值型:数字、小数位、范围;
|
||
- 分类型:只能从 valid category 中选;
|
||
- 日期型:日期格式;
|
||
- 布尔型:true/false;
|
||
- 文本型:长度限制。
|
||
- 同一 `observation_unit_id + observation_variable_id + observation_time_stamp` 可允许重复,但必须在页面展示重复标记、采集人和上传来源。
|
||
|
||
---
|
||
|
||
# 7. 跨表联动规则
|
||
|
||
| 场景 | 联动规则 |
|
||
| ------------------------- | ------------------------------------------------------------ |
|
||
| 创建 observation_variable | 必须先选择 trait、method、scale;系统自动生成变量名称 |
|
||
| 配置 study_variable | 变量选择器优先展示同 crop 或未限定 crop 的变量 |
|
||
| 创建 observation_unit | 选择 study 后自动带出 crop、program、trial |
|
||
| 选择 seed_lot | 可自动带出 germplasm,但允许用户确认 |
|
||
| 录入 observation | 选择 observation_unit 后自动带出 study、trial、program、crop |
|
||
| 录入 observation.value | 根据 observation_variable.scale 动态渲染控件和校验 |
|
||
| 新增 event | 从 study 工作台进入时自动带出 study_id |
|
||
| 选择事件作用范围 | 只能选择同一 study 下的 observation_unit |
|
||
| 上传 image | 如果从 observation_unit 详情页上传,自动绑定 observation_unit_id |
|
||
| 关联 image_observations | 如果图片已绑定 observation_unit,只能关联同 observation_unit 的 observation |
|
||
|
||
---
|
||
|
||
# 8. 删除和停用规则
|
||
|
||
| 对象 | 删除限制 |
|
||
| -------------------- | ------------------------------------------------------------ |
|
||
| ontology | 已被 trait/method/scale/variable 引用时不可物理删除 |
|
||
| trait | 已被 observation_variable 或 germplasm_attribute_definition 引用时不可物理删除 |
|
||
| method | 已被 observation_variable 引用时不可物理删除 |
|
||
| scale | 已被 observation_variable 或 attribute definition 引用时不可物理删除 |
|
||
| observation_variable | 已产生 observation 时不可删除,只能停用或设为 obsolete |
|
||
| study_variable | 若已有该变量的 observation,不允许直接移除 |
|
||
| observation_unit | 已有 observation、image、event、sample 时不可删除 |
|
||
| event | 已有关联 event_param 或 event_observation_units 时删除需级联确认或禁止 |
|
||
| image | 已关联 observation 时不可直接删除,应先解除关系或作废 |
|
||
| observation | 原始数据原则上不建议物理删除;建议保留修改历史或作废状态 |
|
||
|
||
---
|
||
|
||
# 9. 批量导入要求
|
||
|
||
## 9.1 ObservationUnit 导入模板
|
||
|
||
必需列建议:
|
||
|
||
```text
|
||
study_id 或 study_name
|
||
observation_unit_name
|
||
observation_level_name
|
||
observation_level_code
|
||
```
|
||
|
||
强烈建议列:
|
||
|
||
```text
|
||
germplasm_id 或 germplasm_name
|
||
seed_lot_id 或 seed_lot_name
|
||
block
|
||
rep
|
||
plot
|
||
row
|
||
column
|
||
```
|
||
|
||
## 9.2 ObservationVariable 导入模板
|
||
|
||
必需列建议:
|
||
|
||
```text
|
||
trait_name
|
||
method_name
|
||
scale_name
|
||
variable_name
|
||
```
|
||
|
||
可选列:
|
||
|
||
```text
|
||
trait_pui
|
||
method_pui
|
||
scale_pui
|
||
variable_pui
|
||
crop_name
|
||
growth_stage
|
||
status
|
||
```
|
||
|
||
## 9.3 Observation 矩阵导入模板
|
||
|
||
推荐格式:
|
||
|
||
```text
|
||
observation_unit_name,germplasm_name,collection_time,collector,PlantHeight_cm,LodgingScore_0_5,DiseaseScore_1_9
|
||
Plot-001,华占,2026-07-12T09:30:00+08:00,张三,112.5,1,2
|
||
Plot-002,抗倒伏A,2026-07-12T09:35:00+08:00,张三,98.3,0,1
|
||
```
|
||
|
||
导入规则:
|
||
|
||
1. 每个变量列必须能映射到一个 observation_variable。
|
||
2. 每一行必须能匹配一个 observation_unit。
|
||
3. 每个非空单元格生成一条 observation。
|
||
4. 空值不生成 observation,除非用户选择“导入为空观测”。
|
||
5. 导入前必须预校验,错误报告包含行号、列名、错误原因、建议修复方式。
|
||
|
||
## 9.4 Image 导入模板
|
||
|
||
必需列建议:
|
||
|
||
```text
|
||
image_name
|
||
image_url 或 image_file
|
||
```
|
||
|
||
可选列:
|
||
|
||
```text
|
||
observation_unit_name
|
||
observation_id
|
||
capture_time
|
||
longitude
|
||
latitude
|
||
polygon
|
||
copyright
|
||
description
|
||
```
|
||
|
||
---
|
||
|
||
# 10. 后端接口建议
|
||
|
||
## 10.1 主数据接口
|
||
|
||
```text
|
||
GET /ontologies
|
||
POST /ontologies
|
||
GET /ontologies/{id}
|
||
PUT /ontologies/{id}
|
||
DELETE /ontologies/{id}
|
||
|
||
GET /traits
|
||
POST /traits
|
||
GET /traits/{id}
|
||
PUT /traits/{id}
|
||
|
||
GET /methods
|
||
POST /methods
|
||
GET /methods/{id}
|
||
PUT /methods/{id}
|
||
|
||
GET /scales
|
||
POST /scales
|
||
GET /scales/{id}
|
||
PUT /scales/{id}
|
||
GET /scales/{id}/valid-values
|
||
POST /scales/{id}/valid-values
|
||
|
||
GET /observation-variables
|
||
POST /observation-variables
|
||
GET /observation-variables/{id}
|
||
PUT /observation-variables/{id}
|
||
|
||
GET /studies/{studyId}/variables
|
||
POST /studies/{studyId}/variables
|
||
DELETE /studies/{studyId}/variables/{variableId}
|
||
|
||
GET /studies/{studyId}/observation-units
|
||
POST /studies/{studyId}/observation-units/batch-generate
|
||
POST /observation-units
|
||
PUT /observation-units/{id}
|
||
|
||
GET /studies/{studyId}/events
|
||
POST /studies/{studyId}/events
|
||
GET /events/{id}/params
|
||
POST /events/{id}/params
|
||
POST /events/{id}/observation-units
|
||
|
||
GET /images
|
||
POST /images
|
||
POST /images/upload
|
||
POST /images/{id}/observations
|
||
|
||
GET /observations
|
||
POST /observations
|
||
POST /observations/matrix
|
||
POST /observations/import
|
||
```
|
||
|
||
## 10.2 选择器接口
|
||
|
||
```text
|
||
GET /selectors/ontologies
|
||
GET /selectors/traits?ontologyId=&keyword=
|
||
GET /selectors/methods?ontologyId=&keyword=
|
||
GET /selectors/scales?ontologyId=&dataType=&keyword=
|
||
GET /selectors/observation-variables?cropId=&studyId=&keyword=
|
||
GET /selectors/studies?programId=&trialId=&keyword=
|
||
GET /selectors/observation-units?studyId=&level=&germplasmId=&keyword=
|
||
GET /selectors/events?studyId=&eventType=&keyword=
|
||
GET /selectors/images?observationUnitId=&keyword=
|
||
```
|
||
|
||
---
|
||
|
||
# 11. 测试验收清单
|
||
|
||
1. 创建 trait 时,`trait_name` 必填。
|
||
2. 创建 method 时,`name` 必填。
|
||
3. 创建 scale 时,`scale_name` 和 `data_type` 必填。
|
||
4. 分类型 scale 没有 valid value 时,应提示或禁止用于 observation_variable。
|
||
5. 创建 observation_variable 时,trait、method、scale 必选。
|
||
6. observation_variable 名称可自动生成,也允许用户手动修改。
|
||
7. 配置 study_variable 时,不能重复绑定同一个 variable。
|
||
8. 创建 observation_unit 时,study 必选。
|
||
9. 选择 study 后,crop、program、trial 自动带出。
|
||
10. 同一 study 内 observation_unit_name 重复时提示。
|
||
11. observation_unit 至少建议绑定 germplasm、seed_lot、cross 中一个材料来源。
|
||
12. 创建 event 时,study 和 event_type 必填。
|
||
13. event 绑定 observation_unit 时,所有 observation_unit 必须属于该 event 的 study。
|
||
14. 图片上传时,image_data 和 imageurl 至少一个存在。
|
||
15. 图片 MIME 类型必须是允许的图片类型。
|
||
16. observation 创建时,observation_unit、observation_variable、value 必填。
|
||
17. observation.value 必须按 scale.data_type 校验。
|
||
18. 数值型 value 必须在 valid_value_min 和 valid_value_max 范围内。
|
||
19. 分类型 value 必须属于 scale_valid_value_category。
|
||
20. observation 的 study/trial/program/crop 必须与 observation_unit 上下文一致。
|
||
21. 矩阵录入保存时,每个有效单元格生成一条 observation。
|
||
22. 导入失败时必须返回行号、字段、错误原因和修复建议。
|
||
23. 已产生 observation 的 observation_variable 不允许直接删除。
|
||
24. 已被 observation、image、event、sample 引用的 observation_unit 不允许物理删除。
|
||
25. 所有日期时间字段按 ISO 8601 保存,并保留时区或统一转换为 UTC。
|
||
|
||
---
|
||
|
||
# 12. 开发实现重点
|
||
|
||
1. `observation_variable` 是表型指标定义,不是观测值。
|
||
2. `observation_unit` 是被观测对象,不是实际测量值。
|
||
3. `observation` 才是真正的表型事实数据。
|
||
4. `value` 字段虽然数据库是字符串,但前端和后端必须按 scale 做类型校验。
|
||
5. `study` 是 Phenotyping 的核心上下文入口,几乎所有表型数据都应能追溯到 study。
|
||
6. 表型采集页面应优先做矩阵录入,不要只做单条 CRUD。
|
||
7. 图片不要直接塞数据库大字段为主,建议走对象存储 URL + 元数据。
|
||
8. Event 不只是备注,它是解释表型差异的重要上下文,应支持作用范围和参数化。
|
||
|