feat(dats-source,editor,form,schema,ui): 迭代器容器支持配置子项显示条件

This commit is contained in:
roymondchen 2024-06-28 17:44:04 +08:00
parent 0c5485b1d0
commit a164e2be62
18 changed files with 400 additions and 159 deletions

View File

@ -20,13 +20,13 @@ import EventEmitter from 'events';
import { cloneDeep } from 'lodash-es'; import { cloneDeep } from 'lodash-es';
import type { AppCore, DataSourceSchema, Id, MNode } from '@tmagic/schema'; import type { AppCore, DataSourceSchema, DisplayCond, Id, MNode } from '@tmagic/schema';
import { compiledNode } from '@tmagic/utils'; import { compiledNode } from '@tmagic/utils';
import { SimpleObservedData } from './observed-data/SimpleObservedData'; import { SimpleObservedData } from './observed-data/SimpleObservedData';
import { DataSource, HttpDataSource } from './data-sources'; import { DataSource, HttpDataSource } from './data-sources';
import type { ChangeEvent, DataSourceManagerData, DataSourceManagerOptions, ObservedDataClass } from './types'; import type { ChangeEvent, DataSourceManagerData, DataSourceManagerOptions, ObservedDataClass } from './types';
import { compiledNodeField, compliedConditions, compliedIteratorItems } from './utils'; import { compiledNodeField, compliedConditions, compliedIteratorItemConditions, compliedIteratorItems } from './utils';
class DataSourceManager extends EventEmitter { class DataSourceManager extends EventEmitter {
private static dataSourceClassMap = new Map<string, typeof DataSource>(); private static dataSourceClassMap = new Map<string, typeof DataSource>();
@ -214,6 +214,10 @@ class DataSourceManager extends EventEmitter {
return compliedConditions(node, this.data); return compliedConditions(node, this.data);
} }
public compliedIteratorItemConds(itemData: any, displayConds: DisplayCond[] = []) {
return compliedIteratorItemConditions(displayConds, itemData);
}
public compliedIteratorItems(itemData: any, items: MNode[], dataSourceField: string[] = []) { public compliedIteratorItems(itemData: any, items: MNode[], dataSourceField: string[] = []) {
const [dsId, ...keys] = dataSourceField; const [dsId, ...keys] = dataSourceField;
const ds = this.get(dsId); const ds = this.get(dsId);

View File

@ -1,7 +1,7 @@
import { cloneDeep, template } from 'lodash-es'; import { cloneDeep, template } from 'lodash-es';
import { isDataSourceTemplate, isUseDataSourceField, Target, Watcher } from '@tmagic/dep'; import { isDataSourceTemplate, isUseDataSourceField, Target, Watcher } from '@tmagic/dep';
import type { MApp, MNode, MPage, MPageFragment } from '@tmagic/schema'; import type { DisplayCond, DisplayCondItem, MApp, MNode, MPage, MPageFragment } from '@tmagic/schema';
import { import {
compiledCond, compiledCond,
compiledNode, compiledNode,
@ -15,29 +15,69 @@ import {
import type { AsyncDataSourceResolveResult, DataSourceManagerData } from './types'; import type { AsyncDataSourceResolveResult, DataSourceManagerData } from './types';
/**
*
* @param cond
* @param data
* @returns boolean
*/
export const compiledCondition = (cond: DisplayCondItem[], data: DataSourceManagerData) => {
let result = true;
for (const { op, value, range, field } of cond) {
const [sourceId, ...fields] = field;
const dsData = data[sourceId];
if (!dsData || !fields.length) {
break;
}
const fieldValue = getValueByKeyPath(fields.join('.'), dsData);
if (!compiledCond(op, fieldValue, value, range)) {
result = false;
break;
}
}
return result;
};
/** /**
* *
* @param node dsl节点 * @param node dsl节点
* @param data * @param data
* @returns boolean * @returns boolean
*/ */
export const compliedConditions = (node: MNode, data: DataSourceManagerData) => { export const compliedConditions = (node: { displayConds?: DisplayCond[] }, data: DataSourceManagerData) => {
if (!node.displayConds || !Array.isArray(node.displayConds) || !node.displayConds.length) return true; if (!node.displayConds || !Array.isArray(node.displayConds) || !node.displayConds.length) return true;
for (const { cond } of node.displayConds) { for (const { cond } of node.displayConds) {
if (!cond) continue; if (!cond) continue;
if (compiledCondition(cond, data)) {
return true;
}
}
return false;
};
/**
*
* @param displayConds
* @param data
* @returns boolean
*/
export const compliedIteratorItemConditions = (displayConds: DisplayCond[] = [], data: DataSourceManagerData) => {
if (!displayConds || !Array.isArray(displayConds) || !displayConds.length) return true;
for (const { cond } of displayConds) {
if (!cond) continue;
let result = true; let result = true;
for (const { op, value, range, field } of cond) { for (const { op, value, range, field } of cond) {
const [sourceId, ...fields] = field; const fieldValue = getValueByKeyPath(field.join('.'), data);
const dsData = data[sourceId];
if (!dsData || !fields.length) {
break;
}
const fieldValue = getValueByKeyPath(fields.join('.'), data[sourceId]);
if (!compiledCond(op, fieldValue, value, range)) { if (!compiledCond(op, fieldValue, value, range)) {
result = false; result = false;
@ -45,9 +85,7 @@ export const compliedConditions = (node: MNode, data: DataSourceManagerData) =>
} }
} }
if (result) { return result;
return true;
}
} }
return false; return false;

View File

@ -0,0 +1,87 @@
<template>
<TMagicSelect
v-model="model[name]"
clearable
filterable
:size="size"
:disabled="disabled"
@change="fieldChangeHandler"
>
<component
v-for="option in options"
class="tmagic-design-option"
:key="option.value"
:is="optionComponent?.component || 'el-option'"
v-bind="
optionComponent?.props({
label: option.text,
value: option.value,
}) || {
label: option.text,
value: option.value,
}
"
>
</component>
</TMagicSelect>
</template>
<script setup lang="ts">
import { computed, inject } from 'vue';
import { getConfig as getDesignConfig, TMagicSelect } from '@tmagic/design';
import type { FieldProps } from '@tmagic/form';
import type { CondOpSelectConfig, Services } from '@editor/type';
import { arrayOptions, eqOptions, numberOptions } from '@editor/utils';
defineOptions({
name: 'MFieldsCondOpSelect',
});
const emit = defineEmits(['change']);
const { dataSourceService } = inject<Services>('services') || {};
const props = defineProps<FieldProps<CondOpSelectConfig>>();
const optionComponent = getDesignConfig('components')?.option;
const options = computed(() => {
const [id, ...fieldNames] = [...(props.config.parentFields || []), ...props.model.field];
const ds = dataSourceService?.getDataSourceById(id);
let fields = ds?.fields || [];
let type = '';
(fieldNames || []).forEach((fieldName: string) => {
const field = fields.find((f) => f.name === fieldName);
fields = field?.fields || [];
type = field?.type || '';
});
if (type === 'array') {
return arrayOptions;
}
if (type === 'boolean') {
return [
{ text: '是', value: 'is' },
{ text: '不是', value: 'not' },
];
}
if (type === 'number') {
return [...eqOptions, ...numberOptions];
}
if (type === 'string') {
return [...arrayOptions, ...eqOptions];
}
return [...arrayOptions, ...eqOptions, ...numberOptions];
});
const fieldChangeHandler = (v: string[]) => {
emit('change', v);
};
</script>

View File

@ -137,7 +137,7 @@ const dsChangeHandler = (v: string) => {
emit('change', modelValue.value); emit('change', modelValue.value);
}; };
const fieldChangeHandler = (v: string[]) => { const fieldChangeHandler = (v: string[] = []) => {
modelValue.value = [selectDataSourceId.value, ...v]; modelValue.value = [selectDataSourceId.value, ...v];
emit('change', modelValue.value); emit('change', modelValue.value);
}; };

View File

@ -129,10 +129,20 @@ const checkStrictly = computed(() => {
}); });
const onChangeHandler = (value: string[]) => { const onChangeHandler = (value: string[]) => {
if (!Array.isArray(value)) {
emit('change', value);
return;
}
const [dsId, ...keys] = value; const [dsId, ...keys] = value;
const dataSource = dataSources.value.find((ds) => ds.id === removeDataSourceFieldPrefix(dsId)); const dataSource = dataSources.value.find((ds) => ds.id === removeDataSourceFieldPrefix(dsId));
let fields = dataSource?.fields || []; if (!dataSource) {
emit('change', value);
return;
}
let fields = dataSource.fields || [];
let field: DataSchema | undefined; let field: DataSchema | undefined;
(keys || []).forEach((key) => { (keys || []).forEach((key) => {
field = fields.find((f) => f.name === key); field = fields.find((f) => f.name === key);
@ -145,7 +155,6 @@ const onChangeHandler = (value: string[]) => {
} }
if ( if (
!dsId ||
!keys.length || !keys.length ||
(field?.type && (field?.type &&
(field.type === 'any' || dataSourceFieldType.includes('any') || dataSourceFieldType.includes(field.type))) (field.type === 'any' || dataSourceFieldType.includes('any') || dataSourceFieldType.includes(field.type)))

View File

@ -172,6 +172,12 @@ const dataSourceFieldsConfig: FormConfig = [
{ text: 'null', value: 'null' }, { text: 'null', value: 'null' },
{ text: 'any', value: 'any' }, { text: 'any', value: 'any' },
], ],
onChange: (formState, v: string, { model }) => {
if (!['any', 'array', 'object'].includes(v)) {
model.fields = [];
}
return v;
},
}, },
{ {
name: 'name', name: 'name',

View File

@ -0,0 +1,145 @@
<template>
<MGroupList
style="width: 100%"
:config="config"
:name="name"
:disabled="disabled"
:model="model"
:last-values="lastValues"
:prop="prop"
:size="size"
></MGroupList>
</template>
<script lang="ts" setup>
import { computed, inject } from 'vue';
import {
type FieldProps,
type FilterFunction,
filterFunction,
type FormState,
type GroupListConfig,
MGroupList,
} from '@tmagic/form';
import type { Services } from '@editor/type';
import { getCascaderOptionsFromFields } from '@editor/utils';
defineOptions({
name: 'm-fields-display-conds',
});
const props = withDefaults(
defineProps<
FieldProps<{
titlePrefix?: string;
parentFields?: string[] | FilterFunction<string[]>;
}>
>(),
{
disabled: false,
},
);
const { dataSourceService } = inject<Services>('services') || {};
const mForm = inject<FormState | undefined>('mForm');
const parentFields = computed(() => filterFunction<string[]>(mForm, props.config.parentFields, props) || []);
const config = computed<GroupListConfig>(() => ({
type: 'groupList',
name: props.name,
titlePrefix: props.config.titlePrefix,
expandAll: true,
items: [
{
type: 'table',
name: 'cond',
operateColWidth: 50,
items: [
parentFields.value.length
? {
type: 'cascader',
options: () => {
const [dsId, ...keys] = parentFields.value;
const ds = dataSourceService?.getDataSourceById(dsId);
if (!ds) {
return [];
}
let fields = ds.fields || [];
keys.forEach((key) => {
const field = fields.find((f) => f.name === key);
fields = field?.fields || [];
});
return getCascaderOptionsFromFields(fields, ['string', 'number', 'boolean', 'any']);
},
name: 'field',
value: 'key',
label: '字段',
checkStrictly: false,
}
: {
type: 'data-source-field-select',
name: 'field',
value: 'key',
label: '字段',
checkStrictly: false,
dataSourceFieldType: ['string', 'number', 'boolean', 'any'],
},
{
type: 'cond-op-select',
parentFields: parentFields.value,
label: '条件',
width: 100,
name: 'op',
},
{
label: '值',
width: 100,
items: [
{
name: 'value',
type: (mForm, { model }) => {
const [id, ...fieldNames] = model.field;
const ds = dataSourceService?.getDataSourceById(id);
let fields = ds?.fields || [];
let type = '';
(fieldNames || []).forEach((fieldName: string) => {
const field = fields.find((f) => f.name === fieldName);
fields = field?.fields || [];
type = field?.type || '';
});
if (type === 'number') {
return 'number';
}
if (type === 'boolean') {
return 'select';
}
return 'text';
},
options: [
{ text: 'true', value: true },
{ text: 'false', value: false },
],
display: (vm, { model }) => !['between', 'not_between'].includes(model.op),
},
{
name: 'range',
type: 'number-range',
display: (vm, { model }) => ['between', 'not_between'].includes(model.op),
},
],
},
],
},
],
}));
</script>

View File

@ -21,6 +21,7 @@ import Code from './fields/Code.vue';
import CodeLink from './fields/CodeLink.vue'; import CodeLink from './fields/CodeLink.vue';
import CodeSelect from './fields/CodeSelect.vue'; import CodeSelect from './fields/CodeSelect.vue';
import CodeSelectCol from './fields/CodeSelectCol.vue'; import CodeSelectCol from './fields/CodeSelectCol.vue';
import CondOpSelect from './fields/CondOpSelect.vue';
import DataSourceFields from './fields/DataSourceFields.vue'; import DataSourceFields from './fields/DataSourceFields.vue';
import DataSourceFieldSelect from './fields/DataSourceFieldSelect/Index.vue'; import DataSourceFieldSelect from './fields/DataSourceFieldSelect/Index.vue';
import DataSourceInput from './fields/DataSourceInput.vue'; import DataSourceInput from './fields/DataSourceInput.vue';
@ -28,6 +29,7 @@ import DataSourceMethods from './fields/DataSourceMethods.vue';
import DataSourceMethodSelect from './fields/DataSourceMethodSelect.vue'; import DataSourceMethodSelect from './fields/DataSourceMethodSelect.vue';
import DataSourceMocks from './fields/DataSourceMocks.vue'; import DataSourceMocks from './fields/DataSourceMocks.vue';
import DataSourceSelect from './fields/DataSourceSelect.vue'; import DataSourceSelect from './fields/DataSourceSelect.vue';
import DisplayConds from './fields/DisplayConds.vue';
import EventSelect from './fields/EventSelect.vue'; import EventSelect from './fields/EventSelect.vue';
import KeyValue from './fields/KeyValue.vue'; import KeyValue from './fields/KeyValue.vue';
import PageFragmentSelect from './fields/PageFragmentSelect.vue'; import PageFragmentSelect from './fields/PageFragmentSelect.vue';
@ -84,6 +86,8 @@ export { default as Resizer } from './components/Resizer.vue';
export { default as CodeBlockEditor } from './components/CodeBlockEditor.vue'; export { default as CodeBlockEditor } from './components/CodeBlockEditor.vue';
export { default as FloatingBox } from './components/FloatingBox.vue'; export { default as FloatingBox } from './components/FloatingBox.vue';
export { default as PageFragmentSelect } from './fields/PageFragmentSelect.vue'; export { default as PageFragmentSelect } from './fields/PageFragmentSelect.vue';
export { default as DisplayConds } from './fields/DisplayConds.vue';
export { default as CondOpSelect } from './fields/CondOpSelect.vue';
const defaultInstallOpt: InstallOptions = { const defaultInstallOpt: InstallOptions = {
// eslint-disable-next-line no-eval // eslint-disable-next-line no-eval
@ -114,5 +118,7 @@ export default {
app.component('m-fields-data-source-method-select', DataSourceMethodSelect); app.component('m-fields-data-source-method-select', DataSourceMethodSelect);
app.component('m-fields-data-source-field-select', DataSourceFieldSelect); app.component('m-fields-data-source-field-select', DataSourceFieldSelect);
app.component('m-fields-page-fragment-select', PageFragmentSelect); app.component('m-fields-page-fragment-select', PageFragmentSelect);
app.component('m-fields-display-conds', DisplayConds);
app.component('m-fields-cond-op-select', CondOpSelect);
}, },
}; };

View File

@ -677,6 +677,11 @@ export interface DataSourceFieldSelectConfig extends FormItem {
notEditable?: boolean | FilterFunction; notEditable?: boolean | FilterFunction;
} }
export interface CondOpSelectConfig extends FormItem {
type: 'cond-op';
parentFields?: string[];
}
/** 可新增的数据源类型选项 */ /** 可新增的数据源类型选项 */
export interface DatasourceTypeOption { export interface DatasourceTypeOption {
/** 数据源类型 */ /** 数据源类型 */

View File

@ -215,7 +215,10 @@ export const getCascaderOptionsFromFields = (
dataSourceFieldType.push('any'); dataSourceFieldType.push('any');
} }
const children = getCascaderOptionsFromFields(field.fields, dataSourceFieldType); let children: CascaderOption[] = [];
if (field.type && ['any', 'array', 'object'].includes(field.type)) {
children = getCascaderOptionsFromFields(field.fields, dataSourceFieldType);
}
const item = { const item = {
label: `${field.title || field.name}(${field.type})`, label: `${field.title || field.name}(${field.type})`,

View File

@ -1,3 +1,4 @@
/* eslint-disable @typescript-eslint/naming-convention */
/* /*
* Tencent is pleased to support the open source community by making TMagicEditor available. * Tencent is pleased to support the open source community by making TMagicEditor available.
* *
@ -18,19 +19,17 @@
import type { FormConfig, FormState, TabPaneConfig } from '@tmagic/form'; import type { FormConfig, FormState, TabPaneConfig } from '@tmagic/form';
import dataSourceService from '@editor/services/dataSource'; export const arrayOptions = [
const arrayOptions = [
{ text: '包含', value: 'include' }, { text: '包含', value: 'include' },
{ text: '不包含', value: 'not_include' }, { text: '不包含', value: 'not_include' },
]; ];
const eqOptions = [ export const eqOptions = [
{ text: '等于', value: '=' }, { text: '等于', value: '=' },
{ text: '不等于', value: '!=' }, { text: '不等于', value: '!=' },
]; ];
const numberOptions = [ export const numberOptions = [
{ text: '大于', value: '>' }, { text: '大于', value: '>' },
{ text: '大于等于', value: '>=' }, { text: '大于等于', value: '>=' },
{ text: '小于', value: '<' }, { text: '小于', value: '<' },
@ -359,106 +358,10 @@ export const displayTabConfig: TabPaneConfig = {
display: (vm: FormState, { model }: any) => model.type !== 'page', display: (vm: FormState, { model }: any) => model.type !== 'page',
items: [ items: [
{ {
type: 'groupList', type: 'display-conds',
name: 'displayConds', name: 'displayConds',
titlePrefix: '条件组', titlePrefix: '条件组',
expandAll: true, defaultValue: [],
items: [
{
type: 'table',
name: 'cond',
items: [
{
type: 'data-source-field-select',
name: 'field',
value: 'key',
label: '字段',
checkStrictly: false,
dataSourceFieldType: ['string', 'number', 'boolean', 'any'],
},
{
type: 'select',
options: (mForm, { model }) => {
const [id, ...fieldNames] = model.field;
const ds = dataSourceService.getDataSourceById(id);
let fields = ds?.fields || [];
let type = '';
(fieldNames || []).forEach((fieldName: string) => {
const field = fields.find((f) => f.name === fieldName);
fields = field?.fields || [];
type = field?.type || '';
});
if (type === 'array') {
return arrayOptions;
}
if (type === 'boolean') {
return [
{ text: '是', value: 'is' },
{ text: '不是', value: 'not' },
];
}
if (type === 'number') {
return [...eqOptions, ...numberOptions];
}
if (type === 'string') {
return [...arrayOptions, ...eqOptions];
}
return [...arrayOptions, ...eqOptions, ...numberOptions];
},
label: '条件',
name: 'op',
},
{
label: '值',
items: [
{
name: 'value',
type: (mForm, { model }) => {
const [id, ...fieldNames] = model.field;
const ds = dataSourceService.getDataSourceById(id);
let fields = ds?.fields || [];
let type = '';
(fieldNames || []).forEach((fieldName: string) => {
const field = fields.find((f) => f.name === fieldName);
fields = field?.fields || [];
type = field?.type || '';
});
if (type === 'number') {
return 'number';
}
if (type === 'boolean') {
return 'select';
}
return 'text';
},
options: [
{ text: 'true', value: true },
{ text: 'false', value: false },
],
display: (vm, { model }) => !['between', 'not_between'].includes(model.op),
},
{
name: 'range',
type: 'number-range',
display: (vm, { model }) => ['between', 'not_between'].includes(model.op),
},
],
},
],
},
],
}, },
], ],
}; };

View File

@ -49,7 +49,7 @@ const options = ref<CascaderOption[]>([]);
const remoteData = ref<any>(null); const remoteData = ref<any>(null);
const checkStrictly = computed(() => filterFunction(mForm, props.config.checkStrictly, props)); const checkStrictly = computed(() => filterFunction(mForm, props.config.checkStrictly, props));
const valueSeparator = computed(() => filterFunction(mForm, props.config.valueSeparator, props)); const valueSeparator = computed(() => filterFunction<string>(mForm, props.config.valueSeparator, props));
const value = computed({ const value = computed({
get() { get() {

View File

@ -11,7 +11,7 @@ import { computed, inject } from 'vue';
import { TMagicCheckbox, TMagicCheckboxGroup } from '@tmagic/design'; import { TMagicCheckbox, TMagicCheckboxGroup } from '@tmagic/design';
import type { CheckboxGroupConfig, FieldProps, FormState } from '../schema'; import type { CheckboxGroupConfig, CheckboxGroupOption, FieldProps, FormState } from '../schema';
import { filterFunction } from '../utils/form'; import { filterFunction } from '../utils/form';
import { useAddField } from '../utils/useAddField'; import { useAddField } from '../utils/useAddField';
@ -37,7 +37,8 @@ const changeHandler = (v: Array<string | number | boolean>) => {
const mForm = inject<FormState | undefined>('mForm'); const mForm = inject<FormState | undefined>('mForm');
const options = computed(() => { const options = computed(() => {
if (Array.isArray(props.config.options)) return props.config.options; if (Array.isArray(props.config.options)) return props.config.options;
if (typeof props.config.options === 'function') return filterFunction(mForm, props.config.options, props); if (typeof props.config.options === 'function')
return filterFunction<CheckboxGroupOption[]>(mForm, props.config.options, props) || [];
return []; return [];
}); });
</script> </script>

View File

@ -170,6 +170,7 @@ export type FilterFunction<T = boolean> = (
formValue: Record<any, any>; formValue: Record<any, any>;
prop: string; prop: string;
config: any; config: any;
index?: number;
}, },
) => T; ) => T;
@ -433,18 +434,18 @@ export interface ColorPickConfig extends FormItem {
type: 'colorPicker'; type: 'colorPicker';
} }
export interface CheckboxGroupOption {
value: any;
text: string;
disabled?: boolean;
}
/** /**
* *
*/ */
export interface CheckboxGroupConfig extends FormItem { export interface CheckboxGroupConfig extends FormItem {
type: 'checkbox-group'; type: 'checkbox-group';
options: options: CheckboxGroupOption[] | FilterFunction<CheckboxGroupOption[]>;
| {
value: any;
text: string;
disabled?: boolean;
}[]
| Function;
} }
/** /**

View File

@ -24,6 +24,7 @@ import {
ChildConfig, ChildConfig,
ContainerCommonConfig, ContainerCommonConfig,
DaterangeConfig, DaterangeConfig,
FilterFunction,
FormConfig, FormConfig,
FormState, FormState,
FormValue, FormValue,
@ -181,20 +182,24 @@ const getDefaultValue = function (mForm: FormState | undefined, { defaultValue,
return ''; return '';
}; };
export const filterFunction = <T = any>(mForm: FormState | undefined, config: T, props: any) => { export const filterFunction = <T = any>(
if (typeof config !== 'function') { mForm: FormState | undefined,
return config; config: T | FilterFunction<T> | undefined,
props: any,
) => {
if (typeof config === 'function') {
return (config as FilterFunction<T>)(mForm, {
values: mForm?.initValues || {},
model: props.model,
parent: mForm?.parentValues || {},
formValue: mForm?.values || props.model,
prop: props.prop,
config: props.config,
index: props.index,
});
} }
return config(mForm, { return config;
values: mForm?.initValues || {},
model: props.model,
parent: mForm?.parentValues || {},
formValue: mForm?.values || props.model,
prop: props.prop,
config: props.config,
index: props.index,
});
}; };
export const display = function (mForm: FormState | undefined, config: any, props: any) { export const display = function (mForm: FormState | undefined, config: any, props: any) {

View File

@ -139,6 +139,7 @@ export interface MComponent {
style?: { style?: {
[key: string]: any; [key: string]: any;
}; };
displayConds?: DisplayCond[];
[key: string]: any; [key: string]: any;
} }
@ -285,3 +286,14 @@ export type HookData = {
/** 参数 */ /** 参数 */
params?: object; params?: object;
}; };
export interface DisplayCondItem {
field: string[];
op: string;
value?: any;
range?: [number, number];
}
export interface DisplayCond {
cond: DisplayCondItem[];
}

View File

@ -7,7 +7,7 @@
<script lang="ts" setup> <script lang="ts" setup>
import { computed } from 'vue'; import { computed } from 'vue';
import { type MContainer, NodeType } from '@tmagic/schema'; import { type DisplayCond, type MContainer, NodeType } from '@tmagic/schema';
import { useApp } from '@tmagic/vue-runtime-help'; import { useApp } from '@tmagic/vue-runtime-help';
import Container from '../../container'; import Container from '../../container';
@ -20,6 +20,7 @@ const props = withDefaults(
dsField: string[]; dsField: string[];
itemConfig: { itemConfig: {
layout: string; layout: string;
displayConds: DisplayCond[];
style: Record<string, string | number>; style: Record<string, string | number>;
}; };
}; };
@ -46,18 +47,26 @@ const configs = computed(() => {
iteratorData.push({}); iteratorData.push({});
} }
return iteratorData.map((itemData) => ({ return iteratorData.map((itemData) => {
items: const condResult =
app?.dataSourceManager?.compliedIteratorItems(itemData, props.config.items, props.config.dsField) ?? app?.platform !== 'editor'
props.config.items, ? app?.dataSourceManager?.compliedIteratorItemConds(itemData, props.config.itemConfig.displayConds) ?? true
id: '', : true;
type: NodeType.CONTAINER,
style: { return {
...props.config.itemConfig.style, items:
position: 'relative', app?.dataSourceManager?.compliedIteratorItems(itemData, props.config.items, props.config.dsField) ??
left: 0, props.config.items,
top: 0, id: '',
}, type: NodeType.CONTAINER,
})); condResult,
style: {
...props.config.itemConfig.style,
position: 'relative',
left: 0,
top: 0,
},
};
});
}); });
</script> </script>

View File

@ -43,6 +43,13 @@ export default [
title: '子项配置', title: '子项配置',
name: 'itemConfig', name: 'itemConfig',
items: [ items: [
{
type: 'display-conds',
name: 'displayConds',
titlePrefix: '条件组',
parentFields: (formState: any, { formValue }: any) => formValue.dsField,
defaultValue: [],
},
{ {
name: 'layout', name: 'layout',
text: '容器布局', text: '容器布局',