@done-coding/admin-core 0.27.0 → 0.27.1-alpha.0
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/es/bridge/index.mjs +11 -3
- package/es/components/app-layout/AppBody.vue.mjs +1 -1
- package/es/components/app-layout/AppBody.vue2.mjs +14 -5
- package/es/components/app-layout/AppHeader.vue.mjs +1 -1
- package/es/components/app-layout/AppHeader.vue2.mjs +7 -5
- package/es/components/app-layout/AppLayout.vue.mjs +1 -1
- package/es/components/app-layout/AppLayout.vue2.mjs +2 -1
- package/es/components/app-layout/AppPage.vue.mjs +1 -1
- package/es/components/app-layout/AppPage.vue2.mjs +35 -32
- package/es/components/app-layout/app-page-geometry.mjs +16 -16
- package/es/components/app-layout/app-page-recommended.mjs +10 -0
- package/es/components/data-view/DataGridView.vue.mjs +1 -1
- package/es/components/data-view/DataGridView.vue2.mjs +29 -17
- package/es/components/data-view/DataListView.vue.mjs +1 -1
- package/es/components/data-view/DataListView.vue2.mjs +10 -0
- package/es/components/data-view/InfiniteListView.vue.mjs +1 -1
- package/es/components/data-view/InfiniteListView.vue2.mjs +9 -3
- package/es/components/data-view/use-active-scroll.mjs +15 -0
- package/es/components/display/DragFloat.vue.mjs +7 -0
- package/es/components/display/DragFloat.vue2.mjs +109 -0
- package/es/components/display/TabsHeader.vue.mjs +1 -1
- package/es/components/display/TabsHeader.vue2.mjs +9 -10
- package/es/components/display/TabsMain.vue.mjs +22 -7
- package/es/components/display/tabs-variant.mjs +14 -0
- package/es/components/form/FormDivider.vue.mjs +7 -0
- package/es/components/form/FormDivider.vue2.mjs +14 -0
- package/es/components/form/FormGroupTitle.vue.mjs +7 -0
- package/es/components/form/FormGroupTitle.vue2.mjs +59 -0
- package/es/components/form/FormItemNestForm.vue.mjs +1 -1
- package/es/components/form/FormItemNestFormList.vue.mjs +1 -1
- package/es/components/form/FormMain.vue.mjs +1 -1
- package/es/components/form/FormMain.vue2.mjs +69 -9
- package/es/components/form/FormSearch.vue.mjs +1 -1
- package/es/components/form/FormSearch.vue2.mjs +15 -3
- package/es/components/form/FormSubmitPanel.vue.mjs +1 -1
- package/es/components/form/FormSubmitPanel.vue2.mjs +14 -1
- package/es/components/form/ai-schema.mjs +139 -0
- package/es/components/form/group.mjs +81 -0
- package/es/components/form/use-ai-fill.mjs +71 -0
- package/es/components/form/utils.mjs +15 -4
- package/es/components/list-layout/ListLayout.vue.mjs +1 -1
- package/es/components/list-layout/ListLayout.vue2.mjs +103 -62
- package/es/components/modal/ImagePreviewTrigger.vue.mjs +5 -1
- package/es/components/modal/ModalConfirm.vue.mjs +1 -1
- package/es/components/modal/ModalConfirm.vue2.mjs +8 -5
- package/es/components/modal/VideoPreviewTrigger.vue.mjs +1 -1
- package/es/components/modal/VideoPreviewTrigger.vue2.mjs +2 -1
- package/es/components/page-layout/AppPageDetail.vue.mjs +1 -1
- package/es/components/page-layout/AppPageDetail.vue2.mjs +17 -13
- package/es/components/page-layout/AppPageListDetailLayout.vue.mjs +7 -4
- package/es/components/page-layout/AppPageListDetailSheet.vue.mjs +12 -4
- package/es/components/page-layout/AppPageListDetailSplit.vue.mjs +1 -1
- package/es/components/page-layout/AppPageListDetailSplit.vue2.mjs +10 -3
- package/es/components/table/TableMain.vue.mjs +1 -1
- package/es/components/table/TableMain.vue2.mjs +45 -25
- package/es/components/view-layout/ViewLayout.vue.mjs +1 -1
- package/es/components/view-layout/ViewLayout.vue2.mjs +46 -15
- package/es/config/slot-region.mjs +1 -0
- package/es/hooks/use-active-record.mjs +5 -1
- package/es/hooks/use-surface.mjs +27 -0
- package/es/hooks/use-theme-apply.mjs +52 -18
- package/es/index.mjs +81 -59
- package/es/inject/key.mjs +4 -0
- package/es/store/app.mjs +51 -17
- package/es/style.css +361 -184
- package/es/utils/dom.mjs +7 -1
- package/es/utils/gap-scale.mjs +25 -0
- package/es/utils/theme-scale.mjs +27 -0
- package/package.json +2 -2
- package/src/bridge/docs/README.md +30 -0
- package/src/components/app-layout/docs/README-AppBody.md +21 -0
- package/src/components/app-layout/docs/README-AppPage.md +20 -3
- package/src/components/data-view/docs/README-DataGridView.md +15 -0
- package/src/components/data-view/docs/README-DataListView.md +13 -0
- package/src/components/data-view/docs/README-InfiniteListView.md +15 -0
- package/src/components/display/README.md +1 -0
- package/src/components/display/docs/README-DragFloat.md +68 -0
- package/src/components/form/README.md +4 -2
- package/src/components/form/docs/README-FormItemNestForm.md +5 -3
- package/src/components/form/docs/README-FormItemNestFormList.md +7 -1
- package/src/components/form/docs/README-FormMain.md +102 -1
- package/src/components/form/docs/README-FormSearch.md +5 -0
- package/src/components/list-layout/docs/README-ListLayout.md +61 -1
- package/src/components/modal/docs/README-ImagePreviewTrigger.md +2 -0
- package/src/components/modal/docs/README-VideoPreviewTrigger.md +4 -1
- package/src/components/page-layout/docs/README-AppPageDetail.md +11 -1
- package/src/components/page-layout/docs/README-AppPageListDetailLayout.md +64 -6
- package/src/components/table/docs/README-TableMain.md +22 -0
- package/src/components/view-layout/docs/README-ViewLayout.md +27 -2
- package/src/hooks/docs/README.md +30 -1
- package/types/bridge/index.d.ts +69 -10
- package/types/components/app-layout/AppPage.vue.d.ts +15 -7
- package/types/components/app-layout/app-page-geometry.d.ts +19 -10
- package/types/components/app-layout/app-page-recommended.d.ts +12 -0
- package/types/components/app-layout/index.d.ts +1 -0
- package/types/components/data-view/types.d.ts +18 -0
- package/types/components/data-view/use-active-scroll.d.ts +30 -0
- package/types/components/display/BadgeMark.vue.d.ts +2 -2
- package/types/components/display/DragFloat.vue.d.ts +35 -0
- package/types/components/display/TabsHeader.vue.d.ts +7 -0
- package/types/components/display/index.d.ts +8 -1
- package/types/components/display/tabs-variant.d.ts +17 -0
- package/types/components/display/types.d.ts +6 -0
- package/types/components/form/FormDivider.vue.d.ts +2 -0
- package/types/components/form/FormGroupTitle.vue.d.ts +22 -0
- package/types/components/form/FormItemNestForm.vue.d.ts +2 -0
- package/types/components/form/ai-schema.d.ts +24 -0
- package/types/components/form/group.d.ts +36 -0
- package/types/components/form/index.d.ts +2 -0
- package/types/components/form/types.d.ts +94 -3
- package/types/components/form/use-ai-fill.d.ts +59 -0
- package/types/components/form/utils.d.ts +19 -0
- package/types/components/list-layout/ListLayout.vue.d.ts +3 -0
- package/types/components/list-layout/types.d.ts +28 -0
- package/types/components/modal/ModalConfirm.vue.d.ts +1 -1
- package/types/components/modal/VideoPreviewTrigger.vue.d.ts +1 -1
- package/types/components/page-layout/AppPageDetail.vue.d.ts +2 -2
- package/types/components/page-layout/AppPageListDetailLayout.vue.d.ts +3 -7
- package/types/components/page-layout/AppPageListDetailSheet.vue.d.ts +4 -8
- package/types/components/page-layout/AppPageListDetailSplit.vue.d.ts +4 -8
- package/types/components/page-layout/types.d.ts +42 -0
- package/types/components/panel/PanelItemNestForm.vue.d.ts +2 -0
- package/types/components/table/types.d.ts +9 -0
- package/types/components/view-layout/ViewLayout.vue.d.ts +18 -0
- package/types/components/view-layout/types.d.ts +15 -0
- package/types/config/slot-region.d.ts +10 -1
- package/types/hooks/use-surface.d.ts +34 -0
- package/types/inject/key.d.ts +10 -0
- package/types/injectInfo.json.d.ts +1 -1
- package/types/store/app.d.ts +3 -0
- package/types/utils/dom.d.ts +31 -0
- package/types/utils/gap-scale.d.ts +46 -0
- package/types/utils/index.d.ts +1 -0
- package/types/utils/theme-scale.d.ts +33 -0
|
@@ -5,6 +5,8 @@ import _sfc_main$2 from "./FormSubmitBtn.vue.mjs";
|
|
|
5
5
|
import { useFormSubmit } from "./use-form-submit.mjs";
|
|
6
6
|
import _sfc_main$1 from "../display/ActionBtn.vue.mjs";
|
|
7
7
|
import { parseFormData, generateFormData } from "./utils.mjs";
|
|
8
|
+
import { useContextDefaults } from "../../hooks/use-context-defaults.mjs";
|
|
9
|
+
import { SlotRegion } from "../../config/slot-region.mjs";
|
|
8
10
|
const _hoisted_1 = { class: "form-submit-panel-operation-inner" };
|
|
9
11
|
const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
10
12
|
...{ name: "FormSubmitPanel", inheritAttrs: false },
|
|
@@ -17,6 +19,9 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
17
19
|
rowGutter: {},
|
|
18
20
|
layoutScale: {},
|
|
19
21
|
layoutByContainer: { type: Boolean },
|
|
22
|
+
aiFill: { type: Boolean },
|
|
23
|
+
aiFillTrigger: {},
|
|
24
|
+
description: {},
|
|
20
25
|
stringifyData: {},
|
|
21
26
|
submitText: {},
|
|
22
27
|
submitFn: {},
|
|
@@ -29,6 +34,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
29
34
|
operationAffix: { type: [Boolean, Object], default: false },
|
|
30
35
|
divider: { type: Boolean, default: true },
|
|
31
36
|
bare: { type: Boolean, default: false },
|
|
37
|
+
surface: { type: Boolean, default: void 0 },
|
|
32
38
|
rootClass: {}
|
|
33
39
|
},
|
|
34
40
|
emits: ["cancel", "fail", "success", "parseDataChange"],
|
|
@@ -46,11 +52,18 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
46
52
|
if (typeof props.operationAffix === "object") return props.operationAffix;
|
|
47
53
|
return { position: "bottom" };
|
|
48
54
|
});
|
|
55
|
+
const { ctxSurface } = useContextDefaults({
|
|
56
|
+
getProps: () => props,
|
|
57
|
+
defaults: {
|
|
58
|
+
surface: ({ parentInfo, props: rawProps }) => rawProps.surface ?? parentInfo !== SlotRegion.ModalConfirm_Body
|
|
59
|
+
}
|
|
60
|
+
});
|
|
49
61
|
const rootClassList = computed(() => [
|
|
50
62
|
`form-submit-panel_${props.operationPosition}`,
|
|
51
63
|
{
|
|
52
64
|
"form-submit-panel_no-divider": !props.divider,
|
|
53
|
-
"form-submit-panel_bare": props.bare
|
|
65
|
+
"form-submit-panel_bare": props.bare,
|
|
66
|
+
"form-submit-panel_surface": ctxSurface.value
|
|
54
67
|
},
|
|
55
68
|
props.rootClass
|
|
56
69
|
]);
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import { checkFormItemIsIgnore } from "./utils.mjs";
|
|
2
|
+
const AI_SCHEMA_MAX_PROPERTIES = 100;
|
|
3
|
+
const resolveInitValue = (config) => {
|
|
4
|
+
return typeof config.init === "function" ? config.init() : config.init;
|
|
5
|
+
};
|
|
6
|
+
const resolveItemProps = (config, data) => {
|
|
7
|
+
const { props } = config;
|
|
8
|
+
if (!props) return {};
|
|
9
|
+
return typeof props === "function" ? props({ data, config }) : props;
|
|
10
|
+
};
|
|
11
|
+
const resolveItemHide = (config, data) => {
|
|
12
|
+
const { hide } = config;
|
|
13
|
+
if (typeof hide === "function") {
|
|
14
|
+
return !!hide({
|
|
15
|
+
data,
|
|
16
|
+
config,
|
|
17
|
+
getInitValue: () => resolveInitValue(config)
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
return !!hide;
|
|
21
|
+
};
|
|
22
|
+
const inferAiTypeFromInit = (value) => {
|
|
23
|
+
if (value === null || value === void 0) return void 0;
|
|
24
|
+
if (typeof value === "string") return "string";
|
|
25
|
+
if (typeof value === "number") return "number";
|
|
26
|
+
if (typeof value === "boolean") return "boolean";
|
|
27
|
+
if (Array.isArray(value)) {
|
|
28
|
+
if (value.length && value.every((v) => typeof v === "string")) {
|
|
29
|
+
return "array";
|
|
30
|
+
}
|
|
31
|
+
return "unsupported";
|
|
32
|
+
}
|
|
33
|
+
return "unsupported";
|
|
34
|
+
};
|
|
35
|
+
const resolveAiOptions = async (props) => {
|
|
36
|
+
if (typeof props.remoteMethod === "function") return void 0;
|
|
37
|
+
if (Array.isArray(props.options) && props.options.length) {
|
|
38
|
+
return props.options;
|
|
39
|
+
}
|
|
40
|
+
if (typeof props.getOptions === "function") {
|
|
41
|
+
try {
|
|
42
|
+
const options = await props.getOptions();
|
|
43
|
+
if (Array.isArray(options) && options.length) return options;
|
|
44
|
+
} catch (error) {
|
|
45
|
+
console.warn(`[getAiSchema] getOptions 拉取失败,该项不产 enum`, error);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
return void 0;
|
|
49
|
+
};
|
|
50
|
+
const formatAiOptionLabels = (options) => {
|
|
51
|
+
return options.map(
|
|
52
|
+
(item) => String(item.label) === String(item.value) ? String(item.value) : `${item.label}(${item.value})`
|
|
53
|
+
).join("、");
|
|
54
|
+
};
|
|
55
|
+
const buildAiDescription = (config, options) => {
|
|
56
|
+
var _a, _b;
|
|
57
|
+
const parts = [config.label];
|
|
58
|
+
if (typeof config.tip === "string" && config.tip) parts.push(config.tip);
|
|
59
|
+
if ((_a = config.description) == null ? void 0 : _a.suitable) {
|
|
60
|
+
parts.push(`适用:${config.description.suitable}`);
|
|
61
|
+
}
|
|
62
|
+
if ((_b = config.description) == null ? void 0 : _b.unsuitable) {
|
|
63
|
+
parts.push(`不适用:${config.description.unsuitable}`);
|
|
64
|
+
}
|
|
65
|
+
if (options == null ? void 0 : options.length) {
|
|
66
|
+
parts.push(`可选值:${formatAiOptionLabels(options)}`);
|
|
67
|
+
}
|
|
68
|
+
return parts.join(";");
|
|
69
|
+
};
|
|
70
|
+
const projectAiItem = async (config, data) => {
|
|
71
|
+
const props = resolveItemProps(config, data);
|
|
72
|
+
const options = await resolveAiOptions(props);
|
|
73
|
+
let type = config.type;
|
|
74
|
+
if (!type) {
|
|
75
|
+
const inferred = inferAiTypeFromInit(resolveInitValue(config));
|
|
76
|
+
if (inferred === "unsupported") return void 0;
|
|
77
|
+
type = inferred;
|
|
78
|
+
}
|
|
79
|
+
let enumValues;
|
|
80
|
+
if (options && type !== "array" && type !== "boolean") {
|
|
81
|
+
const values = options.map((item) => item.value);
|
|
82
|
+
const uniform = values.every((v) => typeof v === "number") ? "number" : values.every((v) => typeof v === "string") ? "string" : void 0;
|
|
83
|
+
const compatible = uniform && (type === void 0 || type === uniform || type === "integer" && uniform === "number");
|
|
84
|
+
if (compatible) {
|
|
85
|
+
enumValues = values;
|
|
86
|
+
type = type ?? uniform;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
const payload = { type: type ?? "string" };
|
|
90
|
+
if (enumValues) payload.enum = enumValues;
|
|
91
|
+
if (payload.type === "array") payload.items = { type: "string" };
|
|
92
|
+
return {
|
|
93
|
+
description: buildAiDescription(config, options),
|
|
94
|
+
anyOf: [payload, { type: "null" }]
|
|
95
|
+
};
|
|
96
|
+
};
|
|
97
|
+
const resolveFormAiFormDescription = (description) => {
|
|
98
|
+
if (!description) return void 0;
|
|
99
|
+
if (typeof description === "string") return description.trim() || void 0;
|
|
100
|
+
const parts = [];
|
|
101
|
+
if (description.suitable) parts.push(`适用:${description.suitable}`);
|
|
102
|
+
if (description.unsuitable) parts.push(`不适用:${description.unsuitable}`);
|
|
103
|
+
return parts.length ? parts.join(";") : void 0;
|
|
104
|
+
};
|
|
105
|
+
const getFormAiSchema = async (list, data, options) => {
|
|
106
|
+
const candidates = list.filter(
|
|
107
|
+
(config) => !checkFormItemIsIgnore(config) && !config.aiIgnore && !resolveItemHide(config, data)
|
|
108
|
+
);
|
|
109
|
+
const projected = await Promise.all(
|
|
110
|
+
candidates.map((config) => projectAiItem(config, data))
|
|
111
|
+
);
|
|
112
|
+
const properties = {};
|
|
113
|
+
const required = [];
|
|
114
|
+
candidates.forEach((config, index) => {
|
|
115
|
+
const property = projected[index];
|
|
116
|
+
if (!property) return;
|
|
117
|
+
if (required.length >= AI_SCHEMA_MAX_PROPERTIES) return;
|
|
118
|
+
properties[config.key] = property;
|
|
119
|
+
required.push(config.key);
|
|
120
|
+
});
|
|
121
|
+
const exportable = projected.filter(Boolean).length;
|
|
122
|
+
if (exportable > AI_SCHEMA_MAX_PROPERTIES) {
|
|
123
|
+
console.warn(
|
|
124
|
+
`[getAiSchema] 可导出字段 ${exportable} 项超 strict 上限 ${AI_SCHEMA_MAX_PROPERTIES},已截断`
|
|
125
|
+
);
|
|
126
|
+
}
|
|
127
|
+
const formDescription = resolveFormAiFormDescription(options == null ? void 0 : options.description);
|
|
128
|
+
return {
|
|
129
|
+
type: "object",
|
|
130
|
+
...formDescription ? { description: formDescription } : {},
|
|
131
|
+
properties,
|
|
132
|
+
required,
|
|
133
|
+
additionalProperties: false
|
|
134
|
+
};
|
|
135
|
+
};
|
|
136
|
+
export {
|
|
137
|
+
getFormAiSchema,
|
|
138
|
+
resolveFormAiFormDescription
|
|
139
|
+
};
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { markRaw, ref } from "vue";
|
|
2
|
+
import FormGroupTitle from "./FormGroupTitle.vue.mjs";
|
|
3
|
+
import FormDivider from "./FormDivider.vue.mjs";
|
|
4
|
+
let groupKeySeq = 0;
|
|
5
|
+
let dividerKeySeq = 0;
|
|
6
|
+
const COLLAPSED_CLASS = "dc-form-item-collapsed";
|
|
7
|
+
const swiftFormItemGroup = (title, items, options = {}) => {
|
|
8
|
+
const { defaultCollapsed = false, collapsible = true, key } = options;
|
|
9
|
+
const groupKey = key ?? `__GROUP_${groupKeySeq++}`;
|
|
10
|
+
const memberKeys = items.map((item) => item.key);
|
|
11
|
+
const collapsedByData = /* @__PURE__ */ new WeakMap();
|
|
12
|
+
const stateFor = (data) => {
|
|
13
|
+
let state = collapsedByData.get(data);
|
|
14
|
+
if (!state) {
|
|
15
|
+
state = ref(defaultCollapsed);
|
|
16
|
+
collapsedByData.set(data, state);
|
|
17
|
+
}
|
|
18
|
+
return state;
|
|
19
|
+
};
|
|
20
|
+
const titleConfig = {
|
|
21
|
+
key: groupKey,
|
|
22
|
+
label: "",
|
|
23
|
+
// 恒整行(不可配);ceilToTier 上限 24,嵌套 rebase 下不放大
|
|
24
|
+
layout: { span: 24 },
|
|
25
|
+
render: markRaw(FormGroupTitle),
|
|
26
|
+
// props 在 FormItem mainProps computed 内求值 → 读 collapsed ref 即被追踪,
|
|
27
|
+
// toggle 后标题箭头与组内项 viewHide 同步重算
|
|
28
|
+
props: (scope) => ({
|
|
29
|
+
title,
|
|
30
|
+
collapsible,
|
|
31
|
+
collapsed: collapsible ? stateFor(scope.data).value : false,
|
|
32
|
+
// 组内成员 key —— 供标题组件判断「本轮校验错误是否落在本组」,
|
|
33
|
+
// 命中则自动展开(折叠区的错误 [MUST NOT] 静默藏着)
|
|
34
|
+
memberKeys,
|
|
35
|
+
onToggle: () => {
|
|
36
|
+
const state = stateFor(scope.data);
|
|
37
|
+
state.value = !state.value;
|
|
38
|
+
},
|
|
39
|
+
onExpand: () => {
|
|
40
|
+
stateFor(scope.data).value = false;
|
|
41
|
+
}
|
|
42
|
+
}),
|
|
43
|
+
// 伪 item 去表单元素占位:无 label(labelWidth 0 防 EP 给 content 留白)+
|
|
44
|
+
// 校验预留收敛(dc-form-item-pseudo 样式钩子在 FormMain.vue)
|
|
45
|
+
wrapProps: { class: "dc-form-item-pseudo", labelWidth: "0px" }
|
|
46
|
+
};
|
|
47
|
+
const members = collapsible ? items.map((item) => {
|
|
48
|
+
const origWrap = item.wrapProps;
|
|
49
|
+
return {
|
|
50
|
+
...item,
|
|
51
|
+
// 🔴 折叠 = **纯视觉隐藏**(挂 class,样式在 FormMain.vue),
|
|
52
|
+
// [MUST NOT] 改回置 `hide`:那会进 `hideKeyList`、被 validate 抹掉错误
|
|
53
|
+
// ⇒ 折叠区必填项静默失效、数据不完整也能提交。
|
|
54
|
+
// 原有 wrapProps(对象 / 函数两形态)照常合并,不改原配置对象(入参不可变)。
|
|
55
|
+
wrapProps: (scope) => {
|
|
56
|
+
const base = typeof origWrap === "function" ? origWrap(scope) : origWrap ?? {};
|
|
57
|
+
const cls = base.class;
|
|
58
|
+
const merged = {
|
|
59
|
+
...base,
|
|
60
|
+
class: [cls, stateFor(scope.data).value && COLLAPSED_CLASS]
|
|
61
|
+
};
|
|
62
|
+
return merged;
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
}) : items;
|
|
66
|
+
return [titleConfig, ...members];
|
|
67
|
+
};
|
|
68
|
+
const swiftFormItemDivider = () => {
|
|
69
|
+
return {
|
|
70
|
+
key: `__DIVIDER_${dividerKeySeq++}`,
|
|
71
|
+
label: "",
|
|
72
|
+
layout: { span: 24 },
|
|
73
|
+
render: markRaw(FormDivider),
|
|
74
|
+
wrapProps: { class: "dc-form-item-pseudo", labelWidth: "0px" }
|
|
75
|
+
};
|
|
76
|
+
};
|
|
77
|
+
export {
|
|
78
|
+
COLLAPSED_CLASS,
|
|
79
|
+
swiftFormItemDivider,
|
|
80
|
+
swiftFormItemGroup
|
|
81
|
+
};
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { inject, ref, computed } from "vue";
|
|
2
|
+
import { checkFormItemIsIgnore } from "./utils.mjs";
|
|
3
|
+
import { resolveFormAiFormDescription } from "./ai-schema.mjs";
|
|
4
|
+
import { CORE_BRIDGE_KEY, FORM_NEST_REGISTRY_KEY } from "../../inject/key.mjs";
|
|
5
|
+
const useFormAiFill = (options) => {
|
|
6
|
+
const bridge = inject(CORE_BRIDGE_KEY, void 0);
|
|
7
|
+
const parentRegistry = inject(FORM_NEST_REGISTRY_KEY, null);
|
|
8
|
+
const aiFillIsNested = parentRegistry !== null;
|
|
9
|
+
const aiFillSnapshot = ref(null);
|
|
10
|
+
const aiFillTriggerComponent = computed(
|
|
11
|
+
() => options.getTrigger() ?? (bridge == null ? void 0 : bridge.aiFillTrigger.value)
|
|
12
|
+
);
|
|
13
|
+
const aiFillHasDescription = computed(
|
|
14
|
+
() => resolveFormAiFormDescription(options.getDescription()) !== void 0
|
|
15
|
+
);
|
|
16
|
+
let aiFillWarnedNoDescription = false;
|
|
17
|
+
const aiFillVisible = computed(() => {
|
|
18
|
+
var _a;
|
|
19
|
+
if (aiFillIsNested) return false;
|
|
20
|
+
if (options.getEnabled() === false) return false;
|
|
21
|
+
if (!aiFillTriggerComponent.value) return false;
|
|
22
|
+
if (!aiFillHasDescription.value) {
|
|
23
|
+
if ((_a = bridge == null ? void 0 : bridge.aiFillRequireDescription) == null ? void 0 : _a.value) return false;
|
|
24
|
+
if (!aiFillWarnedNoDescription) {
|
|
25
|
+
aiFillWarnedNoDescription = true;
|
|
26
|
+
console.warn(
|
|
27
|
+
"[aiFill] 本表单未配 description(表单目标描述),AI 填充的字段映射质量可能受损——建议给 FormMain 补 description 说明表单用途(bridge 可经 aiFillRequireDescription 强制要求)"
|
|
28
|
+
);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
return true;
|
|
32
|
+
});
|
|
33
|
+
const aiFillItemClass = (key) => aiFillSnapshot.value && key in aiFillSnapshot.value ? "dc-form-item-ai-filled" : void 0;
|
|
34
|
+
const aiFillOnData = (data) => {
|
|
35
|
+
const current = options.getData();
|
|
36
|
+
const snapshot = {};
|
|
37
|
+
options.getList().forEach((cur) => {
|
|
38
|
+
if (checkFormItemIsIgnore(cur)) return;
|
|
39
|
+
if (!Object.prototype.hasOwnProperty.call(data, cur.key)) return;
|
|
40
|
+
const value = data[cur.key];
|
|
41
|
+
if (value === void 0 || value === null) return;
|
|
42
|
+
snapshot[cur.key] = current[cur.key];
|
|
43
|
+
});
|
|
44
|
+
options.applyValues(data);
|
|
45
|
+
aiFillSnapshot.value = snapshot;
|
|
46
|
+
return {
|
|
47
|
+
appliedCount: Object.keys(snapshot).length,
|
|
48
|
+
undo: () => {
|
|
49
|
+
const snap = aiFillSnapshot.value;
|
|
50
|
+
if (!snap) return;
|
|
51
|
+
const target = options.getData();
|
|
52
|
+
Object.entries(snap).forEach(([key, value]) => {
|
|
53
|
+
target[key] = value;
|
|
54
|
+
});
|
|
55
|
+
aiFillSnapshot.value = null;
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
};
|
|
59
|
+
return {
|
|
60
|
+
aiFillVisible,
|
|
61
|
+
aiFillTriggerComponent,
|
|
62
|
+
aiFillTriggerProps: {
|
|
63
|
+
getSchema: options.getSchema,
|
|
64
|
+
onData: aiFillOnData
|
|
65
|
+
},
|
|
66
|
+
aiFillItemClass
|
|
67
|
+
};
|
|
68
|
+
};
|
|
69
|
+
export {
|
|
70
|
+
useFormAiFill
|
|
71
|
+
};
|
|
@@ -65,7 +65,7 @@ const getDatePickerShortcuts = () => {
|
|
|
65
65
|
}
|
|
66
66
|
];
|
|
67
67
|
};
|
|
68
|
-
const
|
|
68
|
+
const checkFormItemIsIgnore = (config) => {
|
|
69
69
|
const { ignore, key } = config;
|
|
70
70
|
return ignore || key.startsWith("__") && key.toUpperCase() === key;
|
|
71
71
|
};
|
|
@@ -75,7 +75,7 @@ const isFn = (init) => {
|
|
|
75
75
|
const generateFormData = (list) => {
|
|
76
76
|
return list.reduce(
|
|
77
77
|
(acc, cur) => {
|
|
78
|
-
if (
|
|
78
|
+
if (checkFormItemIsIgnore(cur)) return acc;
|
|
79
79
|
if (typeof cur.init === "object") {
|
|
80
80
|
console.error(
|
|
81
81
|
`表单项${cur.label}的初始值不能为对象 请设置为返回值的形式`
|
|
@@ -91,7 +91,7 @@ const parseFormData = (data, list) => {
|
|
|
91
91
|
const originData = _cloneDeep(data);
|
|
92
92
|
return list.reduce(
|
|
93
93
|
(acc, cur) => {
|
|
94
|
-
if (
|
|
94
|
+
if (checkFormItemIsIgnore(cur)) return acc;
|
|
95
95
|
if (cur.parse) {
|
|
96
96
|
const res = cur.parse(
|
|
97
97
|
data[cur.key],
|
|
@@ -113,7 +113,7 @@ const stringifyFormData = (data, list) => {
|
|
|
113
113
|
const originData = _cloneDeep(data);
|
|
114
114
|
return list.reduce(
|
|
115
115
|
(acc, cur) => {
|
|
116
|
-
if (
|
|
116
|
+
if (checkFormItemIsIgnore(cur)) return acc;
|
|
117
117
|
if (cur.stringify) {
|
|
118
118
|
const res = cur.stringify(
|
|
119
119
|
data[cur.key],
|
|
@@ -131,6 +131,15 @@ const stringifyFormData = (data, list) => {
|
|
|
131
131
|
{}
|
|
132
132
|
);
|
|
133
133
|
};
|
|
134
|
+
const patchFormData = (data, list, partial) => {
|
|
135
|
+
list.forEach((cur) => {
|
|
136
|
+
if (checkFormItemIsIgnore(cur)) return;
|
|
137
|
+
if (!Object.prototype.hasOwnProperty.call(partial, cur.key)) return;
|
|
138
|
+
const value = partial[cur.key];
|
|
139
|
+
if (value === void 0 || value === null) return;
|
|
140
|
+
data[cur.key] = value;
|
|
141
|
+
});
|
|
142
|
+
};
|
|
134
143
|
const getVModelSugar = ({
|
|
135
144
|
modelValueKey = "modelValue",
|
|
136
145
|
config,
|
|
@@ -262,6 +271,7 @@ export {
|
|
|
262
271
|
FORM_ITEM_CHANGE_LOADING,
|
|
263
272
|
NEST_LAYOUT_TIERS,
|
|
264
273
|
ceilToTier,
|
|
274
|
+
checkFormItemIsIgnore,
|
|
265
275
|
generateFormData,
|
|
266
276
|
getBlurSubmit,
|
|
267
277
|
getChangeSubmit,
|
|
@@ -270,6 +280,7 @@ export {
|
|
|
270
280
|
getPlaceholder,
|
|
271
281
|
getVModelSugar,
|
|
272
282
|
parseFormData,
|
|
283
|
+
patchFormData,
|
|
273
284
|
resolveFormLayout,
|
|
274
285
|
resolveLayoutSpan,
|
|
275
286
|
setInputComponent,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import _sfc_main from "./ListLayout.vue2.mjs";
|
|
2
2
|
/* empty css */
|
|
3
3
|
import _export_sfc from "../../_virtual/_plugin-vue_export-helper.mjs";
|
|
4
|
-
const ListLayout = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-
|
|
4
|
+
const ListLayout = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-abf3c131"]]);
|
|
5
5
|
export {
|
|
6
6
|
ListLayout as default
|
|
7
7
|
};
|