@veltra/desktop 1.0.12 → 1.0.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/action/action-group.js +110 -3
- package/dist/components/action/action-group.js.map +1 -1
- package/dist/components/action/action-group.vue.d.ts +16 -3
- package/dist/components/action/action.js +26 -13
- package/dist/components/action/action.js.map +1 -1
- package/dist/components/action/action.vue.d.ts +1 -1
- package/dist/components/action/style.js +2 -1
- package/dist/components/action/style2.css +35 -7
- package/dist/components/auto-complete/auto-complete.vue.d.ts +2 -2
- package/dist/components/batch-edit/batch-edit-form.js +106 -42
- package/dist/components/batch-edit/batch-edit-form.js.map +1 -1
- package/dist/components/batch-edit/batch-edit-list.js +84 -47
- package/dist/components/batch-edit/batch-edit-list.js.map +1 -1
- package/dist/components/batch-edit/batch-edit.js +42 -10
- package/dist/components/batch-edit/batch-edit.js.map +1 -1
- package/dist/components/batch-edit/style.js +2 -4
- package/dist/components/batch-edit/style2.css +202 -30
- package/dist/components/batch-edit/use-edit.js +45 -9
- package/dist/components/batch-edit/use-edit.js.map +1 -1
- package/dist/components/cascade/cascade.js +3 -1
- package/dist/components/cascade/cascade.js.map +1 -1
- package/dist/components/cascade/cascade.vue.d.ts +3 -3
- package/dist/components/checkbox/checkbox-button.vue.d.ts +1 -1
- package/dist/components/checkbox-group/checkbox-group.vue.d.ts +2 -2
- package/dist/components/code-editor/code-editor.js +145 -49
- package/dist/components/code-editor/code-editor.js.map +1 -1
- package/dist/components/code-editor/code-editor.vue.d.ts +2 -0
- package/dist/components/code-editor/style2.css +87 -19
- package/dist/components/collapse/collapse.js.map +1 -1
- package/dist/components/collapse/collapse.vue.d.ts +2 -10
- package/dist/components/date-picker/date-picker.vue.d.ts +2 -2
- package/dist/components/date-range-picker/date-range-picker.vue.d.ts +2 -2
- package/dist/components/dialog/dialog.js +6 -2
- package/dist/components/dialog/dialog.js.map +1 -1
- package/dist/components/dialog/style2.css +2 -3
- package/dist/components/drawer/drawer.vue.d.ts +2 -2
- package/dist/components/expression-editor/components/path-preview.js +27 -0
- package/dist/components/expression-editor/components/path-preview.js.map +1 -0
- package/dist/components/expression-editor/components/variable-picker.js +199 -153
- package/dist/components/expression-editor/components/variable-picker.js.map +1 -1
- package/dist/components/expression-editor/core/chip.js +54 -0
- package/dist/components/expression-editor/core/chip.js.map +1 -0
- package/dist/components/expression-editor/core/editor.js +424 -0
- package/dist/components/expression-editor/core/editor.js.map +1 -0
- package/dist/components/expression-editor/core/mention.js +91 -0
- package/dist/components/expression-editor/core/mention.js.map +1 -0
- package/dist/components/expression-editor/core/model.js +64 -0
- package/dist/components/expression-editor/core/model.js.map +1 -0
- package/dist/components/expression-editor/di.js +4 -10
- package/dist/components/expression-editor/di.js.map +1 -1
- package/dist/components/expression-editor/expression-editor.js +168 -114
- package/dist/components/expression-editor/expression-editor.js.map +1 -1
- package/dist/components/expression-editor/expression-editor.vue.d.ts +2 -1
- package/dist/components/expression-editor/style.js +0 -2
- package/dist/components/expression-editor/style2.css +145 -219
- package/dist/components/index.js +54 -54
- package/dist/components/input/input.vue.d.ts +2 -2
- package/dist/components/layout/layout.js +12 -11
- package/dist/components/layout/layout.js.map +1 -1
- package/dist/components/multi-select/multi-select.vue.d.ts +3 -3
- package/dist/components/multi-tree-select/multi-tree-select.vue.d.ts +3 -3
- package/dist/components/number/number.vue.d.ts +1 -1
- package/dist/components/number-input/number-input.js +4 -4
- package/dist/components/number-input/number-input.js.map +1 -1
- package/dist/components/number-input/number-input.vue.d.ts +2 -2
- package/dist/components/number-range-input/number-range-input.vue.d.ts +1 -1
- package/dist/components/password-input/password-input.vue.d.ts +1 -1
- package/dist/components/progress-nodes/progress-nodes.vue.d.ts +2 -2
- package/dist/components/radio-group/radio-group.vue.d.ts +2 -2
- package/dist/components/rich-text-editor/rich-text-editor.js +1 -1
- package/dist/components/rich-text-editor/rich-text-editor.vue.d.ts +1 -1
- package/dist/components/rich-text-editor/toolbar.js +2 -2
- package/dist/components/select/select.vue.d.ts +2 -2
- package/dist/components/table/use-table.js +16 -0
- package/dist/components/table/use-table.js.map +1 -1
- package/dist/components/tabs/tabs-horizontal.vue.d.ts +2 -2
- package/dist/components/tabs/tabs-vertical.vue.d.ts +2 -2
- package/dist/components/tabs/tabs.vue.d.ts +2 -2
- package/dist/components/textarea/textarea.vue.d.ts +2 -2
- package/dist/components/tree/style2.css +18 -12
- package/dist/components/tree/tree-node.js +7 -4
- package/dist/components/tree/tree-node.js.map +1 -1
- package/dist/components/tree-select/tree-select.vue.d.ts +3 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.js +83 -83
- package/dist/style.js +3 -3
- package/dist/types/action.d.ts +38 -4
- package/dist/types/cascade.d.ts +2 -3
- package/dist/types/code-editor.d.ts +9 -2
- package/dist/types/collapse.d.ts +6 -5
- package/dist/types/expression-editor.d.ts +9 -1
- package/dist/types/index.d.ts +2 -2
- package/package.json +11 -12
- package/src/components/action/action-group.vue +126 -56
- package/src/components/action/action.vue +35 -12
- package/src/components/action/style.scss +46 -10
- package/src/components/action/style.ts +2 -1
- package/src/components/batch-edit/batch-edit-form.vue +121 -45
- package/src/components/batch-edit/batch-edit-list.vue +56 -39
- package/src/components/batch-edit/batch-edit.vue +57 -6
- package/src/components/batch-edit/style.scss +251 -37
- package/src/components/batch-edit/style.ts +5 -8
- package/src/components/batch-edit/use-edit.ts +58 -11
- package/src/components/cascade/cascade.vue +3 -1
- package/src/components/code-editor/code-editor.vue +198 -63
- package/src/components/code-editor/style.scss +110 -12
- package/src/components/collapse/collapse.vue +5 -24
- package/src/components/dialog/dialog.vue +6 -2
- package/src/components/dialog/style.scss +4 -4
- package/src/components/expression-editor/__test__/chip.test.ts +86 -0
- package/src/components/expression-editor/__test__/mention.test.ts +122 -0
- package/src/components/expression-editor/__test__/model.test.ts +127 -0
- package/src/components/expression-editor/components/path-preview.vue +32 -0
- package/src/components/expression-editor/components/variable-picker.vue +224 -219
- package/src/components/expression-editor/core/chip.ts +101 -0
- package/src/components/expression-editor/core/editor.ts +513 -0
- package/src/components/expression-editor/core/mention.ts +121 -0
- package/src/components/expression-editor/core/model.ts +109 -0
- package/src/components/expression-editor/di.ts +4 -32
- package/src/components/expression-editor/expression-editor.vue +184 -151
- package/src/components/expression-editor/style.scss +148 -220
- package/src/components/expression-editor/style.ts +0 -2
- package/src/components/layout/layout.vue +17 -19
- package/src/components/number-input/number-input.vue +4 -4
- package/src/components/table/use-table.ts +16 -0
- package/src/components/tree/style.scss +30 -33
- package/src/components/tree/tree-node.vue +4 -2
- package/src/types/action.ts +42 -4
- package/src/types/cascade.ts +4 -3
- package/src/types/code-editor.ts +9 -2
- package/src/types/collapse.ts +6 -6
- package/src/types/expression-editor.ts +9 -0
- package/dist/components/action/action-group.vue_vue_type_script_setup_true_lang.js +0 -65
- package/dist/components/action/action-group.vue_vue_type_script_setup_true_lang.js.map +0 -1
- package/dist/components/expression-editor/constants.js +0 -9
- package/dist/components/expression-editor/constants.js.map +0 -1
- package/dist/components/expression-editor/internal/editor-runtime/create-runtime.js +0 -47
- package/dist/components/expression-editor/internal/editor-runtime/create-runtime.js.map +0 -1
- package/dist/components/expression-editor/internal/editor-runtime/model-sync.js +0 -49
- package/dist/components/expression-editor/internal/editor-runtime/model-sync.js.map +0 -1
- package/dist/components/expression-editor/internal/features/commands/register-command-packs.js +0 -215
- package/dist/components/expression-editor/internal/features/commands/register-command-packs.js.map +0 -1
- package/dist/components/expression-editor/internal/features/drag-drop/drag-drop-service.js +0 -33
- package/dist/components/expression-editor/internal/features/drag-drop/drag-drop-service.js.map +0 -1
- package/dist/components/expression-editor/internal/features/insertion/insertion-service.js +0 -33
- package/dist/components/expression-editor/internal/features/insertion/insertion-service.js.map +0 -1
- package/dist/components/expression-editor/nodes/variable-node.js +0 -94
- package/dist/components/expression-editor/nodes/variable-node.js.map +0 -1
- package/dist/components/expression-editor/parser.js +0 -32
- package/dist/components/expression-editor/parser.js.map +0 -1
- package/dist/components/expression-editor/plain-text.js +0 -19
- package/dist/components/expression-editor/plain-text.js.map +0 -1
- package/dist/components/expression-editor/use-context.js +0 -69
- package/dist/components/expression-editor/use-context.js.map +0 -1
- package/dist/components/expression-editor/use-decorators.js +0 -27
- package/dist/components/expression-editor/use-decorators.js.map +0 -1
- package/dist/components/expression-editor/use-expression-drag-drop.js +0 -275
- package/dist/components/expression-editor/use-expression-drag-drop.js.map +0 -1
- package/src/components/batch-edit/batch-edit-new.vue +0 -168
- package/src/components/batch-edit/style-new.scss +0 -35
- package/src/components/batch-edit/use-edit-new.ts +0 -68
- package/src/components/batch-edit/use-tip.ts +0 -47
- package/src/components/expression-editor/__test__/architecture-boundaries.test.ts +0 -103
- package/src/components/expression-editor/__test__/architecture-compatibility.test.ts +0 -52
- package/src/components/expression-editor/__test__/drag-drop.test.ts +0 -171
- package/src/components/expression-editor/__test__/parser.test.ts +0 -62
- package/src/components/expression-editor/constants.ts +0 -6
- package/src/components/expression-editor/internal/contracts/editor-runtime.ts +0 -11
- package/src/components/expression-editor/internal/editor-runtime/create-runtime.ts +0 -64
- package/src/components/expression-editor/internal/editor-runtime/index.ts +0 -1
- package/src/components/expression-editor/internal/editor-runtime/model-sync.ts +0 -68
- package/src/components/expression-editor/internal/features/commands/register-command-packs.ts +0 -517
- package/src/components/expression-editor/internal/features/drag-drop/drag-drop-service.ts +0 -51
- package/src/components/expression-editor/internal/features/insertion/insertion-service.ts +0 -56
- package/src/components/expression-editor/nodes/variable-node.tsx +0 -118
- package/src/components/expression-editor/parser.ts +0 -46
- package/src/components/expression-editor/plain-text.ts +0 -25
- package/src/components/expression-editor/plan.md +0 -22
- package/src/components/expression-editor/use-context.ts +0 -134
- package/src/components/expression-editor/use-decorators.tsx +0 -29
- package/src/components/expression-editor/use-editor.ts +0 -12
- package/src/components/expression-editor/use-expression-drag-drop.ts +0 -396
|
@@ -32,23 +32,43 @@ function useEdit(options) {
|
|
|
32
32
|
watch(() => state.visible, (v) => {
|
|
33
33
|
if (!v) state.dataUpdated = false;
|
|
34
34
|
});
|
|
35
|
-
/**
|
|
36
|
-
|
|
35
|
+
/**
|
|
36
|
+
* 「打开行 / 切换 type」时记录的基线快照
|
|
37
|
+
* @description
|
|
38
|
+
* 用于 changeCb 内部比对 — 若新值与基线相等(深比较)视为无改动,避免某些组件在 mount
|
|
39
|
+
* 阶段把规范化后的值再写回模型时被误判为「用户已修改」
|
|
40
|
+
*/
|
|
41
|
+
let baselineSnapshot;
|
|
42
|
+
function snapshotModelData() {
|
|
43
|
+
return safeRun(() => JSON.parse(JSON.stringify(props.model?.data ?? {})), {});
|
|
44
|
+
}
|
|
37
45
|
watch(() => state.row, (row) => {
|
|
38
46
|
props.model?.resetData();
|
|
39
47
|
if (row) {
|
|
40
48
|
state.type = "update";
|
|
41
49
|
state.visible = true;
|
|
42
|
-
changedByUserInput = false;
|
|
43
50
|
props.model?.setData(row.data);
|
|
44
|
-
nextTick(() => {
|
|
45
|
-
changedByUserInput = true;
|
|
46
|
-
});
|
|
47
51
|
} else state.visible = false;
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
52
|
+
baselineSnapshot = snapshotModelData();
|
|
53
|
+
state.dataUpdated = false;
|
|
54
|
+
}, { flush: "sync" });
|
|
55
|
+
const changeCb = (field, val) => {
|
|
56
|
+
if (baselineSnapshot) {
|
|
57
|
+
if (isSameValue(o(baselineSnapshot).get(field), val)) return;
|
|
58
|
+
}
|
|
59
|
+
state.dataUpdated = true;
|
|
51
60
|
};
|
|
61
|
+
function isSameValue(a, b) {
|
|
62
|
+
if (a === b) return true;
|
|
63
|
+
if (a == null && b == null) return true;
|
|
64
|
+
if (typeof a !== typeof b) return false;
|
|
65
|
+
if (typeof a === "object") try {
|
|
66
|
+
return JSON.stringify(a) === JSON.stringify(b);
|
|
67
|
+
} catch {
|
|
68
|
+
return false;
|
|
69
|
+
}
|
|
70
|
+
return false;
|
|
71
|
+
}
|
|
52
72
|
watch(() => props.model, (model, oldModel) => {
|
|
53
73
|
if (oldModel) oldModel.offChange(changeCb);
|
|
54
74
|
if (model) model.onChange(changeCb);
|
|
@@ -114,6 +134,20 @@ function useEdit(options) {
|
|
|
114
134
|
insertIndexes.value = [...row.indexes, row.children?.length ?? 0];
|
|
115
135
|
});
|
|
116
136
|
}
|
|
137
|
+
/** 编辑指定行(等同于点击行) */
|
|
138
|
+
function handleEdit(row) {
|
|
139
|
+
state.row = row;
|
|
140
|
+
state.depth = row.depth;
|
|
141
|
+
}
|
|
142
|
+
/** 复制指定行:在其下方以 create 模式打开表单,并预填副本数据 */
|
|
143
|
+
function handleCopy(row) {
|
|
144
|
+
runCreate(() => {
|
|
145
|
+
state.depth = row.depth;
|
|
146
|
+
insertIndexes.value = [...row.indexes.slice(0, -1), row.index + 1];
|
|
147
|
+
const cloned = safeRun(() => JSON.parse(JSON.stringify(row.data ?? {})), {});
|
|
148
|
+
props.model?.setData(cloned);
|
|
149
|
+
});
|
|
150
|
+
}
|
|
117
151
|
function runWithLoading(fn) {
|
|
118
152
|
return async (...args) => {
|
|
119
153
|
state.loading = true;
|
|
@@ -183,6 +217,8 @@ function useEdit(options) {
|
|
|
183
217
|
handleInsertToNext,
|
|
184
218
|
handleInsertToPrev,
|
|
185
219
|
handleCreate,
|
|
220
|
+
handleEdit,
|
|
221
|
+
handleCopy,
|
|
186
222
|
handleClose,
|
|
187
223
|
handleSave
|
|
188
224
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-edit.js","names":[],"sources":["../../../src/components/batch-edit/use-edit.ts"],"sourcesContent":["import { last, o, safeRun } from '@cat-kit/core'\nimport { computed, nextTick, shallowReactive, shallowRef, watch, type ShallowRef } from 'vue'\n\nimport type { TableRow, BatchEditEmits, BatchEditProps, TableExposed } 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 tableRef: ShallowRef<TableExposed | undefined>\n}\n\nexport interface BatchEditStates {\n /** 层级 */\n depth?: number\n visible: boolean\n type: 'create' | 'update'\n loading: boolean\n row?: TableRow\n /** 父级,只在添加子级时会有值 */\n parentRow?: TableRow\n /** 数据是否已更新 */\n dataUpdated: boolean\n}\n\nexport interface EditReturned {\n state: BatchEditStates\n insertIndexes: ShallowRef<number[]>\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 useEdit(options: Options): EditReturned {\n const { props, emit, tableRef } = options\n\n /** 组件状态 */\n const state = shallowReactive<BatchEditStates>({\n depth: undefined,\n visible: false,\n type: 'create',\n loading: false,\n dataUpdated: false\n })\n\n const insertIndexes = shallowRef<number[]>([])\n\n watch(\n () => state.visible,\n (v) => {\n if (!v) {\n state.dataUpdated = false\n }\n }\n )\n\n /** 是否是用户输入产生的值变更 */\n let changedByUserInput = true\n\n watch(\n () => state.row,\n (row) => {\n props.model?.resetData()\n if (row) {\n state.type = 'update'\n state.visible = true\n changedByUserInput = false\n props.model?.setData(row.data)\n nextTick(() => {\n changedByUserInput = true\n })\n } else {\n state.visible = false\n }\n }\n )\n\n const changeCb = (_field: string, _val: any) => {\n // 检测到为用户变更时,为数据添加一个已更改状态从而显示修改按钮\n if (changedByUserInput) {\n state.dataUpdated = true\n }\n }\n\n watch(\n () => props.model,\n (model, oldModel) => {\n if (oldModel) {\n oldModel.offChange(changeCb)\n }\n if (model) {\n model.onChange(changeCb)\n }\n },\n { immediate: true }\n )\n\n const childrenKey = computed(() => {\n return typeof props.tree === 'string' ? props.tree : 'children'\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(\n data ?? [],\n insertIndexes.value.slice(0, -1),\n childrenKey.value\n )\n\n if (parent) {\n const children = parent[childrenKey.value]\n if (!children) {\n parent[childrenKey.value] = [item]\n } else {\n children.splice(last(insertIndexes.value), 0, item)\n }\n } else {\n data.splice(last(insertIndexes.value), 0, item)\n }\n\n emit('update:data', data)\n\n return item\n }\n\n function getInsertData(): Record<string, any> {\n return safeRun(() => JSON.parse(JSON.stringify(props.model?.data ?? {})), {})\n }\n\n async function runCreate(cb: () => void) {\n state.parentRow = undefined\n if (state.row) {\n state.row.isCurrent = false\n }\n state.row = undefined\n state.type = 'create'\n props.model?.resetData()\n cb()\n\n let item: Record<string, any> | undefined = undefined\n\n await nextTick()\n\n state.visible = true\n\n if (item) {\n const row = tableRef.value?.getRowByData(item)\n if (row) {\n state.row = row\n }\n }\n }\n\n /**\n * 点击新增按钮\n */\n function handleCreate() {\n const { data } = props\n runCreate(() => {\n state.depth = 1\n insertIndexes.value = [data?.length ?? 0]\n })\n }\n\n function handleInsertToPrev(row: TableRow) {\n runCreate(() => {\n state.depth = row.depth\n insertIndexes.value = [...row.indexes]\n })\n }\n\n function handleInsertToNext(row: TableRow) {\n runCreate(() => {\n state.depth = row.depth\n insertIndexes.value = [...row.indexes.slice(0, -1), row.index + 1]\n })\n }\n\n function handleInsertChild(row: TableRow) {\n runCreate(() => {\n state.parentRow = row\n state.depth = row.depth + 1\n row.expanded = true\n\n insertIndexes.value = [...row.indexes, row.children?.length ?? 0]\n })\n }\n\n function runWithLoading<Arg extends any[]>(fn: (...args: Arg) => Promise<void> | void) {\n return async (...args: Arg) => {\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\n if (!model) return\n\n model.clearValidate()\n const valid = await model.validate()\n\n if (!valid) return\n\n let item = getInsertData()\n if (saveMethod) {\n const result = await saveMethod(item, state.type, state.parentRow)\n if (result) {\n item = result\n }\n }\n\n state.dataUpdated = false\n\n // 新增\n if (state.type === 'create') {\n insert(item)\n\n return model?.resetData()\n }\n // 更新\n if (state.type === 'update') {\n const { row } = state\n row &&\n model.allKeys.forEach((key) => {\n o(row.data).set(key, o(item).get(key))\n })\n }\n })\n\n const handleDelete = runWithLoading(async (row: TableRow) => {\n const { deleteMethod } = props\n\n if (deleteMethod) {\n await deleteMethod([row.data])\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 state.row = undefined\n state.depth = undefined\n }\n\n emit('update:data', data)\n })\n\n function handleClose() {\n state.visible = false\n if (state.row) {\n state.row.isCurrent = false\n }\n state.row = undefined\n state.parentRow = undefined\n state.depth = undefined\n props.model?.resetData()\n insertIndexes.value = []\n }\n\n return {\n state,\n insertIndexes,\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-edit.js","names":[],"sources":["../../../src/components/batch-edit/use-edit.ts"],"sourcesContent":["import { last, o, safeRun } from '@cat-kit/core'\nimport { computed, nextTick, shallowReactive, shallowRef, watch, type ShallowRef } from 'vue'\n\nimport type { TableRow, BatchEditEmits, BatchEditProps, TableExposed } 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 tableRef: ShallowRef<TableExposed | undefined>\n}\n\nexport interface BatchEditStates {\n /** 层级 */\n depth?: number\n visible: boolean\n type: 'create' | 'update'\n loading: boolean\n row?: TableRow\n /** 父级,只在添加子级时会有值 */\n parentRow?: TableRow\n /** 数据是否已更新 */\n dataUpdated: boolean\n}\n\nexport interface EditReturned {\n state: BatchEditStates\n insertIndexes: ShallowRef<number[]>\n handleSave: () => Promise<void>\n handleClose: () => void\n handleCreate: () => void\n handleEdit: (row: TableRow) => void\n handleCopy: (row: TableRow) => 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 useEdit(options: Options): EditReturned {\n const { props, emit, tableRef } = options\n\n /** 组件状态 */\n const state = shallowReactive<BatchEditStates>({\n depth: undefined,\n visible: false,\n type: 'create',\n loading: false,\n dataUpdated: false\n })\n\n const insertIndexes = shallowRef<number[]>([])\n\n watch(\n () => state.visible,\n (v) => {\n if (!v) {\n state.dataUpdated = false\n }\n }\n )\n\n /**\n * 「打开行 / 切换 type」时记录的基线快照\n * @description\n * 用于 changeCb 内部比对 — 若新值与基线相等(深比较)视为无改动,避免某些组件在 mount\n * 阶段把规范化后的值再写回模型时被误判为「用户已修改」\n */\n let baselineSnapshot: Record<string, any> | undefined\n\n function snapshotModelData() {\n return safeRun(() => JSON.parse(JSON.stringify(props.model?.data ?? {})), {})\n }\n\n watch(\n () => state.row,\n (row) => {\n props.model?.resetData()\n if (row) {\n state.type = 'update'\n state.visible = true\n props.model?.setData(row.data)\n } else {\n state.visible = false\n }\n baselineSnapshot = snapshotModelData()\n state.dataUpdated = false\n },\n // sync 保证 setData 完成后立刻取快照,避免 mount 期间组件回写值时丢基线\n { flush: 'sync' }\n )\n\n const changeCb = (field: string, val: any) => {\n // 与基线比较 — 同值(如组件 mount 时把当前值再写一次)不算\"用户修改\"\n if (baselineSnapshot) {\n const baseVal = o(baselineSnapshot).get(field)\n if (isSameValue(baseVal, val)) {\n return\n }\n }\n state.dataUpdated = true\n }\n\n function isSameValue(a: any, b: any) {\n if (a === b) return true\n if (a == null && b == null) return true\n if (typeof a !== typeof b) return false\n if (typeof a === 'object') {\n try {\n return JSON.stringify(a) === JSON.stringify(b)\n } catch {\n return false\n }\n }\n return false\n }\n\n watch(\n () => props.model,\n (model, oldModel) => {\n if (oldModel) {\n oldModel.offChange(changeCb)\n }\n if (model) {\n model.onChange(changeCb)\n }\n },\n { immediate: true }\n )\n\n const childrenKey = computed(() => {\n return typeof props.tree === 'string' ? props.tree : 'children'\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(\n data ?? [],\n insertIndexes.value.slice(0, -1),\n childrenKey.value\n )\n\n if (parent) {\n const children = parent[childrenKey.value]\n if (!children) {\n parent[childrenKey.value] = [item]\n } else {\n children.splice(last(insertIndexes.value), 0, item)\n }\n } else {\n data.splice(last(insertIndexes.value), 0, item)\n }\n\n emit('update:data', data)\n\n return item\n }\n\n function getInsertData(): Record<string, any> {\n return safeRun(() => JSON.parse(JSON.stringify(props.model?.data ?? {})), {})\n }\n\n async function runCreate(cb: () => void) {\n state.parentRow = undefined\n if (state.row) {\n state.row.isCurrent = false\n }\n state.row = undefined\n state.type = 'create'\n props.model?.resetData()\n cb()\n\n let item: Record<string, any> | undefined = undefined\n\n await nextTick()\n\n state.visible = true\n\n if (item) {\n const row = tableRef.value?.getRowByData(item)\n if (row) {\n state.row = row\n }\n }\n }\n\n /**\n * 点击新增按钮\n */\n function handleCreate() {\n const { data } = props\n runCreate(() => {\n state.depth = 1\n insertIndexes.value = [data?.length ?? 0]\n })\n }\n\n function handleInsertToPrev(row: TableRow) {\n runCreate(() => {\n state.depth = row.depth\n insertIndexes.value = [...row.indexes]\n })\n }\n\n function handleInsertToNext(row: TableRow) {\n runCreate(() => {\n state.depth = row.depth\n insertIndexes.value = [...row.indexes.slice(0, -1), row.index + 1]\n })\n }\n\n function handleInsertChild(row: TableRow) {\n runCreate(() => {\n state.parentRow = row\n state.depth = row.depth + 1\n row.expanded = true\n\n insertIndexes.value = [...row.indexes, row.children?.length ?? 0]\n })\n }\n\n /** 编辑指定行(等同于点击行) */\n function handleEdit(row: TableRow) {\n state.row = row\n state.depth = row.depth\n }\n\n /** 复制指定行:在其下方以 create 模式打开表单,并预填副本数据 */\n function handleCopy(row: TableRow) {\n runCreate(() => {\n state.depth = row.depth\n insertIndexes.value = [...row.indexes.slice(0, -1), row.index + 1]\n const cloned = safeRun(() => JSON.parse(JSON.stringify(row.data ?? {})), {})\n props.model?.setData(cloned)\n })\n }\n\n function runWithLoading<Arg extends any[]>(fn: (...args: Arg) => Promise<void> | void) {\n return async (...args: Arg) => {\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\n if (!model) return\n\n model.clearValidate()\n const valid = await model.validate()\n\n if (!valid) return\n\n let item = getInsertData()\n if (saveMethod) {\n const result = await saveMethod(item, state.type, state.parentRow)\n if (result) {\n item = result\n }\n }\n\n state.dataUpdated = false\n\n // 新增\n if (state.type === 'create') {\n insert(item)\n\n return model?.resetData()\n }\n // 更新\n if (state.type === 'update') {\n const { row } = state\n row &&\n model.allKeys.forEach((key) => {\n o(row.data).set(key, o(item).get(key))\n })\n }\n })\n\n const handleDelete = runWithLoading(async (row: TableRow) => {\n const { deleteMethod } = props\n\n if (deleteMethod) {\n await deleteMethod([row.data])\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 state.row = undefined\n state.depth = undefined\n }\n\n emit('update:data', data)\n })\n\n function handleClose() {\n state.visible = false\n if (state.row) {\n state.row.isCurrent = false\n }\n state.row = undefined\n state.parentRow = undefined\n state.depth = undefined\n props.model?.resetData()\n insertIndexes.value = []\n }\n\n return {\n state,\n insertIndexes,\n handleDelete,\n handleInsertChild,\n handleInsertToNext,\n handleInsertToPrev,\n handleCreate,\n handleEdit,\n handleCopy,\n handleClose,\n handleSave\n }\n}\n"],"mappings":"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"}
|
|
@@ -141,7 +141,9 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
141
141
|
watch([qs, forest], ([qs, forest]) => {
|
|
142
142
|
const { filterable } = props;
|
|
143
143
|
if (!filterable || !qs) {
|
|
144
|
-
forest.dfs((node) =>
|
|
144
|
+
forest.dfs((node) => {
|
|
145
|
+
node.visible = true;
|
|
146
|
+
});
|
|
145
147
|
getPanelItemList(forest.roots);
|
|
146
148
|
return;
|
|
147
149
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cascade.js","names":[],"sources":["../../../src/components/cascade/cascade.vue"],"sourcesContent":["<template>\n <u-dropdown\n v-if=\"!readonly\"\n :class=\"[cls.b, bem.is('disabled', disabled), bem.is('multiple', multiple), cls.m(size)]\"\n :content-class=\"[cls.e('panel'), cls.em('panel', size)]\"\n trigger=\"click\"\n ref=\"dropdownRef\"\n :disabled=\"disabled\"\n width=\"auto\"\n @mouseenter=\"hovered = true\"\n @mouseleave=\"hovered = false\"\n @update:visible=\"!$event && (qs = '')\"\n >\n <template #trigger>\n <!-- 单选展示 -->\n <u-input\n v-if=\"!multiple\"\n :size=\"size\"\n :disabled=\"disabled\"\n :placeholder=\"placeholder\"\n :clearable=\"clearable\"\n native-readonly\n :model-value=\"displayedValue\"\n @clear=\"handleClear\"\n >\n <template #suffix>\n <u-icon :class=\"cls.e('arrow')\"><ArrowDown /></u-icon>\n </template>\n </u-input>\n\n <!-- 多选展示 -->\n <template v-if=\"multiple\">\n <span :class=\"cls.e('placeholder')\" v-show=\"!modelValue?.length\">\n {{ placeholder }}\n </span>\n\n <div v-if=\"modelValue?.length\" :class=\"cls.e('tags')\">\n <u-tag\n v-for=\"tag of tags\"\n :key=\"tag.value\"\n :closable=\"!disabled\"\n @close=\"handleCloseTag(tag)\"\n >\n {{ tag.label }}\n </u-tag>\n <u-tag v-if=\"restTag\"> {{ restTag }}+ </u-tag>\n </div>\n\n <transition name=\"zoom-in\" mode=\"out-in\">\n <u-icon\n v-if=\"clearable && modelValue?.length && hovered && !disabled\"\n :class=\"cls.e('clear')\"\n @click.stop=\"handleClear\"\n >\n <Close />\n </u-icon>\n\n <u-icon :class=\"cls.e('arrow')\" v-else><ArrowDown /></u-icon>\n </transition>\n </template>\n </template>\n\n <template #content>\n <!-- 过滤 -->\n <div v-if=\"filterable\" :class=\"cls.e('panel-filter')\">\n <u-input placeholder=\"输入关键字进行过滤\" v-model=\"qs\" :size=\"size\" clearable>\n <template #suffix>\n <u-icon><Search /></u-icon>\n </template>\n </u-input>\n </div>\n\n <div :class=\"cls.e('content')\" v-if=\"panelItemList.length\">\n <UCascadePanelItem\n v-for=\"({ nodes, key }, index) of panelItemList\"\n :data=\"nodes\"\n :key=\"key\"\n :panel-index=\"index\"\n :value=\"selectedNodeKeys[index]\"\n @click=\"handleClick\"\n @check=\"handleCheck\"\n />\n </div>\n\n <div :class=\"cls.e('empty')\" v-else>\n <UEmpty />\n </div>\n </template>\n </u-dropdown>\n\n <!-- 只读 -->\n <template v-else>\n <div :class=\"[cls.m(size)]\" v-if=\"multiple\">\n <div :class=\"cls.e('tags')\">\n <u-tag v-for=\"tag of tags\" :key=\"tag.value\">\n {{ tag.label }}\n </u-tag>\n </div>\n </div>\n <template v-else>\n {{ displayedValue || FORM_EMPTY_CONTENT }}\n </template>\n </template>\n</template>\n\n<script lang=\"ts\" setup>\nimport { Forest, o } from '@cat-kit/core'\nimport { useFormComponent, useFormFallbackProps, useUserAction } from '@veltra/compositions'\nimport { ArrowDown, Close, Search } from '@veltra/icons/normal'\nimport { bem, FORM_EMPTY_CONTENT } from '@veltra/utils'\nimport { computed, provide, shallowRef, triggerRef, watch } from 'vue'\n\nimport type { CascadeProps, CascadeEmits, DropdownExposed } from '../../types'\nimport { UDropdown } from '../dropdown'\nimport { UEmpty } from '../empty'\nimport { UIcon } from '../icon'\nimport { UInput } from '../input'\nimport { UTag } from '../tag'\nimport UCascadePanelItem from './cascade-panel-item.vue'\nimport { CascadeDIKey } from './di'\nimport { CascadeNode } from './node'\nimport { useCheck } from './use-check'\nimport { useDataMap } from './use-data-map'\nimport { useSelect } from './use-select'\n\ndefineOptions({\n name: 'Cascade'\n})\n\nconst props = withDefaults(defineProps<CascadeProps>(), {\n labelKey: 'label',\n valueKey: 'value',\n placeholder: '请选择',\n separator: '/',\n clearable: true,\n disabled: undefined,\n readonly: undefined,\n childrenKey: 'children',\n filterable: false,\n data: () => [],\n visibilityLimit: 3\n})\n\nconst emit = defineEmits<CascadeEmits>()\n\nconst cls = bem('cascade')\n\nconst { formProps } = useFormComponent()\n\nconst { size, disabled, readonly } = useFormFallbackProps([formProps ?? {}, props], {\n size: 'default',\n disabled: false,\n readonly: false\n})\n\nconst dropdownRef = shallowRef<DropdownExposed>()\n\nconst forest = computed(() => {\n return new Forest<Record<string, unknown>, any>({\n data: (props.data ?? []) as Record<string, unknown>[],\n childrenKey: props.childrenKey,\n createNode: (data, index, depth, _forest, parent) => {\n if (!data) {\n return new CascadeNode({\n data,\n index,\n depth,\n value: '',\n label: '',\n parent\n })\n }\n\n return new CascadeNode({\n data,\n index,\n depth,\n value: o(data).get(props.valueKey) ?? '',\n label: o(data).get(props.labelKey) ?? '',\n parent\n })\n }\n })\n})\n\nconst { dataMap } = useDataMap({ props, forest })\n\nconst { userAction, isUserActive } = useUserAction()\n\nconst {\n displayedValue,\n selectItem,\n updateSingleValue,\n panelItemList,\n getPanelItemList,\n createPanelItem,\n selectedNodeKeys\n} = useSelect({\n props,\n emit,\n dataMap,\n forest,\n isUserActive,\n dropdownRef\n})\n\nconst { hovered, tags, restTag, updateMultipleValue, handleCloseTag, checkItem, checkedSet } =\n useCheck({\n props,\n forest,\n getPanelItemList,\n emit,\n dataMap,\n isUserActive,\n disabled,\n readonly\n })\n\nconst commitSingleSelect = userAction((item: CascadeNode) => {\n if (!props.strict) {\n updateSingleValue()\n } else if (!item.children?.length) {\n updateSingleValue()\n }\n})\n\nfunction handleClick(panelIndex: number, item: CascadeNode) {\n selectItem(panelIndex, item)\n\n if (!props.multiple) {\n commitSingleSelect(item)\n }\n}\n\nconst handleCheck = userAction((item: CascadeNode, checked: boolean) => {\n checkItem(item, checked)\n})\n\nfunction handleClear() {\n if (props.multiple) {\n checkedSet.value.clear()\n triggerRef(checkedSet)\n updateMultipleValue()\n } else {\n selectedNodeKeys.value = []\n updateSingleValue()\n }\n\n emit('clear')\n}\n\n// 过滤\nconst qs = shallowRef<string>('')\n\nwatch([qs, forest], ([qs, forest]) => {\n const { filterable } = props\n if (!filterable || !qs) {\n forest.dfs((node) => (node.visible = true))\n getPanelItemList(forest.roots)\n return\n }\n\n const cache = new Set<CascadeNode>()\n\n forest.dfs((node) => {\n if (node.label?.toLowerCase().includes(qs.toLowerCase())) {\n node.visible = true\n let parent = node.parent\n while (parent && !cache.has(parent)) {\n parent.visible = true\n cache.add(parent)\n parent = parent.parent\n }\n } else {\n node.visible = false\n }\n })\n\n panelItemList.value = [createPanelItem(forest.roots)]\n})\n\nprovide(CascadeDIKey, {\n cls,\n size,\n disabled,\n readonly,\n cascadeProps: props,\n checkedSet\n})\n</script>\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"cascade.js","names":[],"sources":["../../../src/components/cascade/cascade.vue"],"sourcesContent":["<template>\n <u-dropdown\n v-if=\"!readonly\"\n :class=\"[cls.b, bem.is('disabled', disabled), bem.is('multiple', multiple), cls.m(size)]\"\n :content-class=\"[cls.e('panel'), cls.em('panel', size)]\"\n trigger=\"click\"\n ref=\"dropdownRef\"\n :disabled=\"disabled\"\n width=\"auto\"\n @mouseenter=\"hovered = true\"\n @mouseleave=\"hovered = false\"\n @update:visible=\"!$event && (qs = '')\"\n >\n <template #trigger>\n <!-- 单选展示 -->\n <u-input\n v-if=\"!multiple\"\n :size=\"size\"\n :disabled=\"disabled\"\n :placeholder=\"placeholder\"\n :clearable=\"clearable\"\n native-readonly\n :model-value=\"displayedValue\"\n @clear=\"handleClear\"\n >\n <template #suffix>\n <u-icon :class=\"cls.e('arrow')\"><ArrowDown /></u-icon>\n </template>\n </u-input>\n\n <!-- 多选展示 -->\n <template v-if=\"multiple\">\n <span :class=\"cls.e('placeholder')\" v-show=\"!modelValue?.length\">\n {{ placeholder }}\n </span>\n\n <div v-if=\"modelValue?.length\" :class=\"cls.e('tags')\">\n <u-tag\n v-for=\"tag of tags\"\n :key=\"tag.value\"\n :closable=\"!disabled\"\n @close=\"handleCloseTag(tag)\"\n >\n {{ tag.label }}\n </u-tag>\n <u-tag v-if=\"restTag\"> {{ restTag }}+ </u-tag>\n </div>\n\n <transition name=\"zoom-in\" mode=\"out-in\">\n <u-icon\n v-if=\"clearable && modelValue?.length && hovered && !disabled\"\n :class=\"cls.e('clear')\"\n @click.stop=\"handleClear\"\n >\n <Close />\n </u-icon>\n\n <u-icon :class=\"cls.e('arrow')\" v-else><ArrowDown /></u-icon>\n </transition>\n </template>\n </template>\n\n <template #content>\n <!-- 过滤 -->\n <div v-if=\"filterable\" :class=\"cls.e('panel-filter')\">\n <u-input placeholder=\"输入关键字进行过滤\" v-model=\"qs\" :size=\"size\" clearable>\n <template #suffix>\n <u-icon><Search /></u-icon>\n </template>\n </u-input>\n </div>\n\n <div :class=\"cls.e('content')\" v-if=\"panelItemList.length\">\n <UCascadePanelItem\n v-for=\"({ nodes, key }, index) of panelItemList\"\n :data=\"nodes\"\n :key=\"key\"\n :panel-index=\"index\"\n :value=\"selectedNodeKeys[index]\"\n @click=\"handleClick\"\n @check=\"handleCheck\"\n />\n </div>\n\n <div :class=\"cls.e('empty')\" v-else>\n <UEmpty />\n </div>\n </template>\n </u-dropdown>\n\n <!-- 只读 -->\n <template v-else>\n <div :class=\"[cls.m(size)]\" v-if=\"multiple\">\n <div :class=\"cls.e('tags')\">\n <u-tag v-for=\"tag of tags\" :key=\"tag.value\">\n {{ tag.label }}\n </u-tag>\n </div>\n </div>\n <template v-else>\n {{ displayedValue || FORM_EMPTY_CONTENT }}\n </template>\n </template>\n</template>\n\n<script lang=\"ts\" setup>\nimport { Forest, o } from '@cat-kit/core'\nimport { useFormComponent, useFormFallbackProps, useUserAction } from '@veltra/compositions'\nimport { ArrowDown, Close, Search } from '@veltra/icons/normal'\nimport { bem, FORM_EMPTY_CONTENT } from '@veltra/utils'\nimport { computed, provide, shallowRef, triggerRef, watch } from 'vue'\n\nimport type { CascadeProps, CascadeEmits, DropdownExposed } from '../../types'\nimport { UDropdown } from '../dropdown'\nimport { UEmpty } from '../empty'\nimport { UIcon } from '../icon'\nimport { UInput } from '../input'\nimport { UTag } from '../tag'\nimport UCascadePanelItem from './cascade-panel-item.vue'\nimport { CascadeDIKey } from './di'\nimport { CascadeNode } from './node'\nimport { useCheck } from './use-check'\nimport { useDataMap } from './use-data-map'\nimport { useSelect } from './use-select'\n\ndefineOptions({\n name: 'Cascade'\n})\n\nconst props = withDefaults(defineProps<CascadeProps>(), {\n labelKey: 'label',\n valueKey: 'value',\n placeholder: '请选择',\n separator: '/',\n clearable: true,\n disabled: undefined,\n readonly: undefined,\n childrenKey: 'children',\n filterable: false,\n data: () => [],\n visibilityLimit: 3\n})\n\nconst emit = defineEmits<CascadeEmits>()\n\nconst cls = bem('cascade')\n\nconst { formProps } = useFormComponent()\n\nconst { size, disabled, readonly } = useFormFallbackProps([formProps ?? {}, props], {\n size: 'default',\n disabled: false,\n readonly: false\n})\n\nconst dropdownRef = shallowRef<DropdownExposed>()\n\nconst forest = computed(() => {\n return new Forest<Record<string, unknown>, any>({\n data: (props.data ?? []) as Record<string, unknown>[],\n childrenKey: props.childrenKey,\n createNode: (data, index, depth, _forest, parent) => {\n if (!data) {\n return new CascadeNode({\n data,\n index,\n depth,\n value: '',\n label: '',\n parent\n })\n }\n\n return new CascadeNode({\n data,\n index,\n depth,\n value: o(data).get(props.valueKey) ?? '',\n label: o(data).get(props.labelKey) ?? '',\n parent\n })\n }\n })\n})\n\nconst { dataMap } = useDataMap({ props, forest })\n\nconst { userAction, isUserActive } = useUserAction()\n\nconst {\n displayedValue,\n selectItem,\n updateSingleValue,\n panelItemList,\n getPanelItemList,\n createPanelItem,\n selectedNodeKeys\n} = useSelect({\n props,\n emit,\n dataMap,\n forest,\n isUserActive,\n dropdownRef\n})\n\nconst { hovered, tags, restTag, updateMultipleValue, handleCloseTag, checkItem, checkedSet } =\n useCheck({\n props,\n forest,\n getPanelItemList,\n emit,\n dataMap,\n isUserActive,\n disabled,\n readonly\n })\n\nconst commitSingleSelect = userAction((item: CascadeNode) => {\n if (!props.strict) {\n updateSingleValue()\n } else if (!item.children?.length) {\n updateSingleValue()\n }\n})\n\nfunction handleClick(panelIndex: number, item: CascadeNode) {\n selectItem(panelIndex, item)\n\n if (!props.multiple) {\n commitSingleSelect(item)\n }\n}\n\nconst handleCheck = userAction((item: CascadeNode, checked: boolean) => {\n checkItem(item, checked)\n})\n\nfunction handleClear() {\n if (props.multiple) {\n checkedSet.value.clear()\n triggerRef(checkedSet)\n updateMultipleValue()\n } else {\n selectedNodeKeys.value = []\n updateSingleValue()\n }\n\n emit('clear')\n}\n\n// 过滤\nconst qs = shallowRef<string>('')\n\nwatch([qs, forest], ([qs, forest]) => {\n const { filterable } = props\n if (!filterable || !qs) {\n forest.dfs((node) => {\n node.visible = true\n })\n getPanelItemList(forest.roots)\n return\n }\n\n const cache = new Set<CascadeNode>()\n\n forest.dfs((node) => {\n if (node.label?.toLowerCase().includes(qs.toLowerCase())) {\n node.visible = true\n let parent = node.parent\n while (parent && !cache.has(parent)) {\n parent.visible = true\n cache.add(parent)\n parent = parent.parent\n }\n } else {\n node.visible = false\n }\n })\n\n panelItemList.value = [createPanelItem(forest.roots)]\n})\n\nprovide(CascadeDIKey, {\n cls,\n size,\n disabled,\n readonly,\n cascadeProps: props,\n checkedSet\n})\n</script>\n"],"mappings":"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"}
|
|
@@ -11,8 +11,6 @@ declare const __VLS_export: _$vue.DefineComponent<CascadeProps, {}, {}, {}, {},
|
|
|
11
11
|
onClear?: (() => any) | undefined;
|
|
12
12
|
onChange?: ((...args: [value?: string | undefined, label?: string | undefined, item?: Record<string, any> | undefined] | [value: string[], label: string[], data: Record<string, any>[]]) => any) | undefined;
|
|
13
13
|
}>, {
|
|
14
|
-
disabled: boolean;
|
|
15
|
-
readonly: boolean;
|
|
16
14
|
labelKey: string;
|
|
17
15
|
valueKey: string;
|
|
18
16
|
childrenKey: string;
|
|
@@ -20,8 +18,10 @@ declare const __VLS_export: _$vue.DefineComponent<CascadeProps, {}, {}, {}, {},
|
|
|
20
18
|
placeholder: string;
|
|
21
19
|
clearable: boolean;
|
|
22
20
|
filterable: boolean;
|
|
23
|
-
|
|
21
|
+
disabled: boolean;
|
|
22
|
+
readonly: boolean;
|
|
24
23
|
visibilityLimit: number;
|
|
24
|
+
separator: string;
|
|
25
25
|
}, {}, {}, {}, string, _$vue.ComponentProvideOptions, false, {}, any>;
|
|
26
26
|
declare const _default: typeof __VLS_export;
|
|
27
27
|
//#endregion
|
|
@@ -20,8 +20,8 @@ declare const __VLS_base: _$vue.DefineComponent<__VLS_PublicProps, {}, {}, {}, {
|
|
|
20
20
|
"onUpdate:modelValue"?: ((checked: boolean) => any) | undefined;
|
|
21
21
|
onChange?: ((checked: boolean) => any) | undefined;
|
|
22
22
|
}>, {
|
|
23
|
-
disabled: boolean;
|
|
24
23
|
type: _$_veltra_utils0.ColorType;
|
|
24
|
+
disabled: boolean;
|
|
25
25
|
readonly: boolean;
|
|
26
26
|
round: boolean;
|
|
27
27
|
}, {}, {}, {}, string, _$vue.ComponentProvideOptions, false, {}, any>;
|
|
@@ -14,10 +14,10 @@ declare const __VLS_export: _$vue.DefineComponent<__VLS_PublicProps, {}, {}, {},
|
|
|
14
14
|
}, string, _$vue.PublicProps, Readonly<__VLS_PublicProps> & Readonly<{
|
|
15
15
|
"onUpdate:modelValue"?: ((value: any[]) => any) | undefined;
|
|
16
16
|
}>, {
|
|
17
|
-
disabled: boolean;
|
|
18
|
-
readonly: boolean;
|
|
19
17
|
labelKey: string;
|
|
20
18
|
valueKey: string;
|
|
19
|
+
disabled: boolean;
|
|
20
|
+
readonly: boolean;
|
|
21
21
|
}, {}, {}, {}, string, _$vue.ComponentProvideOptions, false, {}, any>;
|
|
22
22
|
declare const _default: typeof __VLS_export;
|
|
23
23
|
//#endregion
|
|
@@ -1,18 +1,24 @@
|
|
|
1
1
|
import _sfc_main$1 from "../scroll/scroll.js";
|
|
2
|
-
import { computed, createBlock, createElementVNode, defineComponent, mergeModels, normalizeClass, onBeforeUnmount, openBlock, shallowRef, unref, useModel, useTemplateRef, watch, withCtx, withKeys, withModifiers } from "vue";
|
|
2
|
+
import { computed, createBlock, createElementVNode, defineComponent, mergeModels, normalizeClass, normalizeStyle, onBeforeUnmount, openBlock, shallowRef, unref, useModel, useTemplateRef, watch, withCtx, withKeys, withModifiers } from "vue";
|
|
3
3
|
import { bem, zIndex } from "@veltra/utils";
|
|
4
4
|
import { useFormComponent, useFormFallbackProps } from "@veltra/compositions";
|
|
5
|
-
import { EditorState } from "@codemirror/state";
|
|
5
|
+
import { Compartment, EditorState } from "@codemirror/state";
|
|
6
6
|
import { oneDark } from "@codemirror/theme-one-dark";
|
|
7
|
-
import { tooltips } from "@codemirror/view";
|
|
7
|
+
import { ViewPlugin, tooltips } from "@codemirror/view";
|
|
8
8
|
import { EditorView, basicSetup } from "codemirror";
|
|
9
9
|
//#region src/components/code-editor/code-editor.vue
|
|
10
10
|
const _hoisted_1 = { ref: "container" };
|
|
11
11
|
const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
12
|
+
name: "CodeEditor",
|
|
12
13
|
__name: "code-editor",
|
|
13
14
|
props: /* @__PURE__ */ mergeModels({
|
|
14
15
|
modelValue: {},
|
|
15
16
|
language: {},
|
|
17
|
+
dark: {
|
|
18
|
+
type: Boolean,
|
|
19
|
+
default: false
|
|
20
|
+
},
|
|
21
|
+
defaultLines: { default: 8 },
|
|
16
22
|
tips: {},
|
|
17
23
|
span: {},
|
|
18
24
|
label: {},
|
|
@@ -24,8 +30,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
24
30
|
readonly: {
|
|
25
31
|
type: Boolean,
|
|
26
32
|
default: void 0
|
|
27
|
-
}
|
|
28
|
-
size: {}
|
|
33
|
+
}
|
|
29
34
|
}, {
|
|
30
35
|
"modelValue": {},
|
|
31
36
|
"modelModifiers": {}
|
|
@@ -36,15 +41,17 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
36
41
|
const model = useModel(__props, "modelValue");
|
|
37
42
|
const cls = bem("code-editor");
|
|
38
43
|
const { formProps } = useFormComponent();
|
|
39
|
-
const {
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
cls.b,
|
|
43
|
-
cls.m(size.value),
|
|
44
|
-
bem.is("disabled", disabled.value),
|
|
45
|
-
bem.is("readonly", readonly.value)
|
|
46
|
-
];
|
|
44
|
+
const { disabled, readonly } = useFormFallbackProps([formProps ?? {}, props], {
|
|
45
|
+
disabled: false,
|
|
46
|
+
readonly: false
|
|
47
47
|
});
|
|
48
|
+
const className = computed(() => [
|
|
49
|
+
cls.b,
|
|
50
|
+
bem.is("disabled", disabled.value),
|
|
51
|
+
bem.is("readonly", readonly.value),
|
|
52
|
+
bem.is("dark", props.dark)
|
|
53
|
+
]);
|
|
54
|
+
const rootStyle = computed(() => ({ "--u-code-editor-default-lines": Math.max(1, props.defaultLines) }));
|
|
48
55
|
const containerRef = useTemplateRef("container");
|
|
49
56
|
const editor = shallowRef(null);
|
|
50
57
|
const langLoaders = {
|
|
@@ -53,67 +60,156 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
53
60
|
java: () => import("@codemirror/lang-java").then((m) => m.java()),
|
|
54
61
|
json: () => import("@codemirror/lang-json").then((m) => m.json())
|
|
55
62
|
};
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
63
|
+
const themeCompartment = new Compartment();
|
|
64
|
+
const editableCompartment = new Compartment();
|
|
65
|
+
const readOnlyCompartment = new Compartment();
|
|
66
|
+
const langCompartment = new Compartment();
|
|
67
|
+
let phantomGutter = null;
|
|
68
|
+
let phantomContainer = null;
|
|
69
|
+
let lastPhantomKey = "";
|
|
70
|
+
function resetPhantomCache() {
|
|
71
|
+
phantomGutter = null;
|
|
72
|
+
phantomContainer = null;
|
|
73
|
+
lastPhantomKey = "";
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* 在 .cm-lineNumbers 末尾追加占位行号 DOM,使可视行号数量补齐到 defaultLines。
|
|
77
|
+
* CodeMirror 的 lineNumbers() 仅为真实文档行渲染行号,超出部分由本逻辑补全。
|
|
78
|
+
*/
|
|
79
|
+
function syncPhantomLineNumbers() {
|
|
80
|
+
const view = editor.value;
|
|
81
|
+
if (!view) return;
|
|
82
|
+
if (!phantomGutter || !phantomGutter.isConnected) phantomGutter = view.dom.querySelector(".cm-gutter.cm-lineNumbers");
|
|
83
|
+
if (!phantomGutter) return;
|
|
84
|
+
if (!phantomContainer) {
|
|
85
|
+
phantomContainer = document.createElement("div");
|
|
86
|
+
phantomContainer.className = "cm-phantom-lines";
|
|
87
|
+
}
|
|
88
|
+
if (phantomContainer.parentElement !== phantomGutter || phantomContainer !== phantomGutter.lastElementChild) phantomGutter.appendChild(phantomContainer);
|
|
89
|
+
const realLines = view.state.doc.lines;
|
|
90
|
+
const target = Math.max(0, Math.max(1, props.defaultLines) - realLines);
|
|
91
|
+
const lineHeight = view.defaultLineHeight;
|
|
92
|
+
const key = `${realLines}|${target}|${lineHeight}`;
|
|
93
|
+
if (key === lastPhantomKey) return;
|
|
94
|
+
lastPhantomKey = key;
|
|
95
|
+
while (phantomContainer.children.length > target) phantomContainer.lastElementChild.remove();
|
|
96
|
+
while (phantomContainer.children.length < target) {
|
|
97
|
+
const el = document.createElement("div");
|
|
98
|
+
el.className = "cm-gutterElement cm-gutterElement-phantom";
|
|
99
|
+
phantomContainer.appendChild(el);
|
|
100
|
+
}
|
|
101
|
+
for (let i = 0; i < target; i++) {
|
|
102
|
+
const el = phantomContainer.children[i];
|
|
103
|
+
const num = String(realLines + i + 1);
|
|
104
|
+
if (el.textContent !== num) el.textContent = num;
|
|
105
|
+
if (lineHeight && el.style.height !== `${lineHeight}px`) el.style.height = `${lineHeight}px`;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
const phantomLineNumbersPlugin = ViewPlugin.fromClass(class {
|
|
109
|
+
update(update) {
|
|
110
|
+
if (update.docChanged || update.geometryChanged) syncPhantomLineNumbers();
|
|
111
|
+
}
|
|
112
|
+
});
|
|
113
|
+
function buildExtensions() {
|
|
114
|
+
return [
|
|
61
115
|
basicSetup,
|
|
62
|
-
oneDark,
|
|
63
116
|
tooltips({ parent: document.body }),
|
|
64
|
-
EditorView.theme({ ".cm-tooltip": { zIndex: zIndex() } })
|
|
117
|
+
EditorView.theme({ ".cm-tooltip": { zIndex: zIndex() } }),
|
|
118
|
+
themeCompartment.of(props.dark ? oneDark : []),
|
|
119
|
+
editableCompartment.of(EditorView.editable.of(!disabled.value)),
|
|
120
|
+
readOnlyCompartment.of(EditorState.readOnly.of(readonly.value)),
|
|
121
|
+
langCompartment.of([]),
|
|
122
|
+
phantomLineNumbersPlugin
|
|
65
123
|
];
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
124
|
+
}
|
|
125
|
+
let editorToken = 0;
|
|
126
|
+
let langToken = 0;
|
|
127
|
+
async function applyLanguage() {
|
|
128
|
+
const view = editor.value;
|
|
129
|
+
if (!view) return;
|
|
130
|
+
const myToken = ++langToken;
|
|
131
|
+
const { language } = props;
|
|
132
|
+
const ext = language ? await langLoaders[language]() : [];
|
|
133
|
+
if (myToken !== langToken || editor.value !== view) return;
|
|
134
|
+
view.dispatch({ effects: langCompartment.reconfigure(ext) });
|
|
135
|
+
}
|
|
136
|
+
function destroyEditor() {
|
|
137
|
+
++editorToken;
|
|
138
|
+
++langToken;
|
|
139
|
+
editor.value?.destroy();
|
|
140
|
+
editor.value = null;
|
|
141
|
+
resetPhantomCache();
|
|
142
|
+
}
|
|
143
|
+
function createEditor() {
|
|
144
|
+
destroyEditor();
|
|
145
|
+
const myToken = ++editorToken;
|
|
146
|
+
const parent = containerRef.value;
|
|
147
|
+
if (!parent) return;
|
|
148
|
+
const view = new EditorView({
|
|
73
149
|
doc: model.value,
|
|
74
|
-
extensions,
|
|
75
|
-
parent
|
|
150
|
+
extensions: buildExtensions(),
|
|
151
|
+
parent,
|
|
76
152
|
dispatch(tr) {
|
|
77
|
-
|
|
78
|
-
if (tr.
|
|
79
|
-
model.value = tr.state.doc.toString();
|
|
153
|
+
view.update([tr]);
|
|
154
|
+
if (tr.docChanged) model.value = tr.state.doc.toString();
|
|
80
155
|
}
|
|
81
156
|
});
|
|
157
|
+
if (myToken !== editorToken) {
|
|
158
|
+
view.destroy();
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
editor.value = view;
|
|
162
|
+
syncPhantomLineNumbers();
|
|
163
|
+
applyLanguage();
|
|
82
164
|
}
|
|
83
|
-
watch(
|
|
84
|
-
|
|
85
|
-
()
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
165
|
+
watch(containerRef, (el) => {
|
|
166
|
+
if (el) createEditor();
|
|
167
|
+
else destroyEditor();
|
|
168
|
+
}, {
|
|
169
|
+
immediate: true,
|
|
170
|
+
flush: "post"
|
|
171
|
+
});
|
|
172
|
+
watch(() => props.language, applyLanguage);
|
|
173
|
+
watch(() => props.dark, (dark) => {
|
|
174
|
+
editor.value?.dispatch({ effects: themeCompartment.reconfigure(dark ? oneDark : []) });
|
|
175
|
+
});
|
|
176
|
+
watch(disabled, (v) => {
|
|
177
|
+
editor.value?.dispatch({ effects: editableCompartment.reconfigure(EditorView.editable.of(!v)) });
|
|
178
|
+
});
|
|
179
|
+
watch(readonly, (v) => {
|
|
180
|
+
editor.value?.dispatch({ effects: readOnlyCompartment.reconfigure(EditorState.readOnly.of(v)) });
|
|
181
|
+
});
|
|
182
|
+
watch(() => props.defaultLines, syncPhantomLineNumbers);
|
|
89
183
|
watch([() => props.modelValue, editor], ([v, e]) => {
|
|
90
184
|
if (!e) return;
|
|
91
|
-
if (e.composing
|
|
92
|
-
const
|
|
93
|
-
e
|
|
185
|
+
if (e.composing) return;
|
|
186
|
+
const next = v ?? "";
|
|
187
|
+
if (e.state.doc.toString() === next) return;
|
|
188
|
+
const valueLength = next.length;
|
|
189
|
+
const inRange = e.state.selection.ranges.every((range) => range.anchor <= valueLength && range.head <= valueLength);
|
|
190
|
+
e.dispatch({
|
|
94
191
|
changes: {
|
|
95
192
|
from: 0,
|
|
96
|
-
to: e
|
|
97
|
-
insert:
|
|
193
|
+
to: e.state.doc.length,
|
|
194
|
+
insert: next
|
|
98
195
|
},
|
|
99
|
-
selection:
|
|
196
|
+
selection: inRange ? e.state.selection : {
|
|
100
197
|
anchor: 0,
|
|
101
198
|
head: 0
|
|
102
|
-
}
|
|
199
|
+
},
|
|
103
200
|
scrollIntoView: true
|
|
104
201
|
});
|
|
105
202
|
}, { immediate: true });
|
|
106
|
-
onBeforeUnmount(
|
|
107
|
-
editor.value?.destroy();
|
|
108
|
-
});
|
|
203
|
+
onBeforeUnmount(destroyEditor);
|
|
109
204
|
return (_ctx, _cache) => {
|
|
110
205
|
return openBlock(), createBlock(unref(_sfc_main$1), {
|
|
111
206
|
class: normalizeClass(className.value),
|
|
207
|
+
style: normalizeStyle(rootStyle.value),
|
|
112
208
|
onKeyup: _cache[0] || (_cache[0] = withKeys(withModifiers(() => {}, ["stop"]), ["enter"]))
|
|
113
209
|
}, {
|
|
114
210
|
default: withCtx(() => [createElementVNode("div", _hoisted_1, null, 512)]),
|
|
115
211
|
_: 1
|
|
116
|
-
}, 8, ["class"]);
|
|
212
|
+
}, 8, ["class", "style"]);
|
|
117
213
|
};
|
|
118
214
|
}
|
|
119
215
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"code-editor.js","names":[],"sources":["../../../src/components/code-editor/code-editor.vue"],"sourcesContent":["<template>\n <u-scroll :class=\"className\" @keyup.enter.stop>\n <div ref=\"container\"></div>\n </u-scroll>\n</template>\n\n<script lang=\"ts\" setup>\nimport { EditorState } from '@codemirror/state'\nimport { oneDark } from '@codemirror/theme-one-dark'\nimport { tooltips } from '@codemirror/view'\nimport { useFormComponent, useFormFallbackProps } from '@veltra/compositions'\nimport { bem, zIndex } from '@veltra/utils'\nimport { EditorView, basicSetup } from 'codemirror'\nimport { computed, onBeforeUnmount, shallowRef, useTemplateRef, watch } from 'vue'\n\nimport type { CodeEditorLang, CodeEditorProps } from '../../types'\nimport { UScroll } from '../scroll'\n\nconst props = withDefaults(defineProps<CodeEditorProps>(), {\n disabled: undefined,\n readonly: undefined\n})\n\nconst model = defineModel<string>()\n\nconst cls = bem('code-editor')\n\nconst { formProps } = useFormComponent()\n\nconst { size, disabled, readonly } = useFormFallbackProps([formProps ?? {}, props])\n\nconst className = computed<string[]>(() => {\n return [\n cls.b,\n cls.m(size.value),\n bem.is('disabled', disabled.value),\n bem.is('readonly', readonly.value)\n ]\n})\n\nconst containerRef = useTemplateRef('container')\n\nconst editor = shallowRef<EditorView | null>(null)\n\nconst langLoaders: Record<CodeEditorLang, () => Promise<any>> = {\n js: () => import('@codemirror/lang-javascript').then((m) => m.javascript({ typescript: true })),\n sql: () => import('@codemirror/lang-sql').then((m) => m.sql()),\n java: () => import('@codemirror/lang-java').then((m) => m.java()),\n json: () => import('@codemirror/lang-json').then((m) => m.json())\n}\n\nasync function renderEditor() {\n if (!containerRef.value) return\n editor.value?.destroy()\n\n const { language } = props\n\n const extensions = [\n basicSetup,\n oneDark,\n tooltips({\n parent: document.body\n }),\n EditorView.theme({\n '.cm-tooltip': {\n zIndex: zIndex()\n }\n })\n ]\n\n if (disabled.value) {\n extensions.push(EditorView.editable.of(false))\n }\n if (readonly.value) {\n extensions.push(EditorState.readOnly.of(true))\n }\n if (language) {\n const lang = await langLoaders[language]()\n\n extensions.push(lang)\n }\n\n editor.value = new EditorView({\n doc: model.value,\n extensions,\n parent: containerRef.value,\n\n dispatch(tr) {\n editor.value?.update([tr])\n if (tr.changes.empty || !tr.docChanged) {\n return\n }\n model.value = tr.state.doc.toString()\n }\n })\n}\n\nwatch([containerRef, () => props.language, disabled, readonly], renderEditor)\n\nwatch(\n [() => props.modelValue, editor],\n ([v, e]) => {\n if (!e) return\n\n if (e.composing || e.state.doc.toJSON().join('\\n') === v) {\n return\n }\n const isSelectionOutOfRange = !e?.state.selection.ranges.every(\n (range) => range.anchor < (v?.length ?? 0) && range.head < (v?.length ?? 0)\n )\n e?.dispatch({\n changes: {\n from: 0,\n to: e?.state.doc.length,\n insert: v\n },\n selection: isSelectionOutOfRange ? { anchor: 0, head: 0 } : e?.state.selection,\n scrollIntoView: true\n })\n },\n { immediate: true }\n)\n\nonBeforeUnmount(() => {\n editor.value?.destroy()\n})\n</script>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAkBA,MAAM,QAAQ;EAKd,MAAM,QAAQ,SAAmB,SAAA,aAAC;EAElC,MAAM,MAAM,IAAI,cAAa;EAE7B,MAAM,EAAE,cAAc,kBAAiB;EAEvC,MAAM,EAAE,MAAM,UAAU,aAAa,qBAAqB,CAAC,aAAa,EAAE,EAAE,MAAM,CAAA;EAElF,MAAM,YAAY,eAAyB;AACzC,UAAO;IACL,IAAI;IACJ,IAAI,EAAE,KAAK,MAAM;IACjB,IAAI,GAAG,YAAY,SAAS,MAAM;IAClC,IAAI,GAAG,YAAY,SAAS,MAAK;IACnC;IACD;EAED,MAAM,eAAe,eAAe,YAAW;EAE/C,MAAM,SAAS,WAA8B,KAAI;EAEjD,MAAM,cAA0D;GAC9D,UAAU,OAAO,+BAA+B,MAAM,MAAM,EAAE,WAAW,EAAE,YAAY,MAAM,CAAC,CAAC;GAC/F,WAAW,OAAO,wBAAwB,MAAM,MAAM,EAAE,KAAK,CAAC;GAC9D,YAAY,OAAO,yBAAyB,MAAM,MAAM,EAAE,MAAM,CAAC;GACjE,YAAY,OAAO,yBAAyB,MAAM,MAAM,EAAE,MAAM,CAAA;GAClE;EAEA,eAAe,eAAe;AAC5B,OAAI,CAAC,aAAa,MAAO;AACzB,UAAO,OAAO,SAAQ;GAEtB,MAAM,EAAE,aAAa;GAErB,MAAM,aAAa;IACjB;IACA;IACA,SAAS,EACP,QAAQ,SAAS,MAClB,CAAC;IACF,WAAW,MAAM,EACf,eAAe,EACb,QAAQ,QAAO,EACjB,EACD,CAAA;IACH;AAEA,OAAI,SAAS,MACX,YAAW,KAAK,WAAW,SAAS,GAAG,MAAM,CAAA;AAE/C,OAAI,SAAS,MACX,YAAW,KAAK,YAAY,SAAS,GAAG,KAAK,CAAA;AAE/C,OAAI,UAAU;IACZ,MAAM,OAAO,MAAM,YAAY,WAAU;AAEzC,eAAW,KAAK,KAAI;;AAGtB,UAAO,QAAQ,IAAI,WAAW;IAC5B,KAAK,MAAM;IACX;IACA,QAAQ,aAAa;IAErB,SAAS,IAAI;AACX,YAAO,OAAO,OAAO,CAAC,GAAG,CAAA;AACzB,SAAI,GAAG,QAAQ,SAAS,CAAC,GAAG,WAC1B;AAEF,WAAM,QAAQ,GAAG,MAAM,IAAI,UAAS;;IAEvC,CAAA;;AAGH,QAAM;GAAC;SAAoB,MAAM;GAAU;GAAU;GAAS,EAAE,aAAY;AAE5E,QACE,OAAO,MAAM,YAAY,OAAO,GAC/B,CAAC,GAAG,OAAO;AACV,OAAI,CAAC,EAAG;AAER,OAAI,EAAE,aAAa,EAAE,MAAM,IAAI,QAAQ,CAAC,KAAK,KAAK,KAAK,EACrD;GAEF,MAAM,wBAAwB,CAAC,GAAG,MAAM,UAAU,OAAO,OACtD,UAAU,MAAM,UAAU,GAAG,UAAU,MAAM,MAAM,QAAQ,GAAG,UAAU,GAC3E;AACA,MAAG,SAAS;IACV,SAAS;KACP,MAAM;KACN,IAAI,GAAG,MAAM,IAAI;KACjB,QAAQ;KACT;IACD,WAAW,wBAAwB;KAAE,QAAQ;KAAG,MAAM;KAAG,GAAG,GAAG,MAAM;IACrE,gBAAgB;IACjB,CAAA;KAEH,EAAE,WAAW,MAAK,CACpB;AAEA,wBAAsB;AACpB,UAAO,OAAO,SAAQ;IACvB;;uBA5HC,YAEW,MAAA,YAAA,EAAA;IAFA,OAAK,eAAE,UAAA,MAAS;IAAG,SAAK,OAAA,OAAA,OAAA,KAAA,SAAA,oBAAN,IAAiB,CAAA,OAAA,CAAA,EAAA,CAAA,QAAA,CAAA;;2BACjB,CAA3B,mBAA2B,OAA3B,YAA2B,MAAA,IAAA,CAAA,CAAA"}
|
|
1
|
+
{"version":3,"file":"code-editor.js","names":[],"sources":["../../../src/components/code-editor/code-editor.vue"],"sourcesContent":["<template>\n <u-scroll :class=\"className\" :style=\"rootStyle\" @keyup.enter.stop>\n <div ref=\"container\"></div>\n </u-scroll>\n</template>\n\n<script lang=\"ts\" setup>\nimport { Compartment, EditorState, type Extension } from '@codemirror/state'\nimport { oneDark } from '@codemirror/theme-one-dark'\nimport { ViewPlugin, tooltips, type ViewUpdate } from '@codemirror/view'\nimport { useFormComponent, useFormFallbackProps } from '@veltra/compositions'\nimport { bem, zIndex } from '@veltra/utils'\nimport { EditorView, basicSetup } from 'codemirror'\nimport {\n computed,\n onBeforeUnmount,\n shallowRef,\n useTemplateRef,\n watch,\n type CSSProperties\n} from 'vue'\n\nimport type { CodeEditorLang, CodeEditorProps } from '../../types'\nimport { UScroll } from '../scroll'\n\ndefineOptions({ name: 'CodeEditor' })\n\nconst props = withDefaults(defineProps<CodeEditorProps>(), {\n disabled: undefined,\n readonly: undefined,\n dark: false,\n defaultLines: 8\n})\n\nconst model = defineModel<string>()\n\nconst cls = bem('code-editor')\n\nconst { formProps } = useFormComponent()\n\nconst { disabled, readonly } = useFormFallbackProps([formProps ?? {}, props], {\n disabled: false,\n readonly: false\n})\n\nconst className = computed<string[]>(() => [\n cls.b,\n bem.is('disabled', disabled.value),\n bem.is('readonly', readonly.value),\n bem.is('dark', props.dark)\n])\n\nconst rootStyle = computed<CSSProperties>(() => ({\n '--u-code-editor-default-lines': Math.max(1, props.defaultLines)\n}))\n\nconst containerRef = useTemplateRef('container')\nconst editor = shallowRef<EditorView | null>(null)\n\nconst langLoaders: Record<CodeEditorLang, () => Promise<Extension>> = {\n js: () => import('@codemirror/lang-javascript').then((m) => m.javascript({ typescript: true })),\n sql: () => import('@codemirror/lang-sql').then((m) => m.sql()),\n java: () => import('@codemirror/lang-java').then((m) => m.java()),\n json: () => import('@codemirror/lang-json').then((m) => m.json())\n}\n\nconst themeCompartment = new Compartment()\nconst editableCompartment = new Compartment()\nconst readOnlyCompartment = new Compartment()\nconst langCompartment = new Compartment()\n\nlet phantomGutter: HTMLElement | null = null\nlet phantomContainer: HTMLElement | null = null\nlet lastPhantomKey = ''\n\nfunction resetPhantomCache() {\n phantomGutter = null\n phantomContainer = null\n lastPhantomKey = ''\n}\n\n/**\n * 在 .cm-lineNumbers 末尾追加占位行号 DOM,使可视行号数量补齐到 defaultLines。\n * CodeMirror 的 lineNumbers() 仅为真实文档行渲染行号,超出部分由本逻辑补全。\n */\nfunction syncPhantomLineNumbers() {\n const view = editor.value\n if (!view) return\n\n if (!phantomGutter || !phantomGutter.isConnected) {\n phantomGutter = view.dom.querySelector<HTMLElement>('.cm-gutter.cm-lineNumbers')\n }\n if (!phantomGutter) return\n\n if (!phantomContainer) {\n phantomContainer = document.createElement('div')\n phantomContainer.className = 'cm-phantom-lines'\n }\n if (\n phantomContainer.parentElement !== phantomGutter ||\n phantomContainer !== phantomGutter.lastElementChild\n ) {\n phantomGutter.appendChild(phantomContainer)\n }\n\n const realLines = view.state.doc.lines\n const target = Math.max(0, Math.max(1, props.defaultLines) - realLines)\n const lineHeight = view.defaultLineHeight\n\n const key = `${realLines}|${target}|${lineHeight}`\n if (key === lastPhantomKey) return\n lastPhantomKey = key\n\n while (phantomContainer.children.length > target) {\n phantomContainer.lastElementChild!.remove()\n }\n while (phantomContainer.children.length < target) {\n const el = document.createElement('div')\n el.className = 'cm-gutterElement cm-gutterElement-phantom'\n phantomContainer.appendChild(el)\n }\n for (let i = 0; i < target; i++) {\n const el = phantomContainer.children[i] as HTMLElement\n const num = String(realLines + i + 1)\n if (el.textContent !== num) el.textContent = num\n if (lineHeight && el.style.height !== `${lineHeight}px`) {\n el.style.height = `${lineHeight}px`\n }\n }\n}\n\nconst phantomLineNumbersPlugin = ViewPlugin.fromClass(\n class {\n update(update: ViewUpdate) {\n if (update.docChanged || update.geometryChanged) {\n syncPhantomLineNumbers()\n }\n }\n }\n)\n\nfunction buildExtensions(): Extension[] {\n return [\n basicSetup,\n tooltips({ parent: document.body }),\n EditorView.theme({\n '.cm-tooltip': { zIndex: zIndex() }\n }),\n themeCompartment.of(props.dark ? oneDark : []),\n editableCompartment.of(EditorView.editable.of(!disabled.value)),\n readOnlyCompartment.of(EditorState.readOnly.of(readonly.value)),\n langCompartment.of([]),\n phantomLineNumbersPlugin\n ]\n}\n\nlet editorToken = 0\nlet langToken = 0\n\nasync function applyLanguage() {\n const view = editor.value\n if (!view) return\n const myToken = ++langToken\n const { language } = props\n const ext = language ? await langLoaders[language]() : []\n if (myToken !== langToken || editor.value !== view) return\n view.dispatch({ effects: langCompartment.reconfigure(ext) })\n}\n\nfunction destroyEditor() {\n ++editorToken\n ++langToken\n editor.value?.destroy()\n editor.value = null\n resetPhantomCache()\n}\n\nfunction createEditor() {\n destroyEditor()\n const myToken = ++editorToken\n const parent = containerRef.value\n if (!parent) return\n\n const view = new EditorView({\n doc: model.value,\n extensions: buildExtensions(),\n parent,\n dispatch(tr) {\n view.update([tr])\n if (tr.docChanged) {\n model.value = tr.state.doc.toString()\n }\n }\n })\n\n if (myToken !== editorToken) {\n view.destroy()\n return\n }\n\n editor.value = view\n syncPhantomLineNumbers()\n applyLanguage()\n}\n\nwatch(\n containerRef,\n (el) => {\n if (el) createEditor()\n else destroyEditor()\n },\n { immediate: true, flush: 'post' }\n)\n\nwatch(() => props.language, applyLanguage)\n\nwatch(\n () => props.dark,\n (dark) => {\n editor.value?.dispatch({\n effects: themeCompartment.reconfigure(dark ? oneDark : [])\n })\n }\n)\n\nwatch(disabled, (v) => {\n editor.value?.dispatch({\n effects: editableCompartment.reconfigure(EditorView.editable.of(!v))\n })\n})\n\nwatch(readonly, (v) => {\n editor.value?.dispatch({\n effects: readOnlyCompartment.reconfigure(EditorState.readOnly.of(v))\n })\n})\n\nwatch(() => props.defaultLines, syncPhantomLineNumbers)\n\nwatch(\n [() => props.modelValue, editor],\n ([v, e]) => {\n if (!e) return\n if (e.composing) return\n const next = v ?? ''\n if (e.state.doc.toString() === next) return\n\n const valueLength = next.length\n const inRange = e.state.selection.ranges.every(\n (range) => range.anchor <= valueLength && range.head <= valueLength\n )\n e.dispatch({\n changes: { from: 0, to: e.state.doc.length, insert: next },\n selection: inRange ? e.state.selection : { anchor: 0, head: 0 },\n scrollIntoView: true\n })\n },\n { immediate: true }\n)\n\nonBeforeUnmount(destroyEditor)\n</script>\n"],"mappings":"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"}
|
|
@@ -14,6 +14,8 @@ declare const __VLS_export: _$vue.DefineComponent<__VLS_PublicProps, {}, {}, {},
|
|
|
14
14
|
}>, {
|
|
15
15
|
disabled: boolean;
|
|
16
16
|
readonly: boolean;
|
|
17
|
+
dark: boolean;
|
|
18
|
+
defaultLines: number;
|
|
17
19
|
}, {}, {}, {}, string, _$vue.ComponentProvideOptions, false, {}, any>;
|
|
18
20
|
declare const _default: typeof __VLS_export;
|
|
19
21
|
//#endregion
|