dynamic-form.mdc 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. ---
  2. description: DynamicForm 动态表单定义、挂载与 dig/forms 数据工厂约定
  3. globs: "**/*.vue"
  4. alwaysApply: false
  5. ---
  6. # 动态表单(DynamicForm)使用约定
  7. 本项目采用的是Vue3 web技术栈,其中主要的功能点为表单提交,因此本项目采用了动态表单库 vue-dynamic-form,
  8. 关于动态表单库的使用文档可参考https://docs.imengyu.top/vue-dynamic-form-docs/guide/about.html
  9. 基于 `DynamicForm.vue`、`DynamicForm.ts`(`IDynamicFormOptions` / `IDynamicFormItem`)及 `pages/dig/forms/data/*.ts`(如 `overview.ts`)的实际用法。
  10. ## 组件侧
  11. - 使用 `<DynamicForm :options="..." :model="..." :name="..." :globalParams="..." />`。`model` 与表单双向绑定;`globalParams` 可在条目回调的 `formGlobalParams` 中读取。
  12. - 通过 `ref` 拿到 `IDynamicFormRef`:`validate` / `submit`、`setValueByPath` / `getValueByPath`(路径为点分字符串或数组转点分)、`getFormRef`、`getFormItemControlRef`、`dispatchMessage` / `dispatchReload`(常量 `MESSAGE_RELOAD`)、`initDefaultValuesToModel`、`getVisibleFormNames`。
  13. - 顶层校验:在 `options.formRules`(async-validator `Rules`)或单项 `rules`(`RuleItem[]`)。可选 `formAdditionaProps`、`disabled`、`readonly`、`suppressRootError`、`suppressEmptyError`、`nestObjectMargin`、`emptyText`。
  14. ## 选项结构 `IDynamicFormOptions`
  15. - **必填**:`formItems: IDynamicFormItem[]`。
  16. - 全局默认:可改 `defaultDynamicFormOptions` 或调用 `configDefaultDynamicFormOptions`(勿传入 `formItems`),与单次 `options` 合并。
  17. ## 表单项 `IDynamicFormItem`
  18. - **必填**:`name`(字段路径名)。**常用**:`label`、`type`(内置控件类型字符串)、`additionalProps`(传给具体控件)、`formProps`(传给 `Field`)、`defaultValue`、`rules`、`children`(嵌套对象/数组项)。
  19. - **动态字段**:`label`、`additionalProps`、部分控件字段、`show`、`disabled` 等可写成 **`IDynamicFormItemCallback<T>`**:`{ callback: (model, rawModel, parentModel, params) => T }`。关联远端字段时优先用 **`rawModel`**;列表场景用 **`parentModel`**。`params` 含 `item`、`parent`、`form`(`IDynamicFormRef`)、`formGlobalParams`、`formRules`、`isFirst` / `isLast`。
  20. - **生命周期 / 联动**:`mounted` / `beforeUnmount` / `watch`;跨项赋值在拿到表单 ref 时用 **`form.setValueByPath('field', value)`**(参见 `overview` 中 `select-city` 的 `onSelectedTownship`)。
  21. - **布局容器**:`flat-group` 用于横向/分组排版(可配合 `childrenColProps`、`rowProps`);子项仍占用模型上的 `name`。嵌套对象用带 `children` 的条目(由渲染层按 `type` 区分对象/数组等)。
  22. - **数组子项**:可选 `newChildrenObject`、`deleteChildrenCallback` 控制增删;子层可用 `childrenColProps` / `colProps` / `nestObjectMargin`。
  23. - **默认值**:`defaultValue` 可为字面量或 **`() => value`**(惰性初始化);`initDefaultValuesToModel` 只对仍为 `undefined`/`null` 的路径写入。
  24. - **消息**:条目可实现 `message`,根上 `dispatchMessage` 分发;预置 `MESSAGE_RELOAD` 用于刷新类逻辑。
  25. ## 可用组件
  26. 在 \src\components\dynamicf\index.ts 中的 registerAllFormComponents 函数中有注册了本项目中可用的动态表单组件,可以在这里查阅。
  27. register的一个参数小写名字为组件的唯一标识,在配置中使用。
  28. 本项目大部分使用 ant-design-vue 的组件,少部分组件为二次封装组件,放在项目的 \src\components\dynamicf 文件夹下。
  29. 可用组件简表:
  30. text:单行文本框
  31. password:密码输入框
  32. number:数字输入框
  33. text-area:多行文本框
  34. switch:开关
  35. check-box:boolean类型的勾选框
  36. check-box-int:0,1数字类型的勾选框
  37. rate:评星
  38. select:静态数据下拉选择框
  39. select-value:静态数据下拉选择框,额外参数的options可配置选项数据,格式{text: string,value: unknown}[]
  40. select-id: 动态数据据下拉选择框,额外参数的loadData为回调:
  41. loadData: (searchText: string | null) => Promise<DropdownValues<T>[]>;
  42. DropdownValues<T> {
  43. label: string,
  44. value: number,
  45. raw: T;
  46. }
  47. 可用来加载选项数据。
  48. date:日期选择.
  49. time:时间选择。
  50. date-time:日期+时间选择
  51. date-range:日期范围选择。
  52. time-range:时间范围选择。
  53. date-time-range:日期+时间范围选择。
  54. uploader:单一图片上传。
  55. uploader:多图上传。
  56. formOptions 格式如下:{
  57. formLabelCol: { span: 6 }, //表单标签栅格宽度
  58. formWrapperCol: { span: 24 }, //表单容器栅格宽度
  59. formAdditionaProps: { //指定ant desgin form 的其他参数
  60. layout: 'vertical'
  61. },
  62. formItems: [//表单项目
  63. {
  64. label: '传承人姓名', //标签名称
  65. name: 'name', //字段名称
  66. type: 'text', //组件名称
  67. additionalProps: { //组件的额外参数
  68. placeholder: '请输入姓名'
  69. },
  70. },
  71. {
  72. label: '证件照',
  73. name: 'idPhoto',
  74. type: 'uploader',
  75. additionalProps: {
  76. },
  77. },
  78. {
  79. label: '类型',
  80. name: 'type',
  81. type: 'select-id',//动态下拉加载
  82. additionalProps: {
  83. placeholder: '请选择类型',
  84. //如有动态加载数据,请为我生成类似代码
  85. loadData: async () =>
  86. (await CommonContent.getCategoryList(4)).map(p => ({
  87. label: p.title,
  88. value: p.id,
  89. raw: p
  90. }))
  91. } as IdAsValueDropdownProps<DataModel>,
  92. },
  93. {
  94. label: '性别',
  95. name: 'gender',
  96. type: 'select',
  97. additionalProps: {
  98. options: [
  99. { text: '男', value: '男' },
  100. { text: '女', value: '女' },
  101. ]
  102. },
  103. },
  104. {
  105. label: '生日',
  106. name: 'birthday',
  107. type: 'date',
  108. additionalProps: {
  109. placeholder: '请输入出生日期'
  110. }
  111. },
  112. {
  113. label: '说明',
  114. name: 'jobTitle',
  115. type: 'text-area',
  116. additionalProps: {
  117. placeholder: '请输入说明'
  118. }
  119. },
  120. ],
  121. formRules: { //表单验证项,格式与 async-validator 一致
  122. name: [
  123. { required: true, message: '请输入姓名' },
  124. { min: 2, max: 5, message: '长度在 2 到 5 个字符' }
  125. ],
  126. ichName: [
  127. { required: true, message: '请输入项目名称' }
  128. ],
  129. //....
  130. },
  131. });
  132. ## 建议避免
  133. - 勿猜测未注册的 `type`;新增类型需在动态表单渲染链路中已有对应组件映射。
  134. - 回调里访问兄弟节点不要用错层级:`model` 是当前项值,`rawModel` 是整表根数据(跨深层字段时尤其要用根路径或 `setValueByPath`)。