31 KiB
报工单页面类别与字段控制设计文档
版本: v2.0.003
日期: 2026-03-05
负责人: 周启威
需求整理
原始需求
-
报工单中分了 ABCDE 五类,能否在新增/编辑的时候把五类中任一一类停用,然后写一个配置表、页面上一个按钮可以控制五个类别的停用与启用
-
报工单中分了 ABCDE 五类,在这五类中的字段命名/增删改查能不能也放入配置表,五类中的字段也需要控制与自定义,现在目前程序中现有的字段也需要控制与自定义了
-
规则:停用/启用 对应的是 隐藏/显示,只要是停用就隐藏该字段
-
数据类型也需要自定义,然后控件类型也需要自定义
-
分类也可以自己增加并修改,我新增的自定义字段应该可以指定进入任一分类中
-
ABCDE 的话还是自动排吧,比如我 C 停用了,应该 D→C, E→D,默认是这样的,但是也可以自定义
需求总结
一、类别管理需求
-
系统类别(A/B/C/D/E):
- 可以停用/启用(停用=隐藏)
- 可以修改类别名称
- 不可删除
- 支持名称重置为默认值
-
自定义类别(F/G/H...):
- 可以新增自定义类别
- 可以修改类别名称
- 可以删除(删除前需确认该类别下无字段)
- 可以停用/启用
-
类别排序:
- 支持手动调整排序(拖拽或上下移动)
- 前端显示时,启用的类别自动重新编号为 A、B、C、D...
- 例如:C 停用后,D 自动显示为 C,E 自动显示为 D
二、字段管理需求
-
系统字段(现有字段):
- 可以停用/启用(停用=隐藏)
- 可以修改显示名称(如"报工人"改为"操作员")
- 可以修改控件类型
- 不可删除
- 支持名称重置为默认值
-
自定义字段(新增字段):
- 可以新增自定义字段
- 可以配置字段名称、数据类型、控件类型
- 可以选择放入任一类别中(包括自定义类别)
- 可以移动到其他类别
- 可以删除
- 可以停用/启用
-
字段配置项:
- 字段名称(可自定义)
- 数据类型(STRING/NUMBER/DATE/DATETIME/BOOLEAN/SELECT)
- 控件类型(INPUT/NUMBER/DATE/DATETIME/SELECT/TEXTAREA/SWITCH)
- 下拉选项(SELECT 类型时配置)
- 是否必填
- 排序
三、数据存储需求
- 系统字段:存储在
pro_report表对应列中 - 自定义字段:存储在
pro_report.custom_fieldsJSON 字段中
四、显示规则
- 停用=隐藏:停用的类别和字段在表单中完全隐藏
- 启用=显示:启用的类别和字段在表单中显示
- 自动编号:前端显示时,启用的类别自动重新编号为 A、B、C、D...
一、需求背景
报工单表单中分为五类(A-基础信息、B-数量信息、C-时间节拍、D-成本效益、E-异常记录),需要实现:
-
类别控制:
- 能够在配置中停用/启用任一类别,停用后该类别在新增/编辑时隐藏
- 支持新增自定义类别(如 F、G、H 等)
- 支持修改类别名称(如将"基础信息"改为"基本信息")
- 系统类别(A/B/C/D/E)不可删除,只能停用;自定义类别可删除
-
字段控制:五类中的字段能够单独控制停用/启用(隐藏/显示)
-
字段自定义:
- 现有字段可以自定义显示名称(改名),例如将"报工人"改为"操作员"
- 支持新增自定义字段,可配置字段名称、数据类型、控件类型
- 新增自定义字段时可以选择放入任一类别中(包括自定义类别)
- 自定义字段的值存储在 JSON 扩展字段中
-
规则:停用=隐藏,启用=显示
二、设计方案
2.1 数据库设计
2.1.1 类别配置表(pro_report_category_config)
存储系统类别和自定义类别的配置
| 字段名 | 类型 | 说明 |
|---|---|---|
| id | bigint | 主键ID |
| category_code | varchar(50) | 类别编码(A/B/C/D/E 为系统类别,F/G/H... 为自定义类别) |
| category_name | varchar(100) | 类别名称(可自定义修改) |
| default_category_name | varchar(100) | 默认类别名称(系统初始名称,用于重置) |
| category_type | varchar(20) | 类别类型(SYSTEM=系统类别/CUSTOM=自定义类别) |
| is_enabled | char(1) | 是否启用(Y=启用/N=停用),默认Y |
| sort_order | int | 排序号 |
| remark | varchar(500) | 备注 |
| create_by | varchar(64) | 创建者 |
| create_time | datetime | 创建时间 |
| update_by | varchar(64) | 更新者 |
| update_time | datetime | 更新时间 |
2.1.2 字段配置表(pro_report_field_config)
存储每个类别下字段的启用/停用状态、自定义显示名称、数据类型和控件类型
| 字段名 | 类型 | 说明 |
|---|---|---|
| id | bigint | 主键ID |
| category_code | varchar(50) | 所属类别编码(A/B/C/D/E) |
| field_code | varchar(100) | 字段编码(对应实体类字段名或自定义字段唯一标识,不可修改) |
| field_name | varchar(100) | 字段显示名称(可自定义修改,如"报工人"可改为"操作员") |
| default_field_name | varchar(100) | 默认字段名称(系统初始名称,用于重置) |
| field_type | varchar(20) | 字段类型(SYSTEM=系统字段/CUSTOM=自定义字段) |
| data_type | varchar(50) | 数据类型(STRING=文本/NUMBER=数字/DATE=日期/DATETIME=日期时间/BOOLEAN=布尔/SELECT=下拉选择) |
| control_type | varchar(50) | 控件类型(INPUT=文本框/NUMBER=数字框/DATE=日期选择/DATETIME=日期时间选择/SELECT=下拉框/TEXTAREA=文本域/SWITCH=开关) |
| options | text | 下拉选项(JSON格式,仅当control_type=SELECT时有效,如:[{"label":"选项1","value":"1"}]) |
| is_enabled | char(1) | 是否启用(Y=启用/N=停用),默认Y |
| is_required | char(1) | 是否必填(Y=必填/N=非必填),默认N |
| sort_order | int | 排序号 |
| remark | varchar(500) | 备注 |
| create_by | varchar(64) | 创建者 |
| create_time | datetime | 创建时间 |
| update_by | varchar(64) | 更新者 |
| update_time | datetime | 更新时间 |
2.2 字段清单
A. 基础信息(category_code='A')
| field_code | field_name | field_type | data_type | control_type | is_required | 说明 |
|---|---|---|---|---|---|---|
| reportUserId | 报工人 | SYSTEM | NUMBER | SELECT | Y | 系统字段,必填 |
| reportTime | 报工时间 | SYSTEM | DATETIME | DATETIME | Y | 系统字段,必填 |
| reportType | 报工类型 | SYSTEM | STRING | SELECT | N | 系统字段,字典 |
| shiftName | 班次 | SYSTEM | STRING | SELECT | N | 系统字段,字典 |
| teamName | 班组 | SYSTEM | STRING | SELECT | N | 系统字段,字典 |
| executionStandard | 执行标准 | SYSTEM | STRING | INPUT | N | 系统字段 |
| workshopId | 车间 | SYSTEM | NUMBER | SELECT | Y | 系统字段,必填 |
| stationId | 工位 | SYSTEM | NUMBER | SELECT | Y | 系统字段,必填 |
B. 数量信息(category_code='B')
| field_code | field_name | field_type | data_type | control_type | is_required | 说明 |
|---|---|---|---|---|---|---|
| planCount | 计划数 | SYSTEM | NUMBER | INPUT | N | 系统字段,只读 |
| reportQuantity | 报工数量 | SYSTEM | NUMBER | NUMBER | Y | 系统字段,必填 |
| qualifiedQuantity | 合格数量 | SYSTEM | NUMBER | NUMBER | Y | 系统字段,必填 |
| unqualifiedQuantity | 不合格数量 | SYSTEM | NUMBER | INPUT | N | 系统字段,自动计算 |
| yieldRate | 良品率 | SYSTEM | NUMBER | INPUT | N | 系统字段,自动计算 |
C. 时间节拍(category_code='C')
| field_code | field_name | field_type | data_type | control_type | is_required | 说明 |
|---|---|---|---|---|---|---|
| planStartTime | 计划开始时间 | SYSTEM | DATETIME | INPUT | N | 系统字段,只读 |
| planEndTime | 计划完工时间 | SYSTEM | DATETIME | DATETIME | N | 系统字段 |
| actualStartTime | 实际开始时间 | SYSTEM | DATETIME | DATETIME | N | 系统字段 |
| actualEndTime | 实际完工时间 | SYSTEM | DATETIME | DATETIME | N | 系统字段 |
| theoreticalCycleTime | 理论节拍 | SYSTEM | NUMBER | NUMBER | N | 系统字段 |
| downtimeMinutes | 停机时间 | SYSTEM | NUMBER | NUMBER | N | 系统字段 |
| downtimeReason | 停机原因 | SYSTEM | STRING | INPUT | N | 系统字段 |
D. 成本效益(category_code='D')
| field_code | field_name | field_type | data_type | control_type | is_required | 说明 |
|---|---|---|---|---|---|---|
| performanceWages | 绩效工资 | SYSTEM | NUMBER | NUMBER | N | 系统字段 |
| energyConsumption | 能耗 | SYSTEM | NUMBER | NUMBER | N | 系统字段 |
| materialConsumption | 工耗 | SYSTEM | NUMBER | NUMBER | N | 系统字段 |
| otherCosts | 其他成本 | SYSTEM | NUMBER | NUMBER | N | 系统字段 |
| valueAdded | 增值 | SYSTEM | NUMBER | NUMBER | N | 系统字段 |
| stationOee | 工位OEE | SYSTEM | NUMBER | NUMBER | N | 系统字段 |
| currentBenefit | 本次效益 | SYSTEM | NUMBER | INPUT | N | 系统字段,自动计算 |
| isSettle | 是否结算工资 | SYSTEM | STRING | SELECT | N | 系统字段,字典 |
| wages | 结算工资 | SYSTEM | NUMBER | NUMBER | N | 系统字段 |
E. 异常记录(category_code='E')
| field_code | field_name | field_type | data_type | control_type | is_required | 说明 |
|---|---|---|---|---|---|---|
| stationException | 工位异常情况 | SYSTEM | STRING | TEXTAREA | N | 系统字段 |
| rectificationSuggestion | 整改建议 | SYSTEM | STRING | TEXTAREA | N | 系统字段 |
| remark | 备注 | SYSTEM | STRING | TEXTAREA | N | 系统字段 |
2.3 自定义字段存储方案
2.3.1 存储位置
自定义字段的值存储在 pro_report 表的 custom_fields 字段中(JSON 类型)。
ALTER TABLE `pro_report` ADD COLUMN `custom_fields` json DEFAULT NULL COMMENT '自定义字段值(JSON格式)';
2.3.2 存储格式
{
"custom_field_001": "自定义文本值",
"custom_field_002": 123.45,
"custom_field_003": "2026-03-05 10:30:00",
"custom_field_004": true
}
2.3.3 字段编码规则
- 系统字段:使用实体类字段名(如
reportUserId) - 自定义字段:使用
custom_field_+ 序号(如custom_field_001)
2.3.4 数据类型映射
| data_type | 存储格式 | 示例 |
|---|---|---|
| STRING | 字符串 | "文本内容" |
| NUMBER | 数字 | 123.45 |
| DATE | 字符串(yyyy-MM-dd) | "2026-03-05" |
| DATETIME | 字符串(yyyy-MM-dd HH:mm:ss) | "2026-03-05 10:30:00" |
| BOOLEAN | 布尔值 | true / false |
| SELECT | 字符串(选项值) | "option1" |
2.3.5 字段保存与读取规则
保存报工单时:
-
系统字段(field_type=SYSTEM):
- 直接保存到
pro_report表对应的列 - 例如:
reportUserId保存到report_user_id列 - 使用 MyBatis-Plus 自动映射
- 直接保存到
-
自定义字段(field_type=CUSTOM):
- 保存到
pro_report.custom_fieldsJSON 字段 - 例如:
custom_field_001保存为{"custom_field_001": "值"} - 后端需要将自定义字段值序列化为 JSON
- 保存到
查询报工单时:
-
系统字段:
- 直接从
pro_report表对应列读取 - MyBatis-Plus 自动映射到实体类
- 直接从
-
自定义字段:
- 从
pro_report.custom_fieldsJSON 字段解析 - 后端需要将 JSON 反序列化为 Map 或对象
- 前端合并系统字段和自定义字段数据
- 从
示例代码(后端保存):
// 保存报工单
public void saveReport(Report report, Map<String, Object> customFields) {
// 1. 保存系统字段(MyBatis-Plus 自动处理)
reportMapper.insert(report);
// 2. 保存自定义字段到 JSON
if (customFields != null && !customFields.isEmpty()) {
String customFieldsJson = JSON.toJSONString(customFields);
report.setCustomFields(customFieldsJson);
reportMapper.updateById(report);
}
}
示例代码(后端查询):
// 查询报工单
public ReportVO getReport(Long id) {
Report report = reportMapper.selectById(id);
ReportVO vo = new ReportVO();
// 1. 复制系统字段
BeanUtils.copyProperties(report, vo);
// 2. 解析自定义字段
if (StringUtils.isNotEmpty(report.getCustomFields())) {
Map<String, Object> customFields = JSON.parseObject(
report.getCustomFields(),
new TypeReference<Map<String, Object>>() {}
);
vo.setCustomFields(customFields);
}
return vo;
}
示例代码(前端保存):
// 提交报工单
submitForm() {
const formData = {
// 系统字段
reportUserId: this.form.reportUserId,
reportTime: this.form.reportTime,
reportQuantity: this.form.reportQuantity,
// ... 其他系统字段
// 自定义字段(单独传递)
customFields: {
custom_field_001: this.form.custom_field_001,
custom_field_002: this.form.custom_field_002,
// ... 其他自定义字段
}
};
saveReport(formData).then(response => {
this.$modal.msgSuccess("保存成功");
});
}
三、功能设计
3.1 配置管理页面
3.1.1 类别配置
- 页面路径:
/production/report/categoryConfig - 功能:
- 列表展示所有类别(系统类别 + 自定义类别)的启用状态
- 支持单个类别的启用/停用切换
- 支持新增自定义类别(点击"新增类别"按钮)
- 支持修改类别名称(双击编辑或点击编辑按钮)
- 支持删除自定义类别(系统类别不可删除,只能停用)
- 支持类别名称重置为默认值(仅系统类别)
- 支持批量启用/停用
- 支持排序调整(拖拽排序)
3.1.2 字段配置
- 页面路径:
/production/report/fieldConfig - 功能:
- 按类别分组展示字段列表(包括系统类别和自定义类别)
- 支持新增自定义字段(点击"新增字段"按钮,选择所属类别)
- 支持单个字段的启用/停用切换
- 支持字段显示名称自定义修改(双击编辑或点击编辑按钮)
- 支持字段名称重置为默认值(仅系统字段)
- 支持删除自定义字段(系统字段不可删除,只能停用)
- 支持字段必填属性设置
- 支持字段排序调整
- 支持按类别筛选
- 支持修改字段所属类别(可将字段移动到其他类别)
3.2 报工单表单适配
3.2.1 类别显示控制
- 前端加载配置接口,获取启用的类别列表
- 根据配置动态渲染
el-collapse-item - 停用的类别完全不渲染
- 启用的类别按 sort_order 排序后,自动重新编号为 A、B、C、D...
- 显示格式:
{自动编号}. {类别名称}(如A. 基础信息)
前端实现示例:
// 加载类别配置
async loadCategoryConfig() {
const res = await listCategoryConfig({ isEnabled: 'Y' });
// 按 sort_order 排序
const enabledCategories = res.rows.sort((a, b) => a.sortOrder - b.sortOrder);
// 自动重新编号
this.displayCategories = enabledCategories.map((cat, index) => ({
...cat,
displayCode: String.fromCharCode(65 + index), // A, B, C, D...
displayName: `${String.fromCharCode(65 + index)}. ${cat.categoryName}`
}));
}
3.2.2 字段显示控制
- 前端加载字段配置接口,获取每个类别下启用的字段列表
- 根据配置动态渲染字段控件
- 停用的字段完全不渲染
- 必填字段根据配置动态添加校验规则
四、接口设计
4.1 类别配置接口
4.1.1 查询类别配置列表
GET /production/report/categoryConfig/list
响应:
[
{
"id": 1,
"categoryCode": "A",
"categoryName": "基础信息",
"isEnabled": "Y",
"sortOrder": 1
},
...
]
4.1.2 更新类别配置
PUT /production/report/categoryConfig/{id}
请求体:
{
"isEnabled": "N"
}
4.2 字段配置接口
4.2.1 查询字段配置列表
GET /production/report/fieldConfig/list?categoryCode=A
响应:
[
{
"id": 1,
"categoryCode": "A",
"fieldCode": "reportUserId",
"fieldName": "报工人",
"isEnabled": "Y",
"isRequired": "Y",
"sortOrder": 1
},
...
]
4.2.2 更新字段配置
PUT /production/report/fieldConfig/{id}
请求体:
{
"fieldName": "操作员", // 自定义显示名称
"isEnabled": "N",
"isRequired": "N"
}
4.2.3 重置字段名称
PUT /production/report/fieldConfig/{id}/resetName
响应:
{
"code": 200,
"msg": "重置成功",
"data": {
"fieldName": "报工人" // 恢复为默认名称
}
}
4.2.4 批量更新字段配置
PUT /production/report/fieldConfig/batch
请求体:
[
{
"id": 1,
"isEnabled": "Y"
},
{
"id": 2,
"isEnabled": "N"
}
]
五、前端实现要点
5.1 配置加载
// 在 formA.vue 和 form.vue 的 created 钩子中加载配置
async loadReportConfig() {
// 加载类别配置
const categoryRes = await listCategoryConfig()
this.enabledCategories = categoryRes.rows.filter(c => c.isEnabled === 'Y')
// 加载字段配置
const fieldRes = await listFieldConfig()
this.fieldConfigMap = {}
fieldRes.rows.forEach(f => {
if (!this.fieldConfigMap[f.categoryCode]) {
this.fieldConfigMap[f.categoryCode] = []
}
if (f.isEnabled === 'Y') {
this.fieldConfigMap[f.categoryCode].push(f)
}
})
}
5.2 动态渲染类别
<el-collapse v-model="record._sections">
<template v-for="category in enabledCategories">
<el-collapse-item :name="category.categoryCode" :key="category.categoryCode">
<template slot="title">
<b>{{ category.categoryCode }}. {{ category.categoryName }}</b>
</template>
<!-- 动态渲染字段 -->
<component :is="getCategoryComponent(category.categoryCode)"
:record="record"
:fields="fieldConfigMap[category.categoryCode]" />
</el-collapse-item>
</template>
</el-collapse>
5.3 动态渲染字段
<el-row :gutter="16">
<template v-for="field in fields">
<el-col :xs="24" :sm="12" :md="8" :key="field.fieldCode" v-if="field.isEnabled === 'Y'">
<el-form-item
:label="field.fieldName"
:prop="'reportList.'+rIdx+'.'+field.fieldCode"
:rules="field.isRequired === 'Y' ? rules[field.fieldCode] : []"
label-width="100px">
<!-- 根据字段类型渲染不同控件 -->
<component :is="getFieldComponent(field.fieldCode)"
v-model="record[field.fieldCode]"
:disabled="record.disabledFlag" />
</el-form-item>
</el-col>
</template>
</el-row>
六、后端实现要点
6.1 实体类
// ReportCategoryConfig.java
@Data
@TableName("pro_report_category_config")
public class ReportCategoryConfig extends BaseEntity {
@TableId(type = IdType.AUTO)
private Long id;
private String categoryCode;
private String categoryName;
private String isEnabled;
private Integer sortOrder;
}
// ReportFieldConfig.java
@Data
@TableName("pro_report_field_config")
public class ReportFieldConfig extends BaseEntity {
@TableId(type = IdType.AUTO)
private Long id;
private String categoryCode;
private String fieldCode;
private String fieldName;
private String isEnabled;
private String isRequired;
private Integer sortOrder;
}
6.2 Controller
@RestController
@RequestMapping("/production/report/categoryConfig")
public class ReportCategoryConfigController extends BaseController {
@Autowired
private IReportCategoryConfigService categoryConfigService;
@GetMapping("/list")
public TableDataInfo list(ReportCategoryConfig config) {
startPage();
List<ReportCategoryConfig> list = categoryConfigService.selectList(config);
return getDataTable(list);
}
@PutMapping("/{id}")
public AjaxResult update(@PathVariable Long id, @RequestBody ReportCategoryConfig config) {
config.setId(id);
return toAjax(categoryConfigService.updateById(config));
}
}
@RestController
@RequestMapping("/production/report/fieldConfig")
public class ReportFieldConfigController extends BaseController {
@Autowired
private IReportFieldConfigService fieldConfigService;
@GetMapping("/list")
public TableDataInfo list(ReportFieldConfig config) {
startPage();
List<ReportFieldConfig> list = fieldConfigService.selectList(config);
return getDataTable(list);
}
@PutMapping("/{id}")
public AjaxResult update(@PathVariable Long id, @RequestBody ReportFieldConfig config) {
config.setId(id);
return toAjax(fieldConfigService.updateById(config));
}
@PutMapping("/{id}/resetName")
public AjaxResult resetName(@PathVariable Long id) {
return fieldConfigService.resetFieldName(id);
}
@PutMapping("/batch")
public AjaxResult batchUpdate(@RequestBody List<ReportFieldConfig> configs) {
return toAjax(fieldConfigService.updateBatchById(configs));
}
}
七、菜单权限配置
7.1 新增菜单
| 菜单名称 | 菜单路径 | 权限标识 | 父菜单 |
|---|---|---|---|
| 报工单配置 | /production/report/config | production:report:config | 生产管理 |
| 类别配置 | /production/report/categoryConfig | production:report:categoryConfig | 报工单配置 |
| 字段配置 | /production/report/fieldConfig | production:report:fieldConfig | 报工单配置 |
7.2 权限标识
production:report:categoryConfig:list- 查询类别配置production:report:categoryConfig:edit- 修改类别配置production:report:fieldConfig:list- 查询字段配置production:report:fieldConfig:edit- 修改字段配置production:report:fieldConfig:batchEdit- 批量修改字段配置
八、实施步骤
| 步骤 | 任务 | 工作量 |
|---|---|---|
| 1 | 执行 SQL 脚本创建配置表和初始化数据 | 0.5h |
| 2 | 后端:创建实体类、Mapper、Service、Controller(含重置名称接口) | 2.5h |
| 3 | 前端:创建配置管理页面(类别配置、字段配置,含字段名称编辑) | 5h |
| 4 | 前端:报工单表单适配(动态加载配置、动态渲染、使用自定义名称) | 4h |
| 5 | 联调测试、修复问题 | 2h |
| 合计 | 约 2 个工作日 |
九、核心规则说明
9.1 字段类型规则
| 规则项 | 系统字段(SYSTEM) | 自定义字段(CUSTOM) |
|---|---|---|
| 字段编码 | 使用实体类字段名(如 reportUserId) |
使用 custom_field_ + 序号(如 custom_field_001) |
| 存储位置 | pro_report 表对应列(如 report_user_id) |
pro_report.custom_fields JSON 字段 |
| 字段名称 | 可自定义修改显示名称 | 可自定义修改显示名称 |
| 数据类型 | 固定(由数据库列类型决定) | 可配置(STRING/NUMBER/DATE/DATETIME/BOOLEAN/SELECT) |
| 控件类型 | 可配置 | 可配置 |
| 所属类别 | 固定(不可修改) | 可修改(可移动到其他类别) |
| 是否可删除 | 不可删除,只能停用 | 可删除 |
9.1.1 类别类型规则
| 规则项 | 系统类别(SYSTEM) | 自定义类别(CUSTOM) |
|---|---|---|
| 类别编码 | A/B/C/D/E(固定) | F/G/H/I...(自动生成) |
| 类别名称 | 可自定义修改 | 可自定义修改 |
| 是否可删除 | 不可删除,只能停用 | 可删除(删除前需确认该类别下无字段) |
| 排序 | 可调整 | 可调整 |
9.2 数据保存规则
规则 1:系统字段直接保存到对应列
- 系统字段(field_type=SYSTEM)的值直接保存到
pro_report表对应的列 - 例如:
reportUserId→report_user_id列 - 使用 MyBatis-Plus 自动映射,无需特殊处理
规则 2:自定义字段保存到 JSON
- 自定义字段(field_type=CUSTOM)的值保存到
custom_fieldsJSON 字段 - 所有自定义字段值合并为一个 JSON 对象
- 例如:
{"custom_field_001": "值1", "custom_field_002": 123}
规则 3:JSON 字段格式要求
- 必须是有效的 JSON 格式
- 键名为字段编码(field_code)
- 值类型根据 data_type 确定(字符串、数字、布尔值等)
9.3 数据查询规则
规则 1:系统字段直接读取
- 从
pro_report表对应列直接读取 - MyBatis-Plus 自动映射到实体类
规则 2:自定义字段从 JSON 解析
- 从
custom_fieldsJSON 字段解析 - 后端反序列化为 Map 或对象
- 前端合并系统字段和自定义字段数据
规则 3:字段配置动态加载
- 前端根据字段配置表动态渲染表单
- 系统字段和自定义字段统一处理
- 根据 field_type 判断数据来源
9.4 字段配置规则
规则 1:字段编码不可修改
- field_code 一旦创建不可修改
- 系统字段编码对应实体类字段名
- 自定义字段编码使用
custom_field_前缀
规则 2:字段名称可自定义
- field_name 可随时修改
- 支持重置为 default_field_name
规则 3:停用=隐藏
- is_enabled='N' 时,字段在表单中完全隐藏
- 停用的字段不参与表单验证
- 停用的字段不影响已保存的数据
规则 4:必填字段保护
- 核心必填字段(报工人、报工时间、报工数量等)不允许停用
- 前端和后端都需要校验
9.5 自定义字段管理规则
规则 1:新增自定义字段
- 在字段配置页面点击"新增字段"
- 选择所属类别(可选择系统类别或自定义类别)
- 配置字段名称、数据类型、控件类型
- 系统自动生成 field_code(custom_field_xxx)
规则 2:删除自定义字段
- 只能删除自定义字段(field_type=CUSTOM)
- 系统字段不可删除,只能停用
- 删除前需确认是否有数据使用该字段
规则 3:修改自定义字段
- 可修改字段名称、数据类型、控件类型
- 可修改字段所属类别(移动到其他类别)
- 修改数据类型可能导致已有数据格式不兼容
- 建议修改前备份数据
9.6 自定义类别管理规则
规则 1:新增自定义类别
- 在类别配置页面点击"新增类别"
- 输入类别名称
- 系统自动生成 category_code(F/G/H...)
- 新增的类别默认启用
规则 2:删除自定义类别
- 只能删除自定义类别(category_type=CUSTOM)
- 系统类别(A/B/C/D/E)不可删除,只能停用
- 删除前需确认该类别下没有字段
- 如果类别下有字段,需要先删除或移动字段
规则 3:修改自定义类别
- 可修改类别名称
- 可调整排序
- 系统类别名称可修改,但不可删除
规则 4:类别编码生成规则
- 系统类别:A/B/C/D/E(固定)
- 自定义类别:按字母顺序自动生成(F/G/H/I/J...)
- 如果字母用完,使用 AA/AB/AC...(26 个字母后)
9.7 类别显示与排序规则
规则 1:类别编号自动排序(默认行为)
- 前端显示时,只显示启用的类别
- 启用的类别按
sort_order排序后,自动重新编号为 A、B、C、D... - 例如:
- 配置:A(启用)、B(启用)、C(停用)、D(启用)、E(启用)
- 显示:A. 基础信息、B. 数量信息、C. 成本效益、D. 异常记录
- 实际对应:A→A、B→B、D→C、E→D
规则 2:自定义排序(用户手动调整)
- 用户可以通过拖拽或上下移动按钮调整类别顺序
- 调整后更新
sort_order字段 - 前端按照
sort_order排序显示 - 自定义排序后,仍然自动重新编号
规则 3:类别编号显示规则
- 前端显示格式:
{自动编号}. {类别名称} - 例如:
A. 基础信息、B. 数量信息 - 自动编号不存储在数据库,仅用于前端显示
- 数据库中的
category_code保持不变
规则 4:停用类别的处理
- 停用的类别在报工单表单中完全隐藏
- 停用的类别不参与自动编号
- 停用的类别在配置页面仍然显示(标记为停用状态)
示例说明:
| 数据库配置 | sort_order | is_enabled | 前端显示 |
|---|---|---|---|
| A-基础信息 | 1 | Y | A. 基础信息 |
| B-数量信息 | 2 | Y | B. 数量信息 |
| C-时间节拍 | 3 | N | (隐藏) |
| D-成本效益 | 4 | Y | C. 成本效益 |
| E-异常记录 | 5 | Y | D. 异常记录 |
| F-自定义类别 | 6 | Y | E. 自定义类别 |
十、注意事项
- 必填字段保护:报工人、报工时间、报工数量、合格数量等核心必填字段不允许停用
- 字段编码不可修改:field_code(字段编码)对应数据库字段名或自定义字段标识,不允许修改
- 类别编号自动排序:前端显示时,启用的类别自动重新编号为 A、B、C、D...,停用的类别不参与编号
- 类别编码固定:数据库中的 category_code 保持不变(A/B/C/D/E/F/G...),仅前端显示编号会自动调整
- JSON 字段性能:自定义字段存储在 JSON 中,查询性能较差,不建议在 WHERE 条件中使用
- 数据类型兼容:修改自定义字段的数据类型时,需要考虑已有数据的兼容性
- 配置缓存:前端可以缓存配置数据,避免每次打开表单都请求接口
- 配置变更通知:配置修改后,需要刷新页面才能生效(或使用 WebSocket 推送配置变更)
- 移动端适配:配置管理页面仅在 PC 端显示,移动端隐藏配置入口
- 历史数据兼容:已保存的报工单不受配置影响,配置仅影响新增/编辑时的表单显示
- 名称重置功能:支持将自定义的字段名称和类别名称重置为系统默认名称
- 自定义字段数量限制:建议每个类别的自定义字段不超过 20 个,避免表单过于复杂
- 删除类别前检查:删除自定义类别前,需确认该类别下没有字段
十、扩展规划
10.1 自定义字段(后续版本)
- 支持用户自定义新增字段
- 字段类型:文本、数字、日期、下拉、多选等
- 自定义字段存储在 JSON 字段中
10.2 多配置方案(后续版本)
- 支持不同车间/工位使用不同的配置方案
- 配置方案可以复制、导入、导出
10.3 字段联动(后续版本)
- 支持字段之间的显示/隐藏联动
- 支持字段值的计算联动