## 什么是明细 在实际的业务开发场景当中,我们把诸如`请假单`、`采购订单`、`销售订单`、`会计凭证`之类的业务数据,统一用`原子`的概念进行管理。同时,这些业务单据还往往会包含一些`明细`条目,CabloyJS采用`明细`的概念进行管理 ## 明细的特点 对于`明细`的管理,并不仅仅是简单的`CRUD`操作,同时还具备以下特点: 1. 一个`原子类型`可以关联多个`明细类型` 2. `明细` `CRUD`等指令的权限与`原子`的权限协同 3. 与`原子`一样支持`草稿、正式、历史`的生命周期 4. 支持在审批工作流中控制对`明细`的`CRUD`权限 5. 支持常规指令:`上移`、`下移`、`克隆` 6. 支持`Mobile/PC自适应`:默认情况下,在Mobile中显示`列表`,在PC中显示`表格` ## 业务模块模版:module-business-details 如果要开发一个带明细功能的业务模块,建议使用业务模块模版`module-business-details`创建业务模块的文件骨架。此模版会自动创建与业务相关的代码,大量简化工作量 ``` bash $ cd /path/to/project $ npm run cli :create:module moduleName -- [--template=] [--suite=] [--force] ``` 目前提供了三个`模块文件模版`: | 名称 | 说明 | |----|----| | module-business | 此模版会创建与业务相关的代码,大量简化工作量 | | module-business-details | 在`module-business`的基础上增加了与`明细`业务相关的代码文件 | | module | 此模版仅包含基本的骨架代码文件 | ## 模块依赖 由于明细特性是由模块`a-detail`提供的。因此,需要在业务模块中指定模块的依赖项 `src/module/test-flow/package.json` ``` javascript { "name": "egg-born-module-test-flow", "title": "test-flow", "eggBornModule": { "fileVersion": 2, "dependencies": { "a-instance": "4.0.0", "a-base": "4.0.0", "a-detail": "4.0.0", "a-flow": "4.0.0" } }, ... } ``` ## 统一存储 所有明细数据的基本信息都统一存储到数据表`aDetail`中,与业务相关的字段存储在`业务明细表`中,如模块`test-flow`中实现的采购订单明细业务表:`testFlowPurchaseOrderDetail`。`aDetail`与`业务表`是一对一的关系 这种存储机制体现了`共性`与`个性`的有机统一,有如下好处: 1. 可统一配置`数据权限` 2. 可统一支持`增删改查`等操作 3. 可统一支持`草稿\正式\历史`数据生命周期 4. 可统一支持`审批工作流` ### `aDetail`核心字段清单 | 名称 | 类型 | 缺省值 | 说明 | |----|----|----|----| | id | int | 自动增量 | 关键字段,其他表中引用此字段,名字一般为`detailId` | | createdAt | timestamp | CURRENT_TIMESTAMP | 原子创建时间 | | updatedAt | timestamp | CURRENT_TIMESTAMP | 原子修改时间 | | deleted | int | 0 | 软删除标记 | | iid | int | 0 | 实例id | | atomId | int | 0 | 对应的主表条目Id | | atomStage | int | 0 | 原子阶段,0:草稿 1:正式 2:历史 | | detailItemId | int | 0 | 对应的明细业务表Id | | detailClassId | int | 0 | 对应的明细类型 | | detailCodeId | int | 0 | 对应的明细代码Id | | detailCode | int | 0 | 对应的明细代码 | | detailName | varchar | NULL | 明细标题 | | detailLineNo | int | 0 | 行号 | | detailStatic | int | 0 | 是否为静态数据 | | detailStaticKey | varchar | NULL | 明细Key | | userIdCreated | int | 0 | 创建原子的用户 | | userIdUpdated | int | 0 | 修改原子的用户 | ## 明细类型 `明细类型`是明细对应的元数据信息,在模块的`meta`中设置,如模块`test-flow`中明细类型`default`的元数据信息如下: `src/module/test-flow/backend/src/meta.js` ``` javascript const meta = { detail: { details: { default: { info: { bean: 'purchaseOrder', title: 'Details', tableName: 'testFlowPurchaseOrderDetail', }, actions: { }, validator: 'purchaseOrderDetail', }, }, }, }; ``` * info | 名称 | 说明 | |----|----| | bean | 明细类型对应的Bean组件,用于`增删改查`等指令操作 | | title | 明细类型的标题 | | tableName | 明细类型对应的业务数据表名称 | * actions:定义自定义指令 * validator:指定验证器 该验证器有两个用途: 1. 在前端自动渲染明细表单 2. 在后端对提交的明细表单进行验证 ## 原子类型与明细类型的关联 接下来,需要在`原子类型`中关联`明细类型`,从而建立`主数据`与`明细数据`的对应关系 `src/module/test-flow/backend/src/meta.js` ``` javascript const meta = { base: { atoms: { purchaseOrder: { info: { bean: 'purchaseOrder', title: 'Purchase Order', tableName: 'testFlowPurchaseOrder', details: [ 'default' ], }, actions: { }, validator: 'purchaseOrder', search: { validator: 'purchaseOrderSearch', }, }, }, }, }; ``` * details: \[ ‘default’ \] 由于一个`原子类型`可以关联多个`明细类型`,因此,这里采用数组格式 ## 明细演示 ### 1. PC场景 ![details-pc-zhcn](https://portal.cabloy.com/api/a/file/file/download/f7dd61f5088a4496941b61a7e3af8e52.gif) ### 2. Mobile场景 ![details-mobile-zhcn](https://portal.cabloy.com/api/a/file/file/download/c1206e9ea683405eacfc53dc463a1a4a.gif)