跳转至

视图设计器(View Designer)设计方案

视图设计器用于在模块中配置各类数据展示视图:设计态在 Vue3 设计器中配置基本信息、数据来源、列、操作与事件;运行态由 runtime 按 simpleClassName / 打开方式分发到具体展示组件。各类视图 共用同一设计器壳 View.vue,在「基本信息」中通过 intValue(即 viewType)区分类型,并按类型显示差异化字段与列映射。

层次 实现位置
后端 / Java cn.myapps.core.common.model.view.*(如 ListViewCalendarViewTreeViewMapViewGanttViewCollapsibleViewSheetView
视图设计器(壳) View.vueobpm-designer-vue3/src/components/Modules/View.vue
视图列表入口 ViewList.vue(同目录;新建 / 编辑跳转至设计器)
设计器子页 modulesDetail/ViewBasic.vueViewData.vueViewColumn.vueViewOperation.vueViewEvent.vue
类型选项 / 列映射 assets/js/config.jsoptions()calendarData / treeData / mapData / ganttData
设计态 API ViewApi.jsobpm-designer-vue3/src/service/ViewApi.js
前端运行时(PC) view_delegate.vuesimpleClassName 路由到各 view_* 组件(见下文各类型)

类型枚举定义于设计器 config.jsoptions();保存时以查询参数 viewType=parseInt(intValue) 提交后端。地图视图的专有设计细节另见 map-view.md


不同视图类型

设计器下拉选项与设计态/运行态对应关系如下。

intValue 名称 simpleClassName 设计器文案 key PC 运行时组件
1 列表视图 ListView config.list_view view_listviewopenType == 288 时为 view_gridview
16 日历视图 CalendarView config.cal_view view_calendarview
17 树形视图 TreeView config.tree_view view_treeview
18 地图视图 MapView config.map_view view_mapview
19 甘特视图 GanttView config.gantt_view view_gantt
20 折叠视图 CollapsibleView config.collapse_view view_collapsibleviewcollapsibleShowMode == 'card' 时为 view_cardview
21 Sheet 视图 SheetView config.sheet_view view_sheetview

路由分发见 obpm-runtime-web/.../view/view_delegate.vue 中按 simpleClassNameswitch

总览对比(设计态差异)

能力 列表(1) 日历(16) 树形(17) 地图(18) 甘特(19) 折叠(20) Sheet(21)
分页配置 保存时强制关闭 ✓(随通用规则)
只读开关
总记录数
水印脚本
列映射字段 mappingField
专有基本信息字段 手机端显示模式、网格操作列脚本 节点打开类型 innerType 地图插件 / 展示类型 / 卫星图;另有「默认中心」页签 显示模式 normal/card

说明:「—」表示该类型在 ViewBasic 中通过 show* 计算属性隐藏,或列弹窗不展示映射字段(列表、折叠不配 mappingField)。

列表视图(intValue = 1

表格 形式展示表单数据,是模块中最常用类型;支持列增删(删列不删底层数据)、单建/批量建列、查询表单与视图操作。

  • 设计态要点ViewBasic 新建默认类型;可配置 mobileDisplayModelist / card);openType == 288(网格)时可配 showActivityColumnType 及确认/移除脚本。
  • :普通字段列,无类型专属 mappingField
  • 运行时:常规打开 → view_listview;网格打开 → view_gridview(视图选择框场景会强制按列表展示)。

日历视图(intValue = 16

类似挂历/备忘录,按日期字段以日/周/月呈现数据。表单中须有日期控件。

  • 设计态要点:隐藏分页、只读、总记录数等列表类选项;列弹窗可勾选「是否在月视图中显示」(showMoon)。
  • 列映射mappingField = CldViewDateColum(日历过滤日期列,见 calendarData());绑定字段建议为日期类型。
  • 运行时view_calendarview

树形视图(intValue = 17

按父子关系以树形结构展示节点数据。

  • 设计态要点:配置节点点击打开类型 innerTypeFORM / VIEW / LINK(链接时需选节点链接);隐藏分页与只读。
  • 列映射treeData()):superior_Node(父节点)、current_Node(当前节点编号)、name_Node(当前节点名称)。一级节点可不填父级;父级不存在时节点不显示。
  • 运行时view_treeview

地图视图(intValue = 18

在地图上展示位置信息:地址地理编码打点,或读取 MapField 几何数据渲染。详见 map-view.md

  • 设计态要点mapType(如天地图)、mapDisplayType(点/线/面等)、isSateMap;壳上额外页签「地图默认中心」;数据页可选 mapDataSourceField;隐藏分页等。
  • 列映射mapData()):titlecolumnaddresscolumndetailcolumn(标题 / 详细地址 / 内容)。
  • 运行时view_mapview

甘特视图(intValue = 19

横轴为时间、纵轴为任务,用于查看计划区间与完成度。

  • 设计态要点:隐藏分页、水印等列表类选项。
  • 列映射ganttData()):name(任务名)、start / end(起止日期)、complete(完成度)、colorparent(任务 id / 父任务)等。
  • 运行时view_gantt

折叠视图(intValue = 20

按折叠分组展示数据明细,支持多级分类。第一列常作折叠路径,格式形如 AA\BB

  • 设计态要点collapsibleShowModenormal / card;壳保存时 强制 pagination = false;隐藏只读、水印;列弹窗 配置 mappingField
  • 运行时:普通 → view_collapsibleview;卡片模式 → view_cardview

Sheet 视图(intValue = 21

类 Excel 网格,支持单元格直接录入、从 Excel 复制粘贴,适合批量录入。

  • 设计态要点:需配置视图列,并建议配置 视图保存 类操作后方可落库;视图选择框类列通常需手动创建。
  • 运行时view_sheetview(录入时常需双击单元格)。

前端实现

设计时态

设计时态由 视图列表 + 视图详情壳 + 各页签子组件 组成。各视图类型共用入口与壳;在「基本信息」选择 intValue 后,由 ViewBasicshow* 计算属性及列弹窗条件渲染类型专有项(见上节)。

入口与路由

说明
列表页 路由 softwaresdetails/viewlistViewList.vue
设计器页 路由 softwaresdetails/ViewView.vue(组件名 viewDetail
新建 ViewList.addView()push/home/softwaresdetails/view,query 含 appIdmoduleId(无 viewId
编辑 点击列表行 → query 带上行数据,并设置 viewId: row.id
退出 View.close() → 回 viewlist,并 setCurrentDataSources({})

View 的入参来自 detailData prop,或 $route.querycreated 中赋值给 params)。存在 params.id 时标记 edit = true。另可经 Opener.vue 异步加载同组件嵌入打开。

壳组件结构(View.vue

顶部为 页签 + 工具栏,主区按页签切换挂载/显示子组件:

flowchart TB
  subgraph shell [View.vue]
    Tabs[el-tabs]
    Toolbar[保存 / 创建菜单 / 退出]
  end
  Tabs --> ViewBasic
  Tabs --> ViewData
  Tabs --> ViewColumn
  Tabs --> ViewOperation
  Tabs --> ViewMapDefaultCenter
  Tabs --> ViewEvent
  Toolbar --> Save[save: 合并 basic+data 提交]
  ViewBasic -->|viewModuleData| shell
  CreateMenu[CreateMenu] -.-> Toolbar
页签 name 文案 key 子组件 显示条件
basic view.basic ViewBasicv-show 始终
data view.data ViewDatav-show 始终
list view.list ViewColumnv-if 已有 params.viewId
operation view.operation ViewOperationv-if 已有 params.viewId
mapDefaultCenter view.map_default_center ViewMapDefaultCenter 当前数据源类型 intValue == 18(地图视图)
event view.event ViewEventv-if 始终(切换后挂载)

工具栏:

  • 创建菜单params.viewId 存在时):打开 CreateMenutype="view"
  • 保存:调用各子组件 save(),见下文「保存流程」。
  • 退出showLinkBack):返回视图列表。

页签切换时通过 tabSwitchover 控制显隐,并 dispatch('rightHelpPageParams') 更新右侧帮助页(如列页签对应 application_module_view_info_column_help.html)。

子组件职责

组件路径 职责
modulesDetail/ViewBasic.vue 名称、描述、视图类型、打开方式、权限、分页、只读、水印、样式库等;按 intValue 显示类型专有项(见「不同视图类型」)
modulesDetail/ViewData.vue 数据编辑模式(设计 / DQL / SQL / 存储过程)、关联表单、筛选条件、查询表单等;地图类型可选 mapDataSourceField
modulesDetail/ViewColumn.vue **视图列**列表:单建、批量创建、上下移、删除;弹窗 ViewColumnDialog 配置列字段、格式及类型映射字段
modulesDetail/ViewOperation.vue 视图操作(Activity)列表与 ViewOperationDialog
modulesDetail/ViewEvent.vue 视图事件列表与 ViewEventDialog
modulesDetail/ViewMapDefaultCenter.vue 仅地图视图:默认中心地址与缩放级别

视图类型选项定义于 src/assets/js/config.jsoptions()。列/操作页签依赖已有 viewId:新建一般为「基本信息 + 数据 → 保存 → 再配列与操作」。

保存流程

View.save() 仅汇总 基本信息 + 数据页(及地图默认中心,若类型为地图):

  1. this.$refs.viewbasic.save() → 校验失败则中止。
  2. this.$refs.viewData.save() → 校验失败则中止。
  3. 合并 payload;若 intValue == 20(折叠视图)则 pagination = false
  4. 请求参数:appId(sessionStorage)、moduleIdviewIdviewType = parseInt(basicData.intValue)
  5. viewIdsaveEditModuleView(PUT);无则 saveAddModuleView(POST),成功后把返回 id 写入 params.viewId,并 commit('setCurrentDataSources', …) 供列批量创建使用。

列、操作、事件各自在子组件内通过独立 API 增删改,**不经过**壳组件的「保存」按钮。

视图列设计

ViewColumn.vue + ViewColumnDialog.vue

  • 列表展示列名称,支持上移/下移(调用 updateColumnOrder)、删除(deleteColumnsView)。
  • 单个创建 / 编辑:弹窗配置列名、绑定表单字段、排序、可见性、格式(简单/数值/货币等)、脚本、跳转等;非列表/折叠类型可配 mappingField(日历/树/地图/甘特)。
  • 批量创建:按关联表单字段批量生成列(saveBatchColumnsView)。
  • 主要 API:getViewColumnssaveColumnsViewupdateColumnsViewgetViewColumnsData 等(均在 ViewApi.js)。

列定义在运行时决定表头、单元格取值与格式化;专有映射字段由各视图类型消费(如日历日期列、地图地址列)。

设计态 API 一览(ViewApi.js

用途 方法 HTTP
视图列表 getModuleViewList GET .../modules/views
视图详情 getModuleViewData GET .../modules/views/{viewId}
新建视图 saveAddModuleView POST .../modules/{moduleId}/views?viewType=
更新视图 saveEditModuleView PUT .../modules/{moduleId}/views/{viewId}?viewType=
列 CRUD / 排序 getViewColumnssaveColumnsViewupdateColumnsViewdeleteColumnsViewupdateColumnOrder
操作 CRUD / 排序 getViewActivityssaveActivitysViewupdateActivitysViewdelActivitysViewupdateActivityOrder
事件 getViewEventssaveEventView
复制 / 删除视图 copyViewdeleteModuleView
创建菜单 createViewMenu

路径前缀为设计态:/designer 代理下的 designtime/applications/{appId}/...(见 contextPath)。

状态协作

  • setCurrentDataSources:基本信息变更或新建成功后写入,供 ViewColumn 批量创建、类型联动(含列弹窗按 intValue 切换映射选项)等读取当前视图元数据。
  • rightHelpPageParams / rightHelpFrame:切换页签时刷新右侧帮助文档。
  • currentDataSourcesOption.intValue == 18:控制地图默认中心页签是否出现。

运行时态

运行时由 PC / 移动端 Vue3 按模板元数据分发展示组件,数据与权限由 obpm-runtime REST 提供;视图定义仍从 workspace XML 读取(与设计态同源),业务行数据经 EditMode 查询后转为视图行 items

入口与打开链路

flowchart LR
  MenuOrTab["菜单 / 页签 / Include / 视图选择框"]
  Container["obpm_open_container\nlinkType=VIEW(01)"]
  Delegate["view_delegate.vue"]
  TemplateAPI["GET .../views/{id}/template"]
  Child["view_* 组件"]
  DataAPI["POST .../views/{id}/documents"]

  MenuOrTab --> Container --> Delegate
  Delegate --> TemplateAPI --> Delegate
  Delegate -->|":is=viewType"| Child
  Child --> DataAPI
环节 路径
打开容器 obpm-runtime-web/.../main/obpm_open_container.vueLINK_TYPE.VIEW = '01'
视图代理 .../view/view_delegate.vue
前端 API .../api.jsgetViewTemplateAPIgetViewData / getViewDataAPIgetSearchFormTemplate
openType 常量 .../assets/js/common.jsVIEW_OPEN_TYPE
嵌入场景 包含元素 o_include.vue、视图选择框 o_view_dialog.vue、选项卡等可直接挂载 view_delegate

openParams 关键字段:appIdactionContent(viewId)、linkTypeparentId / isRelateexparamsurlParamsqueryString 等。init()actionContent 拉取 template,再驱动子组件 getData()

两阶段加载

  1. 模板(元数据)GET /views/{viewId}/template
    返回 simpleClassNameopenType、列、活动、分页配置、查询表单 id、类型专有属性等;后端对列执行 columnLabel / hiddenScript 等脚本,过滤不可见活动。
  2. 文档(行数据)POST /views/{viewId}/documents
    Query 含 _currpagelinessortColsortStatusparentId / isRelate 及类型扩展参数;Body 为查询表单字段 JSON。子组件据返回行渲染表格 / 树 / 地图等。

加载顺序:initinitView → template → 处理 columns/activities/分页 → 子组件 getData() → documents。

simpleClassName + openType 分发

view_delegateviewTypeNamesimpleClassName 选择组件;仅 ListView 再看 openType == 288(网格)。模板:<component :is="viewType" ...>

simpleClassName 附加条件 PC 组件
CollapsibleView collapsibleShowMode == 'card' view_cardview
CollapsibleView 默认 view_collapsibleview
CalendarView view_calendarview
TreeView view_treeview
MapView view_mapview
GanttView view_gantt
SheetView view_sheetview
ListView openType == 288 且非视图选择框 view_gridview
ListView 其它 / 视图选择框强制列表 view_listview
(未知) view_emptyview

后端 getSimpleClassName() = 具体视图类简名(如 ListView),与设计保存时 ViewDirector.construct(viewType) 实例一致。

打开方式 openType

主要控制 点击行打开文档的方式,以及 ListView 是否走网格;不参与日历/树/甘特等类型选择。

含义 Java(ViewConstant 十进制 前端(VIEW_OPEN_TYPE
当前页 OPEN_TYPE_NORMAL 1 CURRENTPAGE
弹出窗口 OPEN_TYPE_POP 16 (较少直接用)
父窗口区域 OPEN_TYPE_PARENT 256
网格 OPEN_TYPE_GRID 288 GRID
弹出层 OPEN_TYPE_DIV 277 DIALOG
新页签 OPEN_TYPE_PAGESIGN 293 TAB
新窗口 266 WINDOWOPEN(前端扩展)
抽屉↑ / → 244 / 255 DRAWER_*(前端扩展)

网格(288)要点:

  • ListView + 288 → view_gridview;视图选择框内强制改为列表并设 openType = 1
  • 网格下常隐藏顶部活动栏 / 查询区(showActBtnopenType != 288 判断)。
  • 非网格且非 Sheet 会去掉 type=34(保存)活动;网格保留行内编辑与保存能力。
  • view_gridview 内嵌字段编辑,子表常用 o-view-dialog + gridOpenType=288

打开文档时:view_delegate_open_page / 页签容器按 openType 走当前页、弹层、抽屉、页签或新窗口(isOverlayOpenType 判定弹层类)。

查询表单 / 列 / 活动 / 分页

能力 运行时行为
查询表单 searchFormIdGET .../searchformtemplate;UI 为 view_delegate_searchform_inline / _fullform_searchform。查询字段写入 documents Body;isQueryButton=true 记操作日志。树形搜索可走独立 tree search / 树组件回调。
Template 阶段算好标签与隐藏;前端再按 visible / hiddenColumn 过滤,并用 localStorage 缓存显隐、固定、宽度、排序。单元格由 view_listview_cell*.vue 按字段类型分支。行 items 由后端 manipulationDocumentDatas2ViewDatas 按列 getText 填充。
活动 Template 过滤 hidden/readonly;归档父单、只读时剔除创建/删除/导入等。顶部 activity + 折叠活动;Sheet / Gantt / 网格展示有差异。动作(创建、删除、批量提交、导入导出、跳转、打印等)多在 view_delegate.onAction
分页 视图属性 paginationpageLinesshowTotalRow。请求 _currpage + lines;未开分页时 listview 可能用较大 lines。地图 / 树等后端常一次取全量(lines 极大或不分页)。

类型专有查询参数示例:日历 startDate / endDate;树 treedocid / parentNodeId;折叠 parentParam

运行时 API 一览(PC)

Base:/runtime/api/runtime/{applicationId}(前端常写作 /runtime/{appId}/...)。

用途 Method Path 说明
视图模板 GET /views/{viewId}/template parentIdisRelateisReadonly
文档分页 POST /views/{viewId}/documents Query 分页/排序/父子;Body 查询条件
树节点数据 POST /treeviews/{viewId}/documents 树懒加载
查询表单模板 GET /views/{viewId}/searchformtemplate
树搜索 GET /views/{viewId}/tree/search keyword
列流程提交 POST /views/{viewId}/column/submit
可否打开 GET /views/{viewId}/openable 权限
网格行刷新 POST /views/{viewId}/documents/{docid}/refresh
筛选列候选 POST /views/{viewId}/filterColumns
选择框脚本 POST /views/selectbox/runViewDialogCallbackScript ViewHelperController

控制器:obpm-runtime/.../dynaform/view/controller/ViewController.javaViewHelperController.java

后端查询管线

flowchart TB
  VC[ViewController.doGetDocuments]
  VDS[ViewDesignTimeService.doView]
  SF[searchForm.createDocument]
  VT["view.getViewTypeImpl().getViewDatas"]
  EM[EditMode.getDataPackage]
  MD[manipulationDocumentDatas2ViewDatas]
  RESP[successWithPagination]

  VC --> VDS --> SF --> VT --> EM --> MD --> RESP
职责
AbstractView 及子类 列、活动、openTypesearchFormId、分页、editMode、权限等
ViewDirector viewType 构造具体视图类
EditMode(Design / DQL / SQL / Procedure) 按设计态数据模式查文档
AbstractType / *Type getViewDatas → EditMode;Map 等可重写(如禁分页)
ViewDesignTimeService* 读 workspace 视图 XML;行转换 manipulationDocumentDatas2ViewDatas
DocumentTree 树形节点数据

说明:运行时 没有 独立的 ViewRuntimeProcess 读定义;元数据仍走 DesignTimeService,业务数据走 DocumentProcess / EditMode。TreeView 在通用 documents 接口中可先按 ListView/Normal 取数;真正树节点用 /treeviews/...

设计态 vs 运行态对照

设计时态 运行时态
前端 obpm-designer-vue3View.vue + 页签 obpm-runtime-webview_delegate + view_*
API 前缀 /api/designtime/applications/... /api/runtime/{applicationId}/views/...
Controller designer ViewController runtime ViewController
持久化 workspace 视图 XML 同服务读定义;行数据在业务库
关注点 CRUD 视图/列/活动/事件、viewType template 脚本运算、查数、分页、打开文档
类型路由 保存 ?viewType= → Java 类 返回 simpleClassName + openType → 组件

移动端

路径 说明
H5 obpm-runtime-mobile-vue3/.../view_delegate.vue 同样 getViewTemplateAPI;Collapsible→列表;Calendar/Tree/Map/List;树节点可转 list;无完整 Sheet/Gantt/Grid
UniApp mobile/uniapp/ 原生壳侧视图相关能力

设计态 mobileDisplayMode(list/card)主要影响移动端列表展示;PC 折叠卡片用 collapsibleShowMode。后端另有 MOBILENORMALVIEW / MOBILETABLEVIEWViewConstant)供移动呈现模式使用。

各类型运行时组件(速查)

类型 PC 备注
列表 view_listview / view_gridview 网格见 openType 288
日历 view_calendarview 日期区间参数
树形 view_treeview /treeviews/... + 树搜索
地图 view_mapview 详见 map-view.md
甘特 view_gantt
折叠 view_collapsibleview / view_cardview collapsibleShowMode
Sheet view_sheetview 单元格编辑 / 保存活动

相关 UI 辅助:view_delegate_searchform_*.vueview_delegate_open_page.vueview_delegate_column_setting.vue

后端实现(Java)

设计时态

设计时态由 obpm-designer 暴露 REST,业务与模型在 obpm-core:视图 / 列 / 操作 / 事件以 独立 XML 文件 落在 workspace,经各自 *DesignTimeService + FileSystem*DAO 读写。与表单设计态同属「文件系统 XML + DesignTimeService」模式。

flowchart LR
  FE[设计器前端 ViewApi]
  VC[ViewController]
  VDS[ViewDesignTimeService]
  CDS[ColumnDesignTimeService]
  ADS[ActivityDesignTimeService]
  EDS[EventDesignTimeService]
  WS[(workspace XML)]

  FE --> VC
  VC --> VDS --> WS
  VC --> CDS --> WS
  VC --> ADS --> WS
  VC --> EDS --> WS
层次 路径
REST 入口 obpm-designer/.../designtime/view/controller/ViewController.java(Bean:designer-view-controller
辅助 .../view/controller/ViewHelper.java
View Service obpm-core/.../designtime/view/service/ViewDesignTimeService(.java\|Impl.java)
Column Service obpm-core/.../designtime/view/column/service/ColumnDesignTimeService*
Activity / Event ActivityDesignTimeService*EventDesignTimeService*(经 DesignTimeServiceManager
领域模型 obpm-core/.../common/model/view/AbstractView 及子类、Column
常量 .../common/model/view/constant/ViewConstant.java
选型工厂 .../common/model/view/dto/ViewDirector.java
XML 根映射 .../designtime/common/mapping/DesignTimeModelRootElementMapper.java
按视图建菜单 obpm-designer/.../menu/controller/MenuController.java

API 前缀${myapps.context-path.designer} 可配):

/api/designtime/applications

REST 一览

下表路径均相对上述前缀。

视图主体

Method Path 方法 说明
GET /{appId}/modules/{moduleId}/views doGetViewList 分页列表;searchwordfilterType(排除类型)、pageNolinesPerPage
GET /{appId}/modules/views/{viewId} doGetViewDetailed 详情
POST /{appId}/modules/{moduleId}/views?viewType= doCreateView 新建;viewType 决定反序列化类
PUT /{appId}/modules/{moduleId}/views/{viewId}?viewType= doUpdateView 更新;含列映射校验
DELETE /{appId}/modules/views doDeleteView 批量删除(Body:id 数组)
POST /{appId}/modules/views/copy doCopyViews 复制
POST /{appId}/modules/views?formId= doOneKeyCreateView 一键生成(委托 FormDesignTimeService.oneKeyCreateView

列 / 操作 / 事件

资源 主要 Path 说明
.../views/{viewId}/columns.../columns/{columnId}.../columns/batchPUT .../views/column/order CRUD、批量创建、排序(oId/nId 或 Body ids[]
操作 .../views/{viewId}/activitys.../activitys/{activityId} 路径拼写为 activitys;通用排序见 ActivityControllerPUT .../activity/order
事件 .../views/{viewId}/events.../events/{eventId} CRUD;删除 Body 为 id 数组

辅助 / 菜单

Method Path 说明
GET /{appId}/forms/{formId}/valuestorefields 可存值字段(含系统变量)
GET /{appId}/forms/{formId}/systemscreeningfields 系统筛选字段(ViewHelper
GET /getScopeByField/{authField} 权限字段作用域
POST /{appId}/view/{viewId}/menus 按视图创建菜单(MenuController,非 ViewController)

前端封装见上文「设计态 API 一览」(ViewApi.js)。

Service 与持久化

ViewDesignTimeService 继承 DesignTimeService<AbstractView>,DAO 为 FileSystemViewDAOpathSuffix / fileSuffix = "view")。

能力 说明
CRUD 继承 AbstractDesignTimeServicedoViewfindByIdsave / saveOrUpdate → JAXB 写 XML
重名 get_existViewByNameModule;创建/更新前 doSaveValidate
复制 doCopyViewViewDirector.construct(oldType) → 拷贝属性 → 新 ID/名称 → 再逐列、逐 Activity cloneBean 保存(不复制 Event
一键生成 表单侧:ViewDirector.construct(VIEW_TYPE_NORMAL) → 按字段建 Column + 默认新建/删除 Activity
运行复用 getDataPackagemanipulationDocumentDatas2ViewDatas 等亦被运行时调用

列 / 操作 / 事件各自独立 Service + FileSystem DAO;父子:parentId = viewIdAbstractView.getColumns() / getActivities() / getEvents() 经对应 Service 懒加载;Controller 列表前常 setXxx(null) 强制重载。

模型与 viewType

classDiagram
  AbstractView <|-- ListView
  AbstractView <|-- SheetView
  AbstractView <|-- CardView
  AbstractView <|-- MapView
  AbstractView <|-- TreeView
  AbstractView <|-- CalendarView
  AbstractView <|-- CollapsibleView
  AbstractView <|-- GanttView
  ListView --> NormalType : getViewTypeImpl
  MapView --> MapType
  TreeView --> TreeType
  CalendarView --> CalendarType
  CollapsibleView --> CollapsibleType
  GanttView --> GanttType
  SheetView --> SheetType
  CardView --> CardType
XML 根 Type 实现 ViewConstant(十进制)
ListView ListView NormalType VIEW_TYPE_NORMAL (1)
CalendarView CalendarView CalendarType VIEW_TYPE_CALENDAR (16)
TreeView TreeView TreeType VIEW_TYPE_TREE (17)
MapView MapView MapType VIEW_TYPE_MAP (18)
GanttView GanttView GanttType VIEW_TYPE_GANTT (19)
CollapsibleView CollapsibleView CollapsibleType VIEW_TYPE_COLLAPSIBLE (20)
SheetView SheetView SheetType VIEW_TYPE_SHEET (21)
CardView CardView CardType VIEW_TYPE_CARD (22)

AbstractView.getIntValue()getViewTypeImpl().intValue(),与设计器 intValue 一致。CardView 后端已支持,设计器下拉当前主推的是折叠卡片模式(collapsibleShowMode),未必单独建 Card 类型。

类型专有属性示例:TreeViewinnerType / nodeLinkId 等)、MapViewmapType / mapDisplayType / defaultCenterAddress 等,详见 map-view.md)、GanttView(无模型专有属性,列映射与运行时详见 gantt-view.md)、CardViewcardStyle)。

保存时选型(viewType

新建 / 更新:@RequestParam int viewType + Body JSON → switch(viewType)json2obj(json, XxxView.class)

NORMAL(1) → ListView | SHEET(21) → SheetView | CARD(22) → CardView
MAP(18) → MapView | TREE(17) → TreeView(+ prepareTreeLinkJson)
CALENDAR(16) → CalendarView | COLLAPSIBLE(20) → CollapsibleView | GANTT(19) → GanttView

随后写入 applicationidparentId=moduleId;(新建)分配设计时 ID → 重名校验 → viewService.save / saveOrUpdate

更新时 validate(view) 按已配 mappingField 的列数校验:

类型 最少 mappingField 列数
Tree ≥ 3(superior_Node / current_Node / name_Node
Calendar ≥ 1(CldViewDateColum
Gantt ≥ 4(name / start / end / complete
List / Map / Collapsible 不强制

读盘选型(与 query viewType 独立):DesignTimeModelRootElementMapper 按 XML 根元素名映射到具体类;历史根名 view 则读内部 viewTypeViewDirector.constructNormalViewListView

ViewDirector.construct(viewType) 用于复制、一键生成、升级与 JAXB 映射;设计器 REST 保存主路径是 query viewType + json2obj,不经 Builder.../dto/builder/*ViewBuilder 偏 DTO/预留。

Workspace 路径与根元素

URI 由父子 getPath() 拼接(AbstractViewparentPath + "/" + name + ".view"):

/{应用名}.application/module/{模块名}.module/{视图名}.view
/{应用名}.application/module/{模块名}.module/{视图名}.view/{列名}.column
/.../{视图名}.view/{操作名}.activity
/.../{视图名}.view/{事件名}.event

绝对路径:Environment.getWorkspaceRootPath() + uri。写入:JaxbUtils.convertToXml → 文件系统 → 设计时缓存。

资源 模型 文件后缀 XML 根(典型)
视图 AbstractView 子类 .view ListView / MapView / …
Column .column column
操作 Activity .activity activity
事件 Event .event event

视图元数据在 .view;列 / 操作 / 事件为 同目录下独立文件,不内嵌进视图 XML。

与运行时的关系

设计时态 运行时态
Controller designer ViewController runtime ViewController
基路径 /api/designtime/applications /api/runtime/{applicationId}
职责 CRUD 定义、列/操作/事件、复制、排序、一键生成、建菜单 template、查文档、权限、树展开等
模型 共用 AbstractView 子类、ColumnActivityEventViewConstant 同左
定义读写 DesignTimeService 读写 workspace **同样**经 viewDesignTimeService() **读**定义;业务数据走 EditMode / DocumentProcess

没有两套 View 模型:设计器改 XML,运行时读同一份定义做查询与展示。ViewDesignTimeServiceImpl 中多项转换/查询方法被运行时复用。

运行时态

状态:已实现
Controller:cn.myapps.runtime.dynaform.view.controller.ViewController
辅助:ViewHelperController
定义读取:ViewDesignTimeService(与设计态同源,只读 workspace XML)
查询:view.getViewTypeImpl().getViewDatasEditMode.getDataPackage
行转换:ViewDesignTimeService.manipulationDocumentDatas2ViewDatas
基础路径:/api/runtime/{applicationId}

运行时态 不单独持久化视图定义doView 读设计器写入的 .view / .column / .activity;业务行数据由 EditMode(设计 / DQL / SQL / 存储过程)查业务库,再按列 getText 组装为前端 items。前端协作见上文「前端实现 · 运行时态」。

类结构

classDiagram
    class ViewController {
        +doGetView() template
        +doGetDocuments()
        +doGetTreeDocuments()
        +doGetSearchFormTemplate()
        +filterColumns()
        +refreshDocument()
    }
    class ViewHelperController {
        +runViewDialogCallbackScript()
        +runColumnActionScript()
        +runDispatcherUrlScript()
    }
    class ViewDesignTimeService {
        +doView()
        +manipulationDocumentDatas2ViewDatas()
    }
    class ViewType {
        +getViewDatas()
    }
    class EditMode {
        +getDataPackage()
    }
    ViewController --> ViewDesignTimeService
    ViewController --> ViewType
    ViewType --> EditMode
    ViewController --> ViewDesignTimeService : 行转换
模块 职责
obpm-runtimeViewController HTTP:template、documents、树节点、查询表单、筛选列、行刷新、openable
obpm-runtimeViewHelperController 列动作脚本、跳转 URL 脚本、视图选择框回调/确认脚本、GPS 转换
obpm-coreViewDesignTimeService* 读视图 XML;manipulationDocumentDatas2ViewDatasDocument 转为视图行 Map
obpm-core*Type / EditMode 按视图类型与数据编辑模式查询 DataPackage<Document>
obpm-coreDocumentTree 树形解析父子节点

REST 一览

前缀:/api/runtime/{applicationId}ViewHelperController 部分路径无 {applicationId} 段,见下表)。

Method Path 方法 说明
GET /views/{viewId}/template doGetView 视图元数据:列(脚本后标签/隐藏)、活动(hidden/readonly)、openType、分页、类型专有属性;Excel 导入模板路径按用户加密
POST /views/{viewId}/documents doGetDocuments 分页文档 → 视图行;Query:_currpagelinessortColsortStatusparentId/isRelate、日历区间、折叠 parentParam 等;Body:查询表单字段
POST /treeviews/{viewId}/documents 树节点懒加载(treedocid / parentNodeId / 按名搜索)
GET /views/{viewId}/searchformtemplate 查询表单模板
GET /views/{viewId}/tree/search 树关键字搜索
POST /views/{viewId}/column/submit 列流程提交
GET /views/{viewId}/openable 是否允许打开(私有权限)
POST /views/{viewId}/documents/{docid}/refresh 网格等场景单行刷新
POST /views/{viewId}/filterColumns 列表筛选项候选值

ViewHelperController(前缀 /api/runtime):

Method Path 说明
POST /views/selectbox/runViewDialogCallbackScript 视图选择框回调脚本
POST /views/selectbox/runViewDialogConfirmScript 视图选择框确认脚本
PUT /{applicationId}/views/{viewId}/columns/{columnId}/runActionScript 列动作脚本
PUT /{applicationId}/views/{viewId}/columns/{columnId}/runDispatcherUrlScript 列跳转 URL 脚本
PUT /{applicationId}/views/{viewId}/columns/{columnId}/beforescript / afterscript 列前后脚本
GET /gps/convert GPS 坐标转换(地图等)

路径参数中的 applicationId / viewId / docId 等支持按登录用户 DES 加密传输,Controller 入口统一解密。

Template 组装(GET .../template

  1. viewDesignTimeService.doView 加载定义,BeanUtils.cloneBean 避免污染缓存实例。
  2. 若有 parentId,加载父文档初始化 IRunner(包含元素 / 关联视图上下文)。
  3. 活动:遍历 view.getActivities(),克隆后执行标签脚本、isHidden / isReadonly;父单归档、视图只读时剔除创建/删除/导入等写操作(前端亦可再判);导入 Excel 的 excelTemplate 加密后下发。
  4. :对每列跑 columnLabelhiddenScript 等,得到展示标签与可见性。
  5. 写入类型专有字段(如 Tree linkViewId、Map 地图属性等)后返回前端;simpleClassName 即具体 Java 类简名。

前端用该响应当作「视图模板」,再据此选 view_* 组件并请求 documents。

Documents 查询管线(POST .../documents

flowchart TB
  A[解密 appId/viewId/parentId]
  B[doView → AbstractView]
  C{私有权限?}
  D[组装 ParamsTable + searchDocument]
  E[排序 _sortCol / 默认排序]
  F{Map/Tree?}
  G["lines = MAX 或常规分页"]
  H["getViewTypeImpl().getViewDatas"]
  I[EditMode.getDataPackage]
  J[manipulationDocumentDatas2ViewDatas]
  K[successWithPagination]

  A --> B --> C -->|否/通过| D --> E --> F --> G --> H --> I --> J --> K
  C -->|拒绝| R[返回 false]
步骤 说明
权限 PERMISSION_TYPE_PRIVATEPermissionUtil.check(... FORM_VIEW_ALLOW_OPEN)
TreeView 特例 通用 documents 接口可先拷成 Normal 视图取扁平数据;真正树展开走 /treeviews/... + DocumentTree
查询表单 searchForm.createDocument(params, user),日期等字段按控件格式化后再写入 ParamsTable
排序 sortCol → 表单字段名 + sortStatus;否则 view.getDefaultOrderFieldArr()
全量类型 MapView(及部分场景)后端将 lines 设为 Integer.MAX_VALUE,一次返回全部点位数据
行结构 每行 Map:文档 id / 状态等元数据 + items[columnId]value / showValue / options / formField 等);库列 ITEM_ 前缀在 DAO 读入时已剥除,见下节
折叠 首列路径 AA\BBparentParam、cache 避免重复算文本;子节点探测后写入行

AbstractType.getViewDatasview.getEditModeType()DesignEditMode / DQLEditMode / SQLEditMode / ProcedureEditModegetDataPackage。各 *Type 可覆盖行为(如 Map 禁分页)。

行转换要点(manipulationDocumentDatas2ViewDatas

行为
列值 Column.getText(doc, params, runner, user) 填入 items
表单字段 解析 formField、选项 IOptions(缓存于 optionsMap
TreeView DocumentTree.parse 得到子节点信息并入结果
CollapsibleView 首列作折叠路径;查询按钮时可截断最后一级名称
非 Design 模式 行文档可带自身 Form,按文档表单解析字段

返回列表再经 Controller 包成分页结构(pageNolinesPerPagerowCountdatas)。

动态表命名约定(TLK_ / ITEM_ / 固定列)

视图关联表单后,业务数据落在动态表。命名由 DQLASTUtil 前缀 + TableMappingForm.getTableMapping()new TableMapping(form))统一生成:

约定 常量 形态 含义
内容表名 TBL_PREFIX = "TLK_" TLK_ + 表单名 普通表单业务数据表
日志表 LOG_PREFIX = "LOG_" LOG_ + 表单名 文档操作日志表(TABEL_TYPE_LOG
流程参数表 PARM_PREFIX = "PARM_" PARM_ + 表单名 FORM_TYPE_FLOW_PARAMETER
业务列 ITEM_FIELD_PREFIX = "ITEM_" ITEM_ + 字段名 可存值表单字段对应物理列
查询系统字段 SYSTEM_FIELDS 无前缀,如 AUTHOR 视图条件判定时不加 ITEM_
文档固定列 DOCUMENT_FIXED_COLUMNS 无前缀(含 SYSTEM_FIELDS + 扩展) 文档头列;不建业务 Item、不写 ITEM_xxx
flowchart TB
  Form[Form 关联表单]
  TM[TableMapping]
  TBL["表 TLK_表单名"]
  COL["业务列 ITEM_字段名"]
  FIX["固定列 AUTHOR / PREVAUDITNODE …"]
  EditMode[视图 EditMode SQL]
  DAO[AbstractDocStaticTblDAO]
  Resolve[resolveItemFieldName]
  Base[setBaseProperties]
  Items[Document.Item]
  DocProps[Document 头属性]

  Form --> TM
  TM --> TBL
  TM --> COL
  TBL --> FIX
  TBL --> EditMode --> DAO
  COL --> EditMode
  DAO --> Resolve
  Resolve -->|业务列| Items
  Resolve -.->|固定列跳过| Base --> DocProps
表名 TLK_ + 表单名

生成TableMapping 构造,普通/子表/首页/查询表单):

setTableName(DQLASTUtil.TBL_PREFIX + form.getName())  // → TLK_表单名

流程参数表用 PARM_ + form.getName();数据模型表单不在此分支拼 TLK_

读取 / 归一化

  • TableMapping.getTableName() / getTableName(tableType)DQLASTUtil.getItemTblName(...)(按类型处理;内容表保留已含 TLK_ 的名字并转大写;日志类型改为 LOG_ + 名)。
  • 注释里旧的「在 getItemTblName 内拼 TLK_」代码已注释掉;现行前缀由 TableMapping.setTableName 写入

谁使用

用途 位置
建表 / 改表 DDL ChangeLog.createTableByTypeform.getTableMapping().getTableName(tableType)
文档 CRUD / 视图查数 SQL AbstractDocStaticTblDAOtableMapping.getTableName()
视图 EditMode 经表单 TableMapping 拼 FROM / 条件

视图 Design 模式关联某表单时,查询目标表即为该表单的 TLK_表单名(再经 schema 拼全名,见 DQLASTUtil.getFullTableName)。

业务列与 ITEM_ 前缀

动态表业务字段物理列名为 ITEM_ + 字段名。视图取数链路:查库带前缀,内存 / API 不带前缀

阶段 是否带 ITEM_ 处理位置
库表列名映射 ITEM_字段名 TableMapping(普通表单字段 → 列名)
视图 SQL(条件 / 排序 / 筛选) 业务字段 ✓;系统字段 ✗ AbstractEditMode.addCondition / isSystemField
ResultSet → Document.Item 优先 ITEM_+字段,无则裸字段名 resolveItemFieldName / createItem
组装视图行给前端 ✗ 用字段名 / 列展示值 manipulationDocumentDatas2ViewDatas

生成列名(普通表单,FORM_TYPE_NORMAL 等):

  • TableMapping:可存值字段 → (ITEM_ + field.getName()).toUpperCase
  • getColumnName(fieldName):无显式映射时兜底仍拼 ITEM_ + 字段名(仅应用于业务字段名;勿对固定列名调用后当 Item)
  • AbstractView 取库列名失败时同样返回 ITEM_ + field
固定字段处理逻辑

动态表除 ITEM_* 业务列外,还有一批 文档头固定列(建表见 ChangeLog.getFixedColumns,插入/更新见 DAO 的 PARENT,LASTMODIFIED,…,PREVAUDITNODE,… 字面量)。它们与业务 Item 分离:

集合 定义位置 用途
SYSTEM_FIELDS DQLASTUtil 视图查询条件判定:命中则 SQL 不加 ITEM_AbstractEditMode.isSystemField / addCondition
DOCUMENT_FIXED_COLUMNS DQLASTUtil包含 SYSTEM_FIELDS + 扩展) 读/写文档:不作业务 Item;写库 shouldPersistItem 排除

SYSTEM_FIELDS(查询条件用)IDPARENTLASTMODIFIEDFORMNAMESTATEAUDITDATEAUTHORCREATEDFORMIDISTMPVERSIONSAPPLICATIONIDSTATEINTSTATELABELLASTFLOWOPERATIONAUDITORNAMESAUDITORLISTCOAUDITORLIST

DOCUMENT_FIXED_COLUMNS 额外包含AUDITUSERAUTHORDEPTIDAUTHOR_DEPT_INDEXAUTHOR_USER_INDEXSUBFORMIDSINITIATOROPTIONITEMSIGNLASTMODIFIERDOMAINIDSTATELABELINFOPREVAUDITNODEPREVAUDITUSERKINGGRIDSIGNATUREMAPPINGIDSECRETDOC_ID 等。

判定入口:DQLASTUtil.isDocumentFixedColumn(name)(忽略大小写;支持去掉 $ 前缀与误带的 ITEM_ 前缀后再比)。

flowchart TD
  Col[ResultSet 列标签]
  Col -->|ITEM_xxx| A{字段是固定列?}
  Col -->|裸名 xxx| B{存在 ITEM_xxx?}
  B -->|是| Skip1[跳过裸列优先 ITEM_]
  B -->|否| C{是固定列?}
  C -->|是| Skip2[setBaseProperties]
  C -->|否| D{表单可存值字段?}
  D -->|是| Item[建 Document.Item]
  D -->|否| Skip3[跳过]
  A -->|是| Skip2
  A -->|否| Item

读回resolveItemFieldName):

  1. 优先 ITEM_+字段名 → 映射或剥前缀得字段名;若剥前缀后仍是固定列(如误有 ITEM_PREVAUDITNODE)→ 不建 Item
  2. 裸列名且结果集同时有 ITEM_+同名 → 跳过裸列(优先 ITEM_)。
  3. 裸列名且为固定列 → 跳过(由 setBaseProperties 写入 Document 头属性)。
  4. 列映射命中且非固定列 → 用映射字段名。
  5. 回退裸字段名:仅当 form.findFieldByName 存在且 shouldStoreValue();**禁止**用 getColumnName(任意字符串) 兜底(对 PREVAUDITNODE 会拼出不存在的 ITEM_PREVAUDITNODE,导致 PUT 文档校验失败)。
  6. 无表单(自定义 SQL):非固定列裸名可作为业务字段。

写库shouldPersistItem):

  • isDocumentFixedColumn(item.getName())false,不写入 ITEM_xxx
  • 固定列仍走 setBaseParameters / setBaseProperties,物理列名为 PREVAUDITNODE 等( ITEM_)。

视图条件AbstractEditMode.addCondition):

  • $ 开头先去掉 $
  • isSystemField(查 SYSTEM_FIELDS)→ 条件列名直接用 AUTHOR 等;
  • 否则 → TableMapping.getColumnName / ITEM_+name。

返回前端:视图行 items 仅为业务列展示数据;固定列若需展示,通常来自文档元数据而非 ITEM_*

关联文件:

文件 作用
.../document/dql/DQLASTUtil.java TBL_PREFIX / ITEM_FIELD_PREFIX / SYSTEM_FIELDS / DOCUMENT_FIXED_COLUMNS / isDocumentFixedColumn
.../form/ejb/mapping/TableMapping.java TLK_ 表名 + ITEM_ 列映射
.../table/ddlutil/ChangeLog.java getFixedColumns 建表固定列;getTableName
.../document/dao/AbstractDocStaticTblDAO.java resolveItemFieldName / createItem / shouldPersistItem / setBaseProperties
.../model/view/editmode/AbstractEditMode.java isSystemField + 条件拼列名
.../model/view/AbstractView.java 排序/条件用库列名
.../view/service/ViewDesignTimeServiceImpl.java 行转换,业务列无 ITEM_ 前缀

类型与 Type 实现(运行侧)

simpleClassName Type 查询 / 数据侧差异(摘要)
ListView NormalType 标准分页;前端 list / grid
CalendarView CalendarType startDate / endDate 过滤
TreeView TreeType /treeviews + DocumentTree;通用接口可扁平化
MapView MapType 常全量;可补 mapDataItem(见 map-view.md
GanttView GanttType 任务区间列映射
CollapsibleView CollapsibleType 路径折叠、parentParam
SheetView SheetType 单元格编辑 + 行 refresh / 保存活动
CardView CardType 卡片渲染;设计器多用折叠 collapsibleShowMode=card

活动执行(创建/删除/导入导出 Excel/批量审批等)走 ActivityController 等,不在本 ViewController 内;视图仅提供 impmappingconfigid、选中文档 ID、查询条件等上下文。导出/导入详见 excel-import.md

与设计时态后端对照

设计时态 运行时态
obpm-designerdesigntime.view.controller obpm-runtimedynaform.view.controller
基路径 /api/designtime/applications /api/runtime/{applicationId}
写定义 save / update / 列·活动·事件 CRUD **不写**视图 XML
读定义 DesignTimeService viewDesignTimeService().doView
业务数据 EditMode + DocumentProcess
脚本时机 保存配置 template 组装时算列/活动;查行时 getText / 列动作脚本

没有两套 View 模型:设计器改 XML,运行时读同一份定义做 template 与查询;差异只在「是否写入」与「是否查业务库」。