@veltra/sheet 2.4.0 → 2.5.1

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 (147) hide show
  1. package/dist/components/sheet/formula-bar.js +50 -7
  2. package/dist/components/sheet/style2.css +2 -2
  3. package/dist/index.d.ts +2 -19
  4. package/dist/index.js +2 -15
  5. package/dist/types/index.d.ts +1 -3
  6. package/package.json +5 -6
  7. package/src/components/sheet/__test__/formula-bar.test.ts +29 -0
  8. package/src/components/sheet/formula-bar.vue +67 -6
  9. package/src/components/sheet/style.scss +1 -1
  10. package/src/index.ts +1 -27
  11. package/src/types/index.ts +0 -2
  12. package/dist/components/report/binding-badge.js +0 -118
  13. package/dist/components/report/designer/cell-coords.js +0 -46
  14. package/dist/components/report/designer/col-widths.js +0 -29
  15. package/dist/components/report/designer/conditional-rules/helpers.js +0 -139
  16. package/dist/components/report/designer/drill-dialog.js +0 -258
  17. package/dist/components/report/designer/drop-highlight-overlay.js +0 -76
  18. package/dist/components/report/designer/float-panel.js +0 -434
  19. package/dist/components/report/designer/role.js +0 -17
  20. package/dist/components/report/designer/rule-preview.js +0 -33
  21. package/dist/components/report/designer/rule-row.js +0 -253
  22. package/dist/components/report/designer/rules-dialog.js +0 -118
  23. package/dist/components/report/designer/topology-overlay.js +0 -122
  24. package/dist/components/report/designer/topology.js +0 -64
  25. package/dist/components/report/designer/use-grid-overlay.js +0 -75
  26. package/dist/components/report/designer-hub.js +0 -177
  27. package/dist/components/report/field-panel-helpers.js +0 -33
  28. package/dist/components/report/field-panel.js +0 -132
  29. package/dist/components/report/filter-bar.js +0 -74
  30. package/dist/components/report/hub-connection-form.js +0 -145
  31. package/dist/components/report/hub-dataset-editor.js +0 -409
  32. package/dist/components/report/preview-grid-size.js +0 -32
  33. package/dist/components/report/print.js +0 -39
  34. package/dist/components/report/report-designer.js +0 -428
  35. package/dist/components/report/report-viewer.js +0 -253
  36. package/dist/components/report/style.d.ts +0 -17
  37. package/dist/components/report/style.js +0 -18
  38. package/dist/components/report/style2.css +0 -965
  39. package/dist/components/report/use-report-designer.js +0 -387
  40. package/dist/components/report/use-report-viewer.js +0 -140
  41. package/dist/report/binding.d.ts +0 -83
  42. package/dist/report/binding.js +0 -334
  43. package/dist/report/connector.d.ts +0 -66
  44. package/dist/report/connector.js +0 -159
  45. package/dist/report/drill.d.ts +0 -48
  46. package/dist/report/drill.js +0 -78
  47. package/dist/report/export-xlsx.d.ts +0 -13
  48. package/dist/report/export-xlsx.js +0 -13
  49. package/dist/report/filter-bar.d.ts +0 -10
  50. package/dist/report/filter-bar.js +0 -31
  51. package/dist/report/index.d.ts +0 -14
  52. package/dist/report/params.d.ts +0 -13
  53. package/dist/report/params.js +0 -61
  54. package/dist/report/print.d.ts +0 -23
  55. package/dist/report/print.js +0 -197
  56. package/dist/report/render/aggregate.js +0 -193
  57. package/dist/report/render/builder.d.ts +0 -12
  58. package/dist/report/render/builder.js +0 -139
  59. package/dist/report/render/coordinate.d.ts +0 -25
  60. package/dist/report/render/coordinate.js +0 -733
  61. package/dist/report/render/index.d.ts +0 -14
  62. package/dist/report/render/index.js +0 -21
  63. package/dist/report/render/style-resolver.js +0 -50
  64. package/dist/report/render/template-index.d.ts +0 -24
  65. package/dist/report/render/template-index.js +0 -137
  66. package/dist/report/rules/evaluate.d.ts +0 -25
  67. package/dist/report/rules/evaluate.js +0 -82
  68. package/dist/report/rules/index.d.ts +0 -2
  69. package/dist/report/template.d.ts +0 -63
  70. package/dist/report/template.js +0 -83
  71. package/dist/report/types.d.ts +0 -103
  72. package/dist/types/report-designer.d.ts +0 -51
  73. package/dist/types/report-viewer.d.ts +0 -57
  74. package/src/components/report/__test__/binding-badge.test.ts +0 -92
  75. package/src/components/report/__test__/conditional-rules-helpers.test.ts +0 -88
  76. package/src/components/report/__test__/field-panel-helpers.test.ts +0 -65
  77. package/src/components/report/__test__/float-panel-position.test.ts +0 -45
  78. package/src/components/report/__test__/preview-grid-size.test.ts +0 -63
  79. package/src/components/report/__test__/report-designer.test.ts +0 -559
  80. package/src/components/report/__test__/report-drill.test.ts +0 -692
  81. package/src/components/report/__test__/report-viewer.test.ts +0 -400
  82. package/src/components/report/__test__/topology.test.ts +0 -143
  83. package/src/components/report/__test__/use-report-designer.test.ts +0 -804
  84. package/src/components/report/binding-badge.ts +0 -122
  85. package/src/components/report/designer/cell-coords.ts +0 -95
  86. package/src/components/report/designer/col-widths.ts +0 -56
  87. package/src/components/report/designer/conditional-rules/helpers.ts +0 -189
  88. package/src/components/report/designer/drill-dialog.vue +0 -245
  89. package/src/components/report/designer/drop-highlight-overlay.vue +0 -75
  90. package/src/components/report/designer/float-panel.vue +0 -444
  91. package/src/components/report/designer/role.ts +0 -32
  92. package/src/components/report/designer/rule-preview.vue +0 -40
  93. package/src/components/report/designer/rule-row.vue +0 -252
  94. package/src/components/report/designer/rules-dialog.vue +0 -110
  95. package/src/components/report/designer/topology-overlay.vue +0 -128
  96. package/src/components/report/designer/topology.ts +0 -124
  97. package/src/components/report/designer/use-grid-overlay.ts +0 -114
  98. package/src/components/report/designer-hub.vue +0 -198
  99. package/src/components/report/field-panel-helpers.ts +0 -44
  100. package/src/components/report/field-panel.vue +0 -136
  101. package/src/components/report/filter-bar.vue +0 -77
  102. package/src/components/report/hub-connection-form.vue +0 -124
  103. package/src/components/report/hub-dataset-editor.vue +0 -387
  104. package/src/components/report/index.ts +0 -2
  105. package/src/components/report/preview-grid-size.ts +0 -33
  106. package/src/components/report/print.ts +0 -44
  107. package/src/components/report/report-designer.vue +0 -454
  108. package/src/components/report/report-viewer.vue +0 -289
  109. package/src/components/report/style-designer.scss +0 -653
  110. package/src/components/report/style-hub.scss +0 -292
  111. package/src/components/report/style-viewer.scss +0 -144
  112. package/src/components/report/style.scss +0 -3
  113. package/src/components/report/style.ts +0 -20
  114. package/src/components/report/use-report-designer.ts +0 -603
  115. package/src/components/report/use-report-viewer.ts +0 -227
  116. package/src/report/__test__/binding.test.ts +0 -320
  117. package/src/report/__test__/connector.test.ts +0 -239
  118. package/src/report/__test__/drill.test.ts +0 -194
  119. package/src/report/__test__/export-xlsx.test.ts +0 -96
  120. package/src/report/__test__/filter-bar.test.ts +0 -58
  121. package/src/report/__test__/params.test.ts +0 -156
  122. package/src/report/__test__/print.test.ts +0 -170
  123. package/src/report/__test__/render.test.ts +0 -856
  124. package/src/report/__test__/rules.test.ts +0 -131
  125. package/src/report/__test__/template.test.ts +0 -366
  126. package/src/report/binding.ts +0 -474
  127. package/src/report/connector.ts +0 -206
  128. package/src/report/drill.ts +0 -112
  129. package/src/report/export-xlsx.ts +0 -15
  130. package/src/report/filter-bar.ts +0 -36
  131. package/src/report/index.ts +0 -16
  132. package/src/report/params.ts +0 -96
  133. package/src/report/print.ts +0 -234
  134. package/src/report/render/__test__/aggregate.test.ts +0 -16
  135. package/src/report/render/__test__/coordinate.test.ts +0 -405
  136. package/src/report/render/aggregate.ts +0 -289
  137. package/src/report/render/builder.ts +0 -211
  138. package/src/report/render/coordinate.ts +0 -1239
  139. package/src/report/render/index.ts +0 -30
  140. package/src/report/render/style-resolver.ts +0 -68
  141. package/src/report/render/template-index.ts +0 -200
  142. package/src/report/rules/evaluate.ts +0 -113
  143. package/src/report/rules/index.ts +0 -7
  144. package/src/report/template.ts +0 -145
  145. package/src/report/types.ts +0 -116
  146. package/src/types/report-designer.ts +0 -55
  147. package/src/types/report-viewer.ts +0 -54
@@ -1,253 +0,0 @@
1
- import { RULE_SCOPE_OPTIONS, coerceValueForOperator, isNumericFieldType, operatorsForFieldType, readBetweenValue, resolveEvalFieldType, ruleEvalFieldOptions, writeBetweenValue } from "./conditional-rules/helpers.js";
2
- import _sfc_main$1 from "./rule-preview.js";
3
- import { Fragment, computed, createBlock, createElementBlock, createElementVNode, createTextVNode, createVNode, defineComponent, normalizeClass, openBlock, renderList, toDisplayString, unref, withCtx } from "vue";
4
- import { UButton, UButtonGroup, UInput, UNumberInput, UPalette, USelect } from "@veltra/desktop";
5
- import { bem } from "@veltra/utils";
6
- //#region src/components/report/designer/rule-row.vue
7
- const _hoisted_1 = { title: "背景" };
8
- const _hoisted_2 = { title: "文字" };
9
- const _sfc_main = /*@__PURE__*/ defineComponent({
10
- name: "UReportRuleRow",
11
- __name: "rule-row",
12
- props: {
13
- rule: {},
14
- bindingField: {},
15
- datasetFields: {}
16
- },
17
- emits: ["update:rule", "remove"],
18
- setup(__props, { emit: __emit }) {
19
- const props = __props;
20
- const emit = __emit;
21
- const cls = bem("report-rule-row");
22
- const evalFieldType = computed(() => resolveEvalFieldType(props.rule, props.bindingField, props.datasetFields));
23
- const operatorOptions = computed(() => operatorsForFieldType(evalFieldType.value));
24
- const numericField = computed(() => isNumericFieldType(evalFieldType.value));
25
- const fieldOptions = computed(() => ruleEvalFieldOptions(props.bindingField, props.datasetFields));
26
- const betweenStart = computed(() => readBetweenValue(props.rule.value, 0, evalFieldType.value));
27
- const betweenEnd = computed(() => readBetweenValue(props.rule.value, 1, evalFieldType.value));
28
- const scalarNumber = computed(() => {
29
- const raw = props.rule.value;
30
- if (typeof raw === "number" && Number.isFinite(raw)) return raw;
31
- const parsed = Number(raw);
32
- return Number.isFinite(parsed) ? parsed : 0;
33
- });
34
- function patchRule(patch) {
35
- emit("update:rule", {
36
- ...props.rule,
37
- ...patch
38
- });
39
- }
40
- function onEvalField(field) {
41
- const next = {};
42
- if (!field) next.field = void 0;
43
- else next.field = field;
44
- const nextType = resolveEvalFieldType({
45
- ...props.rule,
46
- ...next
47
- }, props.bindingField, props.datasetFields);
48
- const operator = operatorsForFieldType(nextType)[0]?.value ?? props.rule.operator;
49
- next.operator = operator;
50
- next.value = coerceValueForOperator(operator, nextType, props.rule.value);
51
- patchRule(next);
52
- }
53
- function onScope(scope) {
54
- patchRule({ scope: scope === "cell" ? void 0 : scope });
55
- }
56
- function onOperator(operator) {
57
- patchRule({
58
- operator,
59
- value: coerceValueForOperator(operator, evalFieldType.value, props.rule.value)
60
- });
61
- }
62
- function patchValue(value) {
63
- patchRule({ value });
64
- }
65
- function patchBetween(index, next) {
66
- patchRule({ value: writeBetweenValue(props.rule.value, index, next, evalFieldType.value) });
67
- }
68
- function patchFillColor(color) {
69
- patchRule({ style: {
70
- ...props.rule.style,
71
- fill: color ? { color } : void 0
72
- } });
73
- }
74
- function patchFontColor(color) {
75
- patchRule({ style: {
76
- ...props.rule.style,
77
- font: {
78
- ...props.rule.style.font,
79
- color: color || void 0
80
- }
81
- } });
82
- }
83
- function toggleBold() {
84
- const bold = !props.rule.style.font?.bold;
85
- patchRule({ style: {
86
- ...props.rule.style,
87
- font: {
88
- ...props.rule.style.font,
89
- bold: bold || void 0
90
- }
91
- } });
92
- }
93
- function toggleItalic() {
94
- const italic = !props.rule.style.font?.italic;
95
- patchRule({ style: {
96
- ...props.rule.style,
97
- font: {
98
- ...props.rule.style.font,
99
- italic: italic || void 0
100
- }
101
- } });
102
- }
103
- return (_ctx, _cache) => {
104
- return openBlock(), createElementBlock("div", { class: normalizeClass(unref(cls).b) }, [
105
- createElementVNode("span", {
106
- class: normalizeClass(unref(cls).e("handle")),
107
- title: "拖拽排序"
108
- }, "⋮⋮", 2),
109
- createElementVNode("div", { class: normalizeClass(unref(cls).e("main")) }, [createElementVNode("div", { class: normalizeClass(unref(cls).e("when")) }, [
110
- createElementVNode("span", { class: normalizeClass(unref(cls).e("lead")) }, "当", 2),
111
- createVNode(unref(USelect), {
112
- size: "small",
113
- class: normalizeClass(unref(cls).e("field-select")),
114
- "model-value": __props.rule.field ?? unref(""),
115
- options: fieldOptions.value,
116
- "onUpdate:modelValue": onEvalField
117
- }, null, 8, [
118
- "class",
119
- "model-value",
120
- "options"
121
- ]),
122
- createVNode(unref(USelect), {
123
- size: "small",
124
- class: normalizeClass(unref(cls).e("operator")),
125
- "model-value": __props.rule.operator,
126
- options: operatorOptions.value,
127
- "onUpdate:modelValue": onOperator
128
- }, null, 8, [
129
- "class",
130
- "model-value",
131
- "options"
132
- ]),
133
- createElementVNode("div", { class: normalizeClass(unref(cls).e("value")) }, [__props.rule.operator === "between" ? (openBlock(), createElementBlock(Fragment, { key: 0 }, [
134
- numericField.value ? (openBlock(), createBlock(unref(UNumberInput), {
135
- key: 0,
136
- size: "small",
137
- class: normalizeClass(unref(cls).e("between-input")),
138
- "model-value": betweenStart.value,
139
- "onUpdate:modelValue": _cache[0] || (_cache[0] = (v) => patchBetween(0, v ?? 0))
140
- }, null, 8, ["class", "model-value"])) : (openBlock(), createBlock(unref(UInput), {
141
- key: 1,
142
- size: "small",
143
- class: normalizeClass(unref(cls).e("between-input")),
144
- "model-value": String(betweenStart.value),
145
- "onUpdate:modelValue": _cache[1] || (_cache[1] = (v) => patchBetween(0, String(v ?? "")))
146
- }, null, 8, ["class", "model-value"])),
147
- createElementVNode("span", { class: normalizeClass(unref(cls).e("between-sep")) }, "至", 2),
148
- numericField.value ? (openBlock(), createBlock(unref(UNumberInput), {
149
- key: 2,
150
- size: "small",
151
- class: normalizeClass(unref(cls).e("between-input")),
152
- "model-value": betweenEnd.value,
153
- "onUpdate:modelValue": _cache[2] || (_cache[2] = (v) => patchBetween(1, v ?? 0))
154
- }, null, 8, ["class", "model-value"])) : (openBlock(), createBlock(unref(UInput), {
155
- key: 3,
156
- size: "small",
157
- class: normalizeClass(unref(cls).e("between-input")),
158
- "model-value": String(betweenEnd.value),
159
- "onUpdate:modelValue": _cache[3] || (_cache[3] = (v) => patchBetween(1, String(v ?? "")))
160
- }, null, 8, ["class", "model-value"]))
161
- ], 64)) : __props.rule.operator === "contains" || !numericField.value && __props.rule.operator === "eq" ? (openBlock(), createBlock(unref(UInput), {
162
- key: 1,
163
- size: "small",
164
- class: normalizeClass(unref(cls).e("scalar-input")),
165
- "model-value": String(__props.rule.value ?? ""),
166
- placeholder: "比较值",
167
- "onUpdate:modelValue": _cache[4] || (_cache[4] = (v) => patchValue(String(v ?? "")))
168
- }, null, 8, ["class", "model-value"])) : (openBlock(), createBlock(unref(UNumberInput), {
169
- key: 2,
170
- size: "small",
171
- class: normalizeClass(unref(cls).e("scalar-input")),
172
- "model-value": scalarNumber.value,
173
- "onUpdate:modelValue": _cache[5] || (_cache[5] = (v) => patchValue(v ?? 0))
174
- }, null, 8, ["class", "model-value"]))], 2),
175
- createElementVNode("span", { class: normalizeClass(unref(cls).e("lead")) }, "时", 2)
176
- ], 2), createElementVNode("div", { class: normalizeClass(unref(cls).e("then")) }, [
177
- createElementVNode("span", { class: normalizeClass(unref(cls).e("lead")) }, "样式", 2),
178
- createElementVNode("span", _hoisted_1, [createVNode(unref(UPalette), {
179
- size: "small",
180
- "model-value": __props.rule.style.fill?.color ?? "",
181
- "onUpdate:modelValue": patchFillColor
182
- }, null, 8, ["model-value"])]),
183
- createElementVNode("span", _hoisted_2, [createVNode(unref(UPalette), {
184
- size: "small",
185
- "model-value": __props.rule.style.font?.color ?? "",
186
- "onUpdate:modelValue": patchFontColor
187
- }, null, 8, ["model-value"])]),
188
- createVNode(unref(UButtonGroup), null, {
189
- default: withCtx(() => [createVNode(unref(UButton), {
190
- size: "small",
191
- class: normalizeClass(unref(cls).e("toggle")),
192
- type: __props.rule.style.font?.bold ? "primary" : void 0,
193
- plain: "",
194
- title: "加粗",
195
- onClick: toggleBold
196
- }, {
197
- default: withCtx(() => [..._cache[7] || (_cache[7] = [createTextVNode(" B ", -1)])]),
198
- _: 1
199
- }, 8, ["class", "type"]), createVNode(unref(UButton), {
200
- size: "small",
201
- class: normalizeClass(unref(cls).e("toggle")),
202
- type: __props.rule.style.font?.italic ? "primary" : void 0,
203
- plain: "",
204
- title: "斜体",
205
- onClick: toggleItalic
206
- }, {
207
- default: withCtx(() => [..._cache[8] || (_cache[8] = [createTextVNode(" I ", -1)])]),
208
- _: 1
209
- }, 8, ["class", "type"])]),
210
- _: 1
211
- }),
212
- createVNode(_sfc_main$1, {
213
- class: normalizeClass(unref(cls).e("preview")),
214
- rule: __props.rule
215
- }, null, 8, ["class", "rule"]),
216
- createElementVNode("span", { class: normalizeClass(unref(cls).e("lead")) }, "应用到", 2),
217
- createVNode(unref(UButtonGroup), null, {
218
- default: withCtx(() => [(openBlock(true), createElementBlock(Fragment, null, renderList(unref(RULE_SCOPE_OPTIONS), (option) => {
219
- return openBlock(), createBlock(unref(UButton), {
220
- key: option.value,
221
- size: "small",
222
- plain: "",
223
- type: (__props.rule.scope ?? "cell") === option.value ? "primary" : void 0,
224
- title: option.value === "row" ? "染满物理输出行(交叉表会盖住同行所有列)" : "只改本格",
225
- onClick: ($event) => onScope(option.value)
226
- }, {
227
- default: withCtx(() => [createTextVNode(toDisplayString(option.label), 1)]),
228
- _: 2
229
- }, 1032, [
230
- "type",
231
- "title",
232
- "onClick"
233
- ]);
234
- }), 128))]),
235
- _: 1
236
- })
237
- ], 2)], 2),
238
- createVNode(unref(UButton), {
239
- size: "small",
240
- text: "",
241
- type: "danger",
242
- class: normalizeClass(unref(cls).e("remove")),
243
- onClick: _cache[6] || (_cache[6] = ($event) => emit("remove"))
244
- }, {
245
- default: withCtx(() => [..._cache[9] || (_cache[9] = [createTextVNode(" 删除 ", -1)])]),
246
- _: 1
247
- }, 8, ["class"])
248
- ], 2);
249
- };
250
- }
251
- });
252
- //#endregion
253
- export { _sfc_main as default };
@@ -1,118 +0,0 @@
1
- import { cloneRulesFromDraft, createDraftItem, initDraftFromRules } from "./conditional-rules/helpers.js";
2
- import _sfc_main$1 from "./rule-row.js";
3
- import { Fragment, computed, createBlock, createElementBlock, createElementVNode, createTextVNode, createVNode, defineComponent, normalizeClass, openBlock, ref, renderList, unref, watch, withCtx } from "vue";
4
- import { UButton, UDialog } from "@veltra/desktop";
5
- import { bem } from "@veltra/utils";
6
- import { animations, useDnD } from "@veltra/compositions";
7
- //#region src/components/report/designer/rules-dialog.vue
8
- const _sfc_main = /*@__PURE__*/ defineComponent({
9
- name: "UReportRulesDialog",
10
- __name: "rules-dialog",
11
- props: {
12
- modelValue: { type: Boolean },
13
- rules: {},
14
- bindingField: {},
15
- datasetFields: { default: () => [] },
16
- fieldType: { default: "number" }
17
- },
18
- emits: ["update:modelValue", "save"],
19
- setup(__props, { emit: __emit }) {
20
- const props = __props;
21
- const emit = __emit;
22
- const cls = bem("report-rules-dialog");
23
- const draftItems = ref([]);
24
- const { parentRef } = useDnD({
25
- values: draftItems,
26
- dragHandle: ".u-report-rule-row__handle",
27
- plugins: [animations()]
28
- });
29
- const visible = computed({
30
- get: () => props.modelValue,
31
- set: (value) => emit("update:modelValue", value)
32
- });
33
- watch(() => props.modelValue, (open) => {
34
- if (!open) return;
35
- draftItems.value = initDraftFromRules(props.rules, props.fieldType, props.bindingField);
36
- });
37
- function addRule() {
38
- draftItems.value = [...draftItems.value, createDraftItem(void 0, props.fieldType, props.bindingField)];
39
- }
40
- function removeRule(index) {
41
- draftItems.value = draftItems.value.filter((_, i) => i !== index);
42
- }
43
- function confirm() {
44
- emit("save", cloneRulesFromDraft(draftItems.value));
45
- visible.value = false;
46
- }
47
- function onClose() {
48
- visible.value = false;
49
- }
50
- return (_ctx, _cache) => {
51
- return openBlock(), createBlock(unref(UDialog), {
52
- modelValue: visible.value,
53
- "onUpdate:modelValue": _cache[1] || (_cache[1] = ($event) => visible.value = $event),
54
- title: "条件样式",
55
- style: {
56
- "width": "min(600px, 92vw)",
57
- "max-height": "85vh"
58
- },
59
- onClose
60
- }, {
61
- footer: withCtx(() => [createVNode(unref(UButton), {
62
- size: "small",
63
- onClick: _cache[0] || (_cache[0] = ($event) => visible.value = false)
64
- }, {
65
- default: withCtx(() => [..._cache[3] || (_cache[3] = [createTextVNode("取消", -1)])]),
66
- _: 1
67
- }), createVNode(unref(UButton), {
68
- size: "small",
69
- type: "primary",
70
- onClick: confirm
71
- }, {
72
- default: withCtx(() => [..._cache[4] || (_cache[4] = [createTextVNode("确定", -1)])]),
73
- _: 1
74
- })]),
75
- default: withCtx(() => [createElementVNode("div", { class: normalizeClass(unref(cls).b) }, [
76
- createElementVNode("p", { class: normalizeClass(unref(cls).e("hint")) }, "规则按顺序叠加。整行高亮适合明细表,交叉表会染满整行。", 2),
77
- draftItems.value.length ? (openBlock(), createElementBlock("ul", {
78
- key: 0,
79
- ref_key: "parentRef",
80
- ref: parentRef,
81
- class: normalizeClass(unref(cls).e("list"))
82
- }, [(openBlock(true), createElementBlock(Fragment, null, renderList(draftItems.value, (item, index) => {
83
- return openBlock(), createElementBlock("li", {
84
- key: item.id,
85
- class: normalizeClass(unref(cls).e("item"))
86
- }, [createVNode(_sfc_main$1, {
87
- rule: item.rule,
88
- "binding-field": __props.bindingField,
89
- "dataset-fields": __props.datasetFields,
90
- "onUpdate:rule": ($event) => item.rule = $event,
91
- onRemove: ($event) => removeRule(index)
92
- }, null, 8, [
93
- "rule",
94
- "binding-field",
95
- "dataset-fields",
96
- "onUpdate:rule",
97
- "onRemove"
98
- ])], 2);
99
- }), 128))], 2)) : (openBlock(), createElementBlock("p", {
100
- key: 1,
101
- class: normalizeClass(unref(cls).e("empty"))
102
- }, "还没有规则。", 2)),
103
- createVNode(unref(UButton), {
104
- size: "small",
105
- plain: "",
106
- onClick: addRule
107
- }, {
108
- default: withCtx(() => [..._cache[2] || (_cache[2] = [createTextVNode("添加规则", -1)])]),
109
- _: 1
110
- })
111
- ], 2)]),
112
- _: 1
113
- }, 8, ["modelValue"]);
114
- };
115
- }
116
- });
117
- //#endregion
118
- export { _sfc_main as default };
@@ -1,122 +0,0 @@
1
- import { readCellOverlayRect, readGridOverlaySize, useGridOverlaySync } from "./use-grid-overlay.js";
2
- import { buildTopologyArcPath, collectTopologyLinks } from "./topology.js";
3
- import { Fragment, computed, createCommentVNode, createElementBlock, createElementVNode, defineComponent, normalizeClass, openBlock, ref, renderList, toRef, unref } from "vue";
4
- import { bem } from "@veltra/utils";
5
- //#region src/components/report/designer/topology-overlay.vue
6
- const _hoisted_1 = ["width", "height"];
7
- const _hoisted_2 = ["d", "marker-end"];
8
- const _sfc_main = /*@__PURE__*/ defineComponent({
9
- name: "UReportTopologyOverlay",
10
- __name: "topology-overlay",
11
- props: {
12
- cell: {},
13
- binding: {},
14
- entries: {},
15
- metaTick: {},
16
- hostEl: {},
17
- getGrid: { type: Function },
18
- getBindingAt: { type: Function }
19
- },
20
- setup(__props) {
21
- const props = __props;
22
- const cls = bem("report-topology");
23
- const instanceId = Math.random().toString(36).slice(2, 8);
24
- const rowArrowMarkerId = `u-report-topology-row-arrow-${instanceId}`;
25
- const colArrowMarkerId = `u-report-topology-col-arrow-${instanceId}`;
26
- const hostEl = toRef(props, "hostEl");
27
- const svgWidth = ref(0);
28
- const svgHeight = ref(0);
29
- const arcPaths = ref([]);
30
- const inView = ref(false);
31
- const visible = computed(() => !!props.binding && !!props.cell && inView.value && arcPaths.value.length > 0);
32
- function updateOverlay() {
33
- const cell = props.cell;
34
- const binding = props.binding;
35
- const host = props.hostEl;
36
- if (!cell || !binding || !host) {
37
- inView.value = false;
38
- arcPaths.value = [];
39
- return;
40
- }
41
- const size = readGridOverlaySize(host);
42
- if (!size) {
43
- inView.value = false;
44
- arcPaths.value = [];
45
- return;
46
- }
47
- svgWidth.value = size.width;
48
- svgHeight.value = size.height;
49
- const links = collectTopologyLinks(cell, binding, props.entries, props.getBindingAt);
50
- const paths = [];
51
- for (const link of links) {
52
- const fromRect = readCellOverlayRect(link.from, host, props.getGrid);
53
- const toRect = readCellOverlayRect(link.to, host, props.getGrid);
54
- if (!fromRect || !toRect) continue;
55
- paths.push({
56
- direction: link.direction,
57
- path: buildTopologyArcPath({
58
- x: fromRect.centerX,
59
- y: fromRect.centerY
60
- }, {
61
- x: toRect.centerX,
62
- y: toRect.centerY
63
- })
64
- });
65
- }
66
- arcPaths.value = paths;
67
- inView.value = paths.length > 0;
68
- }
69
- useGridOverlaySync({
70
- hostEl,
71
- getGrid: () => props.getGrid(),
72
- watchSources: () => [
73
- props.cell?.row,
74
- props.cell?.col,
75
- props.binding,
76
- props.metaTick,
77
- props.hostEl
78
- ],
79
- update: updateOverlay
80
- });
81
- return (_ctx, _cache) => {
82
- return visible.value ? (openBlock(), createElementBlock("svg", {
83
- key: 0,
84
- class: normalizeClass(unref(cls).b),
85
- width: svgWidth.value,
86
- height: svgHeight.value,
87
- "aria-hidden": "true"
88
- }, [createElementVNode("defs", null, [createElementVNode("marker", {
89
- id: rowArrowMarkerId,
90
- markerWidth: "8",
91
- markerHeight: "8",
92
- refX: "6",
93
- refY: "4",
94
- orient: "auto",
95
- markerUnits: "strokeWidth"
96
- }, [..._cache[0] || (_cache[0] = [createElementVNode("path", {
97
- d: "M0,0 L8,4 L0,8 Z",
98
- fill: "var(--u-color-primary, #2563eb)"
99
- }, null, -1)])]), createElementVNode("marker", {
100
- id: colArrowMarkerId,
101
- markerWidth: "8",
102
- markerHeight: "8",
103
- refX: "6",
104
- refY: "4",
105
- orient: "auto",
106
- markerUnits: "strokeWidth"
107
- }, [..._cache[1] || (_cache[1] = [createElementVNode("path", {
108
- d: "M0,0 L8,4 L0,8 Z",
109
- fill: "var(--u-color-warning, #d97706)"
110
- }, null, -1)])])]), (openBlock(true), createElementBlock(Fragment, null, renderList(arcPaths.value, (item, index) => {
111
- return openBlock(), createElementBlock("path", {
112
- key: index,
113
- class: normalizeClass([unref(cls).e("arc"), unref(cls).em("arc", item.direction)]),
114
- d: item.path,
115
- "marker-end": `url(#${item.direction === "row" ? rowArrowMarkerId : colArrowMarkerId})`
116
- }, null, 10, _hoisted_2);
117
- }), 128))], 10, _hoisted_1)) : createCommentVNode("v-if", true);
118
- };
119
- }
120
- });
121
- //#endregion
122
- export { _sfc_main as default };
@@ -1,64 +0,0 @@
1
- //#region src/components/report/designer/topology.ts
2
- function linkKey(from, to, direction) {
3
- return `${direction}:${from.row},${from.col}->${to.row},${to.col}`;
4
- }
5
- function sameAddress(a, b) {
6
- return a.row === b.row && a.col === b.col;
7
- }
8
- function pushLink(links, seen, from, to, direction) {
9
- const key = linkKey(from, to, direction);
10
- if (seen.has(key)) return;
11
- links.push({
12
- from,
13
- to,
14
- direction
15
- });
16
- seen.add(key);
17
- }
18
- /** 查找将指定格作为行方向父格的绑定格 */
19
- function findCellsWithRowParent(parent, entries) {
20
- const children = [];
21
- for (const { addr, binding } of entries) if (binding.rowParent && sameAddress(binding.rowParent, parent)) children.push(addr);
22
- return children;
23
- }
24
- /** 查找将指定格作为列方向父格的绑定格 */
25
- function findCellsWithColParent(parent, entries) {
26
- const children = [];
27
- for (const { addr, binding } of entries) if (binding.colParent && sameAddress(binding.colParent, parent)) children.push(addr);
28
- return children;
29
- }
30
- /** 收集选中格相关的拓扑连线:沿 rowParent / colParent 链上行、下行到直接子绑定 */
31
- function collectTopologyLinks(cell, binding, entries, getBindingAt) {
32
- const links = [];
33
- const seen = /* @__PURE__ */ new Set();
34
- let rowCursor = cell;
35
- let rowBinding = binding;
36
- while (rowBinding?.rowParent) {
37
- const parent = rowBinding.rowParent;
38
- pushLink(links, seen, rowCursor, parent, "row");
39
- rowCursor = parent;
40
- rowBinding = getBindingAt(parent);
41
- }
42
- let colCursor = cell;
43
- let colBinding = binding;
44
- while (colBinding?.colParent) {
45
- const parent = colBinding.colParent;
46
- pushLink(links, seen, colCursor, parent, "col");
47
- colCursor = parent;
48
- colBinding = getBindingAt(parent);
49
- }
50
- for (const child of findCellsWithRowParent(cell, entries)) pushLink(links, seen, child, cell, "row");
51
- for (const child of findCellsWithColParent(cell, entries)) pushLink(links, seen, child, cell, "col");
52
- return links;
53
- }
54
- /** 子格 → 父格的二次贝塞尔弧线路径 */
55
- function buildTopologyArcPath(from, to) {
56
- const dx = to.x - from.x;
57
- const dy = to.y - from.y;
58
- const lift = Math.min(48, Math.max(16, (Math.hypot(dx, dy) || 1) * .35));
59
- const cx = (from.x + to.x) / 2;
60
- const cy = (from.y + to.y) / 2 - lift * Math.sign(dy || -1);
61
- return `M ${from.x} ${from.y} Q ${cx} ${cy} ${to.x} ${to.y}`;
62
- }
63
- //#endregion
64
- export { buildTopologyArcPath, collectTopologyLinks, findCellsWithColParent, findCellsWithRowParent };
@@ -1,75 +0,0 @@
1
- import { getCellOverlayRect, resolveGridOverlayLayout } from "./cell-coords.js";
2
- import { onBeforeUnmount, watch } from "vue";
3
- //#region src/components/report/designer/use-grid-overlay.ts
4
- /** 网格滚动时重算 overlay 坐标;避免在 props 不稳定时重复绑定监听 */
5
- function useGridOverlaySync(options) {
6
- let offScroll;
7
- let rafId = 0;
8
- function scheduleUpdate() {
9
- cancelAnimationFrame(rafId);
10
- rafId = requestAnimationFrame(options.update);
11
- }
12
- function bindScroll() {
13
- offScroll?.();
14
- offScroll = void 0;
15
- const grid = options.getGrid();
16
- if (!grid) return;
17
- const table = grid.getTable();
18
- const onScroll = () => scheduleUpdate();
19
- const scrollEvent = "scroll";
20
- table.on(scrollEvent, onScroll);
21
- offScroll = () => table.off(scrollEvent, onScroll);
22
- }
23
- watch(options.watchSources, () => {
24
- bindScroll();
25
- scheduleUpdate();
26
- }, {
27
- immediate: true,
28
- flush: "post"
29
- });
30
- onBeforeUnmount(() => {
31
- cancelAnimationFrame(rafId);
32
- offScroll?.();
33
- });
34
- }
35
- function readCellOverlayRect(cell, host, getGrid) {
36
- const grid = getGrid();
37
- if (!grid) return null;
38
- const resolved = resolveGridOverlayLayout(host);
39
- if (!resolved) return null;
40
- return getCellOverlayRect(grid, cell, resolved.layout);
41
- }
42
- function readGridOverlaySize(host) {
43
- const resolved = resolveGridOverlayLayout(host);
44
- if (!resolved) return null;
45
- const { layout } = resolved;
46
- return {
47
- width: layout.viewW + layout.offsetX,
48
- height: layout.viewH + layout.offsetY
49
- };
50
- }
51
- /** 悬浮编辑卡锚点:空间按网格画布(非宿主顶)计算,避免顶行格误判为上方可放 */
52
- function resolveBindingFloatPanelPosition(rect, layout, panelWidth, panelHeight, hostWidth, options) {
53
- const gap = options?.gap ?? 8;
54
- const edgePad = options?.edgePad ?? 10;
55
- const gridTop = layout.offsetY;
56
- const gridBottom = layout.offsetY + layout.viewH;
57
- let left = rect.centerX;
58
- const halfW = panelWidth / 2;
59
- left = Math.max(edgePad + halfW, Math.min(hostWidth - edgePad - halfW, left));
60
- const spaceAbove = rect.top - gridTop;
61
- const spaceBelow = gridBottom - rect.bottom;
62
- const need = panelHeight + gap;
63
- let placement = spaceAbove >= need || spaceAbove >= spaceBelow ? "above" : "below";
64
- if (placement === "above" && rect.top - gap - panelHeight < gridTop + edgePad) {
65
- if (spaceBelow >= need || spaceBelow > spaceAbove) placement = "below";
66
- }
67
- const top = placement === "above" ? rect.top - gap : rect.bottom + gap;
68
- return {
69
- placement,
70
- left: Math.round(left),
71
- top: Math.round(top)
72
- };
73
- }
74
- //#endregion
75
- export { readCellOverlayRect, readGridOverlaySize, resolveBindingFloatPanelPosition, useGridOverlaySync };