@aspire-ui/element-component-pro 1.0.3 → 1.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -50,6 +50,10 @@ declare const _default: {
50
50
  type: import('vue').PropType<"small" | "medium" | "large">;
51
51
  default: string;
52
52
  };
53
+ immediate: {
54
+ type: import('vue').PropType<boolean>;
55
+ default: boolean;
56
+ };
53
57
  rowSelection: {
54
58
  type: import('vue').PropType<{
55
59
  type?: "checkbox" | "radio";
@@ -146,10 +150,6 @@ declare const _default: {
146
150
  afterFetch: {
147
151
  type: import('vue').PropType<(data: unknown) => unknown>;
148
152
  };
149
- immediate: {
150
- type: import('vue').PropType<boolean>;
151
- default: boolean;
152
- };
153
153
  searchInfo: {
154
154
  type: import('vue').PropType<Record<string, unknown>>;
155
155
  };
@@ -220,6 +220,10 @@ declare const _default: {
220
220
  type: import('vue').PropType<"small" | "medium" | "large">;
221
221
  default: string;
222
222
  };
223
+ immediate: {
224
+ type: import('vue').PropType<boolean>;
225
+ default: boolean;
226
+ };
223
227
  rowSelection: {
224
228
  type: import('vue').PropType<{
225
229
  type?: "checkbox" | "radio";
@@ -316,10 +320,6 @@ declare const _default: {
316
320
  afterFetch: {
317
321
  type: import('vue').PropType<(data: unknown) => unknown>;
318
322
  };
319
- immediate: {
320
- type: import('vue').PropType<boolean>;
321
- default: boolean;
322
- };
323
323
  searchInfo: {
324
324
  type: import('vue').PropType<Record<string, unknown>>;
325
325
  };
@@ -376,6 +376,7 @@ declare const _default: {
376
376
  }, {
377
377
  loading: boolean;
378
378
  size: "medium" | "small" | "large";
379
+ immediate: boolean;
379
380
  rowKey: string;
380
381
  bordered: boolean;
381
382
  striped: boolean;
@@ -395,7 +396,6 @@ declare const _default: {
395
396
  fullScreen?: boolean;
396
397
  };
397
398
  fetchSetting: import('./ProTable').FetchSetting;
398
- immediate: boolean;
399
399
  }, true, import('vue').ComponentOptionsBase<any, any, any, any, any, any, any, any, any, any>> & Readonly<Readonly<import('vue').ExtractPropTypes<{
400
400
  api: {
401
401
  type: import('vue').PropType<(params: Record<string, unknown>) => Promise<{
@@ -431,6 +431,10 @@ declare const _default: {
431
431
  type: import('vue').PropType<"small" | "medium" | "large">;
432
432
  default: string;
433
433
  };
434
+ immediate: {
435
+ type: import('vue').PropType<boolean>;
436
+ default: boolean;
437
+ };
434
438
  rowSelection: {
435
439
  type: import('vue').PropType<{
436
440
  type?: "checkbox" | "radio";
@@ -527,10 +531,6 @@ declare const _default: {
527
531
  afterFetch: {
528
532
  type: import('vue').PropType<(data: unknown) => unknown>;
529
533
  };
530
- immediate: {
531
- type: import('vue').PropType<boolean>;
532
- default: boolean;
533
- };
534
534
  searchInfo: {
535
535
  type: import('vue').PropType<Record<string, unknown>>;
536
536
  };
@@ -635,6 +635,10 @@ declare const _default: {
635
635
  type: import('vue').PropType<"small" | "medium" | "large">;
636
636
  default: string;
637
637
  };
638
+ immediate: {
639
+ type: import('vue').PropType<boolean>;
640
+ default: boolean;
641
+ };
638
642
  rowSelection: {
639
643
  type: import('vue').PropType<{
640
644
  type?: "checkbox" | "radio";
@@ -731,10 +735,6 @@ declare const _default: {
731
735
  afterFetch: {
732
736
  type: import('vue').PropType<(data: unknown) => unknown>;
733
737
  };
734
- immediate: {
735
- type: import('vue').PropType<boolean>;
736
- default: boolean;
737
- };
738
738
  searchInfo: {
739
739
  type: import('vue').PropType<Record<string, unknown>>;
740
740
  };
@@ -805,6 +805,10 @@ declare const _default: {
805
805
  type: import('vue').PropType<"small" | "medium" | "large">;
806
806
  default: string;
807
807
  };
808
+ immediate: {
809
+ type: import('vue').PropType<boolean>;
810
+ default: boolean;
811
+ };
808
812
  rowSelection: {
809
813
  type: import('vue').PropType<{
810
814
  type?: "checkbox" | "radio";
@@ -901,10 +905,6 @@ declare const _default: {
901
905
  afterFetch: {
902
906
  type: import('vue').PropType<(data: unknown) => unknown>;
903
907
  };
904
- immediate: {
905
- type: import('vue').PropType<boolean>;
906
- default: boolean;
907
- };
908
908
  searchInfo: {
909
909
  type: import('vue').PropType<Record<string, unknown>>;
910
910
  };
@@ -995,6 +995,7 @@ declare const _default: {
995
995
  }, string, {
996
996
  loading: boolean;
997
997
  size: "medium" | "small" | "large";
998
+ immediate: boolean;
998
999
  rowKey: string;
999
1000
  bordered: boolean;
1000
1001
  striped: boolean;
@@ -1014,7 +1015,6 @@ declare const _default: {
1014
1015
  fullScreen?: boolean;
1015
1016
  };
1016
1017
  fetchSetting: import('./ProTable').FetchSetting;
1017
- immediate: boolean;
1018
1018
  }> & {
1019
1019
  props: {
1020
1020
  api: {
@@ -1051,6 +1051,10 @@ declare const _default: {
1051
1051
  type: import('vue').PropType<"small" | "medium" | "large">;
1052
1052
  default: string;
1053
1053
  };
1054
+ immediate: {
1055
+ type: import('vue').PropType<boolean>;
1056
+ default: boolean;
1057
+ };
1054
1058
  rowSelection: {
1055
1059
  type: import('vue').PropType<{
1056
1060
  type?: "checkbox" | "radio";
@@ -1147,10 +1151,6 @@ declare const _default: {
1147
1151
  afterFetch: {
1148
1152
  type: import('vue').PropType<(data: unknown) => unknown>;
1149
1153
  };
1150
- immediate: {
1151
- type: import('vue').PropType<boolean>;
1152
- default: boolean;
1153
- };
1154
1154
  searchInfo: {
1155
1155
  type: import('vue').PropType<Record<string, unknown>>;
1156
1156
  };
@@ -1354,6 +1354,9 @@ declare const _default: {
1354
1354
  schemas: {
1355
1355
  type: import('vue').PropType<import('./types').ProFormSchema[]>;
1356
1356
  };
1357
+ modelValue: {
1358
+ type: import('vue').PropType<Record<string, unknown>>;
1359
+ };
1357
1360
  initialValues: {
1358
1361
  type: import('vue').PropType<Record<string, unknown>>;
1359
1362
  };
@@ -1463,6 +1466,9 @@ declare const _default: {
1463
1466
  schemas: {
1464
1467
  type: import('vue').PropType<import('./types').ProFormSchema[]>;
1465
1468
  };
1469
+ modelValue: {
1470
+ type: import('vue').PropType<Record<string, unknown>>;
1471
+ };
1466
1472
  initialValues: {
1467
1473
  type: import('vue').PropType<Record<string, unknown>>;
1468
1474
  };
@@ -1524,6 +1530,7 @@ declare const _default: {
1524
1530
  submit: (values: Record<string, unknown>) => void;
1525
1531
  reset: () => void;
1526
1532
  register: (formAction: import('./types').FormActionType) => void;
1533
+ "update:modelValue": (values: Record<string, unknown>) => void;
1527
1534
  }, {
1528
1535
  showActionButtonGroup: boolean;
1529
1536
  showSubmitButton: boolean;
@@ -1595,6 +1602,9 @@ declare const _default: {
1595
1602
  schemas: {
1596
1603
  type: import('vue').PropType<import('./types').ProFormSchema[]>;
1597
1604
  };
1605
+ modelValue: {
1606
+ type: import('vue').PropType<Record<string, unknown>>;
1607
+ };
1598
1608
  initialValues: {
1599
1609
  type: import('vue').PropType<Record<string, unknown>>;
1600
1610
  };
@@ -1717,6 +1727,9 @@ declare const _default: {
1717
1727
  schemas: {
1718
1728
  type: import('vue').PropType<import('./types').ProFormSchema[]>;
1719
1729
  };
1730
+ modelValue: {
1731
+ type: import('vue').PropType<Record<string, unknown>>;
1732
+ };
1720
1733
  initialValues: {
1721
1734
  type: import('vue').PropType<Record<string, unknown>>;
1722
1735
  };
@@ -1826,6 +1839,9 @@ declare const _default: {
1826
1839
  schemas: {
1827
1840
  type: import('vue').PropType<import('./types').ProFormSchema[]>;
1828
1841
  };
1842
+ modelValue: {
1843
+ type: import('vue').PropType<Record<string, unknown>>;
1844
+ };
1829
1845
  initialValues: {
1830
1846
  type: import('vue').PropType<Record<string, unknown>>;
1831
1847
  };
@@ -1900,6 +1916,7 @@ declare const _default: {
1900
1916
  submit: (values: Record<string, unknown>) => void;
1901
1917
  reset: () => void;
1902
1918
  register: (formAction: import('./types').FormActionType) => void;
1919
+ "update:modelValue": (values: Record<string, unknown>) => void;
1903
1920
  }, string, {
1904
1921
  showActionButtonGroup: boolean;
1905
1922
  showSubmitButton: boolean;
@@ -1972,6 +1989,9 @@ declare const _default: {
1972
1989
  schemas: {
1973
1990
  type: import('vue').PropType<import('./types').ProFormSchema[]>;
1974
1991
  };
1992
+ modelValue: {
1993
+ type: import('vue').PropType<Record<string, unknown>>;
1994
+ };
1975
1995
  initialValues: {
1976
1996
  type: import('vue').PropType<Record<string, unknown>>;
1977
1997
  };
@@ -2036,6 +2056,7 @@ declare const _default: {
2036
2056
  schema: {
2037
2057
  field: string;
2038
2058
  label: string;
2059
+ labelWidth?: string | undefined;
2039
2060
  component?: (import('./types').ProFormBuiltInComponent | import('./types').ProFormCustomComponent) | undefined;
2040
2061
  componentProps?: (Record<string, unknown> | ((params: import('./types').RenderCallbackParams & {
2041
2062
  formActionType?: import('./types').FormActionType;
package/dist/style.css CHANGED
@@ -1 +1 @@
1
- .ecp-pro-table[data-v-c5638c20]{padding:16px;background:#fff;width:100%;box-sizing:border-box}.ecp-pro-table[data-v-c5638c20] .el-table{width:100%!important}.ecp-pro-table__header[data-v-c5638c20]{display:flex;justify-content:space-between;align-items:center;margin-bottom:16px}.ecp-pro-table__title-wrapper[data-v-c5638c20]{display:flex;align-items:center;gap:4px}.ecp-pro-table__title[data-v-c5638c20]{font-size:16px;font-weight:600}.ecp-pro-table__help[data-v-c5638c20]{color:#909399;cursor:help}.ecp-pro-table__toolbar[data-v-c5638c20]{display:flex;align-items:center;gap:8px}.ecp-pro-table__body[data-v-c5638c20]{width:100%}.ecp-pro-table__pagination[data-v-c5638c20]{margin-top:16px;display:flex;justify-content:flex-end}.ecp-pro-table__col-help[data-v-c5638c20]{margin-left:4px;color:#909399;cursor:help}.ecp-table-action[data-v-1b2d6c42],.ecp-table-action__item[data-v-1b2d6c42]{display:inline-flex;align-items:center;gap:4px}.ecp-table-action__icon[data-v-1b2d6c42]{margin-right:4px}.ecp-table-action__more[data-v-1b2d6c42]{display:inline-flex;align-items:center}.ecp-table-action__dropdown-item[data-v-1b2d6c42]{display:inline-flex;align-items:center;gap:4px}.ecp-tree-select[data-v-f30bba11]{position:relative;width:100%}.ecp-tree-select__filter-inner[data-v-f30bba11]{margin-bottom:8px}.ecp-tree-select__dropdown[data-v-f30bba11]{position:absolute;top:100%;left:0;right:0;max-height:280px;overflow:auto;background:#fff;border:1px solid #dcdfe6;border-radius:4px;margin-top:4px;z-index:1000;padding:8px}.ecp-tree-select__loading[data-v-f30bba11]{padding:24px;text-align:center;color:#909399;font-size:14px}.ecp-pro-form-item__help-icon[data-v-0dcbe9b0]{margin-left:4px;color:#909399;cursor:help;font-size:14px}.ecp-pro-form-item__help-icon[data-v-0dcbe9b0]:hover{color:#409eff}.ecp-pro-form-item__help-item[data-v-0dcbe9b0]{margin-bottom:4px}.ecp-pro-form-item__help-item[data-v-0dcbe9b0]:last-child{margin-bottom:0}.ecp-form-actions[data-v-489c88d2]{text-align:right}.ecp-form-actions__advance[data-v-489c88d2]{margin-right:8px}.el-icon-d-arrow-left.up[data-v-489c88d2]{transform:rotate(90deg)}.el-icon-d-arrow-left.down[data-v-489c88d2]{transform:rotate(-90deg)}.ecp-pro-form[data-v-4ee1cb87]{padding:16px;position:relative}.ecp-pro-form__advance[data-v-4ee1cb87]{margin-bottom:16px}.ecp-pro-form_col[data-v-4ee1cb87]{position:relative;float:right}.el-icon-d-arrow-left.up[data-v-4ee1cb87]{transform:rotate(90deg)}.el-icon-d-arrow-left.down[data-v-4ee1cb87]{transform:rotate(-90deg)}.ecp-form-actions__advance[data-v-4ee1cb87]{position:absolute;bottom:0;left:50%;transform:translate(-50%,-50%)}
1
+ .ecp-pro-table[data-v-c5638c20]{padding:16px;background:#fff;width:100%;box-sizing:border-box}.ecp-pro-table[data-v-c5638c20] .el-table{width:100%!important}.ecp-pro-table__header[data-v-c5638c20]{display:flex;justify-content:space-between;align-items:center;margin-bottom:16px}.ecp-pro-table__title-wrapper[data-v-c5638c20]{display:flex;align-items:center;gap:4px}.ecp-pro-table__title[data-v-c5638c20]{font-size:16px;font-weight:600}.ecp-pro-table__help[data-v-c5638c20]{color:#909399;cursor:help}.ecp-pro-table__toolbar[data-v-c5638c20]{display:flex;align-items:center;gap:8px}.ecp-pro-table__body[data-v-c5638c20]{width:100%}.ecp-pro-table__pagination[data-v-c5638c20]{margin-top:16px;display:flex;justify-content:flex-end}.ecp-pro-table__col-help[data-v-c5638c20]{margin-left:4px;color:#909399;cursor:help}.ecp-table-action[data-v-f319e73a],.ecp-table-action__item[data-v-f319e73a]{display:inline-flex;align-items:center;gap:4px}.ecp-table-action__icon[data-v-f319e73a]{margin-right:4px}.ecp-table-action__more[data-v-f319e73a]{display:inline-flex;align-items:center}.ecp-table-action__dropdown-item[data-v-f319e73a]{display:inline-flex;align-items:center;gap:4px}.ecp-tree-select[data-v-f30bba11]{position:relative;width:100%}.ecp-tree-select__filter-inner[data-v-f30bba11]{margin-bottom:8px}.ecp-tree-select__dropdown[data-v-f30bba11]{position:absolute;top:100%;left:0;right:0;max-height:280px;overflow:auto;background:#fff;border:1px solid #dcdfe6;border-radius:4px;margin-top:4px;z-index:1000;padding:8px}.ecp-tree-select__loading[data-v-f30bba11]{padding:24px;text-align:center;color:#909399;font-size:14px}.ecp-pro-form-item__help-icon[data-v-84880e9d]{margin-left:4px;color:#909399;cursor:help;font-size:14px}.ecp-pro-form-item__help-icon[data-v-84880e9d]:hover{color:#409eff}.ecp-pro-form-item__help-item[data-v-84880e9d]{margin-bottom:4px}.ecp-pro-form-item__help-item[data-v-84880e9d]:last-child{margin-bottom:0}.ecp-form-actions[data-v-489c88d2]{text-align:right}.ecp-form-actions__advance[data-v-489c88d2]{margin-right:8px}.el-icon-d-arrow-left.up[data-v-489c88d2]{transform:rotate(90deg)}.el-icon-d-arrow-left.down[data-v-489c88d2]{transform:rotate(-90deg)}.ecp-pro-form[data-v-6171d80d]{padding:16px;position:relative}.ecp-pro-form__advance[data-v-6171d80d]{margin-bottom:16px}.ecp-pro-form_col[data-v-6171d80d]{position:relative;float:right}.el-icon-d-arrow-left.up[data-v-6171d80d]{transform:rotate(90deg)}.el-icon-d-arrow-left.down[data-v-6171d80d]{transform:rotate(-90deg)}.ecp-form-actions__advance[data-v-6171d80d]{position:absolute;bottom:0;left:50%;transform:translate(-50%,-50%)}
@@ -50,6 +50,7 @@ export type FormListeners = Record<string, ((...args: unknown[]) => unknown) | (
50
50
  /** ProForm Props */
51
51
  export interface ProFormProps {
52
52
  schemas?: ProFormSchema[];
53
+ modelValue?: Record<string, unknown>;
53
54
  initialValues?: Record<string, unknown>;
54
55
  labelWidth?: string;
55
56
  labelPosition?: 'left' | 'right' | 'top';
@@ -85,6 +86,8 @@ export interface ProFormSchema {
85
86
  field: string;
86
87
  /** 标签 */
87
88
  label: string;
89
+ /** 单个表单项标签宽度,优先级高于 Form 的 labelWidth */
90
+ labelWidth?: string;
88
91
  /**
89
92
  * 组件类型:
90
93
  * - 内置:'input' | 'select' | 'date-picker' | 'date-range' | 'input-number' | 'switch' | 'cascader' | 'checkbox' | 'radio'
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aspire-ui/element-component-pro",
3
- "version": "1.0.03",
3
+ "version": "1.0.05",
4
4
  "description": "Element UI 二次封装组件库,基于 Vue 2.7 + TypeScript + setup 语法糖,实现 VbenAdmin 风格的 Pro 组件",
5
5
  "type": "module",
6
6
  "main": "./dist/element-component-pro.umd.js",
@@ -22,7 +22,8 @@
22
22
  "dev": "vite",
23
23
  "build": "vite build",
24
24
  "preview": "vite preview",
25
- "test:loading": "node scripts/test-loading.cjs"
25
+ "test:loading": "node scripts/test-loading.cjs",
26
+ "test:proform-vmodel": "node scripts/test-proform-vmodel.cjs"
26
27
  },
27
28
  "peerDependencies": {
28
29
  "element-ui": "^2.15.0",
@@ -1,6 +1,6 @@
1
1
  <template>
2
2
  <div ref="formWrapRef" class="ecp-pro-form">
3
- <el-form class="ecp-pro-form" ref="formRef" :model="formModel" :rules="formRules" :label-width="effectiveProps.labelWidth"
3
+ <el-form class="ecp-pro-form" ref="formRef" :model="currentFormModel" :rules="formRules" :label-width="effectiveProps.labelWidth"
4
4
  :label-position="effectiveProps.labelPosition" :size="effectiveProps.size" :disabled="effectiveProps.disabled"
5
5
  v-bind="$attrs" v-on="formListeners">
6
6
  <slot name="formHeader" />
@@ -8,12 +8,12 @@
8
8
  <template v-for="schema in displaySchemas">
9
9
  <el-col v-if="shouldShow(schema)" :key="schema.field" v-bind="getColProps(schema)"
10
10
  :offset="schema.colProps?.offset ?? effectiveProps.baseColProps?.offset ?? 0" :data-field="schema.field">
11
- <ProFormItem :schema="schema" :form-model="formModel" :form-disabled="effectiveProps.disabled"
11
+ <ProFormItem :schema="schema" :form-model="currentFormModel" :form-disabled="effectiveProps.disabled"
12
12
  :auto-placeholder="effectiveProps.autoSetPlaceholder" :form-action-type="formActionRef"
13
- :custom-components="formCustomComponents">
13
+ :custom-components="formCustomComponents" :on-field-change="handleFieldChange">
14
14
  <template v-if="slots[getSlotName(schema)]">
15
- <slot :name="getSlotName(schema)" :model="formModel" :schema="schema" :field="schema.field"
16
- :values="formModel" />
15
+ <slot :name="getSlotName(schema)" :model="currentFormModel" :schema="schema" :field="schema.field"
16
+ :values="currentFormModel" />
17
17
  </template>
18
18
  </ProFormItem>
19
19
  </el-col>
@@ -65,6 +65,7 @@ import type { ProFormSchema, ProFormProps, FormActionType, ColEx, ScrollToFieldO
65
65
  const props = withDefaults(
66
66
  defineProps<{
67
67
  schemas?: ProFormSchema[]
68
+ modelValue?: Record<string, unknown>
68
69
  initialValues?: Record<string, unknown>
69
70
  labelWidth?: string
70
71
  labelPosition?: 'left' | 'right' | 'top'
@@ -118,6 +119,7 @@ const emit = defineEmits<{
118
119
  (e: 'submit', values: Record<string, unknown>): void
119
120
  (e: 'reset'): void
120
121
  (e: 'register', formAction: FormActionType): void
122
+ (e: 'update:modelValue', values: Record<string, unknown>): void
121
123
  }>()
122
124
  const slots = useSlots()
123
125
  const formRef = ref()
@@ -148,10 +150,17 @@ const getEffectiveSpan = (colProps?: ColEx | null, baseColProps?: ColEx | null,
148
150
 
149
151
  const { getSetting: getComponentSetting } = useComponentSetting()
150
152
  const effectiveProps = computed(() => ({ ...getComponentSetting('ProForm'), ...props, ...innerProps.value }))
153
+ const controlledModelValue = computed(() => effectiveProps.value.modelValue)
154
+ const isControlled = computed(() => controlledModelValue.value !== undefined)
155
+ const currentFormModel = computed<Record<string, unknown>>(() => {
156
+ return isControlled.value
157
+ ? (controlledModelValue.value ?? {})
158
+ : formModel.value
159
+ })
151
160
  /** 传给 ProFormItem 的自定义组件映射:显式合并 setSetting 与 props,避免响应式代理导致组件引用丢失 */
152
161
  const formCustomComponents = computed(() => ({
153
162
  ...(getComponentSetting('ProForm').components as Record<string, unknown> | undefined) ?? {},
154
- ...(props.components ?? {}),
163
+ ...(effectiveProps.value.components ?? {}),
155
164
  ...(innerProps.value.components ?? {}),
156
165
  }))
157
166
  const effectiveActionColOptions = computed(() => effectiveProps.value.actionColOptions ?? { span: 24 })
@@ -190,7 +199,6 @@ const hasMoreFields = computed(() => {
190
199
  const lines = effectiveProps.value.alwaysShowLines ?? 1
191
200
  const baseColProps = effectiveProps.value.baseColProps
192
201
  const maxVisible = getVisibleSchemaCount(schemas, baseColProps, lines, windowWidth.value)
193
- console.log(schemas.length, maxVisible)
194
202
  return schemas.length > maxVisible
195
203
  })
196
204
 
@@ -213,13 +221,13 @@ const shouldShow = (schema: ProFormSchema) => {
213
221
  let ifShow = true
214
222
  let show = true
215
223
  if (typeof schema.ifShow === 'function') {
216
- ifShow = schema.ifShow({ schema, values: formModel.value, model: formModel.value, field: schema.field })
224
+ ifShow = schema.ifShow({ schema, values: currentFormModel.value, model: currentFormModel.value, field: schema.field })
217
225
  }
218
226
  if (typeof schema.ifShow === 'boolean') {
219
227
  ifShow = schema.ifShow
220
228
  }
221
229
  if (typeof schema.show === 'function') {
222
- show = schema.show({ schema, values: formModel.value, model: formModel.value, field: schema.field })
230
+ show = schema.show({ schema, values: currentFormModel.value, model: currentFormModel.value, field: schema.field })
223
231
  }
224
232
  if (typeof schema.show === 'boolean') {
225
233
  show = schema.show
@@ -230,16 +238,44 @@ const getColProps = (schema: ProFormSchema) => {
230
238
  return schema.colProps ?? effectiveProps.value.baseColProps ?? {}
231
239
  }
232
240
  const getSlotName = (schema: ProFormSchema) => schema.slot || schema.field
241
+ /**
242
+ *
243
+ * @param baseModel
244
+ * @param preserveExisting
245
+ */
246
+ const resolveSchemaModel = (baseModel?: Record<string, unknown>, preserveExisting = true) => {
247
+ const nextModel = preserveExisting ? { ...(baseModel ?? {}) } : {}
248
+ const initialValues = effectiveProps.value.initialValues ?? props.initialValues
249
+ innerSchemas.value.forEach((schema) => {
250
+ if (preserveExisting && Object.prototype.hasOwnProperty.call(nextModel, schema.field)) return
251
+ if (schema.defaultValue !== undefined) {
252
+ nextModel[schema.field] = schema.defaultValue
253
+ return
254
+ }
255
+ if (initialValues && Object.prototype.hasOwnProperty.call(initialValues, schema.field)) {
256
+ nextModel[schema.field] = initialValues[schema.field]
257
+ }
258
+ })
259
+ return nextModel
260
+ }
261
+
262
+ const applyFormModel = (nextModel: Record<string, unknown>, shouldEmit = true) => {
263
+ formModel.value = nextModel
264
+ if (shouldEmit) emit('update:modelValue', nextModel)
265
+ }
266
+
267
+ const updateFormModel = (values: Record<string, unknown>) => {
268
+ const nextModel = resolveSchemaModel({ ...currentFormModel.value, ...values })
269
+ applyFormModel(nextModel)
270
+ return nextModel
271
+ }
233
272
 
234
273
  const initForm = () => {
235
- const model: Record<string, unknown> = {}
236
274
  const rules: Record<string, unknown[]> = {}
237
- const initialValues = effectiveProps.value.initialValues ?? props.initialValues
238
275
  innerSchemas.value.forEach((schema) => {
239
- model[schema.field] = schema.defaultValue ?? initialValues?.[schema.field]
240
276
  if (schema.rules?.length) rules[schema.field] = schema.rules
241
277
  })
242
- formModel.value = { ...formModel.value, ...model }
278
+ applyFormModel(resolveSchemaModel(currentFormModel.value), false)
243
279
  formRules.value = rules
244
280
  }
245
281
 
@@ -277,7 +313,7 @@ const handleSubmit = async () => {
277
313
  await effectiveProps.value.submitFunc()
278
314
  } else {
279
315
  submitLoading.value = true
280
- emit('submit', processFieldMapToTime({ ...formModel.value }))
316
+ emit('submit', processFieldMapToTime({ ...currentFormModel.value }))
281
317
  }
282
318
  } catch (e) {
283
319
  console.error('Form validation failed:', e)
@@ -298,15 +334,19 @@ const handleReset = async () => {
298
334
  }
299
335
 
300
336
  const setFieldsValue = (values: Record<string, unknown>) => {
301
- formModel.value = { ...formModel.value, ...values }
337
+ updateFormModel(values)
302
338
  return Promise.resolve()
303
339
  }
304
340
 
305
- const getFieldsValue = () => processFieldMapToTime({ ...formModel.value })
341
+ const getFieldsValue = () => processFieldMapToTime({ ...currentFormModel.value })
306
342
 
307
343
  const resetFields = async () => {
308
344
  formRef.value?.resetFields()
309
- initForm()
345
+ applyFormModel(resolveSchemaModel(undefined, false))
346
+ }
347
+
348
+ const handleFieldChange = (field: string, value: unknown) => {
349
+ updateFormModel({ [field]: value })
310
350
  }
311
351
 
312
352
  const validate = (nameList?: string[]) =>
@@ -398,6 +438,11 @@ onUnmounted(() => {
398
438
  if (typeof window !== 'undefined') window.removeEventListener('resize', handleResize)
399
439
  })
400
440
 
441
+ watch(() => controlledModelValue.value, (value) => {
442
+ if (!isControlled.value || value === undefined) return
443
+ applyFormModel(resolveSchemaModel(value), false)
444
+ }, { deep: true, immediate: true })
445
+
401
446
  watch(() => [props.schemas, props.initialValues], syncSchemas, { deep: true })
402
447
  </script>
403
448
 
@@ -5,6 +5,7 @@
5
5
  :prop="schema.field"
6
6
  :required="schema.required"
7
7
  :rules="effectiveRules"
8
+ :label-width="schema.labelWidth"
8
9
  >
9
10
  <template slot="label">
10
11
  <span>{{ schema.label }}</span>
@@ -180,6 +181,7 @@ const props = defineProps<{
180
181
  formDisabled?: boolean
181
182
  autoPlaceholder?: boolean
182
183
  formActionType?: import('../types').FormActionType
184
+ onFieldChange?: (field: string, value: unknown) => void
183
185
  /** 自定义组件映射(由 ProForm 传入) */
184
186
  customComponents?: Record<string, unknown>
185
187
  }>()
@@ -265,7 +267,7 @@ const resolvedCustomComponent = computed(() => {
265
267
  })
266
268
 
267
269
  const setFieldValue = (v: unknown) => {
268
- props.formModel[props.schema.field] = v
270
+ props.onFieldChange?.(props.schema.field, v)
269
271
  }
270
272
 
271
273
  const renderComponent = computed(() => {
@@ -12,8 +12,8 @@
12
12
  :title="action.popConfirm.title"
13
13
  :confirm-button-text="action.popConfirm.okText || '确定'"
14
14
  :cancel-button-text="action.popConfirm.cancelText || '取消'"
15
- @confirm="(e) => handlePopConfirm(action, 'confirm', e)"
16
- @cancel="(e) => handlePopConfirm(action, 'cancel', e)"
15
+ @confirm="handlePopConfirmConfirm(action, $event)"
16
+ @cancel="handlePopConfirmCancel(action, $event)"
17
17
  >
18
18
  <span slot="reference">
19
19
  <component
@@ -25,7 +25,7 @@
25
25
  size="small"
26
26
  :disabled="action.disabled"
27
27
  v-bind="action.props"
28
- @click="(e) => handleClick(action, e)"
28
+ @click="handleActionClick(action, $event)"
29
29
  >
30
30
  <i v-if="action.icon" :class="['ecp-table-action__icon', action.icon]" />
31
31
  <span>{{ action.label }}</span>
@@ -45,7 +45,7 @@
45
45
  size="small"
46
46
  :disabled="action.disabled"
47
47
  v-bind="action.props"
48
- @click="(e) => handleClick(action, e)"
48
+ @click="handleActionClick(action, $event)"
49
49
  >
50
50
  <i v-if="action.icon" :class="['ecp-table-action__icon', action.icon]" />
51
51
  <span>{{ action.label }}</span>
@@ -133,6 +133,10 @@ const handleClick = (action: TableActionItem, e: MouseEvent) => {
133
133
  action.onClick?.(e)
134
134
  }
135
135
 
136
+ const handleActionClick = (action: TableActionItem, e: MouseEvent) => {
137
+ handleClick(action, e)
138
+ }
139
+
136
140
  const handlePopConfirm = (action: TableActionItem, type: 'confirm' | 'cancel', e: MouseEvent) => {
137
141
  if (props.stopButtonPropagation) {
138
142
  e.stopPropagation()
@@ -145,6 +149,14 @@ const handlePopConfirm = (action: TableActionItem, type: 'confirm' | 'cancel', e
145
149
  }
146
150
  }
147
151
 
152
+ const handlePopConfirmConfirm = (action: TableActionItem, e: MouseEvent) => {
153
+ handlePopConfirm(action, 'confirm', e)
154
+ }
155
+
156
+ const handlePopConfirmCancel = (action: TableActionItem, e: MouseEvent) => {
157
+ handlePopConfirm(action, 'cancel', e)
158
+ }
159
+
148
160
  const handleDropdownCommand = (index: number | string) => {
149
161
  const idx = Number(index)
150
162
  const action = visibleDropDownActions.value[idx]
@@ -190,4 +202,3 @@ const handleDropdownCommand = (index: number | string) => {
190
202
  gap: 4px;
191
203
  }
192
204
  </style>
193
-
@@ -56,6 +56,7 @@ export type FormListeners = Record<string, ((...args: unknown[]) => unknown) | (
56
56
  /** ProForm Props */
57
57
  export interface ProFormProps {
58
58
  schemas?: ProFormSchema[]
59
+ modelValue?: Record<string, unknown>
59
60
  initialValues?: Record<string, unknown>
60
61
  labelWidth?: string
61
62
  labelPosition?: 'left' | 'right' | 'top'
@@ -105,6 +106,8 @@ export interface ProFormSchema {
105
106
  field: string
106
107
  /** 标签 */
107
108
  label: string
109
+ /** 单个表单项标签宽度,优先级高于 Form 的 labelWidth */
110
+ labelWidth?: string
108
111
  /**
109
112
  * 组件类型:
110
113
  * - 内置:'input' | 'select' | 'date-picker' | 'date-range' | 'input-number' | 'switch' | 'cascader' | 'checkbox' | 'radio'