这套做法里,业务开发者只写 TypeScript 子类,页面由固定的解析页面渲染。14 种页面模式覆盖列表、树表、向导、大屏等常见场景。
面向模式的高代码开发
摘要 :本文阐述驰骋 BPM/CCFlow 体系中「面向模式的编程」(Pattern-Oriented Development)方法论。该方法将前端页面抽象为若干可复用的页面模式 ,每种模式由基类 定义规则、由子类 实现业务、由解析页面 (Vue 组件)统一渲染,形成「定义---实现---解析」的铁三角架构。与将业务规则存入数据库、由运行时解析的低代码模式相对,高代码模式以 TypeScript 类文件作为业务载体,借助 ORM 思想实现规则的定义与持久化。本文结合
Vue3/src真实代码,逐一说明 14 种页面模式的作用范围、应用场景与实现要点。
第一章 高代码与低代码
1.1 低代码开发模式
低代码模式指通过拖拉拽设计器生成应用行为的方式。在驰骋平台中,典型入口包括:实体设计、大屏设计、视图设计、表单设计器等。
核心特征:
| 维度 | 说明 |
|---|---|
| 规则载体 | 数据库表(如 Sys_MapAttr、Sys_MapData、菜单配置表等) |
| 实现路径 | 梳理规则 → 定义规则 → 存储规则 → 解析规则 |
| 页面生成 | 设计器将元数据写入库表,前端通用解析器读取元数据动态渲染 |
| 数据库依赖 | 高度依赖------字段、布局、查询条件、权限等均落库 |
低代码适合标准化、配置驱动的场景:快速搭建 CRUD、调整字段可见性、切换列表样式等,无需重新编译前端。
1.2 高代码开发模式
高代码模式指通过 TypeScript 类文件 描述页面操作行为与展现效果的工作方式。业务规则的载体是代码文件;规则的「定义」与「解析」通过面向对象的 ORM 体系完成------实体类 EnMap 描述数据结构,页面基类描述交互行为,解析页面读取基类/子类状态后渲染 UI。
核心特征:
| 维度 | 说明 |
|---|---|
| 规则载体 | .ts 源文件(持久化在代码仓库 / 编译产物中) |
| 实现路径 | 梳理规则 → 定义规则 → 解析规则(无独立的「存储到库表」环节) |
| 页面生成 | 子类继承基类,重写 Init() 等方法;解析页面反射加载子类并绑定 UI |
| 灵活性 | 可编写任意业务逻辑、复杂算法、外部 API 集成 |
1.3 两种模式的对比
scss
低代码: 业务元数据 ──写入──▶ 数据库 ──读取──▶ 通用解析器 ──▶ 页面
高代码: 子类 .ts 文件 ──继承──▶ 基类 ──加载──▶ 解析页面(.vue) ──▶ 页面
二者并非对立,而是在同一平台内互补:低代码负责「可配置的标准能力」,高代码负责「不可配置或高度定制的能力」。驰骋 BPM 的主体功能(流程、表单、组织、单据)大量采用高代码模式实现,低代码设计器则用于元数据维护与快速原型。
第二章 基本理念
2.1 定义
面向模式的编程 (亦称高代码开发 )是:利用代码描述页面操作行为与展现效果的工作方式。开发者不直接编写 .vue 页面,而是编写继承自模式基类的 TypeScript 子类;由少量固定的解析页面读取子类配置,完成 UI 渲染与事件分发。
2.2 抽象:13+1 种页面模式
系统将常见应用场景抽象为 14 种页面模式(用户材料中列举 13 种核心模式 + Panel 等扩展)。每种模式对应:
- 1 个基类 (
PageBase*/Entity/DataVBase/TabsBase) - N 个子类 (
GL_*、GPN_*、TreeEns_*、GPE_*、PG_*及实体类等) - 1 个(或少数几个)解析页面 (
GenerList.vue、En.vue、Search.vue等)
| 序号 | 模式标识 | 中文名称 | 基类 | 解析页面 | 子类命名惯例 |
|---|---|---|---|---|---|
| 1 | GenerList | 通用列表 | PageBaseGenerList |
GenerList.vue |
GL_* |
| 2 | TreeEns | 左树右表 | PageBaseTreeEns |
TreeEns.vue |
TreeEns_* |
| 3 | GPN | 新建(分步/分组) | PageBaseGroupNew |
GroupPageNew.vue |
GPN_* |
| 4 | GPE | 枚举/分组编辑 | PageBaseGroupEdit |
GroupPageEdit.vue |
GPE_* |
| 5 | Entity | 实体编辑 | Entity |
En.vue / EnOnly |
MapAttr*、Student 等 |
| 6 | Search | 查询 | Entity + EnCfg |
Search.vue |
同实体类 |
| 7 | Ens | 批量编辑 | Entities |
Ens.vue |
同实体类 |
| 8 | Group | 分组分析 | Entity + 分组配置 |
SearchGroup 组件 |
同实体类 |
| 9 | DtlSearch | 从表查询 | Entity(从表) |
DtlSearch.vue |
同实体类 |
| 10 | DtlBatch | 从表批量编辑 | Entity(从表) |
DtlBatch.vue |
同实体类 |
| 11 | Tabs | 标签页容器 | TabsBase |
Tabs.vue |
Tabs_* |
| 12 | DataV | 大屏 | DataVBase |
views/data_visualization |
DataV_* |
| 13 | Panel | Icon 列表 | GenerList(BigIcon 等) |
GenerList.vue |
低代码列表入口 |
| 14 | PanelGroup | 分组编辑面板 | PageBasePanelGroup |
PanelGroup.vue |
PG_* |
说明 :Search、Ens、Group、DtlSearch、DtlBatch 与 Entity 共用同一实体类 ;差异体现在
EnCfg组件展现配置及打开的解析页面不同。这是 ORM 思想在前端的典型体现------一份实体定义,多种视图模式。
2.3 设计思路
把后端面向对象的编程思想搬到前端:
- 基类 :封装页面骨架、公共属性、抽象方法(如
Init()、BtnClick()) - 子类:只写与本业务相关的列定义、数据源、按钮响应
- 继承与封装:子类不可绕过基类契约,保证「千人一面」
- 多态 :解析页面通过
ClassID工厂加载不同子类,同一解析器呈现不同业务
2.4 技术储备
学习该模式之前,需要深刻理解:
- 面向对象:基类、子类、继承、封装、多态
- TypeScript 类与抽象类
- 驰骋 ORM:
Entity、Map、Entities、EnMap属性定义 - 异步数据:
Retrieve、Insert、Update、HttpHandler
2.5 页面模式的定义
页面模式 :具有相同布局 与相同操作行为的页面,归为一种模式。
例如:待办列表与已办列表布局一致(工具栏 + 表格 + 行按钮),仅数据源不同 → 同属 GenerList 模式;流程属性编辑与节点属性编辑都是「左侧分组 + 右侧表单项」→ 同属 GPE 或 Entity 模式。
第三章 设计图:铁三角
面向模式开发的核心架构是 基类 --- 子类 --- 解析页面 构成的铁三角:
各环节职责与流向对照:
| 流向 | 内容 |
|---|---|
| 子类 → 基类 | 继承模式契约(Init、BtnClick 等抽象方法) |
| 子类 → 解析页面 | ClassFactory 按 ClassID 动态加载子类实例 |
| 基类 → 解析页面 | 属性契约:Columns / Data / SubPages |
| 解析页面 → 界面 | 读取 Init 结果渲染统一风格 UI |
| 界面 → 子类 | 用户操作回调 BtnClick / LinkFieldClick |
三者职责:
| 角色 | 职责 | 是否随业务增长 |
|---|---|---|
| 基类 | 定义模式契约、公共属性、抽象方法 | 极少变动 |
| 子类 | 业务规则:列、数据、按钮、校验 | 每个功能一个文件 |
| 解析页面 | 布局、组件库、路由、弹窗框架 | 极少变动;技术升级主要改这里 |
铁三角的价值:业务逻辑(子类)与展现技术(解析页面)分离。升级 Vue 版本、替换 UI 组件库时,只需改造解析层,数千个子类文件无需重写。
代码锚点------工厂加载子类(以通用列表为例):
typescript
// WF/GenerList/ClassFactoryOfGenerList.ts(概念示意)
export class ClassFactoryOfGenerList {
public static GetEn(classID: string): PageBaseGenerList {
// 根据 classID 动态 import 对应 GL_* 子类
}
}
解析页面 GenerList.vue 在 InitPage 时调用工厂,获得子类实例,再读取其 Columns、Data、PageTitle 等属性绑定到表格。
第四章 驰骋低代码平台模式数据
驰骋 BPM / CCFlow 前端 Vue3/src 中,各模式子类文件数量(统计口径:仓库内 *_*.ts 文件,含 Demo/App 扩展):
| # | 模式 | 名称 | 基类 | 子类数量(约) | 典型应用 |
|---|---|---|---|---|---|
| 1 | GenerList | 通用列表 | PageBaseGenerList |
122 | 发起、待办、在途、抄送、已完成、近期 |
| 2 | TreeEns | 左树右表 | PageBaseTreeEns |
21 | 组织结构、流程树、表单树、数据源管理 |
| 3 | GPN | 新建 | PageBaseGroupNew |
161 | 新建流程、表单、人员、菜单、条件 |
| 4 | GPE | 枚举/分组编辑 | PageBaseGroupEdit |
121 | 接收人规则、发起规则、考核规则、超时规则 |
| 5 | Entity | 实体 | Entity |
500+ | 流程属性、节点属性、字段属性、业务实体 |
| 6 | Search | 查询 | 同 Entity | 同实体 | 流程查询、待办查询、单据查询 |
| 7 | Ens | 批量编辑 | 同 Entity | 同实体 | 批量修改、导入前编辑 |
| 8 | Group | 分组分析 | 同 Entity | 同实体 | 按维度汇总、分组报表 |
| 9 | DtlSearch | 从表查询 | 同 Entity | 同实体 | 从表数据浏览 |
| 10 | DtlBatch | 从表批量编辑 | 同 Entity | 同实体 | 从表行内编辑、批量维护 |
| 11 | Tabs | 标签页 | TabsBase |
2 | 人员/岗位/岗位类型维护 |
| 12 | DataV | 大屏 | DataVBase |
8 | 管理员主页、人员主页、单流程统计 |
| 13 | Panel | Icon 列表 | GenerList 展示模式 | 1 | 低代码实体列表(BigIcon) |
| 14 | PanelGroup | 分组编辑 | PageBasePanelGroup |
6 | 菜单模块、表单分类、流程分类 |
数据说明:GPN/GL/GPE 数量为文件名匹配统计;Entity 为
extends Entity的类文件,涵盖流程、表单、单据、Demo 等全域实体。数字随版本迭代变化,量级可说明「模式化开发已规模化落地」。
第五章 各模式详解
本章按模式逐一说明:模式描述 、作用范围 、应用场景 、基类与解析页面 、代码示例。
5.1 模式一:GenerList(通用列表)
模式描述
GenerList 是驰骋平台使用最广泛的列表模式。子类在 Init() 中定义列(Columns)、加载数据(Data)、配置工具栏与行按钮;解析页面 GenerList.vue 负责表格/分组/窗口/图表等多种展示形态。
作用范围
- 不需要左侧树的纯列表页
- 支持表格、大图标、分组图标、窗口卡片、饼图/柱图/折线图等展示
- 支持关键字、日期范围、外键条件下拉、列头筛选
应用场景
| 场景 | 子类示例 |
|---|---|
| 待办工作 | GL_Todolist |
| 在途流程 | GL_Runing |
| 抄送 | GL_CC |
| 已完成 | GL_Complete |
| 近期发起 | GL_Start / GL_RecentStart |
| 单据待办 | GL_BillTodolist |
基类关键 API
typescript
// bp/UIEntity/PageBaseGenerList.ts
export abstract class PageBaseGenerList {
public PageTitle: string | null = '待办';
public Columns: Array<Record<string, any>> = [];
public Data: Array<Record<string, any>> = [];
public HisGLShowModel = GenerListPageShowModel.Table; // 展示模式
public LinkField = 'Title'; // 链接列
public BtnOfToolbar = ''; // 工具栏按钮
public BtnsOfRow = ''; // 行按钮
abstract Init();
abstract LinkFieldClick(object: Record<string, any>, linkField?: string);
abstract BtnClick(btnName: string, record: Record<string, any>, ids?: string);
}
子类示例:待办列表
typescript
// WF/GenerList/GL_Todolist.ts
export class GL_Todolist extends PageBaseGenerList {
constructor() {
super('GL_Todolist');
this.PageTitle = '待办';
}
async Init() {
this.DTFieldOfSearch = 'RDT';
this.LinkField = 'Title';
this.GroupFields = 'NodeName,FlowName,StarterName';
this.PageSize = 15;
this.HisGLShowModel = GenerListPageShowModel.Table;
this.Columns = [
{ Key: 'Title', Name: '标题', IsShow: true, width: 350 },
{ Key: 'StarterName', Name: '发起人', IsShow: true, width: 100 },
{ Key: 'RDT', Name: '发起日期', IsShow: true, DataType: DataType.AppDateTime },
{ Key: 'NodeName', Name: '停留节点', IsShow: true, enableSearch: true },
// ...
];
const handler = new HttpHandler('BP.WF.HttpHandler.WF');
handler.AddUrlData();
const data = await handler.DoMethodReturnJson('Todolist_Init');
this.Data = data;
}
LinkFieldClick(record) {
// 打开 MyFlow 处理页
}
BtnClick(btnName, record, ids) {
// 批处理、删除等
}
}
解析页面
WF/views/GenerList.vue:读取子类 Columns/Data,渲染 Ant Design Vue / Naive UI 表格,处理分页、导出、打印、密度切换。
5.2 模式二:TreeEns(左树右表)
模式描述
左侧树形导航 + 右侧明细列表的经典布局。树节点与明细通过 RefKey 关联;支持懒加载、拖拽排序、右键菜单、节点增删改。
作用范围
- 层级结构 + 明细数据联动
- 组织、分类、目录类业务
- 右侧可为表格、Search、GenerList 或纯实体列表
应用场景
| 场景 | 子类示例 |
|---|---|
| 组织人员 | TreeEns_Dept2Emp |
| 流程分类 | TreeEns_FlowSort2Flow |
| 表单分类 | TreeEns_FrmSort2Frm |
| 数据源 | TreeEns_DBSrc |
| 网盘目录 | TreeEns_DirectoryTree2FileDtl |
基类关键 API
typescript
// bp/UIEntity/PageBaseTreeEns.ts
export abstract class PageBaseTreeEns {
public TreeEns?: EntitiesNoName; // 树实体集合
public DtlEns?: EntitiesNoName; // 右侧明细集合
public RefKey: string | null = 'FK_Dept';
public RootNo = '0';
public IsLazy = false;
public Columns: Array<Record<string, any>> = [];
abstract BtnClick(btnLab, treeNodeID, itemIDs, treeNodeOrgNo, record);
async GetDataByTreeNodeID(treeNodeID: string) { /* 按树节点过滤明细 */ }
}
子类示例:组织结构
typescript
// WF/Admin/Organization/TreeEns_Dept2Emp.ts
export class TreeEns_Dept2Emp extends PageBaseTreeEns {
constructor() {
super('TreeEns_Dept2Emp');
this.PageTitle = '组织结构';
}
override async Init(rootNo = '0') {
this.IsLazy = true;
const trees = new Depts();
await trees.Retrieve('ParentNo', rootNo, 'Idx');
this.TreeEns = trees;
this.DtlEns = new Emps();
this.RefKey = 'FK_Dept';
this.Columns = [
{ id: 'Name', name: '名称', IsShow: true, Width: 300 },
{ id: 'StationName', name: '岗位名称', IsShow: true },
// ...
];
}
BtnClick(btnLab, treeNodeID, itemIDs, treeNodeOrgNo, record) {
// 新建人员、批量删除、角色维护等
}
}
5.3 模式三:GPN(Group Page New,新建)
模式描述
GPN 用于分步新建 、分组向导 场景。开发者在 Init() 中调用 AddGroup、TextBox1_Name、SelectItemsByList、FileUpload 等声明式 API 描述表单项;解析页面 GroupPageNew.vue 渲染分步表单并收集参数,最终调用子类 Save() 完成持久化。
作用范围
- 新建实体前的信息采集(一步或多步)
- 需要分组展示、图标、帮助文档的创建向导
- 支持返回
GPNReturnObj打开抽屉、跳转 URL、关闭弹窗等
应用场景
| 场景 | 子类示例 |
|---|---|
| 新建流程 | GPN_NewFlow |
| 新建表单 | GPN_NewFrm |
| 新建人员 | GPN_Emp |
| 新建菜单 | GPN_Menu |
| 新建条件 | GPN_Cond |
基类关键 API
typescript
// bp/UIEntity/PageBaseGroupNew.ts
export abstract class PageBaseGroupNew {
public SubPages: Pages;
public Groups: Groups;
abstract Init();
abstract Save(pageID, sortNo, ...tbValues): Promise<GPNReturnObj>;
public AddGroup(no: string, name: string) { /* 增加分组 */ }
public TextBox1_Name(pageNo, name, help, label, defaultVal) { /* 单文本框 */ }
public SelectItemsByGroupList(pageNo, name, help, multi, groupSrc, itemSrc) { /* 分组列表选择 */ }
}
子类示例:新建流程
typescript
// WF/Admin/FlowLogic/GPN_NewFlow.ts
export class GPN_NewFlow extends PageBaseGroupNew {
constructor() {
super('GPN_NewFlow');
this.PageTitle = '新建流程';
}
public async Init() {
this.AddGroup('A', '内置表单模式');
this.TextBox1_Name('JiJian', '极简模式', GPN_NewFlow.JiJian, '流程名称', '我的极简流程');
this.AddIcon('icon-paper-plane', 'JiJian');
this.AddGroup('B', '绑定表单模式');
this.TextBox1_Name('RefOneFrmTree', '绑定单表单', GPN_NewFlow.RefFrm, '流程名称', '我的单表单流程');
this.SelectItemsByGroupList('RefOneFrmTree.SelectOneFrm', '选择表单', ...);
this.AddGroup('D', '使用高代码');
this.TextBox1_Name('EntityTS', '绑定高代码', this.EntityTS, '流程名称', '我的高代码流程');
}
// Save() 中根据 pageID 创建不同模式的流程
}
5.4 模式四:GPE(Group Page Edit,枚举/分组编辑)
模式描述
GPE 用于编辑某一实体上的枚举字段 或一组相关配置项 。左侧分组导航 + 右侧单选/下拉/表格/自定义组件;每次修改往往直接写回实体字段(如节点的 DeliveryWay)。
作用范围
- 一个字段多种取值,且每种取值对应不同子配置页
- 流程节点规则、表单扩展、字段行为配置
- 支持
SingleEnumRadioButon、SingleEnumDDL、SelfComponent等编辑模型
应用场景
| 场景 | 子类示例 |
|---|---|
| 接收人规则 | GPE_AccepterRole |
| 超时处理 | GPE_OvertimeRole |
| 抄送规则 | GPE_CCRole |
| 字段弹窗 | GPE_Pop |
| 发起限制 | 各 GPE_* 节点/流程规则类 |
子类示例:接收人规则
typescript
// WF/Admin/AttrNode/AccepterRole/GPE_AccepterRole.ts
export class GPE_AccepterRole extends PageBaseGroupEdit {
constructor() {
super('GPE_AccepterRole');
this.PageTitle = '接收人规则';
}
async Init() {
this.entity = new Node();
this.KeyOfEn = NodeAttr.DeliveryWay; // 绑定枚举字段
this.AddGroup('A', '按组织结构绑定');
this.SingleEnumRadioButon('ByStation', '按角色智能计算', 'DeliveryWay', help, 'DeliveryWay', '@0=...');
// 每种规则对应不同子页面与保存逻辑
}
}
5.5 模式五:Entity(实体编辑)
模式描述
Entity 是 ORM 的核心。每个业务对象对应一个实体类,在 EnMap 中声明表名、字段、分组、外键、附件、从表等;解析页面 En.vue 根据 EnMap 自动生成表单,并挂载「相关功能」菜单(Search、GPN、GPE、GL 等)。
作用范围
- 单条记录的增删改查
- 属性页、配置页、主数据维护
- 实体可嵌套从表、附件、关联查询
应用场景
| 场景 | 子类示例 |
|---|---|
| 文本字段属性 | MapAttrString |
| 数值字段属性 | MapAttrNum |
| 流程定义 | FlowExt |
| 节点定义 | NodeExt |
| 业务主数据 | Student、Emp |
子类示例:学生实体
typescript
// App/Demo/Student.ts
export class Student extends EntityNoName {
constructor(pkval?: string) {
super('TS.Demo.Student');
if (!!pkval) this.setPKVal(pkval);
}
public override get EnMap() {
const map = new Map('Demo_Student', '学生');
map.AddGroupAttr('基本字段');
map.AddTBStringPK('No', null, '编号', true, true, 4, 4, 80);
map.AddTBString('Name', null, '名称', true, false, 0, 200, 80);
map.AddDDLSysEnum('ZZMM', 0, '政治面貌', true, true, 'ZZMM', '@0=少先队员@1=团员@2=党员');
map.AddDDLEntities('BanJiNo', null, '班级', new BanJi(), true);
// 相关功能:查询、新建、报表等通过 RefMethod 挂载
return map;
}
}
解析页面
WF/Comm/En.vue:加载实体 → 渲染 EnOnly 表单 → 左侧「相关功能」树 → 内嵌打开 GPE/GPN/GL/Search 等子页面。
5.6 模式六:Search(查询)
模式描述
Search 与 Entity 共用实体类 ,通过 EnCfg(组件展现设置)配置查询列、条件、焦点字段、工具栏按钮等。解析页面 Search.vue 读取实体 EnMap + EnCfg,渲染查询工具栏与结果表格。
作用范围
- 主数据列表查询
- 多条件组合、日期段、数值区间、Pop 弹窗选值
- 点击焦点字段打开
En.vue详情
应用场景
流程查询、学生查询、单据查询、历史数据检索等------凡是以「条件筛选 + 列表展示」为主的页面。
实现要点
typescript
// bp/sys/EnCfg.ts --- 组件展现设置(节选)
export class EnCfg extends EntityNoName {
public override get EnMap() {
const map = new Map('Sys_EnCfg', '组件展现设置');
map.AddTBStringPK('No', null, '实体名称', true, true, 1, 100, 60);
map.AddBoolean('IsEnableFocusField', false, '是否启用焦点字段?', true, true);
map.AddTBString('FocusField', null, '焦点字段', true, false, 0, 30, 60);
// 查询列、排序、按钮等配置...
return map;
}
}
访问方式:GloComm.UrlSearch(enName, paras) → Search.vue?EnName=TS.Demo.Student&...
5.7 模式七:Ens(批量编辑)
模式描述
对实体集合进行表格内批量编辑 :可编辑列、拖拽排序、批量保存、导入导出。共用实体类,解析页面为 Ens.vue。
作用范围
- 需要同时修改多行字段
- 维护类从表、排序类数据
- 与 Search 互补:Search 偏浏览,Ens 偏编辑
应用场景
批量修改状态、批量调整序号、简易数据维护屏。
5.8 模式八:Group(分组分析)
模式描述
在 Search 基础上按指定维度分组汇总 展示,解析组件为 SearchGroup(嵌入 SearchBill.vue 或 Search.vue 的 displayMode === 'group')。
作用范围
- 分组统计、分类汇总
- 按部门/类型/状态聚合列表
应用场景
单据按状态分组、学生按班级分组、报表式分组浏览。
5.9 模式九:DtlSearch(从表查询)
模式描述
专用于从表 (明细表)的查询浏览,解析页面 WF/Comm/Dtl/DtlSearch.vue。从表实体同样在 EnMap 中定义,通过主表 PK 过滤。
作用范围
- 主从结构中的「从」侧只读或轻量浏览
- 从表字段较多、需独立开窗查询
应用场景
订单明细、简历明细、流程子表数据查询。
5.10 模式十:DtlBatch(从表批量编辑)
模式描述
从表的行内编辑 与批量维护,解析页面 WF/Comm/Dtl/DtlBatch.vue。支持可编辑列定义、拖拽排序、批量删除。
作用范围
- 从表需要频繁增删改
- 明细行数多、表单内嵌展示空间不足
应用场景
学生成绩明细、费用明细、从表批量录入。
5.11 模式十一:Tabs(标签页)
模式描述
TabsBase 子类在 Init() 中通过 AddSearch、AddGL、AddSelfUrl 注册多个标签;解析页面统一渲染 Tab 栏,每个 Tab 内嵌已有模式页面。
作用范围
- 同一业务对象多种视图并列
- 减少菜单项、聚合相关功能
应用场景
typescript
// WF/Admin/Tabs_FlowApp.ts
export class Tabs_FlowApp extends TabsBase {
constructor() {
super('Tabs_FlowApp');
this.PageTitle = '流程应用';
}
override Init() {
this.AddSearch('学生女', 'icon-drop', 'TS.Demo.Student', '&XB=0');
this.AddSearch('学生男', 'icon-drop', 'TS.Demo.Student', '&XB=1');
this.AddGL('待办', 'icon-drop', 'GL_Todolist', '&FlowNo=001');
}
}
人员/岗位/岗位类型维护等综合管理页。
5.12 模式十二:DataV(大屏)
模式描述
DataVBase 子类在 Init() 中通过 AddChartPie、AddChartZZT、AddHtmlDtls、Self_TodolistAdmin 等方法组装大屏区块;解析页面 views/data_visualization/index.vue 按网格布局渲染图表与自定义组件。
作用范围
- 管理驾驶舱、个人主页
- 统计图表、指标卡片、流程动态
应用场景
typescript
// WF/Admin/DataV_HomeAdmin.ts
export class DataV_HomeAdmin extends DataVBase {
constructor() {
super('DataV_HomeAdmin');
this.PageTitle = 'Admin统计';
}
override async Init() {
this.Self_Know();
this.Self_MovementFlowAdmin();
this.Self_TodolistAdmin();
this.Self_RuningAdmin();
this.AddHtmlDtls({
title: '平台数据',
icon: 'icon-settings',
colSpan: 4,
children: [
{ icon: 'icon-organization', title: '支持组织结构', docs: '单组织、集团、SAAS' },
// ...
],
});
}
}
管理员主页、人员主页、单流程数据统计(DataV_OneFlowAdmin / DataV_OneFlowEmp)。
5.13 模式十三:Panel(Icon 列表)
模式描述
Panel 并非独立基类,而是 GenerList 的 Icon 展示模式 (GenerListPageShowModel.BigIcon / GroupBigIcon),或低代码实体在设计器中配置的「列表入口」。系统列表、应用入口等以大图标卡片呈现。
作用范围
- 应用门户、功能导航
- 低代码配置的实体列表面板
应用场景
低代码实体列表、「我的系统」类大图标入口(HisGLShowModel = GenerListPageShowModel.BigIcon)。
5.14 模式十四:PanelGroup(分组编辑面板)
模式描述
分组 + 明细分组面板 编辑模式。左侧(或顶部)为分组列表,组内为明细项;支持分组/明细拖拽排序、组内新建、Icon 点击事件。基类 PageBasePanelGroup,解析页面 PanelGroup.vue。
作用范围
- 两级结构:分类 + 项
- 菜单模块、方法分组等「先选组、再管项」场景
- 支持 Table 与 Icon 两种列表模式(
ListModel)
应用场景
typescript
// CCFast/GPM/PG_Module2Menu.ts
export class PG_Module2Menu extends PageBasePanelGroup {
constructor() {
super('PG_Module2Menu');
this.PageTitle = '模块/菜单';
this.HisListModel = ListModel.Table;
}
public async Init() {
this.BtnsTop = '新建模块';
this.BtnsEnGroup = '新建模块,新建菜单,权限';
this.GroupsEns = await new Modules().Retrieve('SystemNo', this.PKVal, 'Idx');
this.DtlEns = await new Menus().Retrieve('SystemNo', this.PKVal, 'Idx');
this.RefKey = MenuAttr.ModuleNo;
this.IsGroupMove = true;
this.IsEnMove = true;
}
}
菜单/模块管理(PG_Module2Menu)、流程分类(PG_FlowSort2Flow)、表单分类(PG_FrmSort2Frm)。
第六章 模式协作与实体相关功能
实体 EnMap 可通过 RefMethod 挂载其他模式,形成以实体为中心的功能网络:
typescript
// bp/en/Map/RefMethod.ts(概念)
// 实体属性页可挂载:
// - RefMethodType.GroupPageNew → GPN
// - RefMethodType.GroupPageEdit → GPE
// - RefMethodType.GenerList → GL
// - RefMethodType.PanelGroup → PG
// - Search / Ens / Tabs / DataV ...
En.vue 根据 RefMethodType 分发到对应解析组件------这是铁三角在组合维度的延伸:实体是 hub,各模式是 spoke。
URL 统一入口 (WF/Comm/GloComm.ts):
typescript
GloComm.UrlGenerList(classID, paras); // 通用列表
GloComm.UrlGPN(classID, pkval, paras); // 新建
GloComm.UrlSearch(enName, paras); // 查询
// 以及 En、TreeEns、DataV 等
第七章 实施的成功标准
驰骋团队在实践中将以下三条作为高代码模式落地的验收标准:
标准一:基本全栈模式化开发
业务功能优先通过 14 种模式子类实现,而非从零编写页面。前端、后端均遵循 Entity/Handler 体系,形成可复制的开发流水线。
标准二:一般不开发 .vue 页面
新业务默认只写 TypeScript 子类 (GL_*、GPN_*、实体类等)。.vue 文件限定在「解析层」与极少数特殊交互;避免业务逻辑散落在 Vue 单文件组件中。
标准三:不需要美工、测试人力显著下降
- 不需要美工:解析页面统一视觉与交互,子类不涉及 CSS 布局
- 测试人员减少约 70%:同一模式行为一致,回归测试可针对解析层;子类主要验证业务数据与按钮逻辑
第八章 优点
8.1 风格统一
所有 GenerList 待办、已办、在途页面共用 GenerList.vue,工具栏位置、表格密度、导出打印交互完全一致。统一解析 → 统一风格 → 统一操作习惯 → 培训成本极低。
8.2 代码规范
基类对子类形成强制性约束:
- 必须实现
Init()、BtnClick()等抽象方法 - 列定义必须遵循
Columns结构 - 工厂按
ClassID注册,避免「野生页面」
实施人员、二开人员代码结构一致,实现千人一面。
8.3 容易升级
前端技术演进时:
vbnet
升级前:GenerList.vue + 122 个 GL_*.ts
升级后:GenerList.vue'(新组件库)+ 122 个 GL_*.ts(无需修改)
业务逻辑与展现技术解耦,使平台可跟进 Vue、UI 库、构建工具的版本更新,而不牵一发而动全身。
8.4 可度量、可治理
模式文件数量可统计(见第四章),代码评审可针对「是否选错模式」「是否在子类写 UI」等明确规则,利于大型团队治理。
第九章 开发实践建议
9.1 如何选择模式
| 需求特征 | 推荐模式 |
|---|---|
| 纯列表、工作台 | GenerList |
| 树 + 列表联动 | TreeEns |
| 向导式新建 | GPN |
| 枚举/规则配置 | GPE |
| 单条表单编辑 | Entity |
| 条件查询 + 列表 | Search |
| 批量改多行 | Ens |
| 分组汇总 | Group |
| 从表明细 | DtlSearch / DtlBatch |
| 多 Tab 聚合 | Tabs |
| 驾驶舱 | DataV |
| 分类 + 项维护 | PanelGroup |
9.2 子类开发最小步骤(以 GenerList 为例)
- 在
WF/GenerList/或业务目录新建GL_MyFeature.ts extends PageBaseGenerList,super('GL_MyFeature')- 实现
Init():配置Columns、请求数据填充Data - 实现
LinkFieldClick、BtnClick - 在
ClassFactoryOfGenerList注册类名 - 菜单或
RefMethod配置 URL:GenerList.vue?EnName=GL_MyFeature
9.3 与低代码的配合
- 实体字段、表单布局:低代码设计器维护
EnMap元数据 - 复杂列表、特殊新建流程:高代码
GL_*/GPN_*扩展 EnCfg桥接两者:低代码配置 Search 列,高代码实体提供数据源
第十章 结论
面向模式的高代码开发,本质是将前端页面开发从「手工 UI 编程」转变为「选模式 → 写子类 → 由解析器呈现」的工业化流程。铁三角(基类、子类、解析页面)保证了:
- 业务可表达:TypeScript 全能力,无低代码表达力天花板
- 体验可统一:解析层集中管控 UI/UX
- 演进可持续:技术升级与业务扩展解耦
驰骋 BPM 在 Vue3/src 中以 500+ 实体、120+ GL、160+ GPN、120+ GPE 的规模验证了该方法论。对于企业级 BPM、单据、组织权限等复杂系统,面向模式的高代码开发是一条可复制、可治理、可度量的工程化路径。
附录 A:基类与解析页面路径速查
| 模式 | 基类路径 | 解析页面路径 |
|---|---|---|
| GenerList | bp/UIEntity/PageBaseGenerList.ts |
WF/views/GenerList.vue |
| TreeEns | bp/UIEntity/PageBaseTreeEns.ts |
WF/Comm/TreeEns.vue |
| GPN | bp/UIEntity/PageBaseGroupNew.ts |
WF/Comm/UIEntity/GroupPageNew.vue |
| GPE | bp/UIEntity/PageBaseGroupEdit.ts |
WF/Comm/UIEntity/GroupPageEdit.vue |
| Entity | bp/en/Entity.ts |
WF/Comm/En.vue |
| Search | Entity + bp/sys/EnCfg.ts |
WF/Comm/Search.vue |
| Ens | bp/en/Entities.ts |
WF/Comm/Ens.vue |
| DtlSearch | Entity | WF/Comm/Dtl/DtlSearch.vue |
| DtlBatch | Entity | WF/Comm/Dtl/DtlBatch.vue |
| Tabs | bp/UIEntity/TabsBase.ts |
WF/Comm/Tabs.vue |
| DataV | bp/UIEntity/DataVBase.ts |
views/data_visualization/index.vue |
| PanelGroup | bp/UIEntity/PageBasePanelGroup.ts |
WF/Comm/PanelGroup.vue |
附录 B:子类文件命名规范
| 前缀 | 模式 | 示例 |
|---|---|---|
GL_ |
GenerList | GL_Todolist |
TreeEns_ |
左树右表 | TreeEns_Dept2Emp |
GPN_ |
新建 | GPN_NewFlow |
GPE_ |
分组编辑 | GPE_AccepterRole |
PG_ |
PanelGroup | PG_Module2Menu |
DataV_ |
大屏 | DataV_HomeAdmin |
Tabs_ |
标签页 | Tabs_FlowApp |
TS.* / 业务名 |
Entity | TS.Demo.Student |