@tmagic/editor 1.4.9 → 1.4.11

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 (41) hide show
  1. package/dist/style.css +26 -0
  2. package/dist/tmagic-editor.js +3231 -2800
  3. package/dist/tmagic-editor.umd.cjs +3257 -2821
  4. package/package.json +12 -10
  5. package/src/Editor.vue +2 -1
  6. package/src/components/CodeParams.vue +11 -1
  7. package/src/editorProps.ts +3 -0
  8. package/src/fields/CondOpSelect.vue +87 -0
  9. package/src/fields/DataSourceFieldSelect/FieldSelect.vue +183 -0
  10. package/src/fields/DataSourceFieldSelect/Index.vue +168 -0
  11. package/src/fields/DataSourceFields.vue +6 -0
  12. package/src/fields/DisplayConds.vue +145 -0
  13. package/src/hooks/use-data-source-method.ts +1 -1
  14. package/src/index.ts +8 -2
  15. package/src/layouts/Framework.vue +4 -2
  16. package/src/layouts/page-bar/PageBar.vue +8 -2
  17. package/src/layouts/page-bar/PageBarScrollContainer.vue +40 -4
  18. package/src/layouts/page-bar/PageList.vue +55 -0
  19. package/src/services/ui.ts +1 -0
  20. package/src/theme/data-source-field-select.scss +16 -0
  21. package/src/theme/page-bar.scss +13 -0
  22. package/src/theme/theme.scss +1 -0
  23. package/src/type.ts +35 -4
  24. package/src/utils/data-source/index.ts +9 -3
  25. package/src/utils/props.ts +6 -103
  26. package/types/editorProps.d.ts +3 -1
  27. package/types/fields/CondOpSelect.vue.d.ts +17 -0
  28. package/types/fields/DataSourceFieldSelect/FieldSelect.vue.d.ts +36 -0
  29. package/types/fields/{DataSourceFieldSelect.vue.d.ts → DataSourceFieldSelect/Index.vue.d.ts} +1 -1
  30. package/types/fields/DisplayConds.vue.d.ts +32 -0
  31. package/types/index.d.ts +3 -1
  32. package/types/layouts/Framework.vue.d.ts +3 -1
  33. package/types/layouts/PropsPanel.vue.d.ts +21 -21
  34. package/types/layouts/page-bar/PageBar.vue.d.ts +6 -0
  35. package/types/layouts/page-bar/PageBarScrollContainer.vue.d.ts +3 -0
  36. package/types/layouts/page-bar/PageList.vue.d.ts +25 -0
  37. package/types/services/ui.d.ts +1 -0
  38. package/types/type.d.ts +30 -4
  39. package/types/utils/data-source/index.d.ts +1 -0
  40. package/types/utils/props.d.ts +12 -0
  41. package/src/fields/DataSourceFieldSelect.vue +0 -149
package/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "1.4.9",
2
+ "version": "1.4.11",
3
3
  "name": "@tmagic/editor",
4
4
  "type": "module",
5
5
  "sideEffects": [
@@ -54,14 +54,16 @@
54
54
  "lodash-es": "^4.17.21",
55
55
  "moveable": "^0.53.0",
56
56
  "serialize-javascript": "^6.0.0",
57
- "@tmagic/dep": "1.4.9",
58
- "@tmagic/table": "1.4.9"
57
+ "sortablejs": "^1.15.2",
58
+ "@tmagic/dep": "1.4.11",
59
+ "@tmagic/table": "1.4.11"
59
60
  },
60
61
  "devDependencies": {
61
62
  "@types/events": "^3.0.0",
62
63
  "@types/lodash-es": "^4.17.4",
63
64
  "@types/node": "^18.19.0",
64
65
  "@types/serialize-javascript": "^5.0.1",
66
+ "@types/sortablejs": "^1.15.8",
65
67
  "@vitejs/plugin-vue": "^5.0.4",
66
68
  "@vue/compiler-sfc": "^3.4.27",
67
69
  "@vue/test-utils": "^2.4.6",
@@ -74,14 +76,14 @@
74
76
  },
75
77
  "peerDependencies": {
76
78
  "monaco-editor": "^0.48.0",
77
- "vue": "^3.4.27",
78
79
  "typescript": "*",
79
- "@tmagic/core": "1.4.9",
80
- "@tmagic/form": "1.4.9",
81
- "@tmagic/design": "1.4.9",
82
- "@tmagic/schema": "1.4.9",
83
- "@tmagic/utils": "1.4.9",
84
- "@tmagic/stage": "1.4.9"
80
+ "vue": "^3.4.27",
81
+ "@tmagic/form": "1.4.11",
82
+ "@tmagic/schema": "1.4.11",
83
+ "@tmagic/core": "1.4.11",
84
+ "@tmagic/stage": "1.4.11",
85
+ "@tmagic/design": "1.4.11",
86
+ "@tmagic/utils": "1.4.11"
85
87
  },
86
88
  "peerDependenciesMeta": {
87
89
  "typescript": {
package/src/Editor.vue CHANGED
@@ -1,5 +1,5 @@
1
1
  <template>
2
- <Framework :disabled-page-fragment="disabledPageFragment">
2
+ <Framework :disabled-page-fragment="disabledPageFragment" :page-bar-sort-options="pageBarSortOptions">
3
3
  <template #header>
4
4
  <slot name="header"></slot>
5
5
  </template>
@@ -106,6 +106,7 @@
106
106
  <template #page-bar><slot name="page-bar"></slot></template>
107
107
  <template #page-bar-title="{ page }"><slot name="page-bar-title" :page="page"></slot></template>
108
108
  <template #page-bar-popover="{ page }"><slot name="page-bar-popover" :page="page"></slot></template>
109
+ <template #page-list-popover="{ list }"><slot name="page-list-popover" :list="list"></slot></template>
109
110
  </Framework>
110
111
  </template>
111
112
 
@@ -44,7 +44,17 @@ const getFormConfig = (items: FormConfig = []) => [
44
44
  },
45
45
  ];
46
46
 
47
- const codeParamsConfig = computed(() => getFormConfig(props.paramsConfig));
47
+ const codeParamsConfig = computed(() =>
48
+ getFormConfig(
49
+ props.paramsConfig.map(({ name, text, extra, ...config }) => ({
50
+ type: 'data-source-field-select',
51
+ name,
52
+ text,
53
+ extra,
54
+ fieldConfig: config,
55
+ })),
56
+ ),
57
+ );
48
58
 
49
59
  /**
50
60
  * 参数值修改更新
@@ -17,6 +17,7 @@ import type {
17
17
  MenuBarData,
18
18
  MenuButton,
19
19
  MenuComponent,
20
+ PageBarSortOptions,
20
21
  SideBarData,
21
22
  StageRect,
22
23
  } from './type';
@@ -90,6 +91,8 @@ export interface EditorProps {
90
91
  /** 用于自定义组件树与画布的右键菜单 */
91
92
  customContentMenu?: (menus: (MenuButton | MenuComponent)[], type: string) => (MenuButton | MenuComponent)[];
92
93
  extendFormState?: (state: FormState) => Record<string, any> | Promise<Record<string, any>>;
94
+ /** 页面顺序拖拽配置参数 */
95
+ pageBarSortOptions?: PageBarSortOptions;
93
96
  }
94
97
 
95
98
  export const defaultEditorProps = {
@@ -0,0 +1,87 @@
1
+ <template>
2
+ <TMagicSelect
3
+ v-model="model[name]"
4
+ clearable
5
+ filterable
6
+ :size="size"
7
+ :disabled="disabled"
8
+ @change="fieldChangeHandler"
9
+ >
10
+ <component
11
+ v-for="option in options"
12
+ class="tmagic-design-option"
13
+ :key="option.value"
14
+ :is="optionComponent?.component || 'el-option'"
15
+ v-bind="
16
+ optionComponent?.props({
17
+ label: option.text,
18
+ value: option.value,
19
+ }) || {
20
+ label: option.text,
21
+ value: option.value,
22
+ }
23
+ "
24
+ >
25
+ </component>
26
+ </TMagicSelect>
27
+ </template>
28
+
29
+ <script setup lang="ts">
30
+ import { computed, inject } from 'vue';
31
+
32
+ import { getConfig as getDesignConfig, TMagicSelect } from '@tmagic/design';
33
+ import type { FieldProps } from '@tmagic/form';
34
+
35
+ import type { CondOpSelectConfig, Services } from '@editor/type';
36
+ import { arrayOptions, eqOptions, numberOptions } from '@editor/utils';
37
+
38
+ defineOptions({
39
+ name: 'MFieldsCondOpSelect',
40
+ });
41
+
42
+ const emit = defineEmits(['change']);
43
+ const { dataSourceService } = inject<Services>('services') || {};
44
+
45
+ const props = defineProps<FieldProps<CondOpSelectConfig>>();
46
+
47
+ const optionComponent = getDesignConfig('components')?.option;
48
+
49
+ const options = computed(() => {
50
+ const [id, ...fieldNames] = [...(props.config.parentFields || []), ...props.model.field];
51
+
52
+ const ds = dataSourceService?.getDataSourceById(id);
53
+
54
+ let fields = ds?.fields || [];
55
+ let type = '';
56
+ (fieldNames || []).forEach((fieldName: string) => {
57
+ const field = fields.find((f) => f.name === fieldName);
58
+ fields = field?.fields || [];
59
+ type = field?.type || '';
60
+ });
61
+
62
+ if (type === 'array') {
63
+ return arrayOptions;
64
+ }
65
+
66
+ if (type === 'boolean') {
67
+ return [
68
+ { text: '是', value: 'is' },
69
+ { text: '不是', value: 'not' },
70
+ ];
71
+ }
72
+
73
+ if (type === 'number') {
74
+ return [...eqOptions, ...numberOptions];
75
+ }
76
+
77
+ if (type === 'string') {
78
+ return [...arrayOptions, ...eqOptions];
79
+ }
80
+
81
+ return [...arrayOptions, ...eqOptions, ...numberOptions];
82
+ });
83
+
84
+ const fieldChangeHandler = (v: string[]) => {
85
+ emit('change', v);
86
+ };
87
+ </script>
@@ -0,0 +1,183 @@
1
+ <template>
2
+ <div class="m-editor-data-source-field-select">
3
+ <template v-if="checkStrictly">
4
+ <TMagicSelect
5
+ :model-value="selectDataSourceId"
6
+ clearable
7
+ filterable
8
+ :size="size"
9
+ :disabled="disabled"
10
+ @change="dsChangeHandler"
11
+ >
12
+ <component
13
+ v-for="option in dataSourcesOptions"
14
+ class="tmagic-design-option"
15
+ :key="option.value"
16
+ :is="optionComponent?.component || 'el-option'"
17
+ v-bind="
18
+ optionComponent?.props({
19
+ label: option.text,
20
+ value: option.value,
21
+ disabled: option.disabled,
22
+ }) || {
23
+ label: option.text,
24
+ value: option.value,
25
+ disabled: option.disabled,
26
+ }
27
+ "
28
+ >
29
+ </component>
30
+ </TMagicSelect>
31
+
32
+ <TMagicCascader
33
+ :model-value="selectFieldsId"
34
+ clearable
35
+ filterable
36
+ :size="size"
37
+ :disabled="disabled"
38
+ :options="fieldsOptions"
39
+ :props="{
40
+ checkStrictly,
41
+ }"
42
+ @change="fieldChangeHandler"
43
+ ></TMagicCascader>
44
+ </template>
45
+
46
+ <TMagicCascader
47
+ v-else
48
+ clearable
49
+ filterable
50
+ :model-value="modelValue"
51
+ :disabled="disabled"
52
+ :size="size"
53
+ :options="cascaderOptions"
54
+ :props="{
55
+ checkStrictly,
56
+ }"
57
+ @change="onChangeHandler"
58
+ ></TMagicCascader>
59
+
60
+ <TMagicButton
61
+ v-if="selectDataSourceId && hasDataSourceSidePanel"
62
+ class="m-fields-select-action-button"
63
+ :size="size"
64
+ @click="editHandler(selectDataSourceId)"
65
+ ><MIcon :icon="!notEditable ? Edit : View"></MIcon
66
+ ></TMagicButton>
67
+ </div>
68
+ </template>
69
+
70
+ <script lang="ts" setup>
71
+ import { computed, inject, ref, watch } from 'vue';
72
+ import { Edit, View } from '@element-plus/icons-vue';
73
+
74
+ import { getConfig as getDesignConfig, TMagicButton, TMagicCascader, TMagicSelect } from '@tmagic/design';
75
+ import { type FilterFunction, filterFunction, type FormState, type SelectOption } from '@tmagic/form';
76
+ import { DataSourceFieldType } from '@tmagic/schema';
77
+ import { DATA_SOURCE_FIELDS_SELECT_VALUE_PREFIX } from '@tmagic/utils';
78
+
79
+ import MIcon from '@editor/components/Icon.vue';
80
+ import { type EventBus, type Services, SideItemKey } from '@editor/type';
81
+ import { getCascaderOptionsFromFields, removeDataSourceFieldPrefix } from '@editor/utils';
82
+
83
+ const props = defineProps<{
84
+ /**
85
+ * 是否要编译成数据源的data。
86
+ * key: 不编译,就是要数据源id和field name;
87
+ * value: 要编译(数据源data[`${filed}`])
88
+ * */
89
+ value?: 'key' | 'value';
90
+ disabled?: boolean;
91
+ checkStrictly?: boolean;
92
+ size?: 'large' | 'default' | 'small';
93
+ dataSourceFieldType?: DataSourceFieldType[];
94
+ /** 是否可以编辑数据源,disable表示的是是否可以选择数据源 */
95
+ notEditable?: boolean | FilterFunction;
96
+ }>();
97
+
98
+ const emit = defineEmits<{
99
+ change: [v: string[]];
100
+ }>();
101
+
102
+ const modelValue = defineModel<string[] | any>('modelValue', { default: [] });
103
+
104
+ const optionComponent = getDesignConfig('components')?.option;
105
+
106
+ const services = inject<Services>('services');
107
+ const mForm = inject<FormState | undefined>('mForm');
108
+ const eventBus = inject<EventBus>('eventBus');
109
+
110
+ const dataSources = computed(() => services?.dataSourceService.get('dataSources') || []);
111
+
112
+ const valueIsKey = computed(() => props.value === 'key');
113
+ const notEditable = computed(() => filterFunction(mForm, props.notEditable, props));
114
+
115
+ const dataSourcesOptions = computed<SelectOption[]>(() =>
116
+ dataSources.value.map((ds) => ({
117
+ text: ds.title || ds.id,
118
+ value: valueIsKey.value ? ds.id : `${DATA_SOURCE_FIELDS_SELECT_VALUE_PREFIX}${ds.id}`,
119
+ })),
120
+ );
121
+
122
+ const selectDataSourceId = ref('');
123
+
124
+ const selectFieldsId = ref<string[]>([]);
125
+
126
+ watch(
127
+ modelValue,
128
+ (value) => {
129
+ if (Array.isArray(value)) {
130
+ const [dsId, ...fields] = value;
131
+ selectDataSourceId.value = dsId;
132
+ selectFieldsId.value = fields;
133
+ } else {
134
+ selectDataSourceId.value = '';
135
+ selectFieldsId.value = [];
136
+ }
137
+ },
138
+ {
139
+ immediate: true,
140
+ },
141
+ );
142
+
143
+ const fieldsOptions = computed(() => {
144
+ const ds = dataSources.value.find((ds) => ds.id === removeDataSourceFieldPrefix(selectDataSourceId.value));
145
+
146
+ if (!ds) return [];
147
+
148
+ return getCascaderOptionsFromFields(ds.fields, props.dataSourceFieldType);
149
+ });
150
+
151
+ const cascaderOptions = computed(() => {
152
+ const options =
153
+ dataSources.value?.map((ds) => ({
154
+ label: ds.title || ds.id,
155
+ value: valueIsKey.value ? ds.id : `${DATA_SOURCE_FIELDS_SELECT_VALUE_PREFIX}${ds.id}`,
156
+ children: getCascaderOptionsFromFields(ds.fields, props.dataSourceFieldType),
157
+ })) || [];
158
+ return options.filter((option) => option.children.length);
159
+ });
160
+
161
+ const dsChangeHandler = (v: string) => {
162
+ modelValue.value = [v];
163
+ emit('change', modelValue.value);
164
+ };
165
+
166
+ const fieldChangeHandler = (v: string[] = []) => {
167
+ modelValue.value = [selectDataSourceId.value, ...v];
168
+ emit('change', modelValue.value);
169
+ };
170
+
171
+ const onChangeHandler = (v: string[] = []) => {
172
+ modelValue.value = v;
173
+ emit('change', v);
174
+ };
175
+
176
+ const hasDataSourceSidePanel = computed(() =>
177
+ (services?.uiService.get('sideBarItems') || []).find((item) => item.$key === SideItemKey.DATA_SOURCE),
178
+ );
179
+
180
+ const editHandler = (id: string) => {
181
+ eventBus?.emit('edit-data-source', removeDataSourceFieldPrefix(id));
182
+ };
183
+ </script>
@@ -0,0 +1,168 @@
1
+ <template>
2
+ <div class="m-fields-data-source-field-select">
3
+ <FieldSelect
4
+ v-if="showDataSourceFieldSelect || !config.fieldConfig"
5
+ :model-value="model[name]"
6
+ :disabled="disabled"
7
+ :size="size"
8
+ :value="config.value"
9
+ :checkStrictly="checkStrictly"
10
+ :dataSourceFieldType="config.dataSourceFieldType"
11
+ @change="onChangeHandler"
12
+ ></FieldSelect>
13
+
14
+ <component
15
+ v-else
16
+ :is="tagName"
17
+ :config="config.fieldConfig"
18
+ :model="model"
19
+ :name="name"
20
+ :disabled="disabled"
21
+ :size="size"
22
+ :last-values="lastValues"
23
+ :init-values="initValues"
24
+ :values="values"
25
+ :prop="`${prop}${prop ? '.' : ''}${name}`"
26
+ @change="onChangeHandler"
27
+ ></component>
28
+
29
+ <TMagicButton
30
+ v-if="config.fieldConfig"
31
+ style="margin-left: 5px"
32
+ :type="showDataSourceFieldSelect ? 'primary' : 'default'"
33
+ :size="size"
34
+ @click="showDataSourceFieldSelect = !showDataSourceFieldSelect"
35
+ ><MIcon :icon="Coin"></MIcon
36
+ ></TMagicButton>
37
+ </div>
38
+ </template>
39
+
40
+ <script setup lang="ts">
41
+ import { computed, inject, ref, resolveComponent, watch } from 'vue';
42
+ import { Coin } from '@element-plus/icons-vue';
43
+
44
+ import { TMagicButton, tMagicMessage } from '@tmagic/design';
45
+ import type { FieldProps, FormState } from '@tmagic/form';
46
+ import { DataSchema } from '@tmagic/schema';
47
+ import { DATA_SOURCE_FIELDS_SELECT_VALUE_PREFIX } from '@tmagic/utils';
48
+
49
+ import MIcon from '@editor/components/Icon.vue';
50
+ import type { DataSourceFieldSelectConfig, Services } from '@editor/type';
51
+ import { removeDataSourceFieldPrefix } from '@editor/utils';
52
+
53
+ import FieldSelect from './FieldSelect.vue';
54
+
55
+ defineOptions({
56
+ name: 'MFieldsDataSourceFieldSelect',
57
+ });
58
+
59
+ const emit = defineEmits(['change']);
60
+
61
+ const props = withDefaults(defineProps<FieldProps<DataSourceFieldSelectConfig>>(), {
62
+ disabled: false,
63
+ });
64
+
65
+ const showDataSourceFieldSelect = ref(false);
66
+
67
+ watch(
68
+ () => props.model[props.name],
69
+ (value) => {
70
+ if (
71
+ Array.isArray(value) &&
72
+ typeof value[0] === 'string' &&
73
+ value[0].startsWith(DATA_SOURCE_FIELDS_SELECT_VALUE_PREFIX)
74
+ ) {
75
+ showDataSourceFieldSelect.value = true;
76
+ } else {
77
+ showDataSourceFieldSelect.value = false;
78
+ }
79
+ },
80
+ {
81
+ immediate: true,
82
+ },
83
+ );
84
+
85
+ const services = inject<Services>('services');
86
+ const mForm = inject<FormState | undefined>('mForm');
87
+
88
+ const dataSources = computed(() => services?.dataSourceService.get('dataSources') || []);
89
+
90
+ const type = computed((): string => {
91
+ let type = props.config.fieldConfig?.type;
92
+ if (typeof type === 'function') {
93
+ type = type(mForm, {
94
+ model: props.model,
95
+ });
96
+ }
97
+ if (type === 'form') return '';
98
+ if (type === 'container') return '';
99
+ return type?.replace(/([A-Z])/g, '-$1').toLowerCase() || (props.config.items ? '' : 'text');
100
+ });
101
+
102
+ const tagName = computed(() => {
103
+ const component = resolveComponent(`m-${props.config.items ? 'form' : 'fields'}-${type.value}`);
104
+ if (typeof component !== 'string') return component;
105
+ return 'm-fields-text';
106
+ });
107
+
108
+ const checkStrictly = computed(() => {
109
+ let value: boolean | undefined;
110
+
111
+ if (typeof props.config.checkStrictly !== 'function') {
112
+ value = props.config.checkStrictly;
113
+ } else {
114
+ const dsId = removeDataSourceFieldPrefix(props.model[0]);
115
+ const dataSource = dataSources.value.find((ds) => ds.id === dsId);
116
+
117
+ value = props.config.checkStrictly(mForm, {
118
+ values: mForm?.initValues || {},
119
+ model: props.model,
120
+ parent: mForm?.parentValues || {},
121
+ formValue: mForm?.values || props.model,
122
+ prop: props.prop,
123
+ config: props.config,
124
+ dataSource,
125
+ });
126
+ }
127
+
128
+ return value ?? props.config.value === 'key';
129
+ });
130
+
131
+ const onChangeHandler = (value: string[]) => {
132
+ if (!Array.isArray(value)) {
133
+ emit('change', value);
134
+ return;
135
+ }
136
+
137
+ const [dsId, ...keys] = value;
138
+ const dataSource = dataSources.value.find((ds) => ds.id === removeDataSourceFieldPrefix(dsId));
139
+
140
+ if (!dataSource) {
141
+ emit('change', value);
142
+ return;
143
+ }
144
+
145
+ let fields = dataSource.fields || [];
146
+ let field: DataSchema | undefined;
147
+ (keys || []).forEach((key) => {
148
+ field = fields.find((f) => f.name === key);
149
+ fields = field?.fields || [];
150
+ });
151
+
152
+ const dataSourceFieldType = props.config.dataSourceFieldType || ['any'];
153
+ if (!dataSourceFieldType.length) {
154
+ dataSourceFieldType.push('any');
155
+ }
156
+
157
+ if (
158
+ !keys.length ||
159
+ (field?.type &&
160
+ (field.type === 'any' || dataSourceFieldType.includes('any') || dataSourceFieldType.includes(field.type)))
161
+ ) {
162
+ emit('change', value);
163
+ } else {
164
+ tMagicMessage.error(`请选择类型为${dataSourceFieldType.join('或')}的字段`);
165
+ emit('change', [dsId]);
166
+ }
167
+ };
168
+ </script>
@@ -172,6 +172,12 @@ const dataSourceFieldsConfig: FormConfig = [
172
172
  { text: 'null', value: 'null' },
173
173
  { text: 'any', value: 'any' },
174
174
  ],
175
+ onChange: (formState, v: string, { model }) => {
176
+ if (!['any', 'array', 'object'].includes(v)) {
177
+ model.fields = [];
178
+ }
179
+ return v;
180
+ },
175
181
  },
176
182
  {
177
183
  name: 'name',
@@ -0,0 +1,145 @@
1
+ <template>
2
+ <MGroupList
3
+ style="width: 100%"
4
+ :config="config"
5
+ :name="name"
6
+ :disabled="disabled"
7
+ :model="model"
8
+ :last-values="lastValues"
9
+ :prop="prop"
10
+ :size="size"
11
+ ></MGroupList>
12
+ </template>
13
+
14
+ <script lang="ts" setup>
15
+ import { computed, inject } from 'vue';
16
+
17
+ import {
18
+ type FieldProps,
19
+ type FilterFunction,
20
+ filterFunction,
21
+ type FormState,
22
+ type GroupListConfig,
23
+ MGroupList,
24
+ } from '@tmagic/form';
25
+
26
+ import type { Services } from '@editor/type';
27
+ import { getCascaderOptionsFromFields } from '@editor/utils';
28
+
29
+ defineOptions({
30
+ name: 'm-fields-display-conds',
31
+ });
32
+
33
+ const props = withDefaults(
34
+ defineProps<
35
+ FieldProps<{
36
+ titlePrefix?: string;
37
+ parentFields?: string[] | FilterFunction<string[]>;
38
+ }>
39
+ >(),
40
+ {
41
+ disabled: false,
42
+ },
43
+ );
44
+
45
+ const { dataSourceService } = inject<Services>('services') || {};
46
+ const mForm = inject<FormState | undefined>('mForm');
47
+
48
+ const parentFields = computed(() => filterFunction<string[]>(mForm, props.config.parentFields, props) || []);
49
+
50
+ const config = computed<GroupListConfig>(() => ({
51
+ type: 'groupList',
52
+ name: props.name,
53
+ titlePrefix: props.config.titlePrefix,
54
+ expandAll: true,
55
+ items: [
56
+ {
57
+ type: 'table',
58
+ name: 'cond',
59
+ operateColWidth: 50,
60
+ items: [
61
+ parentFields.value.length
62
+ ? {
63
+ type: 'cascader',
64
+ options: () => {
65
+ const [dsId, ...keys] = parentFields.value;
66
+ const ds = dataSourceService?.getDataSourceById(dsId);
67
+ if (!ds) {
68
+ return [];
69
+ }
70
+
71
+ let fields = ds.fields || [];
72
+ keys.forEach((key) => {
73
+ const field = fields.find((f) => f.name === key);
74
+ fields = field?.fields || [];
75
+ });
76
+
77
+ return getCascaderOptionsFromFields(fields, ['string', 'number', 'boolean', 'any']);
78
+ },
79
+ name: 'field',
80
+ value: 'key',
81
+ label: '字段',
82
+ checkStrictly: false,
83
+ }
84
+ : {
85
+ type: 'data-source-field-select',
86
+ name: 'field',
87
+ value: 'key',
88
+ label: '字段',
89
+ checkStrictly: false,
90
+ dataSourceFieldType: ['string', 'number', 'boolean', 'any'],
91
+ },
92
+ {
93
+ type: 'cond-op-select',
94
+ parentFields: parentFields.value,
95
+ label: '条件',
96
+ width: 100,
97
+ name: 'op',
98
+ },
99
+ {
100
+ label: '值',
101
+ width: 100,
102
+ items: [
103
+ {
104
+ name: 'value',
105
+ type: (mForm, { model }) => {
106
+ const [id, ...fieldNames] = [...parentFields.value, ...model.field];
107
+
108
+ const ds = dataSourceService?.getDataSourceById(id);
109
+
110
+ let fields = ds?.fields || [];
111
+ let type = '';
112
+ (fieldNames || []).forEach((fieldName: string) => {
113
+ const field = fields.find((f) => f.name === fieldName);
114
+ fields = field?.fields || [];
115
+ type = field?.type || '';
116
+ });
117
+
118
+ if (type === 'number') {
119
+ return 'number';
120
+ }
121
+
122
+ if (type === 'boolean') {
123
+ return 'select';
124
+ }
125
+
126
+ return 'text';
127
+ },
128
+ options: [
129
+ { text: 'true', value: true },
130
+ { text: 'false', value: false },
131
+ ],
132
+ display: (vm, { model }) => !['between', 'not_between'].includes(model.op),
133
+ },
134
+ {
135
+ name: 'range',
136
+ type: 'number-range',
137
+ display: (vm, { model }) => ['between', 'not_between'].includes(model.op),
138
+ },
139
+ ],
140
+ },
141
+ ],
142
+ },
143
+ ],
144
+ }));
145
+ </script>