跳转至

表单字段继承体系(FormField / ValueStoreField)

位置:obpm-core/.../runtime/dynaform/form/ejb/(73 个类)。本文讲**继承骨架与列生成机制**。基类体系见 [[entity-base-hierarchy]];.form 文件 Schema 见 [[../../workspace-mechanism/schemas/form-file]]。

1. 继承骨架

动态表单的 40+ 字段类型不靠类爆炸,而靠**一个抽象基类 + 能力接口(capability interface)组合**:

classDiagram
    class FormElement {
        <<interface>>
    }
    class FormField {
        <<abstract>>
        #String name
        #String fieldtype
        +getOrderdValue()
    }
    class ValueStoreField {
        <<interface>>
        +getFieldtype() String
    }
    class IOptionsField {
        <<interface>>
        选项类字段能力
    }
    class InputField
    class SelectField
    class DateField
    class RadioField
    class AttachmentUploadToDataBaseField
    class LabelField

    FormElement <|.. FormField
    FormField <|-- InputField
    FormField <|-- SelectField
    FormField <|-- DateField
    FormField <|-- LabelField
    FormField <|-- AttachmentUploadToDataBaseField
    ValueStoreField <|.. InputField
    ValueStoreField <|.. SelectField
    ValueStoreField <|.. DateField
    IOptionsField <|.. SelectField

核心角色

类/接口 职责
FormElement(接口) 表单内一切元素的统一契约
FormField(抽象基类) 全部字段的公共态:name(→ 动态表列名)、fieldtype(→ 列类型)、显隐/只读脚本引用、校验等。40+ 具体字段(InputField/SelectField/MapField/HTMLEditorField…)都直接继承它
ValueStoreField(接口) 能力标记:"本字段要落库"。动态表建表时只问 instanceof ValueStoreField——实现它 → 生成 ITEM_{NAME} 列;不实现(如 LabelField 纯展示、IncludeField 包含)→ 不建列
IOptionsField(接口) 选项类能力(Select/Radio/Checkbox),供视图筛选与联动取选项

这是典型的"继承管公共态、接口管能力"设计:字段的存储行为不放进继承树(否则 2^n 种组合爆炸),而由接口正交组合。

2. 列生成机制(字段 → TLK_ 列)

flowchart TD
    A[表单保存<br/>FormDesignTimeService] --> B[FormTableProcessBean<br/>createOrUpdateDynaTable]
    B --> C{遍历 fields<br/>instanceof ValueStoreField?}
    C -->|是| D["列名 = ITEM_ + name 大写<br/>($开头无前缀)"]
    C -->|否| E[跳过,不建列]
    D --> F[fieldtype → JDBC 类型<br/>VARCHAR/NUMBER/DATE/TEXT/BLOB]
    F --> G[ChangeLog 对比新旧结构]
    G --> H["SQLBuilder(按 dbType 选库方言)<br/>Mysql*/Oracle*/PostgreSQL*…"]
    H --> I[DDL 执行<br/>仅加列,不删列]

映射表单(type=65536)例外:列名由 mappingStr.columnMappings 指定,不走 ITEM_ 前缀。

3. 文档侧:Document / Item

字段定义"列",Document 承载"行":

classDiagram
    class ValueObject {
        实体基类(见基类篇)
    }
    class IDocument {
        <<interface>>
    }
    class AbstractDocument {
        <<abstract>>
    }
    class Document
    class Item {
        字段值容器:字段名→值
    }
    class Form {
        定义侧(DesignTimeSerializable 线)
    }
    ValueObject <|-- AbstractDocument
    IDocument <|.. AbstractDocument
    AbstractDocument <|-- Document
    Document "1" o-- "*" Item : items
    Form ..> Document : 定义与实例分离

读写分工:Document/Item 属 ValueObject 线(运行时数据),Form 属 DesignTimeSerializable 线(设计定义)。AbstractDocument(document/model/)持有 getFirstNodeList() 等流程联动方法——文档创建后即知流程首节点,是表单与工作流的桥接点。AbstractDocStaticTblDAO 把 Document+Items 拆行写入 TLK_ 表(机制见 [[dao-process-mechanism]])。