171 lines
4.8 KiB
Vue

<template>
<div class="m-fields-data-source-field-select">
<FieldSelect
v-if="showDataSourceFieldSelect || !config.fieldConfig"
:model-value="model[name]"
:disabled="disabled"
:size="size"
:value="config.value"
:checkStrictly="checkStrictly"
:dataSourceFieldType="config.dataSourceFieldType"
@change="onChangeHandler"
></FieldSelect>
<component
v-else
:is="tagName"
:config="config.fieldConfig"
:model="model"
:name="name"
:disabled="disabled"
:size="size"
:last-values="lastValues"
:init-values="initValues"
:values="values"
:prop="prop"
@change="onChangeHandler"
></component>
<TMagicTooltip v-if="config.fieldConfig" :disabled="showDataSourceFieldSelect" content="选择数据源">
<TMagicButton
style="margin-left: 5px"
:type="showDataSourceFieldSelect ? 'primary' : 'default'"
:size="size"
@click="showDataSourceFieldSelect = !showDataSourceFieldSelect"
><MIcon :icon="Coin"></MIcon
></TMagicButton>
</TMagicTooltip>
</div>
</template>
<script setup lang="ts">
import { computed, inject, ref, resolveComponent, watch } from 'vue';
import { Coin } from '@element-plus/icons-vue';
import { DataSchema } from '@tmagic/core';
import { TMagicButton, tMagicMessage, TMagicTooltip } from '@tmagic/design';
import type { ContainerChangeEventData, FieldProps, FormState } from '@tmagic/form';
import { DATA_SOURCE_FIELDS_SELECT_VALUE_PREFIX } from '@tmagic/utils';
import MIcon from '@editor/components/Icon.vue';
import { useServices } from '@editor/hooks/use-services';
import type { DataSourceFieldSelectConfig } from '@editor/type';
import { removeDataSourceFieldPrefix } from '@editor/utils';
import FieldSelect from './FieldSelect.vue';
defineOptions({
name: 'MFieldsDataSourceFieldSelect',
});
const emit = defineEmits(['change']);
const props = withDefaults(defineProps<FieldProps<DataSourceFieldSelectConfig>>(), {
disabled: false,
});
const showDataSourceFieldSelect = ref(false);
watch(
() => props.model[props.name],
(value) => {
if (
Array.isArray(value) &&
typeof value[0] === 'string' &&
value[0].startsWith(DATA_SOURCE_FIELDS_SELECT_VALUE_PREFIX)
) {
showDataSourceFieldSelect.value = true;
} else {
showDataSourceFieldSelect.value = false;
}
},
{
immediate: true,
},
);
const { dataSourceService } = useServices();
const mForm = inject<FormState | undefined>('mForm');
const dataSources = computed(() => dataSourceService.get('dataSources') || []);
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(() => {
const component = resolveComponent(`m-${props.config.items ? 'form' : 'fields'}-${type.value}`);
if (typeof component !== 'string') return component;
return 'm-fields-text';
});
const checkStrictly = computed(() => {
let value: boolean | undefined;
if (typeof props.config.checkStrictly !== 'function') {
value = props.config.checkStrictly;
} else {
const dsId = removeDataSourceFieldPrefix(props.model[0]);
const dataSource = dataSources.value.find((ds) => ds.id === dsId);
value = props.config.checkStrictly(mForm, {
values: mForm?.initValues || {},
model: props.model,
parent: mForm?.parentValues || {},
formValue: mForm?.values || props.model,
prop: props.prop,
config: props.config,
dataSource,
});
}
return value ?? props.config.value === 'key';
});
const onChangeHandler = (value: string[], eventData?: ContainerChangeEventData) => {
if (!Array.isArray(value)) {
emit('change', value, eventData);
return;
}
const [dsId, ...keys] = value;
const dataSource = dataSources.value.find((ds) => ds.id === removeDataSourceFieldPrefix(dsId));
if (!dataSource) {
emit('change', value, eventData);
return;
}
let fields = dataSource.fields || [];
let field: DataSchema | undefined;
(keys || []).forEach((key) => {
field = fields.find((f) => f.name === key);
fields = field?.fields || [];
});
const dataSourceFieldType = props.config.dataSourceFieldType || ['any'];
if (!dataSourceFieldType.length) {
dataSourceFieldType.push('any');
}
if (
!keys.length ||
(field?.type &&
(field.type === 'any' || dataSourceFieldType.includes('any') || dataSourceFieldType.includes(field.type)))
) {
emit('change', value, eventData);
} else {
tMagicMessage.error(`请选择类型为${dataSourceFieldType.join('或')}的字段`);
emit('change', [dsId], eventData);
}
};
</script>