feat(editor): 优化数据源选择器与代码选择的编辑按钮

This commit is contained in:
roymondchen 2024-04-16 11:52:11 +08:00
parent 4054c6ed57
commit fc1a7a09ff
9 changed files with 149 additions and 38 deletions

View File

@ -9,8 +9,16 @@
:size="size"
@change="onParamsChangeHandler"
></MContainer>
<!-- 查看/编辑按钮 -->
<Icon v-if="model[name]" class="icon" :icon="!notEditable ? Edit : View" @click="editCode(model[name])"></Icon>
<TMagicButton
v-if="model[name] && hasCodeBlockSidePanel"
class="m-fields-select-action-button"
:size="size"
@click="editCode(model[name])"
>
<MIcon :icon="!notEditable ? Edit : View"></MIcon>
</TMagicButton>
</div>
<!-- 参数填写框 -->
@ -31,12 +39,14 @@ import { computed, inject, ref, watch } from 'vue';
import { Edit, View } from '@element-plus/icons-vue';
import { isEmpty, map } from 'lodash-es';
import { TMagicButton } from '@tmagic/design';
import { createValues, type FieldProps, filterFunction, type FormState, MContainer } from '@tmagic/form';
import type { Id } from '@tmagic/schema';
import CodeParams from '@editor/components/CodeParams.vue';
import Icon from '@editor/components/Icon.vue';
import MIcon from '@editor/components/Icon.vue';
import type { CodeParamStatement, CodeSelectColConfig, EventBus, Services } from '@editor/type';
import { SideItemKey } from '@editor/type';
defineOptions({
name: 'MFieldsCodeSelectCol',
@ -47,11 +57,16 @@ const services = inject<Services>('services');
const eventBus = inject<EventBus>('eventBus');
const emit = defineEmits(['change']);
const notEditable = computed(() => filterFunction(mForm, props.config.notEditable, props));
const props = withDefaults(defineProps<FieldProps<CodeSelectColConfig>>(), {
disabled: false,
});
const notEditable = computed(() => filterFunction(mForm, props.config.notEditable, props));
const hasCodeBlockSidePanel = computed(() =>
(services?.uiService.get('sideBarItems') || []).find((item) => item.$key === SideItemKey.CODE_BLOCK),
);
/**
* 根据代码块id获取代码块参数配置
* @param codeId 代码块ID

View File

@ -1,5 +1,5 @@
<template>
<div style="width: 100%; display: flex; align-items: center">
<div class="m-fields-data-source-field-select">
<component
style="width: 100%"
:is="tagName"
@ -14,13 +14,15 @@
:prop="`${prop}${prop ? '.' : ''}${name}`"
@change="onChangeHandler"
></component>
<TMagicButton
v-if="(showDataSourceFieldSelect || !config.fieldConfig) && selectedDataSourceId"
style="margin-left: 5px"
v-if="(showDataSourceFieldSelect || !config.fieldConfig) && selectedDataSourceId && hasDataSourceSidePanel"
class="m-fields-select-action-button"
:size="size"
@click="editHandler(selectedDataSourceId)"
><MIcon :icon="Edit"></MIcon
><MIcon :icon="!notEditable ? Edit : View"></MIcon
></TMagicButton>
<TMagicButton
v-if="config.fieldConfig"
style="margin-left: 5px"
@ -34,16 +36,17 @@
<script setup lang="ts">
import { computed, inject, ref, resolveComponent, watch } from 'vue';
import { Coin, Edit } from '@element-plus/icons-vue';
import { Coin, Edit, View } from '@element-plus/icons-vue';
import { TMagicButton } from '@tmagic/design';
import type { CascaderConfig, CascaderOption, FieldProps, FormState } from '@tmagic/form';
import { MCascader } from '@tmagic/form';
import { filterFunction, MCascader } from '@tmagic/form';
import type { DataSchema, DataSourceFieldType } from '@tmagic/schema';
import { DATA_SOURCE_FIELDS_SELECT_VALUE_PREFIX } from '@tmagic/utils';
import MIcon from '@editor/components/Icon.vue';
import type { DataSourceFieldSelectConfig, EventBus, Services } from '@editor/type';
import { SideItemKey } from '@editor/type';
defineOptions({
name: 'MFieldsDataSourceFieldSelect',
@ -57,6 +60,12 @@ const props = withDefaults(defineProps<FieldProps<DataSourceFieldSelectConfig>>(
disabled: false,
});
const notEditable = computed(() => filterFunction(mForm, props.config.notEditable, props));
const hasDataSourceSidePanel = computed(() =>
(services?.uiService.get('sideBarItems') || []).find((item) => item.$key === SideItemKey.DATA_SOURCE),
);
const selectedDataSourceId = computed(() => {
const value = props.model[props.name];
if (!Array.isArray(value) || !value.length) {

View File

@ -8,12 +8,15 @@
:size="size"
@change="onChangeHandler"
></MContainer>
<Icon
v-if="model[name] && isCustomMethod"
class="icon"
:icon="!notEditable ? Edit : View"
<TMagicButton
v-if="model[name] && isCustomMethod && hasDataSourceSidePanel"
class="m-fields-select-action-button"
:size="size"
@click="editCodeHandler"
></Icon>
>
<MIcon :icon="!notEditable ? Edit : View"></MIcon>
</TMagicButton>
</div>
<CodeParams
@ -32,12 +35,14 @@
import { computed, inject, ref } from 'vue';
import { Edit, View } from '@element-plus/icons-vue';
import { TMagicButton } from '@tmagic/design';
import { createValues, type FieldProps, filterFunction, type FormState, MContainer } from '@tmagic/form';
import type { Id } from '@tmagic/schema';
import CodeParams from '@editor/components/CodeParams.vue';
import Icon from '@editor/components/Icon.vue';
import MIcon from '@editor/components/Icon.vue';
import type { CodeParamStatement, DataSourceMethodSelectConfig, EventBus, Services } from '@editor/type';
import { SideItemKey } from '@editor/type';
defineOptions({
name: 'MFieldsDataSourceMethodSelect',
@ -55,6 +60,10 @@ const props = withDefaults(defineProps<FieldProps<DataSourceMethodSelectConfig>>
disabled: false,
});
const hasDataSourceSidePanel = computed(() =>
(services?.uiService.get('sideBarItems') || []).find((item) => item.$key === SideItemKey.DATA_SOURCE),
);
const notEditable = computed(() => filterFunction(mForm, props.config.notEditable, props));
const dataSources = computed(() => dataSourceService?.get('dataSources'));

View File

@ -1,22 +1,36 @@
<template>
<MSelect
:model="model"
:name="name"
:size="size"
:prop="prop"
:disabled="disabled"
:config="selectConfig"
:last-values="lastValues"
@change="changeHandler"
></MSelect>
<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>
<TMagicButton
v-if="model[name] && hasDataSourceSidePanel"
class="m-fields-select-action-button"
:size="size"
@click="editHandler"
><MIcon :icon="!notEditable ? Edit : View"></MIcon
></TMagicButton>
</div>
</template>
<script setup lang="ts">
import { computed, inject } from 'vue';
import { Edit, View } from '@element-plus/icons-vue';
import { type FieldProps, MSelect, type SelectConfig } from '@tmagic/form';
import { TMagicButton } from '@tmagic/design';
import { type FieldProps, filterFunction, type FormState, MSelect, type SelectConfig } from '@tmagic/form';
import type { DataSourceSelect, Services } from '../type';
import MIcon from '@editor/components/Icon.vue';
import type { DataSourceSelect, EventBus, Services } from '@editor/type';
import { SideItemKey } from '@editor/type';
defineOptions({
name: 'MFieldsDataSourceSelect',
@ -28,10 +42,18 @@ const props = withDefaults(defineProps<FieldProps<DataSourceSelect>>(), {
disabled: false,
});
const { dataSourceService } = inject<Services>('services') || {};
const mForm = inject<FormState | undefined>('mForm');
const { dataSourceService, uiService } = inject<Services>('services') || {};
const eventBus = inject<EventBus>('eventBus');
const dataSources = computed(() => dataSourceService?.get('dataSources') || []);
const notEditable = computed(() => filterFunction(mForm, props.config.notEditable, props));
const hasDataSourceSidePanel = computed(() =>
(uiService?.get('sideBarItems') || []).find((item) => item.$key === SideItemKey.DATA_SOURCE),
);
const selectConfig = computed<SelectConfig>(() => {
const { type, dataSourceType, value, ...config } = props.config;
@ -59,4 +81,18 @@ const selectConfig = computed<SelectConfig>(() => {
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>

View File

@ -9,7 +9,7 @@
:key="config.$key ?? index"
:class="{ 'is-active': activeTabName === config.text }"
:style="config.tabStyle || {}"
@click="activeTabName = config.text || `${index}`"
@click="activeTabName = config.text || config.$key || `${index}`"
@dragstart="dragstartHandler"
@dragend="dragendHandler(config.$key, $event)"
>
@ -21,7 +21,7 @@
class="m-editor-sidebar-content"
v-for="(config, index) in sideBarItems"
:key="config.$key ?? index"
v-show="activeTabName === config.text"
v-show="[config.text, config.$key, `${index}`].includes(activeTabName)"
>
<component
v-if="config && !floatBoxStates[config.$key]?.status"
@ -152,6 +152,7 @@ import {
type SidebarSlots,
type SideComponent,
type SideItem,
SideItemKey,
} from '@editor/type';
import CodeBlockListPanel from './code-block/CodeBlockListPanel.vue';
@ -172,7 +173,11 @@ const props = withDefaults(
customContentMenu?: (menus: (MenuButton | MenuComponent)[], type: string) => (MenuButton | MenuComponent)[];
}>(),
{
data: () => ({ type: 'tabs', status: '组件', items: ['component-list', 'layer', 'code-block', 'data-source'] }),
data: () => ({
type: 'tabs',
status: '组件',
items: [SideItemKey.COMPONENT_LIST, SideItemKey.LAYER, SideItemKey.CODE_BLOCK, SideItemKey.DATA_SOURCE],
}),
},
);
@ -185,8 +190,8 @@ const activeTabName = ref(props.data?.status);
const getItemConfig = (data: SideItem): SideComponent => {
const map: Record<string, SideComponent> = {
'component-list': {
$key: 'component-list',
[SideItemKey.COMPONENT_LIST]: {
$key: SideItemKey.COMPONENT_LIST,
type: 'component',
icon: Goods,
text: '组件',
@ -205,7 +210,7 @@ const getItemConfig = (data: SideItem): SideComponent => {
component: LayerPanel,
slots: {},
},
'code-block': {
[SideItemKey.CODE_BLOCK]: {
$key: 'code-block',
type: 'component',
icon: EditPen,
@ -213,8 +218,8 @@ const getItemConfig = (data: SideItem): SideComponent => {
component: CodeBlockListPanel,
slots: {},
},
'data-source': {
$key: 'data-source',
[SideItemKey.DATA_SOURCE]: {
$key: SideItemKey.DATA_SOURCE,
type: 'component',
icon: Coin,
text: '数据源',
@ -228,6 +233,16 @@ const getItemConfig = (data: SideItem): SideComponent => {
const sideBarItems = computed(() => props.data.items.map((item) => getItemConfig(item)));
watch(
sideBarItems,
(items) => {
services?.uiService.set('sideBarItems', items);
},
{
immediate: true,
},
);
watch(
() => props.data.status,
(status) => {

View File

@ -48,6 +48,7 @@ const state = reactive<UiState>({
propsPanelSize: 'small',
showAddPageButton: true,
hideSlideBar: false,
sideBarItems: [],
navMenuRect: {
left: 0,
top: 0,

View File

@ -0,0 +1,12 @@
.m-fields-data-source-select,
.m-fields-data-source-field-select,
.m-fields-data-source-method-select .data-source-method-select-container,
.m-fields-code-select-col .code-select-container {
width: 100%;
display: flex;
align-items: center;
.m-fields-select-action-button {
margin-left: 5px;
}
}

View File

@ -24,3 +24,4 @@
@import "./tree.scss";
@import "./floating-box.scss";
@import "./page-fragment-select.scss";
@import "./data-source-field.scss";

View File

@ -239,6 +239,8 @@ export interface UiState {
showAddPageButton: boolean;
/** 是否隐藏侧边栏 */
hideSlideBar: boolean;
/** 侧边栏面板配置 */
sideBarItems: SideComponent[];
// navMenu 的宽高
navMenuRect: {
@ -374,7 +376,7 @@ export interface SideComponent extends MenuComponent {
/** tab样式 */
tabStyle?: string | Record<string, any>;
/** vue组件或url */
icon?: Component<{}, {}, any>;
icon?: any;
/** slide 唯一标识 key */
$key: string;
@ -387,12 +389,19 @@ export interface SideComponent extends MenuComponent {
};
}
export enum SideItemKey {
COMPONENT_LIST = 'component-list',
LAYER = 'layer',
CODE_BLOCK = 'code-block',
DATA_SOURCE = 'data-source',
}
/**
* component-list: 组件列表
* layer: 已选组件树
* code-block: 代码块
*/
export type SideItem = 'component-list' | 'layer' | 'code-block' | 'data-source' | SideComponent;
export type SideItem = `${SideItemKey}` | SideComponent;
/** 工具栏 */
export interface SideBarData {
@ -624,6 +633,8 @@ export interface DataSourceSelect extends FormItem, Input {
* value: 要编译data
* */
value?: 'id' | 'value';
/** 是否可以编辑数据源disable表示的是是否可以选择数据源 */
notEditable?: boolean | FilterFunction;
}
export interface DataSourceMethodSelectConfig extends FormItem {
@ -643,6 +654,8 @@ export interface DataSourceFieldSelectConfig extends FormItem {
checkStrictly?: boolean;
dataSourceFieldType?: DataSourceFieldType[];
fieldConfig?: ChildConfig;
/** 是否可以编辑数据源disable表示的是是否可以选择数据源 */
notEditable?: boolean | FilterFunction;
}
/** 可新增的数据源类型选项 */