@veltra/desktop 1.7.18 → 1.8.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.
Files changed (82) hide show
  1. package/dist/components/batch-edit/batch-edit-form.js +40 -26
  2. package/dist/components/batch-edit/batch-edit-form.js.map +1 -1
  3. package/dist/components/batch-edit/batch-edit-list.js +17 -5
  4. package/dist/components/batch-edit/batch-edit-list.js.map +1 -1
  5. package/dist/components/batch-edit/di.js.map +1 -1
  6. package/dist/components/batch-edit/use-handlers.js +3 -3
  7. package/dist/components/batch-edit/use-handlers.js.map +1 -1
  8. package/dist/components/batch-edit/use-shortcut-key.js +4 -2
  9. package/dist/components/batch-edit/use-shortcut-key.js.map +1 -1
  10. package/dist/components/card/style2.css +0 -2
  11. package/dist/components/dialog/style2.css +1 -1
  12. package/dist/components/dropdown/dropdown.js +5 -3
  13. package/dist/components/dropdown/dropdown.js.map +1 -1
  14. package/dist/components/expression-editor/components/path-preview.js +3 -6
  15. package/dist/components/expression-editor/components/path-preview.js.map +1 -1
  16. package/dist/components/expression-editor/components/variable-picker.js +49 -12
  17. package/dist/components/expression-editor/components/variable-picker.js.map +1 -1
  18. package/dist/components/expression-editor/core/chip.js +1 -15
  19. package/dist/components/expression-editor/core/chip.js.map +1 -1
  20. package/dist/components/expression-editor/core/editor.js +20 -18
  21. package/dist/components/expression-editor/core/editor.js.map +1 -1
  22. package/dist/components/expression-editor/expression-editor.js +53 -22
  23. package/dist/components/expression-editor/expression-editor.js.map +1 -1
  24. package/dist/components/expression-editor/style2.css +135 -96
  25. package/dist/components/form/form.js.map +1 -1
  26. package/dist/components/form/form.vue_vue_type_script_setup_true_lang.js +0 -1
  27. package/dist/components/form/form.vue_vue_type_script_setup_true_lang.js.map +1 -1
  28. package/dist/components/form/style2.css +8 -3
  29. package/dist/components/index.d.ts +26 -26
  30. package/dist/components/index.js +52 -52
  31. package/dist/components/multi-select/multi-select.js +16 -12
  32. package/dist/components/multi-select/multi-select.js.map +1 -1
  33. package/dist/components/multi-select/style2.css +7 -0
  34. package/dist/components/multi-tree-select/multi-tree-select.js +82 -56
  35. package/dist/components/multi-tree-select/multi-tree-select.js.map +1 -1
  36. package/dist/components/multi-tree-select/style2.css +7 -0
  37. package/dist/components/select/select.js +7 -3
  38. package/dist/components/select/select.js.map +1 -1
  39. package/dist/components/select/style2.css +7 -0
  40. package/dist/components/select/use-options.js +14 -3
  41. package/dist/components/select/use-options.js.map +1 -1
  42. package/dist/components/tree-select/style2.css +7 -0
  43. package/dist/components/tree-select/tree-select.js +49 -17
  44. package/dist/components/tree-select/tree-select.js.map +1 -1
  45. package/dist/index.d.ts +1 -1
  46. package/dist/index.js +2 -2
  47. package/dist/types/dropdown.d.ts +10 -0
  48. package/dist/types/multi-tree-select.d.ts +7 -1
  49. package/dist/types/tree-select.d.ts +7 -1
  50. package/package.json +1 -1
  51. package/src/components/batch-edit/__test__/batch-edit.test.ts +119 -7
  52. package/src/components/batch-edit/batch-edit-form.vue +21 -2
  53. package/src/components/batch-edit/batch-edit-list.vue +18 -1
  54. package/src/components/batch-edit/di.ts +1 -1
  55. package/src/components/batch-edit/use-handlers.ts +6 -5
  56. package/src/components/batch-edit/use-shortcut-key.ts +5 -2
  57. package/src/components/card/style.scss +0 -2
  58. package/src/components/dialog/style.scss +2 -1
  59. package/src/components/dropdown/dropdown.vue +9 -4
  60. package/src/components/expression-editor/__test__/chip.test.ts +3 -14
  61. package/src/components/expression-editor/components/path-preview.vue +1 -2
  62. package/src/components/expression-editor/components/variable-picker.vue +54 -13
  63. package/src/components/expression-editor/core/chip.ts +3 -29
  64. package/src/components/expression-editor/core/editor.ts +28 -21
  65. package/src/components/expression-editor/expression-editor.vue +47 -21
  66. package/src/components/expression-editor/style.scss +167 -111
  67. package/src/components/form/form.vue +0 -1
  68. package/src/components/form/style.scss +11 -4
  69. package/src/components/multi-select/multi-select.vue +11 -2
  70. package/src/components/multi-select/style.scss +6 -0
  71. package/src/components/multi-tree-select/multi-tree-select.vue +58 -9
  72. package/src/components/multi-tree-select/style.scss +6 -0
  73. package/src/components/select/__test__/select.test.ts +78 -0
  74. package/src/components/select/select.vue +13 -3
  75. package/src/components/select/style.scss +6 -0
  76. package/src/components/select/use-options.ts +25 -4
  77. package/src/components/tree-select/__test__/tree-select.test.ts +116 -0
  78. package/src/components/tree-select/style.scss +6 -0
  79. package/src/components/tree-select/tree-select.vue +63 -13
  80. package/src/types/dropdown.ts +10 -0
  81. package/src/types/multi-tree-select.ts +12 -1
  82. package/src/types/tree-select.ts +12 -1
@@ -51,6 +51,11 @@ const _sfc_main = /*@__PURE__*/ defineComponent({
51
51
  if (props.quickEdit && state.formActionType === "update") return false;
52
52
  return creatable.value || updatable.value || creatableChild.value;
53
53
  });
54
+ /** 弹框模式新增类操作显示「保存并继续」:保存后重置表单继续录入,不关闭弹框 */
55
+ const showSaveContinueBtn = computed(() => {
56
+ if (props.formMode !== "dialog") return false;
57
+ return creatable.value || creatableChild.value;
58
+ });
54
59
  const headerInfo = computed(() => FORM_ACTION_HEADER_MAP[state.formActionType]);
55
60
  /** 头部图标色调修饰类:样式中 createChild 对应的修饰类为 is-child */
56
61
  const iconToneCls = computed(() => {
@@ -118,36 +123,45 @@ const _sfc_main = /*@__PURE__*/ defineComponent({
118
123
  _: 3
119
124
  }, 8, ["class"]),
120
125
  createElementVNode("footer", { class: normalizeClass(unref(cls).e("form-footer")) }, [createElementVNode("span", { class: normalizeClass(unref(cls).e("form-hint")) }, [unref(props).readonly ? (openBlock(), createElementBlock(Fragment, { key: 0 }, [createTextVNode(" 只读模式 ")], 64)) : createCommentVNode("v-if", true), createElementVNode("span", { class: normalizeClass({ [unref(bem).is("concealed")]: !shortcutActive.value }) }, [
121
- !(unref(state).formActionType === "update" && unref(props).quickEdit) ? (openBlock(), createElementBlock(Fragment, { key: 0 }, [createVNode(unref(_sfc_main$4), null, {
122
- default: withCtx(() => [..._cache[0] || (_cache[0] = [createTextVNode("Ctrl + S", -1)])]),
126
+ unref(props).formMode === "panel" && !(unref(state).formActionType === "update" && unref(props).quickEdit) ? (openBlock(), createElementBlock(Fragment, { key: 0 }, [createVNode(unref(_sfc_main$4), null, {
127
+ default: withCtx(() => [..._cache[2] || (_cache[2] = [createTextVNode("Ctrl + S", -1)])]),
123
128
  _: 1
124
- }), _cache[1] || (_cache[1] = createTextVNode(" 保存 · ", -1))], 64)) : createCommentVNode("v-if", true),
129
+ }), _cache[3] || (_cache[3] = createTextVNode(" 保存 · ", -1))], 64)) : createCommentVNode("v-if", true),
125
130
  createVNode(unref(_sfc_main$4), null, {
126
- default: withCtx(() => [..._cache[2] || (_cache[2] = [createTextVNode("Esc", -1)])]),
131
+ default: withCtx(() => [..._cache[4] || (_cache[4] = [createTextVNode("Esc", -1)])]),
127
132
  _: 1
128
133
  }),
129
- _cache[3] || (_cache[3] = createTextVNode(" 关闭 ", -1))
130
- ], 2)], 2), createElementVNode("div", { class: normalizeClass(unref(cls).e("form-actions")) }, [createVNode(unref(_sfc_main$3), {
131
- size: "small",
132
- text: "",
133
- loading: unref(state).loading,
134
- onClick: unref(handleClose)
135
- }, {
136
- default: withCtx(() => [..._cache[4] || (_cache[4] = [createTextVNode(" 取消 ", -1)])]),
137
- _: 1
138
- }, 8, ["loading", "onClick"]), showSaveBtn.value ? (openBlock(), createBlock(unref(_sfc_main$3), {
139
- key: 0,
140
- type: "primary",
141
- size: "small",
142
- title: "保存",
143
- icon: unref(Save),
144
- loading: unref(state).loading,
145
- onClick: unref(handleSave)
146
- }, null, 8, [
147
- "icon",
148
- "loading",
149
- "onClick"
150
- ])) : createCommentVNode("v-if", true)], 2)], 2)
134
+ _cache[5] || (_cache[5] = createTextVNode(" 关闭 ", -1))
135
+ ], 2)], 2), createElementVNode("div", { class: normalizeClass(unref(cls).e("form-actions")) }, [
136
+ createVNode(unref(_sfc_main$3), {
137
+ size: "small",
138
+ text: "",
139
+ loading: unref(state).loading,
140
+ onClick: unref(handleClose)
141
+ }, {
142
+ default: withCtx(() => [..._cache[6] || (_cache[6] = [createTextVNode(" 取消 ", -1)])]),
143
+ _: 1
144
+ }, 8, ["loading", "onClick"]),
145
+ showSaveContinueBtn.value ? (openBlock(), createBlock(unref(_sfc_main$3), {
146
+ key: 0,
147
+ size: "small",
148
+ title: "保存并继续",
149
+ loading: unref(state).loading,
150
+ onClick: _cache[0] || (_cache[0] = ($event) => unref(handleSave)(true))
151
+ }, {
152
+ default: withCtx(() => [..._cache[7] || (_cache[7] = [createTextVNode(" 保存并继续 ", -1)])]),
153
+ _: 1
154
+ }, 8, ["loading"])) : createCommentVNode("v-if", true),
155
+ showSaveBtn.value ? (openBlock(), createBlock(unref(_sfc_main$3), {
156
+ key: 1,
157
+ type: "primary",
158
+ size: "small",
159
+ title: "保存",
160
+ icon: unref(Save),
161
+ loading: unref(state).loading,
162
+ onClick: _cache[1] || (_cache[1] = ($event) => unref(handleSave)())
163
+ }, null, 8, ["icon", "loading"])) : createCommentVNode("v-if", true)
164
+ ], 2)], 2)
151
165
  ], 2)), [[vShow, unref(state).formVisible]]) : createCommentVNode("v-if", true)], 2112);
152
166
  };
153
167
  }
@@ -1 +1 @@
1
- {"version":3,"file":"batch-edit-form.js","names":[],"sources":["../../../src/components/batch-edit/batch-edit-form.vue"],"sourcesContent":["<template>\n <!-- 面板模式:表单常驻挂载(快照只在挂载时对传入的 model 拍一次),仅用 v-show 控制显隐;\n 弹框模式:表单随弹框挂载 / 卸载,model 初始快照由 use-edit-state 维护 -->\n <aside\n :class=\"[cls.e('form'), bem.is('dialog', props.formMode === 'dialog')]\"\n v-if=\"!!props.model\"\n v-show=\"state.formVisible\"\n >\n <header :class=\"cls.e('form-header')\">\n <span :class=\"[cls.e('form-icon'), iconToneCls]\">\n <u-icon>\n <component :is=\"headerInfo.icon\" />\n </u-icon>\n </span>\n <div :class=\"cls.e('form-title')\">\n <h3 :class=\"cls.e('form-title-text')\">{{ headerInfo.title }}</h3>\n </div>\n <u-button\n :class=\"cls.e('form-close')\"\n :icon=\"Close\"\n text\n circle\n size=\"small\"\n title=\"关闭\"\n @click=\"handleClose\"\n />\n </header>\n\n <u-scroll always :class=\"cls.e('form-body')\">\n <transition name=\"fade\" appear mode=\"out-in\">\n <u-form\n ref=\"formComponentRef\"\n :model=\"props.model\"\n :readonly=\"props.readonly\"\n :label-width=\"props.labelWidth\"\n @field:update=\"handleFieldUpdate\"\n >\n <slot\n v-bind=\"{\n row: state.row,\n parentRow: state.parentRow,\n formActionType: state.formActionType,\n depth: state.depth,\n indexes: state.indexPath,\n index: state.row?.index\n }\"\n />\n </u-form>\n </transition>\n </u-scroll>\n\n <footer :class=\"cls.e('form-footer')\">\n <span :class=\"cls.e('form-hint')\">\n <template v-if=\"props.readonly\"> 只读模式 </template>\n\n <span :class=\"{ [bem.is('concealed')]: !shortcutActive }\">\n <template v-if=\"!(state.formActionType === 'update' && props.quickEdit)\">\n <u-kbd>Ctrl + S</u-kbd> 保存 ·\n </template>\n <u-kbd>Esc</u-kbd> 关闭\n </span>\n </span>\n\n <div :class=\"cls.e('form-actions')\">\n <u-button size=\"small\" text :loading=\"state.loading\" @click=\"handleClose\"> 取消 </u-button>\n <u-button\n v-if=\"showSaveBtn\"\n type=\"primary\"\n size=\"small\"\n title=\"保存\"\n :icon=\"Save\"\n :loading=\"state.loading\"\n @click=\"handleSave\"\n />\n </div>\n </footer>\n </aside>\n</template>\n\n<script lang=\"ts\" setup>\nimport { o } from '@cat-kit/core'\nimport { Close, Save } from '@veltra/icons/normal'\nimport { bem } from '@veltra/utils'\nimport { computed, inject, shallowRef, toRef } from 'vue'\n\nimport type { _FormExposed, FormExposed } from '../../types/form'\nimport { UButton } from '../button'\nimport { UForm } from '../form'\nimport { UIcon } from '../icon'\nimport { UKbd } from '../kbd'\nimport { UScroll } from '../scroll'\nimport { BatchEditDIKey } from './di'\nimport { FORM_ACTION_HEADER_MAP } from './form-action-header'\nimport { useDialogEffect } from './use-dialog-effect'\n\ndefineOptions({ name: 'UBatchEditForm' })\n\nconst batchEditCtx = inject(BatchEditDIKey)!\n\nconst { cls, props, state, handleClose, handleSave, staticFeatures, dynamicFeatures, syncing } =\n batchEditCtx\n\nconst focused = toRef(batchEditCtx, 'focused')\n\n// 弹框模式下,弹框自身关闭(遮罩点击 / 右上角关闭)时同步走 handleClose,不保存\nuseDialogEffect({ closeForm: handleClose })\n\n/** 快捷键提示是否可见:面板模式随聚焦显隐;弹框模式弹框打开期间快捷键始终可用 */\nconst shortcutActive = computed(() => {\n return props.formMode === 'dialog' ? state.formVisible : focused.value\n})\n\nconst formComponentRef = shallowRef<FormExposed>()\n\ndefineExpose<_FormExposed>({\n el: toRef(() => formComponentRef.value?.el),\n validate: () => formComponentRef.value?.validate() ?? Promise.resolve(true),\n clearValidate: () => formComponentRef.value?.clearValidate(),\n reset: () => formComponentRef.value?.reset()\n})\n\nfunction handleFieldUpdate(field: string, value: any) {\n // 编程方式重置/回显期间不写回行数据,避免默认值污染源数据\n if (syncing.value) return\n\n if (state.row && props.quickEdit) {\n o(state.row.data).set(field, value)\n }\n}\n\nconst creatable = computed(() => {\n if (state.formActionType !== 'create') return false\n return staticFeatures.value.has('create') || dynamicFeatures.value.create?.(state.row)\n})\n\nconst creatableChild = computed(() => {\n if (state.formActionType !== 'createChild') return false\n return (\n staticFeatures.value.has('createChild') || dynamicFeatures.value.createChild?.(state.parentRow)\n )\n})\n\nconst updatable = computed(() => {\n if (state.formActionType !== 'update') return false\n return staticFeatures.value.has('update') || dynamicFeatures.value.update?.(state.row)\n})\n\nconst showSaveBtn = computed(() => {\n if (props.readonly) return false\n if (props.quickEdit && state.formActionType === 'update') return false\n return creatable.value || updatable.value || creatableChild.value\n})\n\nconst headerInfo = computed(() => FORM_ACTION_HEADER_MAP[state.formActionType])\n\n/** 头部图标色调修饰类:样式中 createChild 对应的修饰类为 is-child */\nconst iconToneCls = computed(() => {\n const type = state.formActionType\n return bem.is(type === 'createChild' ? 'child' : type)\n})\n</script>\n"],"mappings":"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"}
1
+ {"version":3,"file":"batch-edit-form.js","names":[],"sources":["../../../src/components/batch-edit/batch-edit-form.vue"],"sourcesContent":["<template>\n <!-- 面板模式:表单常驻挂载(快照只在挂载时对传入的 model 拍一次),仅用 v-show 控制显隐;\n 弹框模式:表单随弹框挂载 / 卸载,model 初始快照由 use-edit-state 维护 -->\n <aside\n :class=\"[cls.e('form'), bem.is('dialog', props.formMode === 'dialog')]\"\n v-if=\"!!props.model\"\n v-show=\"state.formVisible\"\n >\n <header :class=\"cls.e('form-header')\">\n <span :class=\"[cls.e('form-icon'), iconToneCls]\">\n <u-icon>\n <component :is=\"headerInfo.icon\" />\n </u-icon>\n </span>\n <div :class=\"cls.e('form-title')\">\n <h3 :class=\"cls.e('form-title-text')\">{{ headerInfo.title }}</h3>\n </div>\n <u-button\n :class=\"cls.e('form-close')\"\n :icon=\"Close\"\n text\n circle\n size=\"small\"\n title=\"关闭\"\n @click=\"handleClose\"\n />\n </header>\n\n <u-scroll always :class=\"cls.e('form-body')\">\n <transition name=\"fade\" appear mode=\"out-in\">\n <u-form\n ref=\"formComponentRef\"\n :model=\"props.model\"\n :readonly=\"props.readonly\"\n :label-width=\"props.labelWidth\"\n @field:update=\"handleFieldUpdate\"\n >\n <slot\n v-bind=\"{\n row: state.row,\n parentRow: state.parentRow,\n formActionType: state.formActionType,\n depth: state.depth,\n indexes: state.indexPath,\n index: state.row?.index\n }\"\n />\n </u-form>\n </transition>\n </u-scroll>\n\n <footer :class=\"cls.e('form-footer')\">\n <span :class=\"cls.e('form-hint')\">\n <template v-if=\"props.readonly\"> 只读模式 </template>\n\n <span :class=\"{ [bem.is('concealed')]: !shortcutActive }\">\n <template\n v-if=\"\n props.formMode === 'panel' && !(state.formActionType === 'update' && props.quickEdit)\n \"\n >\n <u-kbd>Ctrl + S</u-kbd> 保存 ·\n </template>\n <u-kbd>Esc</u-kbd> 关闭\n </span>\n </span>\n\n <div :class=\"cls.e('form-actions')\">\n <u-button size=\"small\" text :loading=\"state.loading\" @click=\"handleClose\"> 取消 </u-button>\n <u-button\n v-if=\"showSaveContinueBtn\"\n size=\"small\"\n title=\"保存并继续\"\n :loading=\"state.loading\"\n @click=\"handleSave(true)\"\n >\n 保存并继续\n </u-button>\n <u-button\n v-if=\"showSaveBtn\"\n type=\"primary\"\n size=\"small\"\n title=\"保存\"\n :icon=\"Save\"\n :loading=\"state.loading\"\n @click=\"handleSave()\"\n />\n </div>\n </footer>\n </aside>\n</template>\n\n<script lang=\"ts\" setup>\nimport { o } from '@cat-kit/core'\nimport { Close, Save } from '@veltra/icons/normal'\nimport { bem } from '@veltra/utils'\nimport { computed, inject, shallowRef, toRef } from 'vue'\n\nimport type { _FormExposed, FormExposed } from '../../types/form'\nimport { UButton } from '../button'\nimport { UForm } from '../form'\nimport { UIcon } from '../icon'\nimport { UKbd } from '../kbd'\nimport { UScroll } from '../scroll'\nimport { BatchEditDIKey } from './di'\nimport { FORM_ACTION_HEADER_MAP } from './form-action-header'\nimport { useDialogEffect } from './use-dialog-effect'\n\ndefineOptions({ name: 'UBatchEditForm' })\n\nconst batchEditCtx = inject(BatchEditDIKey)!\n\nconst { cls, props, state, handleClose, handleSave, staticFeatures, dynamicFeatures, syncing } =\n batchEditCtx\n\nconst focused = toRef(batchEditCtx, 'focused')\n\n// 弹框模式下,弹框自身关闭(遮罩点击 / 右上角关闭)时同步走 handleClose,不保存\nuseDialogEffect({ closeForm: handleClose })\n\n/** 快捷键提示是否可见:面板模式随聚焦显隐;弹框模式弹框打开期间快捷键始终可用 */\nconst shortcutActive = computed(() => {\n return props.formMode === 'dialog' ? state.formVisible : focused.value\n})\n\nconst formComponentRef = shallowRef<FormExposed>()\n\ndefineExpose<_FormExposed>({\n el: toRef(() => formComponentRef.value?.el),\n validate: () => formComponentRef.value?.validate() ?? Promise.resolve(true),\n clearValidate: () => formComponentRef.value?.clearValidate(),\n reset: () => formComponentRef.value?.reset()\n})\n\nfunction handleFieldUpdate(field: string, value: any) {\n // 编程方式重置/回显期间不写回行数据,避免默认值污染源数据\n if (syncing.value) return\n\n if (state.row && props.quickEdit) {\n o(state.row.data).set(field, value)\n }\n}\n\nconst creatable = computed(() => {\n if (state.formActionType !== 'create') return false\n return staticFeatures.value.has('create') || dynamicFeatures.value.create?.(state.row)\n})\n\nconst creatableChild = computed(() => {\n if (state.formActionType !== 'createChild') return false\n return (\n staticFeatures.value.has('createChild') || dynamicFeatures.value.createChild?.(state.parentRow)\n )\n})\n\nconst updatable = computed(() => {\n if (state.formActionType !== 'update') return false\n return staticFeatures.value.has('update') || dynamicFeatures.value.update?.(state.row)\n})\n\nconst showSaveBtn = computed(() => {\n if (props.readonly) return false\n if (props.quickEdit && state.formActionType === 'update') return false\n return creatable.value || updatable.value || creatableChild.value\n})\n\n/** 弹框模式新增类操作显示「保存并继续」:保存后重置表单继续录入,不关闭弹框 */\nconst showSaveContinueBtn = computed(() => {\n if (props.formMode !== 'dialog') return false\n return creatable.value || creatableChild.value\n})\n\nconst headerInfo = computed(() => FORM_ACTION_HEADER_MAP[state.formActionType])\n\n/** 头部图标色调修饰类:样式中 createChild 对应的修饰类为 is-child */\nconst iconToneCls = computed(() => {\n const type = state.formActionType\n return bem.is(type === 'createChild' ? 'child' : type)\n})\n</script>\n"],"mappings":"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"}
@@ -12,7 +12,7 @@ const _sfc_main = /*@__PURE__*/ defineComponent({
12
12
  __name: "batch-edit-list",
13
13
  props: { slots: {} },
14
14
  setup(__props) {
15
- const { cls, state, props, emit, staticFeatures, dynamicFeatures, startEdit, handleCreate, handleDelete, handleInsertToNext, handleInsertToPrev, handleInsertChild } = inject(BatchEditDIKey);
15
+ const { cls, state, props, emit, staticFeatures, dynamicFeatures, startEdit, handleClose, handleCreate, handleDelete, handleInsertToNext, handleInsertToPrev, handleInsertChild } = inject(BatchEditDIKey);
16
16
  const tableProps = computed(() => {
17
17
  return o(props).omit([
18
18
  "model",
@@ -53,6 +53,15 @@ const _sfc_main = /*@__PURE__*/ defineComponent({
53
53
  function canDelete(row) {
54
54
  return !props.readonly && allowed("delete", row);
55
55
  }
56
+ /**
57
+ * 点击行打开编辑/查看表单;再次点击当前行取消选中并关闭表单。
58
+ * update 特性关闭时点击行不响应
59
+ */
60
+ function handleUpdateCurrentRow(row) {
61
+ if (!allowed("update", row)) return;
62
+ if (row) startEdit(row);
63
+ else handleClose();
64
+ }
56
65
  const showCreateBtn = computed(() => {
57
66
  if (props.readonly) return false;
58
67
  const hasFeature = staticFeatures.value.has("create") || dynamicFeatures.value.create?.();
@@ -64,13 +73,16 @@ const _sfc_main = /*@__PURE__*/ defineComponent({
64
73
  slots: __props.slots,
65
74
  class: [unref(cls).e("table")],
66
75
  columns: columns.value,
76
+ "highlight-current": "",
67
77
  current: unref(state).row,
68
- "onUpdate:checked": _cache[0] || (_cache[0] = ($event) => unref(emit)("update:checked", $event)),
69
- "onUpdate:selected": _cache[1] || (_cache[1] = ($event) => unref(emit)("update:selected", $event))
78
+ "onUpdate:current": handleUpdateCurrentRow,
79
+ "onUpdate:checked": _cache[1] || (_cache[1] = ($event) => unref(emit)("update:checked", $event)),
80
+ "onUpdate:selected": _cache[2] || (_cache[2] = ($event) => unref(emit)("update:selected", $event))
70
81
  }), createSlots({
71
82
  "column:__action__": withCtx(({ row }) => [createVNode(unref(action_group_default), {
72
83
  max: 5,
73
- circle: ""
84
+ circle: "",
85
+ onClick: _cache[0] || (_cache[0] = withModifiers(() => {}, ["stop"]))
74
86
  }, {
75
87
  default: withCtx(() => [
76
88
  allowed("update", row) ? (openBlock(), createBlock(unref(_sfc_main$3), mergeProps({
@@ -122,7 +134,7 @@ const _sfc_main = /*@__PURE__*/ defineComponent({
122
134
  plain: "",
123
135
  onClick: withModifiers(unref(handleCreate), ["stop"])
124
136
  }, {
125
- default: withCtx(() => [..._cache[2] || (_cache[2] = [createTextVNode(" 新增一行 ", -1)])]),
137
+ default: withCtx(() => [..._cache[3] || (_cache[3] = [createTextVNode(" 新增一行 ", -1)])]),
126
138
  _: 1
127
139
  }, 8, [
128
140
  "class",
@@ -1 +1 @@
1
- {"version":3,"file":"batch-edit-list.js","names":[],"sources":["../../../src/components/batch-edit/batch-edit-list.vue"],"sourcesContent":["<template>\n <u-table\n v-bind=\"tableProps\"\n :slots=\"slots\"\n :class=\"[cls.e('table')]\"\n :columns=\"columns\"\n :current=\"state.row\"\n @update:checked=\"emit('update:checked', $event)\"\n @update:selected=\"emit('update:selected', $event)\"\n >\n <template #column:__action__=\"{ row }\">\n <u-action-group :max=\"5\" circle>\n <u-action\n v-if=\"allowed('update', row)\"\n :icon=\"props.readonly ? View : EditPen\"\n :title=\"props.readonly ? '查看' : '编辑'\"\n @run=\"startEdit(row)\"\n v-bind=\"props.actionsProps?.update\"\n />\n <u-action\n v-if=\"!props.readonly && !!props.tree && allowed('createChild', row)\"\n :icon=\"AddChild\"\n title=\"添加子级\"\n @run=\"handleInsertChild(row)\"\n />\n <u-action\n v-if=\"canDelete(row)\"\n :icon=\"Delete\"\n type=\"danger\"\n title=\"删除\"\n @run=\"handleDelete(row)\"\n v-bind=\"props.actionsProps?.delete\"\n />\n <u-action\n v-if=\"!props.readonly && allowed('create', row)\"\n :icon=\"InsertToPrev\"\n title=\"在上方插入\"\n @run=\"handleInsertToPrev(row)\"\n />\n <u-action\n v-if=\"!props.readonly && allowed('create', row)\"\n :icon=\"InsertToNext\"\n title=\"在下方插入\"\n @run=\"handleInsertToNext(row)\"\n />\n </u-action-group>\n </template>\n\n <!-- 新增按钮 -->\n <template #append v-if=\"showCreateBtn\">\n <div :class=\"cls.e('add')\">\n <u-button\n :class=\"cls.e('add-btn')\"\n :icon=\"Plus\"\n :loading=\"state.loading\"\n type=\"primary\"\n plain\n @click.stop=\"handleCreate\"\n >\n 新增一行\n </u-button>\n </div>\n </template>\n </u-table>\n</template>\n\n<script setup lang=\"ts\">\nimport { o } from '@cat-kit/core'\nimport {\n AddChild,\n Delete,\n EditPen,\n InsertToNext,\n InsertToPrev,\n Plus,\n View\n} from '@veltra/icons/normal'\nimport { computed, inject, type Slots } from 'vue'\n\nimport type { BatchEditFeature, TableRow } from '../../types'\nimport { UAction, UActionGroup } from '../action'\nimport { UButton } from '../button'\nimport { UTable } from '../table'\nimport { BatchEditDIKey } from './di'\n\ndefineOptions({ name: 'UBatchEditList' })\n\ndefineProps<{ slots: Slots }>()\n\nconst {\n cls,\n state,\n props,\n emit,\n staticFeatures,\n dynamicFeatures,\n startEdit,\n handleCreate,\n handleDelete,\n handleInsertToNext,\n handleInsertToPrev,\n handleInsertChild\n} = inject(BatchEditDIKey)!\n\nconst tableProps = computed(() => {\n return o(props as Record<string, any>).omit([\n 'model',\n 'columns',\n 'cols',\n 'readonly',\n 'deleteMethod',\n 'saveMethod',\n 'features',\n 'beforeCreate',\n 'formMode',\n 'quickEdit',\n 'labelWidth',\n 'actionsProps'\n ])\n})\n\nconst hasNot = (value: BatchEditFeature[]) => value.every((v) => !staticFeatures.value.has(v))\n\nconst allowed = (feature: BatchEditFeature, row?: TableRow) => {\n return staticFeatures.value.has(feature) || !!dynamicFeatures.value[feature]?.(row)\n}\n\nconst columns = computed(() => {\n // 只读模式的操作列只保留「查看」入口\n const related: BatchEditFeature[] = props.readonly\n ? ['update']\n : ['create', 'delete', 'createChild', 'update']\n if (hasNot(related)) return props.columns\n\n return (props.columns ?? []).concat({\n name: '操作',\n key: '__action__',\n align: 'center',\n width: 180,\n fixed: 'right',\n resizable: false\n })\n})\n\nfunction canDelete(row: TableRow) {\n return !props.readonly && allowed('delete', row)\n}\n\nconst showCreateBtn = computed(() => {\n if (props.readonly) return false\n\n const hasFeature = staticFeatures.value.has('create') || dynamicFeatures.value.create?.()\n const createActionVisible = state.formActionType === 'create' && state.formVisible\n return hasFeature && !createActionVisible\n})\n</script>\n"],"mappings":"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"}
1
+ {"version":3,"file":"batch-edit-list.js","names":[],"sources":["../../../src/components/batch-edit/batch-edit-list.vue"],"sourcesContent":["<template>\n <u-table\n v-bind=\"tableProps\"\n :slots=\"slots\"\n :class=\"[cls.e('table')]\"\n :columns=\"columns\"\n highlight-current\n :current=\"state.row\"\n @update:current=\"handleUpdateCurrentRow\"\n @update:checked=\"emit('update:checked', $event)\"\n @update:selected=\"emit('update:selected', $event)\"\n >\n <template #column:__action__=\"{ row }\">\n <u-action-group :max=\"5\" circle @click.stop>\n <u-action\n v-if=\"allowed('update', row)\"\n :icon=\"props.readonly ? View : EditPen\"\n :title=\"props.readonly ? '查看' : '编辑'\"\n @run=\"startEdit(row)\"\n v-bind=\"props.actionsProps?.update\"\n />\n <u-action\n v-if=\"!props.readonly && !!props.tree && allowed('createChild', row)\"\n :icon=\"AddChild\"\n title=\"添加子级\"\n @run=\"handleInsertChild(row)\"\n />\n <u-action\n v-if=\"canDelete(row)\"\n :icon=\"Delete\"\n type=\"danger\"\n title=\"删除\"\n @run=\"handleDelete(row)\"\n v-bind=\"props.actionsProps?.delete\"\n />\n <u-action\n v-if=\"!props.readonly && allowed('create', row)\"\n :icon=\"InsertToPrev\"\n title=\"在上方插入\"\n @run=\"handleInsertToPrev(row)\"\n />\n <u-action\n v-if=\"!props.readonly && allowed('create', row)\"\n :icon=\"InsertToNext\"\n title=\"在下方插入\"\n @run=\"handleInsertToNext(row)\"\n />\n </u-action-group>\n </template>\n\n <!-- 新增按钮 -->\n <template #append v-if=\"showCreateBtn\">\n <div :class=\"cls.e('add')\">\n <u-button\n :class=\"cls.e('add-btn')\"\n :icon=\"Plus\"\n :loading=\"state.loading\"\n type=\"primary\"\n plain\n @click.stop=\"handleCreate\"\n >\n 新增一行\n </u-button>\n </div>\n </template>\n </u-table>\n</template>\n\n<script setup lang=\"ts\">\nimport { o } from '@cat-kit/core'\nimport {\n AddChild,\n Delete,\n EditPen,\n InsertToNext,\n InsertToPrev,\n Plus,\n View\n} from '@veltra/icons/normal'\nimport { computed, inject, type Slots } from 'vue'\n\nimport type { BatchEditFeature, TableRow } from '../../types'\nimport { UAction, UActionGroup } from '../action'\nimport { UButton } from '../button'\nimport { UTable } from '../table'\nimport { BatchEditDIKey } from './di'\n\ndefineOptions({ name: 'UBatchEditList' })\n\ndefineProps<{ slots: Slots }>()\n\nconst {\n cls,\n state,\n props,\n emit,\n staticFeatures,\n dynamicFeatures,\n startEdit,\n handleClose,\n handleCreate,\n handleDelete,\n handleInsertToNext,\n handleInsertToPrev,\n handleInsertChild\n} = inject(BatchEditDIKey)!\n\nconst tableProps = computed(() => {\n return o(props as Record<string, any>).omit([\n 'model',\n 'columns',\n 'cols',\n 'readonly',\n 'deleteMethod',\n 'saveMethod',\n 'features',\n 'beforeCreate',\n 'formMode',\n 'quickEdit',\n 'labelWidth',\n 'actionsProps'\n ])\n})\n\nconst hasNot = (value: BatchEditFeature[]) => value.every((v) => !staticFeatures.value.has(v))\n\nconst allowed = (feature: BatchEditFeature, row?: TableRow) => {\n return staticFeatures.value.has(feature) || !!dynamicFeatures.value[feature]?.(row)\n}\n\nconst columns = computed(() => {\n // 只读模式的操作列只保留「查看」入口\n const related: BatchEditFeature[] = props.readonly\n ? ['update']\n : ['create', 'delete', 'createChild', 'update']\n if (hasNot(related)) return props.columns\n\n return (props.columns ?? []).concat({\n name: '操作',\n key: '__action__',\n align: 'center',\n width: 180,\n fixed: 'right',\n resizable: false\n })\n})\n\nfunction canDelete(row: TableRow) {\n return !props.readonly && allowed('delete', row)\n}\n\n/**\n * 点击行打开编辑/查看表单;再次点击当前行取消选中并关闭表单。\n * update 特性关闭时点击行不响应\n */\nfunction handleUpdateCurrentRow(row?: TableRow) {\n if (!allowed('update', row)) return\n\n if (row) {\n startEdit(row)\n } else {\n handleClose()\n }\n}\n\nconst showCreateBtn = computed(() => {\n if (props.readonly) return false\n\n const hasFeature = staticFeatures.value.has('create') || dynamicFeatures.value.create?.()\n const createActionVisible = state.formActionType === 'create' && state.formVisible\n return hasFeature && !createActionVisible\n})\n</script>\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"di.js","names":[],"sources":["../../../src/components/batch-edit/di.ts"],"sourcesContent":["import type { BEM } from '@veltra/utils'\nimport type { ComputedRef, InjectionKey, ShallowRef } from 'vue'\n\nimport type {\n BatchEditEmits,\n BatchEditFeature,\n BatchEditProps,\n BatchEditStates,\n TableRow\n} from '../../types'\nimport type { EditReturned } from './use-handlers'\n\nexport const BatchEditDIKey: InjectionKey<\n {\n cls: BEM<'batch-edit', 'u-'>\n props: BatchEditProps\n emit: BatchEditEmits\n state: BatchEditStates\n staticFeatures: ComputedRef<Set<BatchEditFeature>>\n dynamicFeatures: ComputedRef<\n Record<BatchEditFeature, ((row?: TableRow) => boolean) | undefined>\n >\n /** 组件或其子节点是否处于聚焦状态 */\n focused: ShallowRef<boolean>\n /** 是否正在以编程方式重置/回显表单,此期间禁止 quick-edit 回写行数据 */\n syncing: ShallowRef<boolean>\n /** 开始编辑/查看一行(操作列「编辑」按钮触发) */\n startEdit: (row: TableRow) => void\n } & EditReturned\n> = Symbol('BatchEditDIKey')\n"],"mappings":";AAYA,MAAa,iBAiBT,OAAO,gBAAgB"}
1
+ {"version":3,"file":"di.js","names":[],"sources":["../../../src/components/batch-edit/di.ts"],"sourcesContent":["import type { BEM } from '@veltra/utils'\nimport type { ComputedRef, InjectionKey, ShallowRef } from 'vue'\n\nimport type {\n BatchEditEmits,\n BatchEditFeature,\n BatchEditProps,\n BatchEditStates,\n TableRow\n} from '../../types'\nimport type { EditReturned } from './use-handlers'\n\nexport const BatchEditDIKey: InjectionKey<\n {\n cls: BEM<'batch-edit', 'u-'>\n props: BatchEditProps\n emit: BatchEditEmits\n state: BatchEditStates\n staticFeatures: ComputedRef<Set<BatchEditFeature>>\n dynamicFeatures: ComputedRef<\n Record<BatchEditFeature, ((row?: TableRow) => boolean) | undefined>\n >\n /** 组件或其子节点是否处于聚焦状态 */\n focused: ShallowRef<boolean>\n /** 是否正在以编程方式重置/回显表单,此期间禁止 quick-edit 回写行数据 */\n syncing: ShallowRef<boolean>\n /** 开始编辑/查看一行(点击行或操作列「编辑」按钮触发) */\n startEdit: (row: TableRow) => void\n } & EditReturned\n> = Symbol('BatchEditDIKey')\n"],"mappings":";AAYA,MAAa,iBAiBT,OAAO,gBAAgB"}
@@ -97,8 +97,8 @@ function useHandlers(options) {
97
97
  if (state.row) state.row.operating = false;
98
98
  };
99
99
  }
100
- /** 保存 */
101
- const handleSave = runWithLoading(async () => {
100
+ /** 保存;keepOpen 为 true 时(「保存并继续」)新增保存后不关闭表单 */
101
+ const handleSave = runWithLoading(async (keepOpen = false) => {
102
102
  const { model, saveMethod } = props;
103
103
  const valid = await formRef.value?.validate();
104
104
  if (!model || !valid) return;
@@ -110,7 +110,7 @@ function useHandlers(options) {
110
110
  if (result) item = result;
111
111
  }
112
112
  insert(item);
113
- if (props.formMode === "dialog") {
113
+ if (props.formMode === "dialog" && !keepOpen) {
114
114
  resetState();
115
115
  return;
116
116
  }
@@ -1 +1 @@
1
- {"version":3,"file":"use-handlers.js","names":[],"sources":["../../../src/components/batch-edit/use-handlers.ts"],"sourcesContent":["import { copy, last, o } from '@cat-kit/core'\nimport { computed, nextTick, type ShallowRef } from 'vue'\n\nimport type {\n TableRow,\n BatchEditEmits,\n BatchEditProps,\n BatchEditStates,\n FormExposed\n} from '../../types'\n\n/** 按索引路径在原始数据树中定位节点(等价于历史 Forest.visit 路径访问) */\nfunction visitDataByIndexPath<T extends Record<string, unknown>>(\n roots: T[],\n indexPath: number[],\n childrenKey: string\n): T | undefined {\n if (!indexPath.length) return undefined\n let currentList: T[] | undefined = roots\n let node: T | undefined\n for (let i = 0; i < indexPath.length; i++) {\n const idx = indexPath[i]!\n if (!currentList) return undefined\n node = currentList[idx]\n if (node === undefined) return undefined\n if (i < indexPath.length - 1) {\n const next = node[childrenKey]\n currentList = Array.isArray(next) ? (next as T[]) : undefined\n }\n }\n return node\n}\n\ninterface Options {\n props: BatchEditProps\n emit: BatchEditEmits\n state: BatchEditStates\n formRef: ShallowRef<FormExposed | null>\n resetState: () => void\n}\n\nexport interface EditReturned {\n handleSave: () => Promise<void>\n handleClose: () => void\n handleCreate: () => void\n handleDelete: (row: TableRow) => Promise<void>\n handleInsertToNext: (row: TableRow) => void\n handleInsertToPrev: (row: TableRow) => void\n handleInsertChild: (row: TableRow) => void\n}\n\nexport function useHandlers(options: Options): EditReturned {\n const { props, emit, state, resetState, formRef } = options\n\n const childrenKey = computed(() => {\n return typeof props.tree === 'string' ? props.tree : 'children'\n })\n\n function getInsertData(): Record<string, any> {\n return copy(props.model ?? {})\n }\n\n /**\n * 插入数据\n * @param item 数据\n */\n function insert(item: Record<string, any>) {\n const data = [...(props.data ?? [])]\n\n const parent = visitDataByIndexPath(data ?? [], state.indexPath.slice(0, -1), childrenKey.value)\n\n if (parent) {\n const children = parent[childrenKey.value]\n if (!children) {\n parent[childrenKey.value] = [item]\n } else {\n children.splice(last(state.indexPath), 0, item)\n }\n } else {\n data.splice(last(state.indexPath), 0, item)\n }\n\n emit('update:data', data)\n\n return item\n }\n\n /**\n * 点击新增按钮\n */\n function handleCreate() {\n const { data } = props\n\n resetState()\n\n nextTick(() => {\n state.formActionType = 'create'\n state.formVisible = true\n state.depth = 1\n state.indexPath = [data?.length ?? 0]\n emit('create')\n })\n }\n\n function handleInsertToPrev(row: TableRow) {\n resetState()\n state.formActionType = 'create'\n state.formVisible = true\n state.parentRow = row.parent\n state.depth = row.depth\n state.indexPath = [...row.indexes]\n emit('create-prev', row)\n }\n\n function handleInsertToNext(row: TableRow) {\n resetState()\n state.formActionType = 'create'\n state.formVisible = true\n state.parentRow = row.parent\n state.depth = row.depth\n state.indexPath = [...row.indexes.slice(0, -1), row.index + 1]\n emit('create-next', row)\n }\n\n function handleInsertChild(row: TableRow) {\n resetState()\n state.formActionType = 'createChild'\n state.formVisible = true\n state.parentRow = row\n state.depth = row.depth + 1\n row.expanded = true\n state.indexPath = [...row.indexes, row.children?.length ?? 0]\n emit('create-child', row)\n }\n\n function runWithLoading<Arg extends any[]>(fn: (...args: Arg) => Promise<void> | void) {\n return async (...args: Arg) => {\n // 重入保护:进行中(快捷键/按钮并发触发)直接忽略\n if (state.loading) return\n state.loading = true\n if (state.row) {\n state.row.operating = true\n }\n try {\n await fn.apply(null, args)\n } catch (error) {\n console.error(error)\n }\n state.loading = false\n if (state.row) {\n state.row.operating = false\n }\n }\n }\n\n /** 保存 */\n const handleSave = runWithLoading(async () => {\n const { model, saveMethod } = props\n const valid = await formRef.value?.validate()\n if (!model || !valid) return\n\n let item = getInsertData()\n\n // 新增\n if (state.formActionType === 'create' || state.formActionType === 'createChild') {\n await props.beforeCreate?.(item, state.parentRow?.data)\n if (saveMethod) {\n const result = await saveMethod(item, state.formActionType, state.parentRow?.data)\n if (result) {\n item = result\n }\n }\n insert(item)\n\n // 弹框模式保存成功即关闭,不走面板的连续新增\n if (props.formMode === 'dialog') {\n resetState()\n return\n }\n\n // 推进插入点,便于连续新增;并重置表单到初始默认值\n const next = last(state.indexPath) + 1\n state.indexPath = [...state.indexPath.slice(0, -1), next]\n formRef.value?.reset()\n return\n }\n\n // 普通模式下的编辑\n if (saveMethod) {\n const result = await saveMethod(item, state.formActionType, state.parentRow?.data)\n if (result) {\n item = result\n }\n }\n\n const { row } = state\n row &&\n Object.keys(item).forEach((key) => {\n o(row.data).set(key, o(item).get(key))\n })\n\n if (props.formMode === 'dialog') {\n resetState()\n }\n })\n\n const handleDelete = runWithLoading(async (row: TableRow) => {\n const { deleteMethod } = props\n\n if (deleteMethod) {\n const result = await deleteMethod([row.data])\n if (result === false) {\n return\n }\n }\n\n const data = [...(props.data ?? [])]\n\n const parent = visitDataByIndexPath(data, row.indexes.slice(0, -1), childrenKey.value)\n\n if (parent) {\n const children = parent[childrenKey.value]\n if (children) {\n children.splice(row.index, 1)\n } else {\n console.error('行路径不正确')\n }\n } else {\n data.splice(row.index, 1)\n }\n\n if (state.row === row) {\n resetState()\n }\n\n emit('update:data', data)\n })\n\n function handleClose() {\n resetState()\n }\n\n return {\n handleDelete,\n handleInsertChild,\n handleInsertToNext,\n handleInsertToPrev,\n handleCreate,\n handleClose,\n handleSave\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"use-handlers.js","names":[],"sources":["../../../src/components/batch-edit/use-handlers.ts"],"sourcesContent":["import { copy, last, o } from '@cat-kit/core'\nimport { computed, nextTick, type ShallowRef } from 'vue'\n\nimport type {\n TableRow,\n BatchEditEmits,\n BatchEditProps,\n BatchEditStates,\n FormExposed\n} from '../../types'\n\n/** 按索引路径在原始数据树中定位节点(等价于历史 Forest.visit 路径访问) */\nfunction visitDataByIndexPath<T extends Record<string, unknown>>(\n roots: T[],\n indexPath: number[],\n childrenKey: string\n): T | undefined {\n if (!indexPath.length) return undefined\n let currentList: T[] | undefined = roots\n let node: T | undefined\n for (let i = 0; i < indexPath.length; i++) {\n const idx = indexPath[i]!\n if (!currentList) return undefined\n node = currentList[idx]\n if (node === undefined) return undefined\n if (i < indexPath.length - 1) {\n const next = node[childrenKey]\n currentList = Array.isArray(next) ? (next as T[]) : undefined\n }\n }\n return node\n}\n\ninterface Options {\n props: BatchEditProps\n emit: BatchEditEmits\n state: BatchEditStates\n formRef: ShallowRef<FormExposed | null>\n resetState: () => void\n}\n\nexport interface EditReturned {\n /** @param keepOpen 新增类操作保存后不关闭表单(弹框模式「保存并继续」) */\n handleSave: (keepOpen?: boolean) => Promise<void>\n handleClose: () => void\n handleCreate: () => void\n handleDelete: (row: TableRow) => Promise<void>\n handleInsertToNext: (row: TableRow) => void\n handleInsertToPrev: (row: TableRow) => void\n handleInsertChild: (row: TableRow) => void\n}\n\nexport function useHandlers(options: Options): EditReturned {\n const { props, emit, state, resetState, formRef } = options\n\n const childrenKey = computed(() => {\n return typeof props.tree === 'string' ? props.tree : 'children'\n })\n\n function getInsertData(): Record<string, any> {\n return copy(props.model ?? {})\n }\n\n /**\n * 插入数据\n * @param item 数据\n */\n function insert(item: Record<string, any>) {\n const data = [...(props.data ?? [])]\n\n const parent = visitDataByIndexPath(data ?? [], state.indexPath.slice(0, -1), childrenKey.value)\n\n if (parent) {\n const children = parent[childrenKey.value]\n if (!children) {\n parent[childrenKey.value] = [item]\n } else {\n children.splice(last(state.indexPath), 0, item)\n }\n } else {\n data.splice(last(state.indexPath), 0, item)\n }\n\n emit('update:data', data)\n\n return item\n }\n\n /**\n * 点击新增按钮\n */\n function handleCreate() {\n const { data } = props\n\n resetState()\n\n nextTick(() => {\n state.formActionType = 'create'\n state.formVisible = true\n state.depth = 1\n state.indexPath = [data?.length ?? 0]\n emit('create')\n })\n }\n\n function handleInsertToPrev(row: TableRow) {\n resetState()\n state.formActionType = 'create'\n state.formVisible = true\n state.parentRow = row.parent\n state.depth = row.depth\n state.indexPath = [...row.indexes]\n emit('create-prev', row)\n }\n\n function handleInsertToNext(row: TableRow) {\n resetState()\n state.formActionType = 'create'\n state.formVisible = true\n state.parentRow = row.parent\n state.depth = row.depth\n state.indexPath = [...row.indexes.slice(0, -1), row.index + 1]\n emit('create-next', row)\n }\n\n function handleInsertChild(row: TableRow) {\n resetState()\n state.formActionType = 'createChild'\n state.formVisible = true\n state.parentRow = row\n state.depth = row.depth + 1\n row.expanded = true\n state.indexPath = [...row.indexes, row.children?.length ?? 0]\n emit('create-child', row)\n }\n\n function runWithLoading<Arg extends any[]>(fn: (...args: Arg) => Promise<void> | void) {\n return async (...args: Arg) => {\n // 重入保护:进行中(快捷键/按钮并发触发)直接忽略\n if (state.loading) return\n state.loading = true\n if (state.row) {\n state.row.operating = true\n }\n try {\n await fn.apply(null, args)\n } catch (error) {\n console.error(error)\n }\n state.loading = false\n if (state.row) {\n state.row.operating = false\n }\n }\n }\n\n /** 保存;keepOpen 为 true 时(「保存并继续」)新增保存后不关闭表单 */\n const handleSave = runWithLoading(async (keepOpen = false) => {\n const { model, saveMethod } = props\n const valid = await formRef.value?.validate()\n if (!model || !valid) return\n\n let item = getInsertData()\n\n // 新增\n if (state.formActionType === 'create' || state.formActionType === 'createChild') {\n await props.beforeCreate?.(item, state.parentRow?.data)\n if (saveMethod) {\n const result = await saveMethod(item, state.formActionType, state.parentRow?.data)\n if (result) {\n item = result\n }\n }\n insert(item)\n\n // 弹框模式保存成功即关闭,连续新增只能由「保存并继续」显式触发\n if (props.formMode === 'dialog' && !keepOpen) {\n resetState()\n return\n }\n\n // 推进插入点,便于连续新增;并重置表单到初始默认值\n const next = last(state.indexPath) + 1\n state.indexPath = [...state.indexPath.slice(0, -1), next]\n formRef.value?.reset()\n return\n }\n\n // 普通模式下的编辑\n if (saveMethod) {\n const result = await saveMethod(item, state.formActionType, state.parentRow?.data)\n if (result) {\n item = result\n }\n }\n\n const { row } = state\n row &&\n Object.keys(item).forEach((key) => {\n o(row.data).set(key, o(item).get(key))\n })\n\n if (props.formMode === 'dialog') {\n resetState()\n }\n })\n\n const handleDelete = runWithLoading(async (row: TableRow) => {\n const { deleteMethod } = props\n\n if (deleteMethod) {\n const result = await deleteMethod([row.data])\n if (result === false) {\n return\n }\n }\n\n const data = [...(props.data ?? [])]\n\n const parent = visitDataByIndexPath(data, row.indexes.slice(0, -1), childrenKey.value)\n\n if (parent) {\n const children = parent[childrenKey.value]\n if (children) {\n children.splice(row.index, 1)\n } else {\n console.error('行路径不正确')\n }\n } else {\n data.splice(row.index, 1)\n }\n\n if (state.row === row) {\n resetState()\n }\n\n emit('update:data', data)\n })\n\n function handleClose() {\n resetState()\n }\n\n return {\n handleDelete,\n handleInsertChild,\n handleInsertToNext,\n handleInsertToPrev,\n handleCreate,\n handleClose,\n handleSave\n }\n}\n"],"mappings":"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"}
@@ -24,15 +24,17 @@ function useShortcutKey(options) {
24
24
  /**
25
25
  * 键盘快捷键:
26
26
  * - Esc 关闭表单
27
- * - ⌘/Ctrl + S 保存(快速编辑模式下编辑行时除外)
27
+ * - ⌘/Ctrl + S 保存(仅面板模式;快速编辑模式下编辑行时除外)
28
28
  *
29
29
  * 面板模式仅组件获焦时生效;弹框模式表单被 teleport 到 body,
30
- * 组件聚焦状态覆盖不到,改为弹框打开期间生效
30
+ * 组件聚焦状态覆盖不到,改为弹框打开期间生效。
31
+ * 弹框模式不支持 ⌘/Ctrl + S 保存,保存只能走底部按钮
31
32
  */
32
33
  function handleKeydown(e) {
33
34
  if (!(props.formMode === "dialog" ? state.formVisible : focused.value)) return;
34
35
  if (props.readonly && e.key !== "Escape") return;
35
36
  if (e.key === "Escape") return runEscape(e);
37
+ if (props.formMode === "dialog") return;
36
38
  if (!(e.metaKey || e.ctrlKey)) return;
37
39
  if (e.key.toLowerCase() === "s") return runSave(e);
38
40
  }
@@ -1 +1 @@
1
- {"version":3,"file":"use-shortcut-key.js","names":[],"sources":["../../../src/components/batch-edit/use-shortcut-key.ts"],"sourcesContent":["import { shallowRef } from 'vue'\n\nimport type { BatchEditProps, BatchEditStates } from '../../types'\n\ninterface Options {\n props: BatchEditProps\n onSave: () => void\n onClose: () => void\n state: BatchEditStates\n}\nexport function useShortcutKey(options: Options) {\n const { props, onClose, onSave, state } = options\n const focused = shallowRef(false)\n\n function handleFocusIn() {\n focused.value = true\n }\n\n function handleFocusOut(e: FocusEvent) {\n const root = e.currentTarget as HTMLElement\n if (!root.contains(e.relatedTarget as Node | null)) {\n focused.value = false\n }\n }\n\n function runEscape(e: KeyboardEvent) {\n if (!state.formVisible) return\n e.preventDefault()\n e.stopPropagation()\n onClose()\n }\n\n function runSave(e: KeyboardEvent) {\n if (!state.formVisible) return\n if (props.quickEdit && state.formActionType === 'update') return\n e.preventDefault()\n onSave()\n }\n\n /**\n * 键盘快捷键:\n * - Esc 关闭表单\n * - ⌘/Ctrl + S 保存(快速编辑模式下编辑行时除外)\n *\n * 面板模式仅组件获焦时生效;弹框模式表单被 teleport 到 body,\n * 组件聚焦状态覆盖不到,改为弹框打开期间生效\n */\n function handleKeydown(e: KeyboardEvent) {\n const active = props.formMode === 'dialog' ? state.formVisible : focused.value\n if (!active) return\n if (props.readonly && e.key !== 'Escape') return\n\n if (e.key === 'Escape') return runEscape(e)\n\n const meta = e.metaKey || e.ctrlKey\n if (!meta) return\n\n const key = e.key.toLowerCase()\n\n if (key === 's') return runSave(e)\n }\n\n return { focused, handleFocusIn, handleFocusOut, handleKeydown }\n}\n"],"mappings":";;AAUA,SAAgB,eAAe,SAAkB;CAC/C,MAAM,EAAE,OAAO,SAAS,QAAQ,UAAU;CAC1C,MAAM,UAAU,WAAW,KAAK;CAEhC,SAAS,gBAAgB;EACvB,QAAQ,QAAQ;CAClB;CAEA,SAAS,eAAe,GAAe;EAErC,IAAI,CADS,EAAE,cACL,SAAS,EAAE,aAA4B,GAC/C,QAAQ,QAAQ;CAEpB;CAEA,SAAS,UAAU,GAAkB;EACnC,IAAI,CAAC,MAAM,aAAa;EACxB,EAAE,eAAe;EACjB,EAAE,gBAAgB;EAClB,QAAQ;CACV;CAEA,SAAS,QAAQ,GAAkB;EACjC,IAAI,CAAC,MAAM,aAAa;EACxB,IAAI,MAAM,aAAa,MAAM,mBAAmB,UAAU;EAC1D,EAAE,eAAe;EACjB,OAAO;CACT;;;;;;;;;CAUA,SAAS,cAAc,GAAkB;EAEvC,IAAI,EADW,MAAM,aAAa,WAAW,MAAM,cAAc,QAAQ,QAC5D;EACb,IAAI,MAAM,YAAY,EAAE,QAAQ,UAAU;EAE1C,IAAI,EAAE,QAAQ,UAAU,OAAO,UAAU,CAAC;EAG1C,IAAI,EADS,EAAE,WAAW,EAAE,UACjB;EAIX,IAFY,EAAE,IAAI,YAEZ,MAAM,KAAK,OAAO,QAAQ,CAAC;CACnC;CAEA,OAAO;EAAE;EAAS;EAAe;EAAgB;CAAc;AACjE"}
1
+ {"version":3,"file":"use-shortcut-key.js","names":[],"sources":["../../../src/components/batch-edit/use-shortcut-key.ts"],"sourcesContent":["import { shallowRef } from 'vue'\n\nimport type { BatchEditProps, BatchEditStates } from '../../types'\n\ninterface Options {\n props: BatchEditProps\n onSave: () => void\n onClose: () => void\n state: BatchEditStates\n}\nexport function useShortcutKey(options: Options) {\n const { props, onClose, onSave, state } = options\n const focused = shallowRef(false)\n\n function handleFocusIn() {\n focused.value = true\n }\n\n function handleFocusOut(e: FocusEvent) {\n const root = e.currentTarget as HTMLElement\n if (!root.contains(e.relatedTarget as Node | null)) {\n focused.value = false\n }\n }\n\n function runEscape(e: KeyboardEvent) {\n if (!state.formVisible) return\n e.preventDefault()\n e.stopPropagation()\n onClose()\n }\n\n function runSave(e: KeyboardEvent) {\n if (!state.formVisible) return\n if (props.quickEdit && state.formActionType === 'update') return\n e.preventDefault()\n onSave()\n }\n\n /**\n * 键盘快捷键:\n * - Esc 关闭表单\n * - ⌘/Ctrl + S 保存(仅面板模式;快速编辑模式下编辑行时除外)\n *\n * 面板模式仅组件获焦时生效;弹框模式表单被 teleport 到 body,\n * 组件聚焦状态覆盖不到,改为弹框打开期间生效。\n * 弹框模式不支持 ⌘/Ctrl + S 保存,保存只能走底部按钮\n */\n function handleKeydown(e: KeyboardEvent) {\n const active = props.formMode === 'dialog' ? state.formVisible : focused.value\n if (!active) return\n if (props.readonly && e.key !== 'Escape') return\n\n if (e.key === 'Escape') return runEscape(e)\n\n if (props.formMode === 'dialog') return\n\n const meta = e.metaKey || e.ctrlKey\n if (!meta) return\n\n const key = e.key.toLowerCase()\n\n if (key === 's') return runSave(e)\n }\n\n return { focused, handleFocusIn, handleFocusOut, handleKeydown }\n}\n"],"mappings":";;AAUA,SAAgB,eAAe,SAAkB;CAC/C,MAAM,EAAE,OAAO,SAAS,QAAQ,UAAU;CAC1C,MAAM,UAAU,WAAW,KAAK;CAEhC,SAAS,gBAAgB;EACvB,QAAQ,QAAQ;CAClB;CAEA,SAAS,eAAe,GAAe;EAErC,IAAI,CADS,EAAE,cACL,SAAS,EAAE,aAA4B,GAC/C,QAAQ,QAAQ;CAEpB;CAEA,SAAS,UAAU,GAAkB;EACnC,IAAI,CAAC,MAAM,aAAa;EACxB,EAAE,eAAe;EACjB,EAAE,gBAAgB;EAClB,QAAQ;CACV;CAEA,SAAS,QAAQ,GAAkB;EACjC,IAAI,CAAC,MAAM,aAAa;EACxB,IAAI,MAAM,aAAa,MAAM,mBAAmB,UAAU;EAC1D,EAAE,eAAe;EACjB,OAAO;CACT;;;;;;;;;;CAWA,SAAS,cAAc,GAAkB;EAEvC,IAAI,EADW,MAAM,aAAa,WAAW,MAAM,cAAc,QAAQ,QAC5D;EACb,IAAI,MAAM,YAAY,EAAE,QAAQ,UAAU;EAE1C,IAAI,EAAE,QAAQ,UAAU,OAAO,UAAU,CAAC;EAE1C,IAAI,MAAM,aAAa,UAAU;EAGjC,IAAI,EADS,EAAE,WAAW,EAAE,UACjB;EAIX,IAFY,EAAE,IAAI,YAEZ,MAAM,KAAK,OAAO,QAAQ,CAAC;CACnC;CAEA,OAAO;EAAE;EAAS;EAAe;EAAgB;CAAc;AACjE"}
@@ -18,14 +18,12 @@
18
18
  .u-card {
19
19
  border-radius: var(--u-card-radius, var(--u-radius-large));
20
20
  background-color: var(--u-bg-color-top);
21
- border: var(--u-border-muted);
22
21
  box-shadow: var(--u-shadow-sm);
23
22
  backdrop-filter: var(--u-bg-filter);
24
23
  -webkit-backdrop-filter: var(--u-bg-filter);
25
24
  overflow: hidden;
26
25
  }
27
26
  .u-card.is-integrate {
28
- border: none;
29
27
  box-shadow: none;
30
28
  --u-card-header-bg: transparent;
31
29
  --u-card-action-bg: transparent;
@@ -92,7 +92,7 @@
92
92
  backdrop-filter: var(--u-bg-filter);
93
93
  flex-grow: 1;
94
94
  }
95
- .u-dialog__body .u-scroll__content {
95
+ .u-dialog__body > .u-scroll__container > .u-scroll__content {
96
96
  padding: 8px;
97
97
  }
98
98
  .u-dialog__footer {
@@ -1,6 +1,6 @@
1
1
  import NodeRender from "../node-render/node-render.js";
2
2
  import { useNest } from "../tip/use-nest.js";
3
- import { Fragment, Teleport, cloneVNode, computed, createBlock, createCommentVNode, createElementBlock, createVNode, defineComponent, normalizeClass, normalizeStyle, openBlock, renderSlot, resolveDynamicComponent, shallowRef, unref, useAttrs, useSlots, useTemplateRef, withCtx, withDirectives } from "vue";
3
+ import { Fragment, Teleport, cloneVNode, computed, createBlock, createCommentVNode, createElementBlock, createVNode, defineComponent, normalizeClass, normalizeStyle, openBlock, renderSlot, resolveDynamicComponent, shallowRef, toRef, unref, useAttrs, useSlots, useTemplateRef, withCtx, withDirectives } from "vue";
4
4
  import { useModel as useModel$1, usePop, useTransition } from "@veltra/compositions";
5
5
  import { bem, extractNormalVNodes, setStyles, zIndex } from "@veltra/utils";
6
6
  import { vClickOutside } from "@veltra/directives";
@@ -11,6 +11,8 @@ const _sfc_main = /*@__PURE__*/ defineComponent({
11
11
  __name: "dropdown",
12
12
  props: {
13
13
  trigger: { default: "hover" },
14
+ direction: { default: "bottom" },
15
+ alignment: { default: "start" },
14
16
  width: {},
15
17
  minWidth: {},
16
18
  contentTag: { default: "div" },
@@ -86,8 +88,8 @@ const _sfc_main = /*@__PURE__*/ defineComponent({
86
88
  const { update, popperContainerId } = usePop({
87
89
  triggerRef: triggerDom,
88
90
  contentRef,
89
- direction: "bottom",
90
- alignment: "start",
91
+ direction: toRef(() => props.direction),
92
+ alignment: toRef(() => props.alignment),
91
93
  onPop(position) {
92
94
  transitionName.value = position.placement.includes("top") ? "slide-up" : "slide-down";
93
95
  transition.enter();
@@ -1 +1 @@
1
- {"version":3,"file":"dropdown.js","names":[],"sources":["../../../src/components/dropdown/dropdown.vue"],"sourcesContent":["<template>\n <UNodeRender :content=\"renderTriggerNode()\" ref=\"trigger\" />\n\n <Teleport :to=\"`#${popperContainerId}`\">\n <component\n v-if=\"dropdownVisible\"\n ref=\"contentRef\"\n :is=\"contentTag\"\n :class=\"dropdownContentClass\"\n :style=\"[{ zIndex: zIndex() }, contentStyle]\"\n @mouseenter=\"eventsHandlers.onMouseenter\"\n @mouseleave=\"eventsHandlers.onMouseleave\"\n @keydown=\"emit('keydown', $event)\"\n v-click-outside=\"trigger === 'click' ? handleClickOutside : undefined\"\n >\n <slot name=\"content\" />\n </component>\n </Teleport>\n</template>\n\n<script lang=\"ts\" setup>\nimport { useModel, usePop, useTransition } from '@veltra/compositions'\nimport { vClickOutside } from '@veltra/directives'\nimport { bem, extractNormalVNodes, setStyles, zIndex } from '@veltra/utils'\nimport { shallowRef, computed, createVNode, cloneVNode, useTemplateRef, useAttrs } from 'vue'\n\nimport type { DropdownProps, DropdownExposed, DropdownEmits } from '../../types'\nimport { UNodeRender } from '../node-render'\nimport { useNest } from '../tip/use-nest'\n\ndefineOptions({ name: 'UDropdown', inheritAttrs: false })\n\nconst props = withDefaults(defineProps<DropdownProps>(), { trigger: 'hover', contentTag: 'div' })\n\nconst emit = defineEmits<DropdownEmits>()\n\nconst slots = defineSlots<{\n /** 内容 */\n content?: () => any\n /** 触发器 */\n trigger?: () => any\n}>()\n\nconst cls = bem('dropdown')\n\nconst dropdownContentClass = computed(() => {\n let fixed = [cls.e('content')]\n const className = props.contentClass\n if (!className) return fixed\n if (!Array.isArray(className)) {\n return [...fixed, className]\n }\n return [...fixed, ...className]\n})\n\nconst triggerRef = useTemplateRef('trigger')\nconst customTriggerRef = shallowRef<HTMLElement>()\nconst contentRef = shallowRef<HTMLElement>()\n\nconst triggerDom = computed(() => {\n return customTriggerRef.value || triggerRef.value?.$el\n})\n\n/**显示隐藏 */\nconst visible = useModel({ defaultValue: false, propName: 'visible', props, emit })\n\nconst dropdownVisible = useNest(visible)\n\nlet closeTimer: number | undefined\n\nconst attrs = useAttrs()\nfunction renderTriggerNode() {\n const slotsNode = slots.trigger?.()\n if (!slotsNode) return null\n const nodes = extractNormalVNodes(slotsNode)\n const props = { class: cls.b, ...attrs, ...eventsHandlers.value }\n if (nodes.length === 1) return cloneVNode(nodes[0]!, props)\n\n return createVNode('div', props, nodes)\n}\n\nfunction stopClose() {\n closeTimer !== undefined && clearTimeout(closeTimer)\n}\n\n/** 打开下拉框 */\nfunction open(config?: { trigger?: HTMLElement }) {\n stopClose()\n const { trigger } = config || {}\n if (trigger && trigger instanceof HTMLElement) {\n customTriggerRef.value = trigger\n }\n\n visible.value = true\n}\n\nfunction close() {\n if (props.trigger === 'hover') {\n // 给200毫秒重新浮动的缓冲时间\n closeTimer = setTimeout(() => {\n transition.leave()\n }, 200)\n } else {\n transition.leave()\n }\n}\n\n/** 点击外部 */\nfunction handleClickOutside(e: MouseEvent) {\n const { trigger } = props\n // 当下拉框为点击时触发时,点击触发元素时不关闭\n // 其他任何时候点击外部都关闭下拉器\n if (trigger === 'click' && triggerDom.value.contains(e.target as Node)) {\n return\n }\n close()\n}\n\nconst transitionName = shallowRef('slide-down')\n\nconst { update, popperContainerId } = usePop({\n triggerRef: triggerDom,\n contentRef,\n direction: 'bottom',\n alignment: 'start',\n onPop(position) {\n transitionName.value = position.placement.includes('top') ? 'slide-up' : 'slide-down'\n\n transition.enter()\n },\n\n onTriggerPositionChange() {\n close()\n },\n\n onBeforeUpdate(triggerEl, contentEl) {\n setStyles(contentEl, {\n width: props.width ?? `${triggerEl.offsetWidth}px`,\n minWidth: props.minWidth\n })\n }\n})\n\nconst transition = useTransition('css', {\n name: transitionName,\n target: contentRef,\n afterLeave() {\n visible.value = false\n },\n\n leaveCanceled() {\n visible.value = false\n }\n})\n\nfunction triggerClick() {\n if (visible.value) {\n close()\n } else {\n open()\n }\n}\n\nconst eventsHandlers = computed(() => {\n const { trigger, disabled } = props\n\n const handlers: Record<string, Function> = {}\n if (disabled || trigger === 'custom') return handlers\n\n if (trigger === 'click') {\n handlers.onClick = triggerClick\n } else if (trigger === 'hover') {\n handlers.onMouseenter = open\n handlers.onMouseleave = close\n }\n\n return handlers\n})\n\ndefineExpose<DropdownExposed>({\n open,\n close,\n /**暴露出更新dropdown内容位置方法 适用与级联选择器组件 */\n updateDropdown: update\n})\n</script>\n"],"mappings":"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"}
1
+ {"version":3,"file":"dropdown.js","names":[],"sources":["../../../src/components/dropdown/dropdown.vue"],"sourcesContent":["<template>\n <UNodeRender :content=\"renderTriggerNode()\" ref=\"trigger\" />\n\n <Teleport :to=\"`#${popperContainerId}`\">\n <component\n v-if=\"dropdownVisible\"\n ref=\"contentRef\"\n :is=\"contentTag\"\n :class=\"dropdownContentClass\"\n :style=\"[{ zIndex: zIndex() }, contentStyle]\"\n @mouseenter=\"eventsHandlers.onMouseenter\"\n @mouseleave=\"eventsHandlers.onMouseleave\"\n @keydown=\"emit('keydown', $event)\"\n v-click-outside=\"trigger === 'click' ? handleClickOutside : undefined\"\n >\n <slot name=\"content\" />\n </component>\n </Teleport>\n</template>\n\n<script lang=\"ts\" setup>\nimport { useModel, usePop, useTransition } from '@veltra/compositions'\nimport { vClickOutside } from '@veltra/directives'\nimport { bem, extractNormalVNodes, setStyles, zIndex } from '@veltra/utils'\nimport { shallowRef, computed, createVNode, cloneVNode, useTemplateRef, useAttrs, toRef } from 'vue'\n\nimport type { DropdownProps, DropdownExposed, DropdownEmits } from '../../types'\nimport { UNodeRender } from '../node-render'\nimport { useNest } from '../tip/use-nest'\n\ndefineOptions({ name: 'UDropdown', inheritAttrs: false })\n\nconst props = withDefaults(defineProps<DropdownProps>(), {\n trigger: 'hover',\n direction: 'bottom',\n alignment: 'start',\n contentTag: 'div'\n})\n\nconst emit = defineEmits<DropdownEmits>()\n\nconst slots = defineSlots<{\n /** 内容 */\n content?: () => any\n /** 触发器 */\n trigger?: () => any\n}>()\n\nconst cls = bem('dropdown')\n\nconst dropdownContentClass = computed(() => {\n let fixed = [cls.e('content')]\n const className = props.contentClass\n if (!className) return fixed\n if (!Array.isArray(className)) {\n return [...fixed, className]\n }\n return [...fixed, ...className]\n})\n\nconst triggerRef = useTemplateRef('trigger')\nconst customTriggerRef = shallowRef<HTMLElement>()\nconst contentRef = shallowRef<HTMLElement>()\n\nconst triggerDom = computed(() => {\n return customTriggerRef.value || triggerRef.value?.$el\n})\n\n/**显示隐藏 */\nconst visible = useModel({ defaultValue: false, propName: 'visible', props, emit })\n\nconst dropdownVisible = useNest(visible)\n\nlet closeTimer: number | undefined\n\nconst attrs = useAttrs()\nfunction renderTriggerNode() {\n const slotsNode = slots.trigger?.()\n if (!slotsNode) return null\n const nodes = extractNormalVNodes(slotsNode)\n const props = { class: cls.b, ...attrs, ...eventsHandlers.value }\n if (nodes.length === 1) return cloneVNode(nodes[0]!, props)\n\n return createVNode('div', props, nodes)\n}\n\nfunction stopClose() {\n closeTimer !== undefined && clearTimeout(closeTimer)\n}\n\n/** 打开下拉框 */\nfunction open(config?: { trigger?: HTMLElement }) {\n stopClose()\n const { trigger } = config || {}\n if (trigger && trigger instanceof HTMLElement) {\n customTriggerRef.value = trigger\n }\n\n visible.value = true\n}\n\nfunction close() {\n if (props.trigger === 'hover') {\n // 给200毫秒重新浮动的缓冲时间\n closeTimer = setTimeout(() => {\n transition.leave()\n }, 200)\n } else {\n transition.leave()\n }\n}\n\n/** 点击外部 */\nfunction handleClickOutside(e: MouseEvent) {\n const { trigger } = props\n // 当下拉框为点击时触发时,点击触发元素时不关闭\n // 其他任何时候点击外部都关闭下拉器\n if (trigger === 'click' && triggerDom.value.contains(e.target as Node)) {\n return\n }\n close()\n}\n\nconst transitionName = shallowRef('slide-down')\n\nconst { update, popperContainerId } = usePop({\n triggerRef: triggerDom,\n contentRef,\n direction: toRef(() => props.direction),\n alignment: toRef(() => props.alignment),\n onPop(position) {\n transitionName.value = position.placement.includes('top') ? 'slide-up' : 'slide-down'\n\n transition.enter()\n },\n\n onTriggerPositionChange() {\n close()\n },\n\n onBeforeUpdate(triggerEl, contentEl) {\n setStyles(contentEl, {\n width: props.width ?? `${triggerEl.offsetWidth}px`,\n minWidth: props.minWidth\n })\n }\n})\n\nconst transition = useTransition('css', {\n name: transitionName,\n target: contentRef,\n afterLeave() {\n visible.value = false\n },\n\n leaveCanceled() {\n visible.value = false\n }\n})\n\nfunction triggerClick() {\n if (visible.value) {\n close()\n } else {\n open()\n }\n}\n\nconst eventsHandlers = computed(() => {\n const { trigger, disabled } = props\n\n const handlers: Record<string, Function> = {}\n if (disabled || trigger === 'custom') return handlers\n\n if (trigger === 'click') {\n handlers.onClick = triggerClick\n } else if (trigger === 'hover') {\n handlers.onMouseenter = open\n handlers.onMouseleave = close\n }\n\n return handlers\n})\n\ndefineExpose<DropdownExposed>({\n open,\n close,\n /**暴露出更新dropdown内容位置方法 适用与级联选择器组件 */\n updateDropdown: update\n})\n</script>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;EAgCA,MAAM,QAAQ;EAOd,MAAM,OAAO;EAEb,MAAM,QAAQ,SAAA;EAOd,MAAM,MAAM,IAAI,UAAU;EAE1B,MAAM,uBAAuB,eAAe;GAC1C,IAAI,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;GAC7B,MAAM,YAAY,MAAM;GACxB,IAAI,CAAC,WAAW,OAAO;GACvB,IAAI,CAAC,MAAM,QAAQ,SAAS,GAC1B,OAAO,CAAC,GAAG,OAAO,SAAS;GAE7B,OAAO,CAAC,GAAG,OAAO,GAAG,SAAS;EAChC,CAAC;EAED,MAAM,aAAa,eAAe,SAAS;EAC3C,MAAM,mBAAmB,WAAwB;EACjD,MAAM,aAAa,WAAwB;EAE3C,MAAM,aAAa,eAAe;GAChC,OAAO,iBAAiB,SAAS,WAAW,OAAO;EACrD,CAAC;;EAGD,MAAM,UAAU,WAAS;GAAE,cAAc;GAAO,UAAU;GAAW;GAAO;EAAK,CAAC;EAElF,MAAM,kBAAkB,QAAQ,OAAO;EAEvC,IAAI;EAEJ,MAAM,QAAQ,SAAS;EACvB,SAAS,oBAAoB;GAC3B,MAAM,YAAY,MAAM,UAAU;GAClC,IAAI,CAAC,WAAW,OAAO;GACvB,MAAM,QAAQ,oBAAoB,SAAS;GAC3C,MAAM,QAAQ;IAAE,OAAO,IAAI;IAAG,GAAG;IAAO,GAAG,eAAe;GAAM;GAChE,IAAI,MAAM,WAAW,GAAG,OAAO,WAAW,MAAM,IAAK,KAAK;GAE1D,OAAO,YAAY,OAAO,OAAO,KAAK;EACxC;EAEA,SAAS,YAAY;GACnB,eAAe,KAAA,KAAa,aAAa,UAAU;EACrD;;EAGA,SAAS,KAAK,QAAoC;GAChD,UAAU;GACV,MAAM,EAAE,YAAY,UAAU,CAAC;GAC/B,IAAI,WAAW,mBAAmB,aAChC,iBAAiB,QAAQ;GAG3B,QAAQ,QAAQ;EAClB;EAEA,SAAS,QAAQ;GACf,IAAI,MAAM,YAAY,SAEpB,aAAa,iBAAiB;IAC5B,WAAW,MAAM;GACnB,GAAG,GAAG;QAEN,WAAW,MAAM;EAErB;;EAGA,SAAS,mBAAmB,GAAe;GACzC,MAAM,EAAE,YAAY;GAGpB,IAAI,YAAY,WAAW,WAAW,MAAM,SAAS,EAAE,MAAc,GACnE;GAEF,MAAM;EACR;EAEA,MAAM,iBAAiB,WAAW,YAAY;EAE9C,MAAM,EAAE,QAAQ,sBAAsB,OAAO;GAC3C,YAAY;GACZ;GACA,WAAW,YAAY,MAAM,SAAS;GACtC,WAAW,YAAY,MAAM,SAAS;GACtC,MAAM,UAAU;IACd,eAAe,QAAQ,SAAS,UAAU,SAAS,KAAK,IAAI,aAAa;IAEzE,WAAW,MAAM;GACnB;GAEA,0BAA0B;IACxB,MAAM;GACR;GAEA,eAAe,WAAW,WAAW;IACnC,UAAU,WAAW;KACnB,OAAO,MAAM,SAAS,GAAG,UAAU,YAAY;KAC/C,UAAU,MAAM;IAClB,CAAC;GACH;EACF,CAAC;EAED,MAAM,aAAa,cAAc,OAAO;GACtC,MAAM;GACN,QAAQ;GACR,aAAa;IACX,QAAQ,QAAQ;GAClB;GAEA,gBAAgB;IACd,QAAQ,QAAQ;GAClB;EACF,CAAC;EAED,SAAS,eAAe;GACtB,IAAI,QAAQ,OACV,MAAM;QAEN,KAAK;EAET;EAEA,MAAM,iBAAiB,eAAe;GACpC,MAAM,EAAE,SAAS,aAAa;GAE9B,MAAM,WAAqC,CAAC;GAC5C,IAAI,YAAY,YAAY,UAAU,OAAO;GAE7C,IAAI,YAAY,SACd,SAAS,UAAU;QACd,IAAI,YAAY,SAAS;IAC9B,SAAS,eAAe;IACxB,SAAS,eAAe;GAC1B;GAEA,OAAO;EACT,CAAC;EAED,SAA8B;GAC5B;GACA;;GAEA,gBAAgB;EAClB,CAAC;;GA5LC,OAAA,UAAA,GAAA,mBAAA,UAAA,MAAA,CAAA,YAA4D,MAAA,UAAA,GAAA;IAA9C,SAAS,kBAAiB;IAAI,KAAI;GAEhD,GAAA,MAAA,GAAA,CAAA,SAAA,CAAA,IAAA,UAAA,GAAA,YAcW,UAAA,EAdA,IAAE,IAAM,MAAA,iBAAA,IAAA,GAAA,CAET,MAAA,eAAA,IADR,gBAAA,UAAA,GAAA,YAYY,wBATL,QAAA,UAAU,GAAA;;IADX,SAAA;IAAJ,KAAI;IAEH,OAAK,eAAE,qBAAA,KAAoB;IAC3B,OAAK,eAAA,CAAA,EAAA,QAAa,MAAA,MAAA,CAAM,CAAA,EAAA,GAAM,QAAA,YAAY,CAAA;IAC1C,cAAY,eAAA,MAAe;IAC3B,cAAY,eAAA,MAAe;IAC3B,WAAO,OAAA,OAAA,OAAA,MAAA,WAAE,KAAI,WAAY,MAAM;;IAGhC,SAAA,cAAuB,CAAvB,WAAuB,KAAA,QAAA,SAAA,CAAA,CAAA;;;;;;;GAFN,CAAA,IAAA,CAAA,CAAA,MAAA,aAAA,GAAA,QAAA,YAAO,UAAe,qBAAqB,KAAA,CAAS,CAAA,CAAA,IAAA,mBAAA,QAAA,IAAA,CAAA,GAAA,GAAA,CAAA,IAAA,CAAA,EAAA,GAAA,EAAA"}
@@ -1,4 +1,4 @@
1
- import { Fragment, createCommentVNode, createElementBlock, createElementVNode, defineComponent, normalizeClass, normalizeStyle, openBlock, renderList, toDisplayString, unref } from "vue";
1
+ import { Fragment, createElementBlock, createElementVNode, defineComponent, normalizeClass, normalizeStyle, openBlock, renderList, toDisplayString, unref } from "vue";
2
2
  import { bem } from "@veltra/utils";
3
3
  //#region src/components/expression-editor/components/path-preview.vue
4
4
  const _sfc_main = /*@__PURE__*/ defineComponent({
@@ -12,11 +12,8 @@ const _sfc_main = /*@__PURE__*/ defineComponent({
12
12
  return openBlock(), createElementBlock("li", {
13
13
  key: `${i}-${node.value || node.label}`,
14
14
  class: normalizeClass([unref(cls).e("path-tree-item"), unref(bem).is("active", i === __props.path.length - 1)]),
15
- style: normalizeStyle({ paddingLeft: `${i * 14}px` })
16
- }, [i > 0 ? (openBlock(), createElementBlock("span", {
17
- key: 0,
18
- class: normalizeClass(unref(cls).e("path-tree-branch"))
19
- }, "└", 2)) : createCommentVNode("v-if", true), createElementVNode("span", { class: normalizeClass(unref(cls).e("path-tree-label")) }, toDisplayString(node.label), 3)], 6);
15
+ style: normalizeStyle({ "--depth": i })
16
+ }, [createElementVNode("span", { class: normalizeClass(unref(cls).e("path-tree-label")) }, toDisplayString(node.label), 3)], 6);
20
17
  }), 128))], 2)], 2);
21
18
  };
22
19
  }
@@ -1 +1 @@
1
- {"version":3,"file":"path-preview.js","names":[],"sources":["../../../../src/components/expression-editor/components/path-preview.vue"],"sourcesContent":["<template>\n <div :class=\"cls.e('path-preview')\">\n <div :class=\"cls.e('path-preview-title')\">变量路径</div>\n <ul :class=\"cls.e('path-tree')\">\n <li\n v-for=\"(node, i) in path\"\n :key=\"`${i}-${node.value || node.label}`\"\n :class=\"[cls.e('path-tree-item'), bem.is('active', i === path.length - 1)]\"\n :style=\"{ paddingLeft: `${i * 14}px` }\"\n >\n <span v-if=\"i > 0\" :class=\"cls.e('path-tree-branch')\">└</span>\n <span :class=\"cls.e('path-tree-label')\">{{ node.label }}</span>\n </li>\n </ul>\n </div>\n</template>\n\n<script lang=\"ts\" setup>\nimport { bem } from '@veltra/utils'\n\nimport type { VariableItem } from '../../../types'\n\ndefineOptions({ name: 'UExpressionPathPreview' })\n\ndefineProps<{ path: VariableItem[] }>()\n\nconst cls = bem('expression-editor')\n</script>\n"],"mappings":";;;;;;;;EA0BA,MAAM,MAAM,IAAI,mBAAmB;;GAzBjC,OAAA,UAAA,GAAA,mBAaM,OAAA,EAbA,OAAK,eAAE,MAAA,GAAA,CAAG,CAAC,EAAC,cAAA,CAAA,EAAA,GAChB,CAAA,mBAAoD,OAAA,EAA9C,OAAK,eAAE,MAAA,GAAA,CAAG,CAAC,EAAC,oBAAA,CAAA,EAAwB,GAAA,QAAI,CAAA,GAC9C,mBAUK,MAAA,EAVA,OAAK,eAAE,MAAA,GAAA,CAAG,CAAC,EAAC,WAAA,CAAA,EAAA,GACf,EAAA,UAAA,IAAA,GAAA,mBAQK,UAAA,MAAA,WAPiB,QAAA,OAAZ,MAAM,MAAC;IADjB,OAAA,UAAA,GAAA,mBAQK,MAAA;KANF,KAAG,GAAK,EAAC,GAAI,KAAK,SAAS,KAAK;KAChC,OAAK,eAAA,CAAG,MAAA,GAAA,CAAG,CAAC,EAAC,gBAAA,GAAoB,MAAA,GAAA,CAAG,CAAC,GAAE,UAAW,MAAM,QAAA,KAAK,SAAM,CAAA,CAAA,CAAA;KACnE,OAAK,eAAA,EAAA,aAAA,GAAoB,IAAC,GAAA,IAAA,CAAA;IAEf,GAAA,CAAA,IAAC,KAAb,UAAA,GAAA,mBAA8D,QAAA;;KAA1C,OAAK,eAAE,MAAA,GAAA,CAAG,CAAC,EAAC,kBAAA,CAAA;IAAsB,GAAA,KAAC,CAAA,KAAA,mBAAA,QAAA,IAAA,GACvD,mBAA+D,QAAA,EAAxD,OAAK,eAAE,MAAA,GAAA,CAAG,CAAC,EAAC,iBAAA,CAAA,EAAwB,GAAA,gBAAA,KAAK,KAAK,GAAA,CAAA,CAAA,GAAA,CAAA"}
1
+ {"version":3,"file":"path-preview.js","names":[],"sources":["../../../../src/components/expression-editor/components/path-preview.vue"],"sourcesContent":["<template>\n <div :class=\"cls.e('path-preview')\">\n <div :class=\"cls.e('path-preview-title')\">变量路径</div>\n <ul :class=\"cls.e('path-tree')\">\n <li\n v-for=\"(node, i) in path\"\n :key=\"`${i}-${node.value || node.label}`\"\n :class=\"[cls.e('path-tree-item'), bem.is('active', i === path.length - 1)]\"\n :style=\"{ '--depth': i }\"\n >\n <span :class=\"cls.e('path-tree-label')\">{{ node.label }}</span>\n </li>\n </ul>\n </div>\n</template>\n\n<script lang=\"ts\" setup>\nimport { bem } from '@veltra/utils'\n\nimport type { VariableItem } from '../../../types'\n\ndefineOptions({ name: 'UExpressionPathPreview' })\n\ndefineProps<{ path: VariableItem[] }>()\n\nconst cls = bem('expression-editor')\n</script>\n"],"mappings":";;;;;;;;EAyBA,MAAM,MAAM,IAAI,mBAAmB;;GAxBjC,OAAA,UAAA,GAAA,mBAYM,OAAA,EAZA,OAAK,eAAE,MAAA,GAAA,CAAG,CAAC,EAAC,cAAA,CAAA,EAAA,GAChB,CAAA,mBAAoD,OAAA,EAA9C,OAAK,eAAE,MAAA,GAAA,CAAG,CAAC,EAAC,oBAAA,CAAA,EAAwB,GAAA,QAAI,CAAA,GAC9C,mBASK,MAAA,EATA,OAAK,eAAE,MAAA,GAAA,CAAG,CAAC,EAAC,WAAA,CAAA,EAAA,GACf,EAAA,UAAA,IAAA,GAAA,mBAOK,UAAA,MAAA,WANiB,QAAA,OAAZ,MAAM,MAAC;IADjB,OAAA,UAAA,GAAA,mBAOK,MAAA;KALF,KAAG,GAAK,EAAC,GAAI,KAAK,SAAS,KAAK;KAChC,OAAK,eAAA,CAAG,MAAA,GAAA,CAAG,CAAC,EAAC,gBAAA,GAAoB,MAAA,GAAA,CAAG,CAAC,GAAE,UAAW,MAAM,QAAA,KAAK,SAAM,CAAA,CAAA,CAAA;KACnE,OAAK,eAAA,EAAA,WAAe,EAAC,CAAA;IAEtB,GAAA,CAAA,mBAA+D,QAAA,EAAxD,OAAK,eAAE,MAAA,GAAA,CAAG,CAAC,EAAC,iBAAA,CAAA,EAAwB,GAAA,gBAAA,KAAK,KAAK,GAAA,CAAA,CAAA,GAAA,CAAA"}