tmagic-editor/packages/editor/src/fields/DataSourceSelect.vue
roymondchen cbc4b25072 feat(editor): 字段对比模式逐项展示差异并补充历史记录面板文档
- CodeSelect/CodeSelectCol/EventSelect/DataSource 等复合字段在对比模式下
  按索引对齐前后值,逐项展示新增/删除/修改高亮,并隐藏写操作按钮
- form 容器/列表/表格支持对比模式只读展示
- 新增「历史记录面板」指南文档,完善表单对比文档及 menu props 说明
- 补充相关单元测试

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-29 15:51:47 +08:00

108 lines
2.9 KiB
Vue

<template>
<div class="m-fields-data-source-select">
<MSelect
:model="model"
:name="name"
:size="size"
:prop="prop"
:disabled="disabled"
:config="selectConfig"
:last-values="lastValues"
@change="changeHandler"
></MSelect>
<TMagicTooltip v-if="model[name] && hasDataSourceSidePanel && !isCompare" :content="notEditable ? '查看' : '编辑'">
<TMagicButton class="m-fields-select-action-button" :size="size" @click="editHandler"
><MIcon :icon="!notEditable ? Edit : View"></MIcon
></TMagicButton>
</TMagicTooltip>
</div>
</template>
<script setup lang="ts">
import { computed, inject } from 'vue';
import { Edit, View } from '@element-plus/icons-vue';
import { TMagicButton, TMagicTooltip } from '@tmagic/design';
import {
type DataSourceSelect,
type FieldProps,
filterFunction,
type FormState,
MSelect,
type SelectConfig,
} from '@tmagic/form';
import MIcon from '@editor/components/Icon.vue';
import { useServices } from '@editor/hooks/use-services';
import type { EventBus } from '@editor/type';
import { SideItemKey } from '@editor/type';
defineOptions({
name: 'MFieldsDataSourceSelect',
});
const emit = defineEmits(['change']);
const props = withDefaults(defineProps<FieldProps<DataSourceSelect>>(), {
disabled: false,
});
const mForm = inject<FormState | undefined>('mForm');
const { dataSourceService, uiService } = useServices();
const eventBus = inject<EventBus>('eventBus');
const dataSources = computed(() => dataSourceService.get('dataSources'));
const notEditable = computed(() => filterFunction(mForm, props.config.notEditable, props));
/** 对比模式下隐藏查看/编辑操作按钮,仅保留只读展示。 */
const isCompare = computed(() => Boolean(mForm?.isCompare));
const hasDataSourceSidePanel = computed(() =>
uiService.get('sideBarItems').find((item) => item.$key === SideItemKey.DATA_SOURCE),
);
const selectConfig = computed<SelectConfig>(() => {
const { type, dataSourceType, value, ...config } = props.config;
const valueIsId = props.config.value === 'id';
return {
...config,
type: 'select',
valueKey: 'dataSourceId',
options: dataSources.value
.filter((ds) => !props.config.dataSourceType || ds.type === props.config.dataSourceType)
.map((ds) => ({
value: valueIsId
? ds.id
: {
isBindDataSource: true,
dataSourceType: ds.type,
dataSourceId: ds.id,
},
text: ds.title || ds.id,
})),
};
});
const changeHandler = (value: any) => {
emit('change', value);
};
const editHandler = () => {
const value = props.model[props.name];
if (!value) return;
const id = typeof value === 'string' ? value : value.dataSourceId;
const dataSource = dataSourceService.getDataSourceById(id);
if (!dataSource) return;
eventBus?.emit('edit-data-source', id);
};
</script>