Skip to content

Commit

Permalink
feat(editor): 样式配置支持配置数据源字段
Browse files Browse the repository at this point in the history
  • Loading branch information
roymondchen committed Mar 8, 2024
1 parent 900acb6 commit cda6c0f
Show file tree
Hide file tree
Showing 6 changed files with 258 additions and 64 deletions.
122 changes: 101 additions & 21 deletions packages/editor/src/fields/DataSourceFieldSelect.vue
Original file line number Diff line number Diff line change
@@ -1,22 +1,37 @@
<template>
<MCascader
:config="cascaderConfig"
:model="model"
:name="name"
:disabled="disabled"
:size="size"
:last-values="lastValues"
:init-values="initValues"
:values="values"
:prop="`${prop}${prop ? '.' : ''}${name}`"
@change="onChangeHandler"
></MCascader>
<div style="width: 100%; display: flex; align-items: center">
<component
style="width: 100%"
:is="tagName"
:config="showDataSourceFieldSelect || !config.fieldConfig ? cascaderConfig : config.fieldConfig"
:model="model"
:name="name"
:disabled="disabled"
:size="size"
:last-values="lastValues"
:init-values="initValues"
:values="values"
:prop="`${prop}${prop ? '.' : ''}${name}`"
@change="onChangeHandler"
></component>
<TMagicButton
v-if="config.fieldConfig"
style="margin-left: 5px"
link
:type="showDataSourceFieldSelect ? 'primary' : 'default'"
:icon="Coin"
:size="size"
@click="showDataSourceFieldSelect = !showDataSourceFieldSelect"
></TMagicButton>
</div>
</template>

<script setup lang="ts">
import { computed, inject } from 'vue';
import { computed, inject, onMounted, ref, resolveComponent } from 'vue';
import { Coin } from '@element-plus/icons-vue';
import type { CascaderConfig, CascaderOption, FieldProps } from '@tmagic/form';
import { TMagicButton } from '@tmagic/design';
import type { CascaderConfig, CascaderOption, FieldProps, FormState } from '@tmagic/form';
import { MCascader } from '@tmagic/form';
import type { DataSchema, DataSourceFieldType } from '@tmagic/schema';
import { DATA_SOURCE_FIELDS_SELECT_VALUE_PREFIX } from '@tmagic/utils';
Expand All @@ -36,14 +51,42 @@ const props = withDefaults(defineProps<FieldProps<DataSourceFieldSelectConfig>>(
const dataSources = computed(() => services?.dataSourceService.get('dataSources'));
const getOptionChildren = (fields: DataSchema[] = [], fieldType: DataSourceFieldType[] = []): CascaderOption[] =>
fields
.filter((field) => !fieldType.length || fieldType.includes(field.type || 'string') || field.type === 'object')
.map((field) => ({
const getOptionChildren = (
fields: DataSchema[] = [],
dataSourceFieldType: DataSourceFieldType[] = ['any'],
): CascaderOption[] => {
const child: CascaderOption[] = [];
fields.forEach((field) => {
if (!dataSourceFieldType.length) {
dataSourceFieldType.push('any');
}
const children = getOptionChildren(field.fields, dataSourceFieldType);
const item = {
label: field.title || field.name,
value: field.name,
children: field.type === 'array' ? [] : getOptionChildren(field.fields, fieldType),
}));
children,
};
const fieldType = field.type || 'any';
if (dataSourceFieldType.includes('any') || dataSourceFieldType.includes(fieldType)) {
child.push(item);
return;
}
if (!dataSourceFieldType.includes(fieldType) && fieldType !== 'object') {
return;
}
if (!children.length && ['object', 'array', 'any'].includes(field.type || '')) {
return;
}
child.push(item);
});
return child;
};
const cascaderConfig = computed<CascaderConfig>(() => {
const valueIsKey = props.config.value === 'key';
Expand All @@ -57,13 +100,50 @@ const cascaderConfig = computed<CascaderConfig>(() => {
dataSources.value?.map((ds) => ({
label: ds.title || ds.id,
value: valueIsKey ? ds.id : `${DATA_SOURCE_FIELDS_SELECT_VALUE_PREFIX}${ds.id}`,
children: getOptionChildren(ds.fields, props.config.fieldType),
children: getOptionChildren(ds.fields, props.config.dataSourceFieldType),
})) || [];
return options.filter((option) => option.children.length);
},
};
});
const showDataSourceFieldSelect = ref(false);
onMounted(() => {
const value = props.model[props.name];
if (
Array.isArray(value) &&
typeof value[0] === 'string' &&
value[0].startsWith(DATA_SOURCE_FIELDS_SELECT_VALUE_PREFIX)
) {
return (showDataSourceFieldSelect.value = true);
}
});
const mForm = inject<FormState | undefined>('mForm');
const type = computed((): string => {
let type = props.config.fieldConfig?.type;
if (typeof type === 'function') {
type = type(mForm, {
model: props.model,
});
}
if (type === 'form') return '';
if (type === 'container') return '';
return type?.replace(/([A-Z])/g, '-$1').toLowerCase() || (props.config.items ? '' : 'text');
});
const tagName = computed(() => {
if (showDataSourceFieldSelect.value || !props.config.fieldConfig) {
return MCascader;
}
const component = resolveComponent(`m-${props.config.items ? 'form' : 'fields'}-${type.value}`);
if (typeof component !== 'string') return component;
return 'm-fields-text';
});
const onChangeHandler = (value: any) => {
emit('change', value);
};
Expand Down
5 changes: 3 additions & 2 deletions packages/editor/src/type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
import type { Component } from 'vue';
import type { PascalCasedProperties } from 'type-fest';

import type { ColumnConfig, FilterFunction, FormConfig, FormItem, Input } from '@tmagic/form';
import type { ChildConfig, ColumnConfig, FilterFunction, FormConfig, FormItem, Input } from '@tmagic/form';
import type {
CodeBlockContent,
CodeBlockDSL,
Expand Down Expand Up @@ -642,7 +642,8 @@ export interface DataSourceFieldSelectConfig extends FormItem {
value?: 'key' | 'value';
/** 是否严格的遵守父子节点不互相关联 */
checkStrictly?: boolean;
fieldType?: DataSourceFieldType[];
dataSourceFieldType?: DataSourceFieldType[];
fieldConfig?: ChildConfig;
}

/** 可新增的数据源类型选项 */
Expand Down
Loading

0 comments on commit cda6c0f

Please sign in to comment.