初始代码

This commit is contained in:
hhh
2026-04-02 10:38:23 +08:00
parent d8b4140f50
commit aed67ce1fd
1937 changed files with 447678 additions and 1 deletions

View File

@@ -0,0 +1,887 @@
# 报工单页面类别与字段控制设计文档
**版本:** v2.0.003
**日期:** 2026-03-05
**负责人:** 周启威
---
## 需求整理
### 原始需求
1. **报工单中分了 ABCDE 五类**,能否在新增/编辑的时候把五类中任一一类停用,然后写一个配置表、页面上一个按钮可以控制五个类别的停用与启用
2. **报工单中分了 ABCDE 五类**,在这五类中的字段命名/增删改查能不能也放入配置表,五类中的字段也需要控制与自定义,现在目前程序中现有的字段也需要控制与自定义了
3. **规则**:停用/启用 对应的是 隐藏/显示,只要是停用就隐藏该字段
4. **数据类型也需要自定义**,然后控件类型也需要自定义
5. **分类也可以自己增加并修改**,我新增的自定义字段应该可以指定进入任一分类中
6. **ABCDE 的话还是自动排吧**,比如我 C 停用了,应该 D→C, E→D默认是这样的但是也可以自定义
### 需求总结
#### 一、类别管理需求
1. **系统类别A/B/C/D/E**
- 可以停用/启用(停用=隐藏)
- 可以修改类别名称
- 不可删除
- 支持名称重置为默认值
2. **自定义类别F/G/H...**
- 可以新增自定义类别
- 可以修改类别名称
- 可以删除(删除前需确认该类别下无字段)
- 可以停用/启用
3. **类别排序**
- 支持手动调整排序(拖拽或上下移动)
- 前端显示时,启用的类别自动重新编号为 A、B、C、D...
- 例如C 停用后D 自动显示为 CE 自动显示为 D
#### 二、字段管理需求
1. **系统字段(现有字段)**
- 可以停用/启用(停用=隐藏)
- 可以修改显示名称(如"报工人"改为"操作员"
- 可以修改控件类型
- 不可删除
- 支持名称重置为默认值
2. **自定义字段(新增字段)**
- 可以新增自定义字段
- 可以配置字段名称、数据类型、控件类型
- 可以选择放入任一类别中(包括自定义类别)
- 可以移动到其他类别
- 可以删除
- 可以停用/启用
3. **字段配置项**
- 字段名称(可自定义)
- 数据类型STRING/NUMBER/DATE/DATETIME/BOOLEAN/SELECT
- 控件类型INPUT/NUMBER/DATE/DATETIME/SELECT/TEXTAREA/SWITCH
- 下拉选项SELECT 类型时配置)
- 是否必填
- 排序
#### 三、数据存储需求
1. **系统字段**:存储在 `pro_report` 表对应列中
2. **自定义字段**:存储在 `pro_report.custom_fields` JSON 字段中
#### 四、显示规则
1. **停用=隐藏**:停用的类别和字段在表单中完全隐藏
2. **启用=显示**:启用的类别和字段在表单中显示
3. **自动编号**:前端显示时,启用的类别自动重新编号为 A、B、C、D...
---
## 一、需求背景
报工单表单中分为五类A-基础信息、B-数量信息、C-时间节拍、D-成本效益、E-异常记录),需要实现:
1. **类别控制**
- 能够在配置中停用/启用任一类别,停用后该类别在新增/编辑时隐藏
- 支持新增自定义类别(如 F、G、H 等)
- 支持修改类别名称(如将"基础信息"改为"基本信息"
- 系统类别A/B/C/D/E不可删除只能停用自定义类别可删除
2. **字段控制**:五类中的字段能够单独控制停用/启用(隐藏/显示)
3. **字段自定义**
- 现有字段可以自定义显示名称(改名),例如将"报工人"改为"操作员"
- 支持新增自定义字段,可配置字段名称、数据类型、控件类型
- **新增自定义字段时可以选择放入任一类别中(包括自定义类别)**
- 自定义字段的值存储在 JSON 扩展字段中
4. **规则**:停用=隐藏,启用=显示
---
## 二、设计方案
### 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 类型)。
```sql
ALTER TABLE `pro_report` ADD COLUMN `custom_fields` json DEFAULT NULL COMMENT '自定义字段值JSON格式';
```
#### 2.3.2 存储格式
```json
{
"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 字段保存与读取规则
**保存报工单时**
1. **系统字段field_type=SYSTEM**
- 直接保存到 `pro_report` 表对应的列
- 例如:`reportUserId` 保存到 `report_user_id`
- 使用 MyBatis-Plus 自动映射
2. **自定义字段field_type=CUSTOM**
- 保存到 `pro_report.custom_fields` JSON 字段
- 例如:`custom_field_001` 保存为 `{"custom_field_001": "值"}`
- 后端需要将自定义字段值序列化为 JSON
**查询报工单时**
1. **系统字段**
- 直接从 `pro_report` 表对应列读取
- MyBatis-Plus 自动映射到实体类
2. **自定义字段**
-`pro_report.custom_fields` JSON 字段解析
- 后端需要将 JSON 反序列化为 Map 或对象
- 前端合并系统字段和自定义字段数据
**示例代码(后端保存)**
```java
// 保存报工单
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);
}
}
```
**示例代码(后端查询)**
```java
// 查询报工单
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;
}
```
**示例代码(前端保存)**
```javascript
// 提交报工单
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. 基础信息`**
**前端实现示例**
```javascript
// 加载类别配置
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 配置加载
```javascript
// 在 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 动态渲染类别
```vue
<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 动态渲染字段
```vue
<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 实体类
```java
// 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
```java
@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_fields` JSON 字段
- 所有自定义字段值合并为一个 JSON 对象
- 例如:`{"custom_field_001": "值1", "custom_field_002": 123}`
**规则 3JSON 字段格式要求**
- 必须是有效的 JSON 格式
- 键名为字段编码field_code
- 值类型根据 data_type 确定(字符串、数字、布尔值等)
### 9.3 数据查询规则
**规则 1系统字段直接读取**
-`pro_report` 表对应列直接读取
- MyBatis-Plus 自动映射到实体类
**规则 2自定义字段从 JSON 解析**
-`custom_fields` JSON 字段解析
- 后端反序列化为 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_codecustom_field_xxx
**规则 2删除自定义字段**
- 只能删除自定义字段field_type=CUSTOM
- 系统字段不可删除,只能停用
- 删除前需确认是否有数据使用该字段
**规则 3修改自定义字段**
- 可修改字段名称、数据类型、控件类型
- **可修改字段所属类别(移动到其他类别)**
- 修改数据类型可能导致已有数据格式不兼容
- 建议修改前备份数据
### 9.6 自定义类别管理规则
**规则 1新增自定义类别**
- 在类别配置页面点击"新增类别"
- 输入类别名称
- 系统自动生成 category_codeF/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. 自定义类别 |
## 十、注意事项
1. **必填字段保护**:报工人、报工时间、报工数量、合格数量等核心必填字段不允许停用
2. **字段编码不可修改**field_code字段编码对应数据库字段名或自定义字段标识不允许修改
3. **类别编号自动排序**:前端显示时,启用的类别自动重新编号为 A、B、C、D...,停用的类别不参与编号
4. **类别编码固定**:数据库中的 category_code 保持不变A/B/C/D/E/F/G...),仅前端显示编号会自动调整
5. **JSON 字段性能**:自定义字段存储在 JSON 中,查询性能较差,不建议在 WHERE 条件中使用
6. **数据类型兼容**:修改自定义字段的数据类型时,需要考虑已有数据的兼容性
7. **配置缓存**:前端可以缓存配置数据,避免每次打开表单都请求接口
8. **配置变更通知**:配置修改后,需要刷新页面才能生效(或使用 WebSocket 推送配置变更)
9. **移动端适配**:配置管理页面仅在 PC 端显示,移动端隐藏配置入口
10. **历史数据兼容**:已保存的报工单不受配置影响,配置仅影响新增/编辑时的表单显示
11. **名称重置功能**:支持将自定义的字段名称和类别名称重置为系统默认名称
12. **自定义字段数量限制**:建议每个类别的自定义字段不超过 20 个,避免表单过于复杂
13. **删除类别前检查**:删除自定义类别前,需确认该类别下没有字段
---
## 十、扩展规划
### 10.1 自定义字段(后续版本)
- 支持用户自定义新增字段
- 字段类型:文本、数字、日期、下拉、多选等
- 自定义字段存储在 JSON 字段中
### 10.2 多配置方案(后续版本)
- 支持不同车间/工位使用不同的配置方案
- 配置方案可以复制、导入、导出
### 10.3 字段联动(后续版本)
- 支持字段之间的显示/隐藏联动
- 支持字段值的计算联动