跳转至

动态表单字段

动态表单字段是 OBPM 表单系统的核心构成单元。一个字段在后端(Java)与前端(PC,Vue 3)各有实现,二者通过**表单模板 JSON** 协同:

  • 后端定义字段的存储类型、脚本钩子、权限模型,并输出包含 <o-xxx> 标签的表单模板 HTML;
  • 前端将 <o-xxx> 标签渲染为可交互控件,绑定字段值、处理刷新与校验。

本文档分为两部分:后端实现(Java)前端实现(PC)

后端实现(Java)

描述动态表单中的各种字段类型,包含 InputField、SelectField、CheckboxField 等。所有字段位于 obpm-core/src/main/java/cn/myapps/core/runtime/dynaform/form/ejb/,继承自 FormElement

平台共提供 39 个可实例化字段类,按功能分为:文本、选项、日期/编号、上传、用户/组织、布局/容器、业务集成、多媒体/特殊。

核心机制

类继承层次

FormElement(接口)
└── FormField(抽象基类,提供公共属性/脚本/权限)
    ├── ValueStoreField(标记接口)
    │   ├── 文本/选项/日期/编号/上传等(存值 → TLK_ 表 ITEM_ 列)
    │   └── AbstractUploadField(上传抽象基类)
    │       ├── AttachmentUploadField / ImageUploadField / KmsDataField
    │       └── ...
    └── 纯 UI 字段(不存值)
        ├── TabField / SplitField / ButtonField / ...
        └── ...

ValueStoreField:存值的分水岭

public interface ValueStoreField {
    public String getFieldtype();
}

实现 ValueStoreField 的字段会持久化值到 TLK_<表单名> 表的 ITEM_<字段名>;不实现的就是纯 UI、布局、动作或展示字段。

FormField.shouldStoreValue() 的判定:this instanceof ValueStoreField && !onlyCalculate

getTagName() 与 HTML 标签

getTagName() 默认实现返回类简单名(ObjectUtil.getSimpleName(getClass())):

// FormField.java
public String getTagName() {
    return ObjectUtil.getSimpleName(getClass());
}

只有 3 个字段重写了它: - InputField / NoField —— 当 fieldtype=VALUE_TYPE_NUMBER 时返回 "NumberField" - TextareaField —— 固定返回 "TextAreaField"(注意 A 大写,类名是 TextareaField

注意getTagName()(前端 _fieldType 用)和 toHtmlTemplate() 输出的 <o-xxx> 标签是**两套独立命名**,例如 DateField.getTagName() 返回 DateField,但 HTML 是 <o-date-picker>

值类型(fieldtype)

字段的存储类型由 fieldtype 属性决定,影响动态表列的数据类型。常见取值(定义在 Item 接口):

常量 说明 典型字段
VALUE_TYPE_VARCHAR 字符串 InputField、SelectField、UserField
VALUE_TYPE_NUMBER 数值 InputField(数字模式)、NoField(数字模式)
VALUE_TYPE_DATE 日期 DateField
VALUE_TYPE_TEXT 长文本 TextareaField、HTMLEditorField、附件 JSON
VALUE_TYPE_BLOB 二进制 AttachmentUploadToDataBaseField(已废弃)
VALUE_TYPE_INCLUDE 包含视图标记 IncludeField(不存值)

FormField 公共属性

所有字段共享以下属性,子类只在此基础上添加特有配置:

标识类

属性 类型 说明
id String 字段唯一标识(UUID)
name String 字段名(决定 TLK_ 表的列名:ITEM_ + name 大写)
alias String 字段别名
discript String 描述说明
orderno int 排序号
seq int 次序号
formid String 所属表单 ID
attributeId String 属性 ID

类型类

属性 类型 说明
fieldtype String 字段值类型(VALUE_TYPE_VARCHAR/NUMBER/DATE/TEXT/BLOB/INCLUDE),决定动态表列的数据类型
textType String 文本框展现类型:text(普通)/ password(密码)/ readonly(只读)/ hidden(隐藏)
type String 字段控件类型标记

脚本钩子

均通过 GraalVM JavaScript 引擎执行。脚本中可用 $CURRDOC(当前文档)、$WEBUSER(当前用户)等内置变量。

属性 返回值 执行时机 用途
valueScript 任意值(String/Number/Date 等) 表单加载、字段刷新(recalculate)、保存前 值计算脚本。计算结果通过 applyValueScriptResult 写入文档 Item,决定字段显示值。支持两种模式:脚本模式直接执行 valueScript;设计模式(editMode=1)按 processDescription 拼接算术表达式
hiddenScript boolean 渲染时(getDisplayType第一优先级 隐藏脚本。返回 true 时字段完全隐藏(PermissionType.HIDDEN)。优先级最高,隐藏后字段不可见也不可编辑
readonlyScript boolean 渲染时(getDisplayType第三优先级 只读脚本。返回 true 时字段只读(PermissionType.READONLY)。在隐藏、禁用判断之后执行
hiddenPrintScript boolean 打印时(getPrintDisplayType 打印隐藏脚本。返回 true 时打印不显示该字段,并将 printValue 标记为 HIDDENPRINTVALUE
validateRule String(非空表示失败) 表单提交前校验 校验脚本。返回非空字符串视为校验失败,字符串内容作为错误提示展示给用户;返回空或 null 表示通过
validateLibs String 校验时 校验依赖库(引入的公共校验函数库)
hiddenValue String 字段被隐藏时 当字段因 hiddenScripttextType=hidden 隐藏时,显示此静态值(HTML 解码后)
printHiddenValue String 打印隐藏时 打印时字段被隐藏,显示此替代值

显示类型优先级getDisplayType 方法):HIDDEN(最高)→ DISABLED(文档不可编辑时)→ READONLY → MODIFY(可编辑)。 ButtonField 是唯一豁免 DISABLED 的字段——按钮不受文档编辑状态限制。

行为类

属性 类型 说明
refreshOnChanged boolean 字段值变更时是否触发其它字段刷新
calculateOnRefresh boolean 被其它字段刷新时是否重新计算本字段
onlyCalculate boolean 仅用于计算(shouldStoreValue 会排除,不落库到 TLK_ 表)
instantValidate boolean 是否即时校验(输入时即触发,不等提交)
refreshMode int 刷新模式
refreshFields String 本字段变更时需要联动刷新的字段列表
editMode String 值脚本编辑模式:0=脚本模式(直接执行 valueScript)/ 1=设计模式(按 processDescription 拼接算术表达式)
filtercondition String 设计模式下的过滤条件
processDescription String 设计模式下的计算过程描述(格式 "[];[]",分号分隔两段:参数列表和运算表达式)

布局类

属性 类型 说明
width String 字段宽度
widthunit String 宽度单位(px/%)
fieldWidth String 输入框宽度
showWidth String 显示宽度
layout String 布局方式
layoutType String 布局类型
mobile boolean 是否在移动端显示
borderType String 边框类型

权限类

属性 类型 说明
authority String 字段权限配置
hideType String 隐藏类型
isHideType boolean 是否启用隐藏类型

其它

属性 类型 说明
showLog boolean 是否记录字段变更日志(影响 LOG_ 表生成)
secretText String 密级文本
readOnlyShowValOnly boolean 只读时仅显示值(不显示标签)

文本类字段

InputField(单行文本框)

  • Tag Name: InputField(数字模式为 NumberField
  • 存值: 是(VALUE_TYPE_VARCHAR / VALUE_TYPE_NUMBER
  • HTML 标签: <o-input>
  • 用途: 单行文本输入,支持普通文本、数字、密码等模式
  • 特有属性:
  • textType - 文本类型(text/number/password/readonly/hidden)
  • numberPattern - 数字显示模式(默认 ##.#######
  • fieldkeyevent - 键盘事件(EnterKey/TabKey)
  • dialogView - 弹出对话视图
  • suggest / popToChoice - 联想 / 弹出选择
  • defaultValueIsNull - 数字默认值是否为空

TextareaField(多行文本框)

  • Tag Name: TextAreaField(注意 A 大写)
  • 存值: 是(VALUE_TYPE_TEXT
  • HTML 标签: <o-textarea>
  • 特有属性: textareaHeight(多行框高度)

HTMLEditorField(富文本编辑器)

  • Tag Name: HTMLEditorField
  • 存值: 是(强制 VALUE_TYPE_TEXT
  • HTML 标签: <o-html>
  • 特有属性: areaWidth(默认 600px)、areaHeight(默认 200px)

CalctextField(计算文本)

  • Tag Name: CalctextField
  • 存值: (纯展示)
  • HTML 标签: <o-calctext>
  • 用途: 通过 valueScript 实时计算显示,不创建数据库字段

CustomField(自定义控件)

  • Tag Name: CustomField
  • 存值: 是(由 fieldtype 决定)
  • HTML 标签: <o-custom>
  • 特有属性: htmlScript(HTML 模板)、initScriptclickScriptchangeScript

选项类字段(IOptionsField)

均实现 IOptionsField 接口,共享选项配置:optionsScriptoptionsEditMode(00 设计/01 脚本)、dialogViewoptionsValueoptionsText

SelectField(下拉选择框)

  • Tag Name: SelectField
  • 存值: 是(VALUE_TYPE_VARCHAR
  • HTML 标签: <o-select>
  • 特有属性: multiSelect(是否多选)

CheckboxField(复选框)

  • Tag Name: CheckboxField
  • 存值: 是(VALUE_TYPE_VARCHAR,多值以 ; 分隔)
  • HTML 标签: <o-checkbox>
  • 特有属性: newlineCount(换行个数,默认 3)

RadioField(单选框)

  • Tag Name: RadioField
  • 存值: 是(VALUE_TYPE_VARCHAR
  • HTML 标签: <o-radio>
  • 特有属性: showFieldTitle(是否显示字段标题)

SuggestField(智能选择/自动补全)

  • Tag Name: SuggestField
  • 存值: 是(VALUE_TYPE_VARCHAR
  • HTML 标签: <o-suggest>
  • 特有属性: dataMode(local/remote,查询数据方式)

SelectAboutField(联动选择框)

  • Tag Name: SelectAboutField
  • 存值: 是(VALUE_TYPE_VARCHAR
  • HTML 标签: <o-select-about>
  • 用途: 基于其它字段值过滤选项的联动选择

日期/编号字段

DateField(日期)

  • Tag Name: DateField
  • 存值: 是(VALUE_TYPE_DATE
  • HTML 标签: <o-date-picker>
  • 特有属性:
  • datePattern - 日期模式(Y/YM/YMD/YMD_HMS/YMD_HM/HMS
  • prev_Name - 前一个日期字段名(用于区间校验)

NoField(自动编号)

  • Tag Name: NoField(数字模式为 NumberField
  • 存值: 是(VALUE_TYPE_VARCHAR / VALUE_TYPE_NUMBER
  • HTML 标签: <o-no>
  • 用途: 自动生成流水号(带前缀,可含年月日)
  • 特有属性: headText(前缀)、isYear/isMonth/isDaydigit(位数)

上传类字段(继承 AbstractUploadField)

均通过 AbstractUploadField 间接存值,存为 VALUE_TYPE_TEXT(JSON 字符串存储文件列表)。

AbstractUploadField 公共属性: - 大小/数量限制limitsizelimitTypelimitNumber - 类型限制fileType(00 全部/01 自定义)、customizeType - 保存路径fileCatalogfilePattern - 水印openWaterMarkwaterMarkSupportModewaterMarkScript - 在线编辑previewEditshowTrackRevisionsselectEditPlugpreviewType - 操作脚本开关editScriptpreviewScriptrenameScriptdeleteScriptdownloadScriptversionCompareScriptnewVersionScriptrestoreScript

AttachmentUploadField(附件上传)

  • Tag Name: AttachmentUploadField
  • HTML 标签: <o-file-upload>
  • 特有属性: 继承全部,imgh/imgw

ImageUploadField(图片上传)

  • Tag Name: ImageUploadField
  • HTML 标签: <o-image-upload>
  • 特有属性: imgh/imgw(图片高/宽)

KmsDataField(KMS 知识库附件)

  • Tag Name: KmsDataField
  • HTML 标签: <o-file-kms>
  • 用途: 关联知识管理系统(KMS)文件

GenericWordField(Word 文档在线编辑)

  • Tag Name: GenericWordField
  • 存值: 是(VALUE_TYPE_TEXT,文件路径)
  • HTML 标签: <o-word>
  • 特有属性: openTypeselectEditPlug(默认 tray)、showTrackRevisions

WordField.java 不存在,已被 GenericWordField 取代。

已废弃

  • AttachmentUploadToDataBaseField - 文件直接入库(@Deprecated
  • FileManagerField - 文件管理器(@Deprecated

用户/组织类字段(IOptionsField)

UserField(用户选择)

  • Tag Name: UserField
  • 存值: 是(VALUE_TYPE_VARCHAR,用户 ID,多值 ; 分隔)
  • HTML 标签: <o-user-select>
  • 特有属性: filterField(过滤条件)、limitByUserlimitSum(限制数量)、selectMode

DepartmentField(部门选择)

  • Tag Name: DepartmentField
  • 存值: 是(VALUE_TYPE_VARCHAR,部门 ID)
  • HTML 标签: <o-dept-select>
  • 特有属性:
  • defaultOptionType - 默认选项类型(如 16=首选项,256=用户所在部门)
  • relatedField - 级联的上级部门 Field ID
  • allowEmpty

TreeDepartmentField(树形部门选择)

  • Tag Name: TreeDepartmentField
  • 存值: 是(VALUE_TYPE_VARCHAR
  • HTML 标签: <o-dept-tree-select>
  • 特有属性: limit(限制选择数量)

布局/容器类字段(不存值)

TabField(页签)

  • Tag Name: TabField
  • 存值:
  • HTML 标签: <o-tab>
  • 特有属性: relStrshowModeopenAlltabnameselectedScripttabselwidthtabselheighttabs

SplitField(分栏/分割)

  • Tag Name: SplitField
  • 存值:
  • HTML 标签: <o-split>
  • 特有属性: titleScript(标题脚本)、height

IncludeField(包含视图)

  • Tag Name: IncludeField
  • 存值:
  • HTML 标签: <o-include>
  • 用途: 在表单中嵌入其它视图(父子表/子视图)
  • 特有属性:
  • includeType - 包含类型(INCLUDE_TYPE_VIEW="0"
  • viewId - 嵌入的视图 ID
  • relate - 是否父子关联
  • fixationmobileDisplayMode(默认 tile)

ButtonField(按钮)

  • Tag Name: ButtonField
  • 存值:
  • HTML 标签: <o-button>
  • 用途: 表单操作按钮(保存/提交/流程/打印等)
  • 特有属性: actType(动作类型)、actionViewactionFormactionFlowactionPrintcolorTypelabel
  • 特殊: 在 getDisplayType() 中有豁免,按钮不受 doc.isEditAble() 自动 DISABLED 限制

ViewDialogField(视图对话框)

  • Tag Name: ViewDialogField
  • 存值:
  • HTML 标签: <o-view-dialog>
  • 用途: 弹出视图选择(常与 InputField 配合做选择回填)
  • 特有属性: openTypedialogViewokScriptcallbackScriptmappingeventMappingmutilSelect

业务集成类字段

FlowHistoryField(流程历史)

  • Tag Name: FlowHistoryField
  • 存值:
  • HTML 标签: <o-flow-history>
  • 特有属性: showMode(text / diagram / textAndDiagram)

FlowReminderHistoryField(催办历史)

  • Tag Name: FlowReminderHistoryField
  • 存值:
  • HTML 标签: <o-reminder-history>

CommentField(评论)

  • Tag Name: CommentField
  • 存值:
  • HTML 标签: <o-comment>
  • 特有属性: title(评论标题)

SurveyField(调查/问卷)

  • Tag Name: SurveyField
  • 存值: 是(VALUE_TYPE_TEXT,问卷结果 JSON)
  • HTML 标签: <o-survey>
  • 特有属性: questionScript

ReminderField(提醒/催办)

  • Tag Name: ReminderField
  • 存值: 是(VALUE_TYPE_VARCHAR
  • 特有属性: reminderid

多媒体/特殊类字段

MapField(地图)

  • Tag Name: MapField
  • 存值: 是(VALUE_TYPE_TEXT,GeoJSON)
  • HTML 标签: <o-map>
  • 特有属性:
  • openType - 打开地图类型
  • valueType - 数据存储类型Point/LineString/Bounds/Polygon(字段内自有 valueType,非 Item 值类型)
  • defaultCenterAddress - 默认中心地址
  • level - 默认缩放级别(1–18)

WeixinGpsField(微信 GPS 定位)

  • Tag Name: WeixinGpsField
  • 存值: 是(VALUE_TYPE_VARCHAR
  • HTML 标签: <o-gps>

WeixinRecordField(微信录音)

  • Tag Name: WeixinRecordField
  • 存值: 是(VALUE_TYPE_VARCHAR
  • HTML 标签: <o-record>

OnLineTakePhotoField(在线拍照)

  • Tag Name: OnLineTakePhotoField
  • 存值: 是(VALUE_TYPE_TEXT
  • 特有属性: imghimgwcameraPixelType(0=160×120 / 1=400×300 / 2=800×600)、album

QRCodeField(二维码)

  • Tag Name: QRCodeField
  • 存值:
  • HTML 标签: <o-qrcode>
  • 特有属性: handleType(text/link/callback_event)、size(默认 200)、codeType(默认 qr_code)、callbackScript

ScancodeField(扫码)

  • Tag Name: ScancodeField
  • 存值:
  • HTML 标签: <o-scancode>
  • 特有属性: mapping(扫码结果映射的目标字段)

HandwritingField(手写签名 - 已废弃)

  • Tag Name: HandwritingField
  • 存值: @Deprecated

NullField(空组件)

  • Tag Name: NullField
  • 存值:
  • 用途: 空占位组件,name 以 $ 开头时读取 Document 属性,或显示静态值

字段速查总表

字段类 中文名 存值 HTML 标签 值类型
InputField 单行文本框 <o-input> VARCHAR/NUMBER
TextareaField 多行文本框 <o-textarea> TEXT
HTMLEditorField 富文本 <o-html> TEXT
CalctextField 计算文本 <o-calctext> -
CustomField 自定义控件 <o-custom> 可变
SelectField 下拉选择 <o-select> VARCHAR
CheckboxField 复选框 <o-checkbox> VARCHAR
RadioField 单选框 <o-radio> VARCHAR
SuggestField 智能选择 <o-suggest> VARCHAR
SelectAboutField 联动选择 <o-select-about> VARCHAR
DateField 日期 <o-date-picker> DATE
NoField 自动编号 <o-no> VARCHAR/NUMBER
AttachmentUploadField 附件上传 <o-file-upload> TEXT
ImageUploadField 图片上传 <o-image-upload> TEXT
KmsDataField KMS 附件 <o-file-kms> TEXT
GenericWordField Word 编辑 <o-word> TEXT
UserField 用户选择 <o-user-select> VARCHAR
DepartmentField 部门选择 <o-dept-select> VARCHAR
TreeDepartmentField 树形部门 <o-dept-tree-select> VARCHAR
TabField 页签 <o-tab> -
SplitField 分栏 <o-split> -
IncludeField 包含视图 <o-include> -
ButtonField 按钮 <o-button> -
ViewDialogField 视图对话框 <o-view-dialog> -
FlowHistoryField 流程历史 <o-flow-history> -
FlowReminderHistoryField 催办历史 <o-reminder-history> -
CommentField 评论 <o-comment> -
SurveyField 问卷 <o-survey> TEXT
ReminderField 提醒 - VARCHAR
MapField 地图 <o-map> TEXT
WeixinGpsField GPS 定位 <o-gps> VARCHAR
WeixinRecordField 录音 <o-record> VARCHAR
OnLineTakePhotoField 在线拍照 - TEXT
QRCodeField 二维码 <o-qrcode> -
ScancodeField 扫码 <o-scancode> -
HandwritingField 手写签名 - -
NullField 空占位 - -

统计:共 37 个(不含已废弃的 AttachmentUploadToDataBaseField、FileManagerField)。其中存值字段 23 个,不存值字段 14 个。

前端实现(PC)

PC 端基于 Vue 3 组合式 API(<script setup>)+ Element Plus 实现。所有 o-* 字段组件位于 src/components/field/,表单容器为 src/components/form/form_normalform.vue。两端约定:后端把字段渲染成带 <o-xxx> 标签的 HTML 模板字符串,前端把这些标签当作全局组件渲染。

组件注册

注册入口在 registerFormComponents.ts,由 main.ts 调用 registerFormComponents(app) 把约 36 个 o-* 组件注册为**全局组件**:

export const formComponents = {
  'o-input': defineAsyncComponent(() => import('@/components/field/o_input.vue')),
  'o-select': defineAsyncComponent(() => import('@/components/field/o_select.vue')),
  // ... 其余字段组件
  'o-calctext': o_calctext,   // 同步注册
  'o-include': o_include,     // 同步注册
  'o-tab': o_tab,             // 同步注册
}
  • 绝大多数字段用 defineAsyncComponent 按需懒加载
  • o-calctext / o-include / o-tab 改为**同步注册**——避免「异步表单组件内再嵌套异步子组件」时,部分 Vue 版本触发 onMounted called with no active instance 告警;
  • 另注册了辅助/布局组件:o-icono-titlefont

表单渲染机制(模板编译)

后端返回的表单 JSON 包含两块关键字段:

  • data.formTemplate.template —— 一段 HTML 字符串,内含 <o-xxx> 标签与布局结构(即后端 toHtmlTemplate() 的产物);
  • data.fields —— 字段数据对象数组,每个对象携带该字段的 idnamevaluedisplayTypeformField(后端类名)、options、脚本结果等。

form_normalform.vue 用一个 _template 计算属性把这段 HTML 包成**动态组件定义**渲染:

const _template = computed(() => ({
  methods: { findField, refresh, checkData, getAllFields, addTabs, getStateId },
  template: `<div class='formHtml' ref='formHtmlDom'>${data.formTemplate.template}</div>`
}))
// 模板中:<component name="formTemplate" :is="_template" />
  • <component :is="_template"> 编译模板字符串,其中的 <o-xxx> 即解析为上面注册的全局组件;
  • 表单样式(后端 data.style.content)以 <style class="formStyle_<docId>"> 注入到 #formTemplate_<docId> 作用域下,实现每份表单独立样式。

字段数据流(initField 模式)

字段组件不通过 props 接收完整字段配置,而是只接收 id,再向**父表单**查回字段对象(同一个引用):

const props = defineProps({ id: String, callback: Function, gridOpenType: String })
const refresh   = inject('refresh', () => {})   // 触发字段刷新
const findField = inject('findField', () => {})  // 按 id 取字段对象
const checkData = inject('checkData', null)      // 取待校验表单数据

const field = ref({ textType: '', fieldtype: '' })
const initField = () => {
  const formData = findField(props.id)   // 返回 data.fields 中对应对象的同一引用
  field.value = formData
}
onMounted(initField)

要点:

  • findField(id) 按 id **尾段**匹配(复制文档时 fieldid 不变,但前缀不同),命中后回填 activities;找不到时返回一个 displayType=HIDDEN 的占位对象;
  • field.value 与表单 data.fields 中的对象是**同一引用**,组件内直接改 field.value.value 即同步到表单状态,无需 $emit 回传;
  • 控件值通常经一个本地 ref(如 inputWrapValue)中转,再用 watchfield.value.value 双向同步(便于做数字格式化、电话截断等本地处理)。

显示类型(displayType)与模板分支

displayType 镜像后端 PermissionType,取值定义在 Constant.js

常量 含义
PermissionType_READONLY 1 只读
PermissionType_MODIFY 2 可编辑
PermissionType_HIDDEN 3 隐藏
PermissionType_DISABLED 4 禁用
PermissionType_PRINT 5 打印

字段组件模板按 displayType + textType 分支渲染(以 o_input.vue 为例):

  1. HIDDENtextType=hidden → 不渲染控件,仅输出 hiddenValue(打印时输出 printHiddenValue);
  2. PRINT → 纯文本展示(密码显示 •••);
  3. READONLY / DISABLED → 禁用态 Element Plus 控件;当 readOnlyShowValOnly 为真时退化为纯文本;
  4. MODIFY → 可编辑 Element Plus 控件(el-input / el-select / el-tree-select 等)。

分支优先级与后端 getDisplayType() 一致:HIDDEN > DISABLED > READONLY > MODIFYtextType(text / password / readonly / hidden / tel)在其上做进一步细分。

字段刷新(refresh)与联动

值变化时按需触发服务端重算依赖字段:

watch(() => field.value.value, (newV, oldV) => {
  inputWrapValue.value = newV
  if (field.value.refreshOnChanged && (refreshMode == 0 || refreshMode == 1)
      && newV != oldV && oldV !== undefined) {   // oldV===undefined 跳过初始化
    refresh(props.id, newV)
  }
  if (field.value.instantValidate) handleBlurChange()
}, { deep: true })
  • refresh(id, value)form_normalform.vue provide,最终调用 refreshFormAPI 让后端按 refreshFields 重算,再把返回的字段数据**合并回 data.fields**——因为是同一引用,被刷新字段的组件会自动响应更新;
  • refreshOnChanged(本字段变更是否触发刷新)、calculateOnRefresh(被刷新时是否重算本字段)、refreshMode 共同决定联动行为;
  • 数字字段(VALUE_TYPE_NUMBER + numberPattern)在 onChange 时用 NumberFormater.format 按模式格式化后再写回。

即时校验(instantValidate)

开启 instantValidate 的字段在失焦/值变化时即时校验,无需等提交:

const response = await formValidationAPI(window.$root.appid, formData, {})
if (response.data.errcode == 4001) {           // 校验失败
  const hit = response.data.errors.find(e => e.field == field.value.name)
  if (hit) { isActive.value = true; errorMessage.value = hit.errmsg }
}

失败时在控件下方展示 .tips 错误条(errorMessage)。提交前整表校验同样走 formValidationAPI,对应后端 validateRule / validateLibs

工作模式(workmode)与 AI 辅助

workModeStore.isHuman 区分人工录入与 AI 录入模式,同一字段在两种模式下渲染不同控件:

<template v-if="workModeStore.isHuman"> ...真正的 el-input... </template>
<template v-else>
  <o_input_ai :field="field" @change="onAiInputChange" />   <!-- AI 辅助录入 -->
</template>

各基础字段都有对应 AI 变体:o_input_ai.vueo_select_ai.vueo_date_picker_ai.vueo_textarea_ai.vue

视图选择框回写(field.js)

src/components/field/field.js 提供字段值的**兼容回写**与**展示值换算**工具,供视图选择框(o-view-dialog)、SheetView 单元格等场景统一调用:

  • installFieldSetCompatibleValue(formData, onAfterSet)formData.formField 类型挂载 formData.setCompatibleValue(incomingValue, options),把传入的**显示值 / 真实值 / 多值(;分隔)** 统一解析成字段存储格式:
  • TreeDepartmentFieldapplyTreeDeptCompatibleValue(写 value/val/showValue/data
  • UserFieldapplyUserCompatibleValue(写 value/userName/showValue/data
  • SelectField / RadioField / CheckboxFieldapplySelectCompatibleValue(多选判定 + 回写 checkShowValue/displayValue
  • ImageUploadFieldapplyImageUploadCompatibleValue(JSON 字符串解析为数组 + 同步 pathLists
  • 展示值换算(存值 → 文案):buildSelectShowValuebuildUserShowValuebuildTreeDeptShowValuebuildSuggestShowValuebuildSelectAboutShowValue;网格/电子表格单元格统一入口 resolveSelectCellDisplay(raw, column)(优先 showVal/showValue,否则按 value+options/data 匹配,受 showType==='01' 影响显示真实值)。
  • markFieldRequiredAndDescript(controlEl, fieldValue):当 validateLibscheckEmpty_system 时,给字段标题加 <span class="field-required-mark">*</span> 必填标记。

操作日志(hislogs)

字段值被修改(isModified)且开启 showLog 时,控件右侧显示历史图标 o-icon.icon-history;点击经 hisLogs(Pinia)打开 form_operation_log.vue 展示该字段的修改记录。

前端组件 ↔ 后端字段对照表

下表为「后端字段类 → 前端组件文件」的对应关系(按 registerFormComponents.ts 注册项核对):

后端字段类 HTML 标签 前端组件文件 备注
InputField <o-input> o_input.vue AI 变体 o_input_ai.vue
TextareaField <o-textarea> o_textarea.vue AI 变体 o_textarea_ai.vue
HTMLEditorField <o-html> o_html.vue 富文本编辑器
CalctextField <o-calctext> o_calctext.vue 同步注册
SelectField <o-select> o_select.vue AI 变体 o_select_ai.vue
CheckboxField <o-checkbox> o_checkbox.vue
RadioField <o-radio> o_radio.vue
SuggestField <o-suggest> o_suggest.vue
SelectAboutField <o-select-about> o_select_about.vue
DateField <o-date-picker> o_date_picker.vue AI 变体 o_date_picker_ai.vue
NoField <o-no> o_no.vue 自动编号
AttachmentUploadField <o-file-upload> o_file_upload.vue
ImageUploadField <o-image-upload> o_image_upload.vue
KmsDataField <o-file-kms> o_file_kms.vue
GenericWordField <o-word> o_word.vue Word 在线编辑
UserField <o-user-select> o_user_select.vue
DepartmentField <o-dept-select> o_dept_select.vue 另注册有 o_department.vue
TreeDepartmentField <o-dept-tree-select> o_dept_tree_select.vue
TabField <o-tab> o_tab.vue 同步注册
IncludeField <o-include> o_include.vue 同步注册
ButtonField <o-button> o_button.vue
ViewDialogField <o-view-dialog> o_view_dialog.vue 配套 viewDialogDoAction.js、viewdialog_event_btn.vue
FlowHistoryField <o-flow-history> o_flow_history.vue 表格子组件 o_flow_history_table.vue
FlowReminderHistoryField <o-reminder-history> o_reminder_history.vue
CommentField <o-comment> o_comment.vue
SurveyField <o-survey> o_survey.vue
MapField <o-map> o_map.vue 配套 o_map_value.js
WeixinGpsField <o-gps> o_gps.vue
WeixinRecordField <o-record> o_record.vue
QRCodeField <o-qrcode> o_qrcode.vue

说明:SplitField<o-split>)、ScancodeField<o-scancode>)、OnLineTakePhotoFieldReminderFieldNullFieldHandwritingField 在 PC 端无独立的全局字段组件,或由布局层/其它机制承载;注册表中另有 o-titleo-codingo-dialogo-actionfonto-photoo-icon 等辅助/布局组件,不与单一后端字段类一一对应。