@dazhicheng/ui 1.5.199 → 1.5.202
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/_virtual/_plugin-vue_export-helper.js +9 -0
- package/dist/api/dataTypeContext.js +17 -0
- package/dist/assets/img/empty_images/no_data.png.js +4 -0
- package/dist/assets/img/empty_images/search.png.js +4 -0
- package/dist/assets/img/image_status/develop.png.js +4 -0
- package/dist/assets/img/image_status/loading.gif.js +4 -0
- package/dist/assets/img/image_status/loading_fail.png.js +4 -0
- package/dist/assets/img/image_status/no_network.png.js +4 -0
- package/dist/assets/img/image_status/no_permission.png.js +4 -0
- package/dist/assets/svg/RiRefreshLine.svg.js +4 -0
- package/dist/assets/svg/action_more.svg.js +4 -0
- package/dist/assets/svg/add.svg.js +4 -0
- package/dist/assets/svg/addCircleLine.svg.js +4 -0
- package/dist/assets/svg/arrowDown.svg.js +4 -0
- package/dist/assets/svg/arrowLineDown.svg.js +5 -0
- package/dist/assets/svg/arrowSUp.svg.js +4 -0
- package/dist/assets/svg/arrowUp.svg.js +4 -0
- package/dist/assets/svg/close.svg.js +4 -0
- package/dist/assets/svg/columnSet.svg.js +4 -0
- package/dist/assets/svg/determinateCircleLine.svg.js +5 -0
- package/dist/assets/svg/drag.svg.js +5 -0
- package/dist/assets/svg/exportSvg.svg.js +4 -0
- package/dist/assets/svg/fileSvg.svg.js +4 -0
- package/dist/assets/svg/help.svg.js +4 -0
- package/dist/assets/svg/item_error.svg.js +4 -0
- package/dist/assets/svg/paixu-jiangxu.svg.js +4 -0
- package/dist/assets/svg/paixu-moren.svg.js +4 -0
- package/dist/assets/svg/paixu-shengxu.svg.js +4 -0
- package/dist/assets/svg/quanping.svg.js +4 -0
- package/dist/assets/svg/suoxiao.svg.js +4 -0
- package/dist/components/tt-api-component/index.js +7 -0
- package/dist/components/tt-api-component/index.vue.js +7 -0
- package/dist/components/tt-api-component/index.vue2.js +199 -0
- package/dist/components/tt-area/TtArea.vue.js +7 -0
- package/dist/components/tt-area/TtArea.vue3.js +36 -0
- package/dist/components/tt-button/components/AddButton.vue.js +24 -0
- package/dist/components/tt-button/components/AddButton.vue2.js +4 -0
- package/dist/components/tt-button/index.js +9 -0
- package/dist/components/tt-button/index.vue.js +7 -0
- package/dist/components/tt-button/index.vue2.js +68 -0
- package/dist/components/tt-checkbox/index.js +7 -0
- package/dist/components/tt-checkbox/index.vue.js +77 -0
- package/dist/components/tt-checkbox/index.vue2.js +4 -0
- package/dist/components/tt-drawer/index.js +14 -0
- package/dist/components/tt-drawer/src/RenderDrawer.vue.js +157 -0
- package/dist/components/tt-drawer/src/RenderDrawer.vue3.js +5 -0
- package/dist/components/tt-drawer/src/components/DrawerFooter.vue.js +56 -0
- package/dist/components/tt-drawer/src/components/DrawerFooter.vue3.js +5 -0
- package/dist/components/tt-drawer/src/components/DrawerHeader.vue.js +7 -0
- package/dist/components/tt-drawer/src/components/DrawerHeader.vue2.js +21 -0
- package/dist/components/tt-drawer/src/hooks/useDrawerRender.js +124 -0
- package/dist/components/tt-drawer/src/hooks/useResizable.js +98 -0
- package/dist/components/tt-drawer/src/index.js +17 -0
- package/dist/components/tt-drawer/src/props.js +72 -0
- package/dist/components/tt-drawer/src/utils/drawer-api.js +191 -0
- package/dist/components/tt-empty/index.js +34 -0
- package/dist/components/tt-form/index.js +59 -0
- package/dist/components/tt-form/src/components/ExpandableArrow.vue2.js +38 -0
- package/dist/components/tt-form/src/components/ExpandableArrow.vue3.js +5 -0
- package/dist/components/tt-form/src/components/FormActions.vue2.js +177 -0
- package/dist/components/tt-form/src/components/FormActions.vue3.js +5 -0
- package/dist/components/tt-form/src/components/FormElInput.vue.js +80 -0
- package/dist/components/tt-form/src/components/FormElInput.vue2.js +4 -0
- package/dist/components/tt-form/src/components/Slot.js +28 -0
- package/dist/components/tt-form/src/config.js +57 -0
- package/dist/components/tt-form/src/form/FormControl.vue.js +16 -0
- package/dist/components/tt-form/src/form/FormControl.vue2.js +4 -0
- package/dist/components/tt-form/src/form/FormDescription.vue.js +21 -0
- package/dist/components/tt-form/src/form/FormDescription.vue2.js +4 -0
- package/dist/components/tt-form/src/form/FormItem.vue.js +20 -0
- package/dist/components/tt-form/src/form/FormItem.vue2.js +4 -0
- package/dist/components/tt-form/src/form/FormLabel.vue.js +19 -0
- package/dist/components/tt-form/src/form/FormLabel.vue2.js +4 -0
- package/dist/components/tt-form/src/form/FormMessage.vue.js +18 -0
- package/dist/components/tt-form/src/form/FormMessage.vue2.js +4 -0
- package/dist/components/tt-form/src/form/FormMessageToolTip.vue.js +30 -0
- package/dist/components/tt-form/src/form/FormMessageToolTip.vue2.js +4 -0
- package/dist/components/tt-form/src/form/RenderContent.vue.js +31 -0
- package/dist/components/tt-form/src/form/RenderContent.vue2.js +4 -0
- package/dist/components/tt-form/src/form/injectionKeys.js +4 -0
- package/dist/components/tt-form/src/form/useFormField.js +24 -0
- package/dist/components/tt-form/src/form-render/FormField.vue.js +4 -0
- package/dist/components/tt-form/src/form-render/FormField.vue2.js +345 -0
- package/dist/components/tt-form/src/form-render/FormFieldContact.js +54 -0
- package/dist/components/tt-form/src/form-render/FormLabel.vue.js +4 -0
- package/dist/components/tt-form/src/form-render/FormLabel.vue2.js +101 -0
- package/dist/components/tt-form/src/form-render/array-register/FormArrayRegister.js +195 -0
- package/dist/components/tt-form/src/form-render/array-register/props.js +47 -0
- package/dist/components/tt-form/src/form-render/array-register/utils.js +12 -0
- package/dist/components/tt-form/src/form-render/context.js +15 -0
- package/dist/components/tt-form/src/form-render/dependencies.js +51 -0
- package/dist/components/tt-form/src/form-render/expandable.js +46 -0
- package/dist/components/tt-form/src/form-render/form.vue2.js +196 -0
- package/dist/components/tt-form/src/form-render/form.vue3.js +5 -0
- package/dist/components/tt-form/src/form-render/helper.js +22 -0
- package/dist/components/tt-form/src/form-render/rootWrapperClass.js +10 -0
- package/dist/components/tt-form/src/formApi.js +790 -0
- package/dist/components/tt-form/src/group-form/GroupForm.vue2.js +223 -0
- package/dist/components/tt-form/src/group-form/GroupForm.vue3.js +5 -0
- package/dist/components/tt-form/src/group-form/GroupSection.vue2.js +277 -0
- package/dist/components/tt-form/src/group-form/GroupSection.vue3.js +5 -0
- package/dist/components/tt-form/src/group-form/LazyFormField.vue.js +153 -0
- package/dist/components/tt-form/src/group-form/LazyFormField.vue3.js +5 -0
- package/dist/components/tt-form/src/group-form/groupFormApi.js +700 -0
- package/dist/components/tt-form/src/group-form/lazyContext.js +38 -0
- package/dist/components/tt-form/src/group-form/useGroupForm.js +83 -0
- package/dist/components/tt-form/src/group-form/utils.js +106 -0
- package/dist/components/tt-form/src/hooks/useArrayRegistry.js +22 -0
- package/dist/components/tt-form/src/hooks/useFieldArray.js +137 -0
- package/dist/components/tt-form/src/hooks/useForwardPriorityValues.js +33 -0
- package/dist/components/tt-form/src/hooks/useSelectCollapse.js +81 -0
- package/dist/components/tt-form/src/index.vue2.js +147 -0
- package/dist/components/tt-form/src/index.vue3.js +5 -0
- package/dist/components/tt-form/src/shared/createContext.js +14 -0
- package/dist/components/tt-form/src/shared/global-state.js +22 -0
- package/dist/components/tt-form/src/shared/zod-defaults.js +47 -0
- package/dist/components/tt-form/src/types/forms.js +6 -0
- package/dist/components/tt-form/src/useForm.js +28 -0
- package/dist/components/tt-form/src/useFormContext.js +320 -0
- package/dist/components/tt-form/src/utils/array-path.js +18 -0
- package/dist/components/tt-form-item-error-tooltip/index.js +9 -0
- package/dist/components/tt-form-item-error-tooltip/index.vue.js +183 -0
- package/dist/components/tt-form-item-error-tooltip/index.vue3.js +5 -0
- package/dist/components/tt-icon/components/AddIcon.vue.js +28 -0
- package/dist/components/tt-icon/components/AddIcon.vue2.js +4 -0
- package/dist/components/tt-icon/components/SubIcon.vue.js +28 -0
- package/dist/components/tt-icon/components/SubIcon.vue2.js +4 -0
- package/dist/components/tt-icon/index.js +11 -0
- package/dist/components/tt-icon/index.vue.js +8 -0
- package/dist/components/tt-icon/index.vue2.js +115 -0
- package/dist/components/tt-image/index.js +9 -0
- package/dist/components/tt-image/src/components/ImageViewer.js +41 -0
- package/dist/components/tt-image/tt-image.js +55 -0
- package/dist/components/tt-loading/index.js +8 -0
- package/dist/components/tt-loading/src/directive.js +51 -0
- package/dist/components/tt-loading/src/loading.vue.js +7 -0
- package/dist/components/tt-loading/src/loading.vue2.js +75 -0
- package/dist/components/tt-loading/src/service.js +79 -0
- package/dist/components/tt-log/index.js +7 -0
- package/dist/components/tt-log/index.vue.js +31 -0
- package/dist/components/tt-log/index.vue2.js +4 -0
- package/dist/components/tt-modal/index.js +14 -0
- package/dist/components/tt-modal/src/RenderModal.vue.js +310 -0
- package/dist/components/tt-modal/src/RenderModal.vue3.js +5 -0
- package/dist/components/tt-modal/src/components/ModalFooter.vue.js +7 -0
- package/dist/components/tt-modal/src/components/ModalFooter.vue2.js +74 -0
- package/dist/components/tt-modal/src/components/ModalHeader.vue.js +7 -0
- package/dist/components/tt-modal/src/components/ModalHeader.vue2.js +22 -0
- package/dist/components/tt-modal/src/components/ModalWrapper.vue.js +48 -0
- package/dist/components/tt-modal/src/components/ModalWrapper.vue2.js +4 -0
- package/dist/components/tt-modal/src/hooks/useModalRender.js +131 -0
- package/dist/components/tt-modal/src/index.js +17 -0
- package/dist/components/tt-modal/src/props.js +75 -0
- package/dist/components/tt-modal/src/utils/modal-api.js +200 -0
- package/dist/components/tt-modal/src/utils/modal-stack.js +28 -0
- package/dist/components/tt-modal-form/hooks/useModalFormSlot.js +22 -0
- package/dist/components/tt-modal-form/index.vue.js +201 -0
- package/dist/components/tt-modal-form/index.vue2.js +4 -0
- package/dist/components/tt-modal-form/useModalForm.js +30 -0
- package/dist/components/tt-nav-anchor/index.js +8 -0
- package/dist/components/tt-nav-anchor/src/TtNavAnchor.vue.js +234 -0
- package/dist/components/tt-nav-anchor/src/TtNavAnchor.vue3.js +5 -0
- package/dist/components/tt-nav-anchor/src/constants.js +4 -0
- package/dist/components/tt-panel-select/index.js +7 -0
- package/dist/components/tt-panel-select/src/common.js +4 -0
- package/dist/components/tt-panel-select/src/components/PanelLeft.vue.js +56 -0
- package/dist/components/tt-panel-select/src/components/PanelLeft.vue2.js +4 -0
- package/dist/components/tt-panel-select/src/components/PanelMiddle.vue.js +277 -0
- package/dist/components/tt-panel-select/src/components/PanelMiddle.vue2.js +4 -0
- package/dist/components/tt-panel-select/src/components/PanelRight.vue.js +108 -0
- package/dist/components/tt-panel-select/src/components/PanelRight.vue2.js +4 -0
- package/dist/components/tt-panel-select/src/hooks/usePanelData.js +184 -0
- package/dist/components/tt-panel-select/src/hooks/usePanelSelection.js +91 -0
- package/dist/components/tt-panel-select/src/index.vue.js +386 -0
- package/dist/components/tt-panel-select/src/index.vue2.js +4 -0
- package/dist/components/tt-select/index.js +8 -0
- package/dist/components/tt-select/src/Select.vue.js +315 -0
- package/dist/components/tt-select/src/Select.vue3.js +5 -0
- package/dist/components/tt-select/src/components/SelectTable.vue.js +86 -0
- package/dist/components/tt-select/src/components/SelectTable.vue3.js +5 -0
- package/dist/components/tt-select/src/components/Table.vue.js +307 -0
- package/dist/components/tt-select/src/components/Table.vue3.js +5 -0
- package/dist/components/tt-select/src/const.js +19 -0
- package/dist/components/tt-select/src/hooks/useDataSource.js +196 -0
- package/dist/components/tt-select/src/hooks/useGrid.js +97 -0
- package/dist/components/tt-select/src/hooks/useKeyboard.js +63 -0
- package/dist/components/tt-select/src/hooks/usePagination.js +45 -0
- package/dist/components/tt-select/src/hooks/useSelect.js +100 -0
- package/dist/components/tt-select/src/hooks/useSelectTableEvent.d.ts +1 -1
- package/dist/components/tt-select/src/hooks/useSelectTableEvent.js +345 -0
- package/dist/components/tt-select/src/props.js +201 -0
- package/dist/components/tt-select/src/utils/index.js +16 -0
- package/dist/components/tt-table/index.js +63 -0
- package/dist/components/tt-table/src/Table.vue.js +623 -0
- package/dist/components/tt-table/src/Table.vue3.js +5 -0
- package/dist/components/tt-table/src/TableForm.vue.js +356 -0
- package/dist/components/tt-table/src/TableForm.vue2.js +4 -0
- package/dist/components/tt-table/src/componentMap.js +4 -0
- package/dist/components/tt-table/src/components/RowContext.js +24 -0
- package/dist/components/tt-table/src/components/TableAction.vue.js +222 -0
- package/dist/components/tt-table/src/components/TableAction.vue2.js +4 -0
- package/dist/components/tt-table/src/components/TableButtons.js +117 -0
- package/dist/components/tt-table/src/components/TableColumnModal.vue2.js +234 -0
- package/dist/components/tt-table/src/components/TableColumnModal.vue3.js +5 -0
- package/dist/components/tt-table/src/components/TableToobalTools.vue.js +87 -0
- package/dist/components/tt-table/src/components/TableToobalTools.vue2.js +4 -0
- package/dist/components/tt-table/src/emits.js +15 -0
- package/dist/components/tt-table/src/hooks/useCellArea.js +15 -0
- package/dist/components/tt-table/src/hooks/useColumns.js +275 -0
- package/dist/components/tt-table/src/hooks/useCustomColumns.js +53 -0
- package/dist/components/tt-table/src/hooks/useDataSource.js +224 -0
- package/dist/components/tt-table/src/hooks/useLeftRightSlot.js +64 -0
- package/dist/components/tt-table/src/hooks/usePagination.js +44 -0
- package/dist/components/tt-table/src/hooks/useRowSelection.js +84 -0
- package/dist/components/tt-table/src/hooks/useTableContext.js +20 -0
- package/dist/components/tt-table/src/hooks/useTableEvent.js +197 -0
- package/dist/components/tt-table/src/hooks/useTableForm.js +60 -0
- package/dist/components/tt-table/src/hooks/useTableRender.js +33 -0
- package/dist/components/tt-table/src/hooks/useTableSlot.js +17 -0
- package/dist/components/tt-table/src/props.js +482 -0
- package/dist/components/tt-table/src/toolProps.js +30 -0
- package/dist/components/tt-table/src/utils/context.js +17 -0
- package/dist/components/tt-table/src/utils/table-api.js +386 -0
- package/dist/components/tt-table/src/utils/table-form-api.js +122 -0
- package/dist/components/tt-text/index.js +7 -0
- package/dist/components/tt-text/index.vue.js +7 -0
- package/dist/components/tt-text/index.vue2.js +73 -0
- package/dist/components/tt-upload/index.js +9 -0
- package/dist/components/tt-upload/src/TtUpload.vue.js +306 -0
- package/dist/components/tt-upload/src/TtUpload.vue2.js +4 -0
- package/dist/components/tt-upload/src/typing.js +107 -0
- package/dist/directives/auto-tip/index.js +62 -0
- package/dist/directives/dialog-resize/index.js +49 -0
- package/dist/directives/dialog-resize/use-css-variable.js +44 -0
- package/dist/directives/dialog-resize/use-draggable.js +35 -0
- package/dist/directives/dialog-resize/use-fullscreen.js +38 -0
- package/dist/directives/dialog-resize/use-parse-translate.js +9 -0
- package/dist/directives/dialog-resize/use-resizer.js +37 -0
- package/dist/directives/disabled-tip/index.js +78 -0
- package/dist/directives/index.js +8 -0
- package/dist/hooks/useDataPermissionOptions.js +142 -0
- package/dist/hooks/useFormSchemasLink.js +261 -0
- package/dist/hooks/useFormat.js +44 -0
- package/dist/hooks/useLoading.js +22 -0
- package/dist/hooks/useScreenshotOss.js +69 -0
- package/dist/hooks/useSetup.js +59 -0
- package/dist/hooks/useTable.js +13 -0
- package/dist/hooks/useTemplateSlot.js +13 -0
- package/dist/index.js +142 -60274
- package/dist/plugins/default/renderCellContent.js +58 -0
- package/dist/plugins/vxeTable/switchStatus.js +91 -0
- package/dist/plugins.js +4 -146
- package/dist/style.css +1 -1
- package/dist/utils/xhr.js +8 -0
- package/package.json +5 -3
- package/dist/index-NG5FNCLD.js +0 -3430
- package/dist/index.modern-4Cf3dcJP.js +0 -3069
|
@@ -0,0 +1,700 @@
|
|
|
1
|
+
var M = Object.defineProperty;
|
|
2
|
+
var A = (u, c, e) => c in u ? M(u, c, { enumerable: !0, configurable: !0, writable: !0, value: e }) : u[c] = e;
|
|
3
|
+
var n = (u, c, e) => A(u, typeof c != "symbol" ? c + "" : c, e);
|
|
4
|
+
import { isFunction as S, isString as b, isBoolean as G } from "@dazhicheng/utils";
|
|
5
|
+
import { isPlainObject as p, get as v, cloneDeep as V } from "lodash-es";
|
|
6
|
+
import { ref as N, reactive as f, nextTick as C } from "vue";
|
|
7
|
+
import { FormApi as P } from "../formApi.js";
|
|
8
|
+
import { resolveValueByFieldName as E } from "../form-render/dependencies.js";
|
|
9
|
+
import { resolveSchemaFieldInitialValue as k } from "../useFormContext.js";
|
|
10
|
+
import { normalizeArrayFieldPath as y, childArrayPath as H } from "../utils/array-path.js";
|
|
11
|
+
import { extractFlatSchemas as m, collectDefaultCollapseStates as w, getGroupValues as K, cloneSchemaTree as _, insertFieldsByPosition as O, removeFieldsFromGroup as j, removeGroupsFromGroup as T, isGroupSchema as R, isRowSchema as x } from "./utils.js";
|
|
12
|
+
class L extends P {
|
|
13
|
+
/**
|
|
14
|
+
* @param {TtFormProps} formProps - 底层表单配置(已展平的 schema、layout 等)
|
|
15
|
+
* @param {GroupFormApiOptions} groupOptions - 分组场景专属配置
|
|
16
|
+
*/
|
|
17
|
+
constructor(e, t) {
|
|
18
|
+
super(e);
|
|
19
|
+
/** 是否启用虚拟化(IntersectionObserver 懒渲染) */
|
|
20
|
+
n(this, "virtual");
|
|
21
|
+
/** 构造时的导航锚点默认配置,作为 store 未设置时的 fallback */
|
|
22
|
+
n(this, "_defaultNavAnchorProps");
|
|
23
|
+
/** 校验失败时是否自动滚动到第一个有错误的分组,默认 true */
|
|
24
|
+
n(this, "_scrollToFirstError");
|
|
25
|
+
/** 滚动容器高度 */
|
|
26
|
+
n(this, "_containerHeight");
|
|
27
|
+
/** IntersectionObserver rootMargin */
|
|
28
|
+
n(this, "_rootMargin");
|
|
29
|
+
/** 预估每个表单项高度(px) */
|
|
30
|
+
n(this, "_estimateFieldHeight");
|
|
31
|
+
/** 滚动到分组时的顶部偏移量(px),补偿固定元素遮挡 */
|
|
32
|
+
n(this, "_scrollOffset");
|
|
33
|
+
/** 各分组折叠状态(key → 是否折叠) */
|
|
34
|
+
n(this, "collapseStates");
|
|
35
|
+
/** 当前被 ifShow 隐藏的分组 key 集合 */
|
|
36
|
+
n(this, "hiddenGroupKeys");
|
|
37
|
+
/** 当前被 ifShow 隐藏的字段名集合 */
|
|
38
|
+
n(this, "hiddenFieldNames");
|
|
39
|
+
/** 导航各分组的错误数量,validate 后自动更新 */
|
|
40
|
+
n(this, "navErrorCounts");
|
|
41
|
+
/** 共享错误缓存,validate 写入 → LazyFormField 挂载时读取恢复 */
|
|
42
|
+
n(this, "errorCacheMap", /* @__PURE__ */ new Map());
|
|
43
|
+
/** 重置信号,递增时通知所有 LazyFormField 清空 cachedError */
|
|
44
|
+
n(this, "resetSignal", N(0));
|
|
45
|
+
/** 初始传入的分组 schema(用于 fallback) */
|
|
46
|
+
n(this, "_initialGroupSchema");
|
|
47
|
+
/** 初始展平后的 flatSchema(用于 fallback) */
|
|
48
|
+
n(this, "_initialFlatSchema");
|
|
49
|
+
/** 各分组 key → 其直属字段名(不含子分组的字段) */
|
|
50
|
+
n(this, "_groupFieldMap", {});
|
|
51
|
+
/** 各分组 key → 其直属子分组 key 列表 */
|
|
52
|
+
n(this, "_groupChildrenMap", {});
|
|
53
|
+
/** 字段名 → 所属分组 key 的反向映射,用于快速判断字段是否属于隐藏分组 */
|
|
54
|
+
n(this, "_fieldToGroupKey", {});
|
|
55
|
+
/** 子分组 key → 父分组 key 的映射,用于递归向上查找祖先分组是否被隐藏 */
|
|
56
|
+
n(this, "_groupParentMap", {});
|
|
57
|
+
/** 字段名 → 字段 schema 的映射,用于隐藏清空时读取默认值 */
|
|
58
|
+
n(this, "_fieldSchemaMap", {});
|
|
59
|
+
/** 分组 key 构建时的去重集合,用于检测重复 key */
|
|
60
|
+
n(this, "_groupKeySet", /* @__PURE__ */ new Set());
|
|
61
|
+
/** 是否已执行过 validate,用于控制导航栏错误同步是否需要重新校验未挂载字段 */
|
|
62
|
+
n(this, "_hasValidated", !1);
|
|
63
|
+
/** VirtualGroupForm 组件实例引用,由 useGroupForm 的 h() 渲染时赋值 */
|
|
64
|
+
n(this, "groupFormRef", N(null));
|
|
65
|
+
/**
|
|
66
|
+
* @description 响应式读取 store 状态,由 useGroupForm 在运行时注入实现
|
|
67
|
+
* @param {Function} [selector] - 可选的状态选择器
|
|
68
|
+
* @returns {Readonly<Ref<T>>} 响应式状态引用
|
|
69
|
+
*/
|
|
70
|
+
n(this, "useStore");
|
|
71
|
+
const {
|
|
72
|
+
groupSchema: r,
|
|
73
|
+
virtual: s = !0,
|
|
74
|
+
navAnchorProps: o,
|
|
75
|
+
scrollToFirstError: i = !0,
|
|
76
|
+
containerHeight: a = "100%",
|
|
77
|
+
rootMargin: l = "400px 0px",
|
|
78
|
+
estimateFieldHeight: h = 52,
|
|
79
|
+
scrollOffset: d = 0
|
|
80
|
+
} = t;
|
|
81
|
+
this.virtual = s, this._defaultNavAnchorProps = { show: !0, ...o }, this._scrollToFirstError = i, this._containerHeight = a, this._rootMargin = l, this._estimateFieldHeight = h, this._scrollOffset = d, this._initialGroupSchema = r, this._initialFlatSchema = m(r), this.collapseStates = f({}), w(r, this.collapseStates), this.hiddenGroupKeys = f(/* @__PURE__ */ new Set()), this.hiddenFieldNames = f(/* @__PURE__ */ new Set()), this.navErrorCounts = f({}), this._buildGroupFieldMap(r), this.setState({
|
|
82
|
+
groupSchema: r,
|
|
83
|
+
navAnchorProps: this._defaultNavAnchorProps,
|
|
84
|
+
virtual: s,
|
|
85
|
+
containerHeight: a,
|
|
86
|
+
rootMargin: l,
|
|
87
|
+
estimateFieldHeight: h,
|
|
88
|
+
scrollOffset: d
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* @description 从 store 响应式读取 navAnchorProps,支持通过 setState({ navAnchorProps }) 动态修改
|
|
93
|
+
* @returns {Required<Pick<UseGroupFormNavAnchorProps, "show">> & UseGroupFormNavAnchorProps} 导航锚点配置
|
|
94
|
+
*/
|
|
95
|
+
get navAnchorProps() {
|
|
96
|
+
return this.store.state.navAnchorProps ?? this._defaultNavAnchorProps;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* @description 覆盖基类 setState,扩展支持 GroupFormExtraState 中的字段(navAnchorProps、groupSchema 等)。
|
|
100
|
+
* @param {Partial<GroupFormState> | ((prev: GroupFormState) => Partial<GroupFormState>)} stateOrFn - 新状态或更新函数
|
|
101
|
+
*/
|
|
102
|
+
setState(e) {
|
|
103
|
+
const t = this.store.state, r = S(e) ? e(t) : e;
|
|
104
|
+
if (super.setState(e), r.groupSchema === void 0)
|
|
105
|
+
return;
|
|
106
|
+
const s = this.store.state.groupSchema;
|
|
107
|
+
!s || s === t.groupSchema || (this._buildGroupFieldMap(s), super.setState({ schema: m(s) }));
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* @description 分组表单以 `groupSchema` 展平结果为字段全集。仅依赖 store 中的 `schema` 时,若与 `groupSchema` 不同步(例如外部只 `setState` 了 `groupSchema`、或合并顺序导致 `schema` 滞后),`setValues` 默认过滤会误删合法字段;此处优先按 `groupSchema` 展平生成白名单。
|
|
111
|
+
* @returns {string[]} 允许 `setValues` 写入的 fieldName 列表
|
|
112
|
+
*/
|
|
113
|
+
getFieldNamesForSetValuesFilter() {
|
|
114
|
+
const e = this.store.state.groupSchema;
|
|
115
|
+
return e != null && e.length ? m(e).map((t) => t.fieldName).filter((t) => typeof t == "string" && t.length > 0) : super.getFieldNamesForSetValuesFilter();
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* @description schema 中移除字段后清空 vee 值/错误,并同步清理虚拟列表 errorCacheMap
|
|
119
|
+
* @param {string[]} removedFieldNames 已移除的 fieldName 列表
|
|
120
|
+
*/
|
|
121
|
+
onRemovedSchemaFields(e) {
|
|
122
|
+
if (e.length) {
|
|
123
|
+
super.onRemovedSchemaFields(e);
|
|
124
|
+
for (const t of e)
|
|
125
|
+
this.errorCacheMap.delete(t), this.unregisterArrayField(t);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* @description 校验表单(含未挂载的虚拟字段),支持通过第二个参数控制是否滚动到第一个错误分组
|
|
130
|
+
* @param {Partial<ValidationOptions>} [opts] - 原始 validate 选项
|
|
131
|
+
* @param {boolean} [scrollToError] - 是否滚动到第一个错误分组,不传时使用全局配置 scrollToFirstError
|
|
132
|
+
* @returns {Promise<{valid: boolean; errors: Record<string, string>; results?: any}>} 校验结果
|
|
133
|
+
* @example
|
|
134
|
+
* await formApi.validate();
|
|
135
|
+
* @example
|
|
136
|
+
* await formApi.validate(undefined, true);
|
|
137
|
+
* @example
|
|
138
|
+
* await formApi.validate(undefined, false);
|
|
139
|
+
*/
|
|
140
|
+
async validate(e, t) {
|
|
141
|
+
let r = await super.validate(e);
|
|
142
|
+
return this.hiddenFieldNames.size > 0 && (r = this._stripHiddenFieldErrors(r)), this.virtual && (this.errorCacheMap.clear(), this._hasValidated = !0, r = await this._validateUnmountedFields(r)), this.navAnchorProps.show && await this.syncNavErrorCountsFromForm(), (t ?? this._scrollToFirstError) && !r.valid && this._scrollToFirstErrorGroup(r.errors), r;
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* @description 校验并提交表单
|
|
146
|
+
* @returns {Promise<any>} 提交结果,校验失败时返回 undefined
|
|
147
|
+
*/
|
|
148
|
+
async validateAndSubmitForm() {
|
|
149
|
+
if ((await this.validate()).valid)
|
|
150
|
+
return await this.submitForm();
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* @description 重置表单(含清空虚拟字段错误缓存和导航错误计数)
|
|
154
|
+
* @param {Partial<FormState<GenericObject>>} [state] - 重置后的表单状态
|
|
155
|
+
* @param {Partial<ResetFormOpts>} [opts] - 重置选项
|
|
156
|
+
*/
|
|
157
|
+
async resetForm(e, t) {
|
|
158
|
+
return this.virtual && (this._clearAllCachedErrors(), this._hasValidated = !1), this.navAnchorProps.show && this._clearNavErrorCounts(), await super.resetForm(e, t);
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* @description 重置校验状态(含清空虚拟字段错误缓存和导航错误计数)
|
|
162
|
+
*/
|
|
163
|
+
async resetValidate() {
|
|
164
|
+
return this.virtual && (this._clearAllCachedErrors(), this._hasValidated = !1), this.navAnchorProps.show && this._clearNavErrorCounts(), await super.resetValidate();
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* @description 获取表单值
|
|
168
|
+
* @param {boolean} [isGroup] - 为 true 时返回按分组 key 嵌套的对象,默认 false 返回扁平值
|
|
169
|
+
* @returns {Promise<T>} 表单值
|
|
170
|
+
*/
|
|
171
|
+
async getValues(e = !1) {
|
|
172
|
+
const t = await super.getValues();
|
|
173
|
+
if (e) {
|
|
174
|
+
const r = this.store.state.groupSchema ?? this._initialGroupSchema;
|
|
175
|
+
return K(r, t);
|
|
176
|
+
}
|
|
177
|
+
return t;
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* @description 滚动到指定分组(外部可通过 formApi.scrollToGroup 调用)
|
|
181
|
+
* @param {string} key - 分组 key
|
|
182
|
+
*/
|
|
183
|
+
scrollToGroup(e) {
|
|
184
|
+
var r;
|
|
185
|
+
const t = this.groupFormRef.value;
|
|
186
|
+
(r = t == null ? void 0 : t.scrollToGroup) == null || r.call(t, e);
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* @description 切换分组折叠状态
|
|
190
|
+
* @param {string} key - 分组 key
|
|
191
|
+
*/
|
|
192
|
+
toggleCollapse(e) {
|
|
193
|
+
this.collapseStates[e] = !this.collapseStates[e];
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* @description 设置分组折叠状态
|
|
197
|
+
* @param {string} key - 分组 key
|
|
198
|
+
* @param {boolean} collapsed - 是否折叠
|
|
199
|
+
*/
|
|
200
|
+
setGroupCollapsed(e, t) {
|
|
201
|
+
this.collapseStates[e] = t;
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* @description 设置容器的可见性状态,由 GroupSection 组件在 ifShow 求值后调用。
|
|
205
|
+
* group 隐藏时额外维护 {@link hiddenGroupKeys} 供导航和渲染判断;
|
|
206
|
+
* group / row 隐藏时都会清空其下字段校验,并把字段加入 {@link hiddenFieldNames},使隐藏字段不参与校验。
|
|
207
|
+
* 可见性变化后在下一帧调用 {@link syncNavErrorCountsFromForm},使「先 validate 再隐藏再显示」时
|
|
208
|
+
* 导航徽标、{@link errorCacheMap} 与表单项错误展示保持一致。
|
|
209
|
+
* @param {string} key - 分组 key
|
|
210
|
+
* @param {boolean} visible - 是否可见
|
|
211
|
+
* @param {string[]} [fieldNames] - 兼容旧内部调用的字段名列表,传入时按字段集合显隐处理
|
|
212
|
+
*/
|
|
213
|
+
setGroupVisible(e, t, r) {
|
|
214
|
+
if (r) {
|
|
215
|
+
this.setFieldsVisible(r, t);
|
|
216
|
+
return;
|
|
217
|
+
}
|
|
218
|
+
const s = this.getGroupFieldNames(e);
|
|
219
|
+
t ? (this.hiddenGroupKeys.delete(e), this._setFieldsHidden(s, !1)) : (this._setFieldsHidden(s, !0), this._clearHiddenFieldValues(s), this.hiddenGroupKeys.add(e)), C(() => {
|
|
220
|
+
this.syncNavErrorCountsFromForm();
|
|
221
|
+
});
|
|
222
|
+
}
|
|
223
|
+
/**
|
|
224
|
+
* @description 设置字段集合的可见性状态,用于 row 容器隐藏时同步字段值、校验和错误缓存。
|
|
225
|
+
* @param {string[]} fieldNames - 字段名列表
|
|
226
|
+
* @param {boolean} visible - 是否可见
|
|
227
|
+
*/
|
|
228
|
+
setFieldsVisible(e, t) {
|
|
229
|
+
t ? this._setFieldsHidden(e, !1) : (this._setFieldsHidden(e, !0), this._clearHiddenFieldValues(e)), C(() => {
|
|
230
|
+
this.syncNavErrorCountsFromForm();
|
|
231
|
+
});
|
|
232
|
+
}
|
|
233
|
+
/**
|
|
234
|
+
* @description 判断字段是否属于被隐藏的字段集合
|
|
235
|
+
* @param {string} fieldName - 字段名
|
|
236
|
+
* @returns {boolean} 是否属于隐藏字段
|
|
237
|
+
*/
|
|
238
|
+
_isFieldHidden(e) {
|
|
239
|
+
if (this.hiddenFieldNames.size === 0) return !1;
|
|
240
|
+
for (const t of this.hiddenFieldNames)
|
|
241
|
+
if (this._matchFieldOrNested(e, t)) return !0;
|
|
242
|
+
return !1;
|
|
243
|
+
}
|
|
244
|
+
/**
|
|
245
|
+
* @description 判断错误键是否命中字段(支持数组/对象嵌套键)
|
|
246
|
+
* @param {string} errorKey - 错误键(如 a[0].b)
|
|
247
|
+
* @param {string} field - schema 字段(如 a)
|
|
248
|
+
* @returns {boolean}
|
|
249
|
+
*/
|
|
250
|
+
_matchFieldOrNested(e, t) {
|
|
251
|
+
const r = y(e), s = y(t);
|
|
252
|
+
return r === s || r.startsWith(`${s}.`) || r.startsWith(`${s}[`);
|
|
253
|
+
}
|
|
254
|
+
/**
|
|
255
|
+
* @description 按当前 store 中的 groupSchema(若无则用初始 schema)重置折叠状态:
|
|
256
|
+
* 先清空已有 key,再按 `defaultCollapsed` 写入默认值。
|
|
257
|
+
* 用于同一 `formApi` 实例下分组表单卸载后再次挂载(如弹框 `destroy-on-close`)时,避免沿用上次折叠状态。
|
|
258
|
+
*/
|
|
259
|
+
resetCollapseStatesToDefault() {
|
|
260
|
+
const e = this.store.state.groupSchema ?? this._initialGroupSchema;
|
|
261
|
+
for (const t of Object.keys(this.collapseStates))
|
|
262
|
+
delete this.collapseStates[t];
|
|
263
|
+
w(e, this.collapseStates);
|
|
264
|
+
}
|
|
265
|
+
/**
|
|
266
|
+
* @description 全量应用分组 schema 树到 store(扁平 schema、groupSchema、分组字段映射、折叠默认值)。
|
|
267
|
+
*/
|
|
268
|
+
_applyGroupSchema(e) {
|
|
269
|
+
this.setState({ groupSchema: e });
|
|
270
|
+
}
|
|
271
|
+
/**
|
|
272
|
+
* @description 增量插入字段到分组 schema 树中,无需全量重建 schema。
|
|
273
|
+
* 通过 position 的 before/after 在整棵树中递归查找锚点并就地插入;
|
|
274
|
+
* 不传 position 时追加到顶层 schema 末尾。
|
|
275
|
+
* @param {GroupFormSchema[]} fields - 要插入的字段或子结构(字段、slot、row 等均可)
|
|
276
|
+
* @param {InsertPosition} [position] - 插入位置,省略则追加到顶层末尾
|
|
277
|
+
* @example
|
|
278
|
+
* formApi.appendFields([newField], { before: 'phone' });
|
|
279
|
+
* @example
|
|
280
|
+
* formApi.appendFields([newField], { after: 'email' });
|
|
281
|
+
* @example
|
|
282
|
+
* formApi.appendFields([newGroup]);
|
|
283
|
+
*/
|
|
284
|
+
appendFields(e, t) {
|
|
285
|
+
const r = this.store.state.groupSchema ?? [], s = _(r);
|
|
286
|
+
t && (t.before || t.after) ? O(s, e, t) || s.push(...e) : s.push(...e), this._applyGroupSchema(s), this.seedDefaultsForAppendedFields(m(e));
|
|
287
|
+
}
|
|
288
|
+
/**
|
|
289
|
+
* @description 按标识从 groupSchema 树中移除节点,无需全量重建 schema。
|
|
290
|
+
* 支持匹配 fieldName(普通字段 / row 内字段)和 slot 的字符串 content
|
|
291
|
+
* @param {string[]} fieldNames - 要移除的标识列表(fieldName 或 slot content 字符串)
|
|
292
|
+
* @example
|
|
293
|
+
* formApi.removeFields(['v_phone', 'v_email']);
|
|
294
|
+
*/
|
|
295
|
+
removeFields(e) {
|
|
296
|
+
if (!e.length) return;
|
|
297
|
+
const t = this.store.state.groupSchema ?? [], r = j(_(t), new Set(e));
|
|
298
|
+
this._applyGroupSchema(r);
|
|
299
|
+
}
|
|
300
|
+
/**
|
|
301
|
+
* @description 清理已移除分组的运行时状态(隐藏集、折叠、导航徽标等)
|
|
302
|
+
* @param keysToRemove - 待移除的分组 key(含子分组)
|
|
303
|
+
*/
|
|
304
|
+
_purgeRemovedGroupState(e) {
|
|
305
|
+
for (const r of e)
|
|
306
|
+
this._setFieldsHidden(this.getGroupFieldNames(r), !1), this.hiddenGroupKeys.delete(r), Reflect.deleteProperty(this.navErrorCounts, r), Reflect.deleteProperty(this.collapseStates, r);
|
|
307
|
+
const t = this.navAnchorProps.extraBadgeCounts;
|
|
308
|
+
if (t)
|
|
309
|
+
for (const r of e)
|
|
310
|
+
Reflect.deleteProperty(t, r);
|
|
311
|
+
for (const r of Object.keys(this.navErrorCounts))
|
|
312
|
+
r in this._groupFieldMap || Reflect.deleteProperty(this.navErrorCounts, r);
|
|
313
|
+
}
|
|
314
|
+
/**
|
|
315
|
+
* @description 按分组 key 移除分组及其子分组(从 groupSchema 树删除),并清空其下字段值与相关状态
|
|
316
|
+
* @param groupKey - 分组 key(单个或数组)
|
|
317
|
+
* @example
|
|
318
|
+
* formApi.removeGroups(['group1', 'group2']);
|
|
319
|
+
* formApi.removeGroups('group1');
|
|
320
|
+
*/
|
|
321
|
+
removeGroups(e) {
|
|
322
|
+
const t = Array.isArray(e) ? e : [e], r = this._collectGroupKeysWithDescendants(t);
|
|
323
|
+
if (!r.length)
|
|
324
|
+
return;
|
|
325
|
+
const s = [...new Set(r.flatMap((a) => this.getGroupFieldNames(a, !0)))], o = this.store.state.groupSchema ?? [], i = T(_(o), new Set(r));
|
|
326
|
+
this._applyGroupSchema(i), s.length && this.onRemovedSchemaFields(s), this._purgeRemovedGroupState(r), this.navAnchorProps.show && this.syncNavErrorCountsFromForm();
|
|
327
|
+
}
|
|
328
|
+
/**
|
|
329
|
+
* @description 合并 vee-validate 实时 errors 与虚拟列表未挂载字段的 errorCacheMap,用于导航徽标与输入联动
|
|
330
|
+
* @returns {Record<string, string>} 合并后的错误映射
|
|
331
|
+
*/
|
|
332
|
+
_mergeErrorsForNav() {
|
|
333
|
+
var r, s;
|
|
334
|
+
const e = (s = (r = this.form) == null ? void 0 : r.errors) == null ? void 0 : s.value, t = {};
|
|
335
|
+
if (e && typeof e == "object")
|
|
336
|
+
for (const o of Object.keys(e)) {
|
|
337
|
+
if (this._isFieldHidden(o)) continue;
|
|
338
|
+
const i = e[o];
|
|
339
|
+
i && (t[o] = i);
|
|
340
|
+
}
|
|
341
|
+
return this.virtual && this.errorCacheMap.forEach((o, i) => {
|
|
342
|
+
this._isFieldHidden(i) || o && t[i] === void 0 && (t[i] = o);
|
|
343
|
+
}), t;
|
|
344
|
+
}
|
|
345
|
+
/**
|
|
346
|
+
* @description 同步导航错误计数。
|
|
347
|
+
* 当开启虚拟列表且已执行过 validate 时,会重新对未挂载字段做可见性检查和校验,
|
|
348
|
+
* 确保 dependencies 条件变化后错误计数实时更新。
|
|
349
|
+
*/
|
|
350
|
+
async syncNavErrorCountsFromForm() {
|
|
351
|
+
var a, l;
|
|
352
|
+
if (!this.virtual || !this._hasValidated) {
|
|
353
|
+
this._updateNavErrorCounts(this._mergeErrorsForNav());
|
|
354
|
+
return;
|
|
355
|
+
}
|
|
356
|
+
const e = this.form;
|
|
357
|
+
if (!(e != null && e.values)) {
|
|
358
|
+
this._updateNavErrorCounts(this._mergeErrorsForNav());
|
|
359
|
+
return;
|
|
360
|
+
}
|
|
361
|
+
const t = e.values, r = (l = (a = this.form) == null ? void 0 : a.errors) == null ? void 0 : l.value, s = /* @__PURE__ */ new Set();
|
|
362
|
+
if (r)
|
|
363
|
+
for (const h of Object.keys(r))
|
|
364
|
+
s.add(h);
|
|
365
|
+
const o = {};
|
|
366
|
+
if (r && typeof r == "object")
|
|
367
|
+
for (const h of Object.keys(r)) {
|
|
368
|
+
if (this._isFieldHidden(h)) continue;
|
|
369
|
+
const d = r[h];
|
|
370
|
+
d && (o[h] = d);
|
|
371
|
+
}
|
|
372
|
+
const i = this.store.state.schema ?? this._initialFlatSchema;
|
|
373
|
+
for (const h of i) {
|
|
374
|
+
const d = h.fieldName;
|
|
375
|
+
if (!d || s.has(d)) continue;
|
|
376
|
+
if (!await this._isFieldVisible(h, t)) {
|
|
377
|
+
this.errorCacheMap.delete(d);
|
|
378
|
+
continue;
|
|
379
|
+
}
|
|
380
|
+
const F = E(t, d), g = await this._validateFieldValue(F, h.rules, d);
|
|
381
|
+
g ? (this.errorCacheMap.set(d, g), o[d] = g) : this.errorCacheMap.delete(d);
|
|
382
|
+
}
|
|
383
|
+
this._updateNavErrorCounts(o);
|
|
384
|
+
}
|
|
385
|
+
/**
|
|
386
|
+
* @description 清空导航各分组的错误计数
|
|
387
|
+
*/
|
|
388
|
+
_clearNavErrorCounts() {
|
|
389
|
+
for (const e of Object.keys(this.navErrorCounts))
|
|
390
|
+
this.navErrorCounts[e] = 0;
|
|
391
|
+
}
|
|
392
|
+
/**
|
|
393
|
+
* @description 校验失败后展开包含错误的分组,并滚动到该分组标题
|
|
394
|
+
* @param {Record<string, string>} errors - 合并后的所有错误
|
|
395
|
+
*/
|
|
396
|
+
_scrollToFirstErrorGroup(e) {
|
|
397
|
+
const t = this._findFirstErrorGroupKey(e);
|
|
398
|
+
t && (this.collapseStates[t] && this.toggleCollapse(t), this.scrollToGroup(t));
|
|
399
|
+
}
|
|
400
|
+
/**
|
|
401
|
+
* @description 从校验结果中剔除属于隐藏字段集合的错误,并重新判定 valid 状态
|
|
402
|
+
* @param {object} result - 校验结果
|
|
403
|
+
* @returns {object} 过滤后的校验结果
|
|
404
|
+
*/
|
|
405
|
+
_stripHiddenFieldErrors(e) {
|
|
406
|
+
const t = {};
|
|
407
|
+
let r = !1;
|
|
408
|
+
for (const [s, o] of Object.entries(e.errors))
|
|
409
|
+
this._isFieldHidden(s) || (t[s] = o, o && (r = !0));
|
|
410
|
+
return { ...e, errors: t, valid: !r };
|
|
411
|
+
}
|
|
412
|
+
/**
|
|
413
|
+
* @description 对单个字段值执行 rules 校验(纯数据,不挂载组件)。
|
|
414
|
+
* 支持字符串规则("required" / "selectRequired")和 Zod schema。
|
|
415
|
+
* @param {unknown} value - 字段值
|
|
416
|
+
* @param {FormSchemaRuleType | undefined} rules - 校验规则
|
|
417
|
+
* @param {string} fieldName - 字段名
|
|
418
|
+
* @returns {Promise<string | undefined>} 错误信息,无错误返回 undefined
|
|
419
|
+
*/
|
|
420
|
+
async _validateFieldValue(e, t, r) {
|
|
421
|
+
var s;
|
|
422
|
+
if (t) {
|
|
423
|
+
if (b(t)) {
|
|
424
|
+
if (t === "required") {
|
|
425
|
+
if (e == null || e === "")
|
|
426
|
+
return "请输入";
|
|
427
|
+
} else if (t === "selectRequired" && (e == null || Array.isArray(e) && e.length === 0 || e === ""))
|
|
428
|
+
return "请选择";
|
|
429
|
+
return;
|
|
430
|
+
}
|
|
431
|
+
try {
|
|
432
|
+
const i = t.safeParse(e);
|
|
433
|
+
if (!i.success)
|
|
434
|
+
return ((s = i.error.issues[0]) == null ? void 0 : s.message) || `${r} 校验失败`;
|
|
435
|
+
} catch {
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
/**
|
|
440
|
+
* @description 检查字段的 dependencies 条件,判断字段在当前值下是否应该被校验。
|
|
441
|
+
* 与 FormField.vue 保持一致:visible = !hide && isIf && isShow
|
|
442
|
+
* @param {FormSchema} schema - 字段 schema
|
|
443
|
+
* @param {Record<string, any>} values - 当前表单值
|
|
444
|
+
* @returns {Promise<boolean>} 字段是否可见
|
|
445
|
+
*/
|
|
446
|
+
async _isFieldVisible(e, t) {
|
|
447
|
+
if (e.fieldName && this._isFieldHidden(e.fieldName) || e.hide) return !1;
|
|
448
|
+
const r = e.dependencies;
|
|
449
|
+
if (!r) return !0;
|
|
450
|
+
const s = r.if;
|
|
451
|
+
if (s != null && (G(s) && !s || S(s) && !await s(t, this.form)))
|
|
452
|
+
return !1;
|
|
453
|
+
const o = r.show;
|
|
454
|
+
return !(o != null && (G(o) && !o || S(o) && !await o(t, this.form)));
|
|
455
|
+
}
|
|
456
|
+
/**
|
|
457
|
+
* @description 对所有未挂载的字段做纯值校验,补充到 validate 结果中,
|
|
458
|
+
* 并将错误写入 errorCacheMap 以便 LazyFormField 挂载时恢复。
|
|
459
|
+
* 会跳过因 dependencies.if 条件不满足而不应渲染的字段,与原始表单校验行为一致。
|
|
460
|
+
* @param {object} validateResult - 父类 validate 返回的校验结果
|
|
461
|
+
* @returns {Promise<object>} 补充未挂载字段错误后的校验结果
|
|
462
|
+
*/
|
|
463
|
+
async _validateUnmountedFields(e) {
|
|
464
|
+
const t = this.form;
|
|
465
|
+
if (!(t != null && t.values)) return e;
|
|
466
|
+
const r = t.values, s = new Set(Object.keys(e.results || {})), o = {}, i = this.store.state.schema ?? this._initialFlatSchema;
|
|
467
|
+
for (const a of i) {
|
|
468
|
+
const l = a.fieldName;
|
|
469
|
+
if (!l || s.has(l) || !await this._isFieldVisible(a, r)) continue;
|
|
470
|
+
const h = E(r, l), d = await this._validateFieldValue(h, a.rules, l);
|
|
471
|
+
d && (o[l] = d, this.errorCacheMap.set(l, d));
|
|
472
|
+
}
|
|
473
|
+
return Object.keys(o).length > 0 ? {
|
|
474
|
+
valid: !1,
|
|
475
|
+
errors: { ...e.errors, ...o },
|
|
476
|
+
results: e.results
|
|
477
|
+
} : e;
|
|
478
|
+
}
|
|
479
|
+
/**
|
|
480
|
+
* @description 清空所有缓存的错误并递增重置信号
|
|
481
|
+
*/
|
|
482
|
+
_clearAllCachedErrors() {
|
|
483
|
+
this.errorCacheMap.clear(), this.resetSignal.value++;
|
|
484
|
+
}
|
|
485
|
+
/**
|
|
486
|
+
* @description 收集分组 key 及其所有子分组 key(去重)
|
|
487
|
+
* @param keys - 起始分组 key 列表
|
|
488
|
+
*/
|
|
489
|
+
_collectGroupKeysWithDescendants(e) {
|
|
490
|
+
const t = /* @__PURE__ */ new Set(), r = (s) => {
|
|
491
|
+
if (!(!s || t.has(s))) {
|
|
492
|
+
t.add(s);
|
|
493
|
+
for (const o of this._groupChildrenMap[s] ?? [])
|
|
494
|
+
r(o);
|
|
495
|
+
}
|
|
496
|
+
};
|
|
497
|
+
for (const s of e)
|
|
498
|
+
r(s);
|
|
499
|
+
return [...t];
|
|
500
|
+
}
|
|
501
|
+
/**
|
|
502
|
+
* @description 递归构建各分组 key → 其直属字段名的映射
|
|
503
|
+
* @param {GroupFormSchema[]} schemas - 分组 schema 数组
|
|
504
|
+
* @param {string} [parentKey] - 父分组 key
|
|
505
|
+
*/
|
|
506
|
+
_buildGroupFieldMap(e, t) {
|
|
507
|
+
var r;
|
|
508
|
+
t || (this._groupFieldMap = {}, this._groupChildrenMap = {}, this._fieldToGroupKey = {}, this._groupParentMap = {}, this._fieldSchemaMap = {}, this._groupKeySet.clear());
|
|
509
|
+
for (const s of e)
|
|
510
|
+
if (R(s)) {
|
|
511
|
+
if (this._groupKeySet.has(s.key))
|
|
512
|
+
throw new Error(
|
|
513
|
+
`[GroupFormApi] duplicate group key detected: "${s.key}". Group key must be unique in groupSchema tree.`
|
|
514
|
+
);
|
|
515
|
+
this._groupKeySet.add(s.key), this._groupFieldMap[s.key] = [], this._groupChildrenMap[s.key] = [], t && (this._groupParentMap[s.key] = t, (r = this._groupChildrenMap)[t] ?? (r[t] = []), this._groupChildrenMap[t].push(s.key)), this._buildGroupFieldMap(s.children, s.key);
|
|
516
|
+
} else x(s) ? this._buildGroupFieldMap(s.children, t) : t && "fieldName" in s && s.fieldName ? (this._groupFieldMap[t].push(s.fieldName), this._fieldToGroupKey[s.fieldName] = t, this._fieldSchemaMap[s.fieldName] = s) : "fieldName" in s && s.fieldName && (this._fieldSchemaMap[s.fieldName] = s);
|
|
517
|
+
}
|
|
518
|
+
/**
|
|
519
|
+
* @description 根据错误映射更新导航各分组的错误计数
|
|
520
|
+
* @param {Record<string, string>} errors - 字段错误映射
|
|
521
|
+
*/
|
|
522
|
+
_updateNavErrorCounts(e) {
|
|
523
|
+
const t = Object.keys(e).filter((r) => !!e[r]);
|
|
524
|
+
for (const r of Object.keys(this._groupFieldMap)) {
|
|
525
|
+
const o = this.getGroupFieldNames(r).filter(
|
|
526
|
+
(i) => t.some((a) => this._matchFieldOrNested(a, i))
|
|
527
|
+
).length;
|
|
528
|
+
this.navErrorCounts[r] = o;
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
/**
|
|
532
|
+
* @description 根据错误字段找到第一个包含错误的分组 key(按 schema 定义顺序)
|
|
533
|
+
* @param {Record<string, string>} errors - 错误字段映射
|
|
534
|
+
* @returns {string | undefined} 第一个有错误的分组 key
|
|
535
|
+
*/
|
|
536
|
+
_findFirstErrorGroupKey(e) {
|
|
537
|
+
const t = Object.keys(e).filter((r) => e[r]);
|
|
538
|
+
if (t.length !== 0)
|
|
539
|
+
for (const r of Object.keys(this._groupFieldMap)) {
|
|
540
|
+
const s = this.getGroupFieldNames(r);
|
|
541
|
+
if (s != null && s.some((o) => t.some((i) => this._matchFieldOrNested(i, o)))) return r;
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
/**
|
|
545
|
+
* @description 获取指定分组下的字段名列表,默认会获取该分组下的所有字段
|
|
546
|
+
* @param {string} key - 分组 key
|
|
547
|
+
* @param {boolean} 是否包含子分组字段
|
|
548
|
+
* @returns {string[]} 字段名列表
|
|
549
|
+
*/
|
|
550
|
+
getGroupFieldNames(e, t = !0) {
|
|
551
|
+
return this._getGroupFieldNamesWithVisited(e, t, /* @__PURE__ */ new Set());
|
|
552
|
+
}
|
|
553
|
+
/**
|
|
554
|
+
* @description 获取指定分组字段名(带防环保护),避免异常 schema 导致递归栈溢出
|
|
555
|
+
*/
|
|
556
|
+
_getGroupFieldNamesWithVisited(e, t, r) {
|
|
557
|
+
if (r.has(e))
|
|
558
|
+
return [];
|
|
559
|
+
r.add(e);
|
|
560
|
+
const s = this._groupFieldMap[e] ?? [];
|
|
561
|
+
if (!t)
|
|
562
|
+
return [...s];
|
|
563
|
+
const o = [...s], i = this._groupChildrenMap[e] ?? [];
|
|
564
|
+
for (const a of i)
|
|
565
|
+
o.push(...this._getGroupFieldNamesWithVisited(a, !0, r));
|
|
566
|
+
return r.delete(e), Array.from(new Set(o));
|
|
567
|
+
}
|
|
568
|
+
/**
|
|
569
|
+
* @description 获取字段所属分组 key,支持数组/对象嵌套路径回溯到 schema 字段。
|
|
570
|
+
* @param {string} fieldName 字段名
|
|
571
|
+
* @returns {string | undefined} 所属分组 key
|
|
572
|
+
*/
|
|
573
|
+
_getFieldGroupKey(e) {
|
|
574
|
+
const t = this._fieldToGroupKey[e];
|
|
575
|
+
if (t) return t;
|
|
576
|
+
for (const r of Object.keys(this._fieldToGroupKey))
|
|
577
|
+
if (this._matchFieldOrNested(e, r))
|
|
578
|
+
return this._fieldToGroupKey[r];
|
|
579
|
+
}
|
|
580
|
+
/**
|
|
581
|
+
* @description 判断字段所属分组或祖先分组是否仍处于隐藏状态,用于避免字段显示时绕过仍隐藏的父级分组。
|
|
582
|
+
* @param {string} fieldName 字段名
|
|
583
|
+
* @returns {boolean} 是否存在隐藏的所属分组或祖先分组
|
|
584
|
+
*/
|
|
585
|
+
_hasHiddenGroup(e) {
|
|
586
|
+
let t = this._getFieldGroupKey(e);
|
|
587
|
+
for (; t; ) {
|
|
588
|
+
if (this.hiddenGroupKeys.has(t)) return !0;
|
|
589
|
+
t = this._groupParentMap[t];
|
|
590
|
+
}
|
|
591
|
+
return !1;
|
|
592
|
+
}
|
|
593
|
+
/**
|
|
594
|
+
* @description 设置字段隐藏状态
|
|
595
|
+
* @param {string[]} fieldNames 字段名列表
|
|
596
|
+
* @param {boolean} hidden 是否隐藏
|
|
597
|
+
*/
|
|
598
|
+
_setFieldsHidden(e, t) {
|
|
599
|
+
for (const r of e)
|
|
600
|
+
t ? this.hiddenFieldNames.add(r) : this._hasHiddenGroup(r) || this.hiddenFieldNames.delete(r);
|
|
601
|
+
}
|
|
602
|
+
/**
|
|
603
|
+
* @description 生成清空后的值:数组和对象保留结构,叶子值按默认值回填,否则置为 undefined
|
|
604
|
+
* @param {unknown} value 原始值
|
|
605
|
+
* @param {unknown} defaultValue 默认值
|
|
606
|
+
* @returns {unknown} 清空后的值
|
|
607
|
+
*/
|
|
608
|
+
_clearValueKeepStructure(e, t) {
|
|
609
|
+
if (Array.isArray(e)) {
|
|
610
|
+
const r = Array.isArray(t) ? t : [];
|
|
611
|
+
return e.map((s, o) => this._clearValueKeepStructure(s, r[o] ?? r[0]));
|
|
612
|
+
}
|
|
613
|
+
if (p(e)) {
|
|
614
|
+
const r = p(t) ? t : {};
|
|
615
|
+
return Object.fromEntries(
|
|
616
|
+
Object.keys(e).map((s) => [
|
|
617
|
+
s,
|
|
618
|
+
this._clearValueKeepStructure(v(e, s), v(r, s))
|
|
619
|
+
])
|
|
620
|
+
);
|
|
621
|
+
}
|
|
622
|
+
if (e === void 0 && (Array.isArray(t) || p(t)))
|
|
623
|
+
return this._clearValueKeepStructure(t, t);
|
|
624
|
+
if (t !== void 0 && !Array.isArray(t) && !p(t))
|
|
625
|
+
return V(t);
|
|
626
|
+
}
|
|
627
|
+
/**
|
|
628
|
+
* @description 清空隐藏字段的值、校验状态和虚拟错误缓存,数组和对象保留结构
|
|
629
|
+
* @param {string[]} fieldNames 字段名列表
|
|
630
|
+
*/
|
|
631
|
+
_clearHiddenFieldValues(e) {
|
|
632
|
+
var t, r, s, o, i, a, l;
|
|
633
|
+
if (e.length)
|
|
634
|
+
for (const h of e) {
|
|
635
|
+
const d = v((t = this.form) == null ? void 0 : t.values, h), F = this._fieldSchemaMap[h] ? k(this._fieldSchemaMap[h]) : void 0;
|
|
636
|
+
(s = (r = this.form) == null ? void 0 : r.setFieldValue) == null || s.call(r, h, this._clearValueKeepStructure(d, F), !1), (i = (o = this.form) == null ? void 0 : o.setFieldError) == null || i.call(o, h, void 0), (l = (a = this.form) == null ? void 0 : a.setFieldTouched) == null || l.call(a, h, !1), this.errorCacheMap.delete(h);
|
|
637
|
+
}
|
|
638
|
+
}
|
|
639
|
+
/**
|
|
640
|
+
* @description 卸载分组表单时恢复初始schema
|
|
641
|
+
*/
|
|
642
|
+
get arrayAction() {
|
|
643
|
+
var o;
|
|
644
|
+
const e = super.arrayAction;
|
|
645
|
+
let t = ((o = this.resetSignal) == null ? void 0 : o.value) ?? 0;
|
|
646
|
+
const r = () => {
|
|
647
|
+
var a;
|
|
648
|
+
if (!this.navAnchorProps.show) return;
|
|
649
|
+
const i = ((a = this.resetSignal) == null ? void 0 : a.value) ?? 0;
|
|
650
|
+
if (i !== t) {
|
|
651
|
+
t = i, this.syncNavErrorCountsFromForm();
|
|
652
|
+
return;
|
|
653
|
+
}
|
|
654
|
+
this._hasValidated && this.syncNavErrorCountsFromForm();
|
|
655
|
+
}, s = (i) => y(i);
|
|
656
|
+
return {
|
|
657
|
+
get: (i) => e.get(s(i)),
|
|
658
|
+
push: (i, a) => {
|
|
659
|
+
e.push(s(i), a), r();
|
|
660
|
+
},
|
|
661
|
+
remove: (i, a) => {
|
|
662
|
+
e.remove(s(i), a), r();
|
|
663
|
+
},
|
|
664
|
+
replace: (i, a) => {
|
|
665
|
+
e.replace(s(i), a), r();
|
|
666
|
+
},
|
|
667
|
+
update: (i, a, l) => {
|
|
668
|
+
e.update(s(i), a, l), r();
|
|
669
|
+
},
|
|
670
|
+
insert: (i, a, l) => {
|
|
671
|
+
e.insert(s(i), a, l), r();
|
|
672
|
+
},
|
|
673
|
+
prepend: (i, a) => {
|
|
674
|
+
e.prepend(s(i), a), r();
|
|
675
|
+
},
|
|
676
|
+
move: (i, a, l) => {
|
|
677
|
+
e.move(s(i), a, l), r();
|
|
678
|
+
},
|
|
679
|
+
swap: (i, a, l) => {
|
|
680
|
+
e.swap(s(i), a, l), r();
|
|
681
|
+
},
|
|
682
|
+
/**
|
|
683
|
+
* @description 获取嵌套数组路径下的操作器
|
|
684
|
+
* @param parentPath 父数组路径,或完整路径(仅传 path)
|
|
685
|
+
* @param index 父数组索引
|
|
686
|
+
* @param childField 子数组字段名
|
|
687
|
+
*/
|
|
688
|
+
at: (i, a, l) => {
|
|
689
|
+
const h = e.at(H(s(i), a, l));
|
|
690
|
+
return this._wrapNestedArrayHandle(h, r);
|
|
691
|
+
}
|
|
692
|
+
};
|
|
693
|
+
}
|
|
694
|
+
unmount() {
|
|
695
|
+
this._applyGroupSchema(_(this._initialGroupSchema)), this.hiddenGroupKeys.clear(), this.hiddenFieldNames.clear(), this.virtual && (this._clearAllCachedErrors(), this._hasValidated = !1), this._clearNavErrorCounts(), super.unmount();
|
|
696
|
+
}
|
|
697
|
+
}
|
|
698
|
+
export {
|
|
699
|
+
L as GroupFormApi
|
|
700
|
+
};
|