+
+
+
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>(
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) {
diff --git a/packages/editor/src/fields/DataSourceMethodSelect.vue b/packages/editor/src/fields/DataSourceMethodSelect.vue
index f0b6d174..40213f3f 100644
--- a/packages/editor/src/fields/DataSourceMethodSelect.vue
+++ b/packages/editor/src/fields/DataSourceMethodSelect.vue
@@ -8,12 +8,15 @@
:size="size"
@change="onChangeHandler"
>
-
+ >
+
+
>
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'));
diff --git a/packages/editor/src/fields/DataSourceSelect.vue b/packages/editor/src/fields/DataSourceSelect.vue
index d92f8125..dfda2ef8 100644
--- a/packages/editor/src/fields/DataSourceSelect.vue
+++ b/packages/editor/src/fields/DataSourceSelect.vue
@@ -1,22 +1,36 @@
-
+
+
+
+
+
diff --git a/packages/editor/src/layouts/sidebar/Sidebar.vue b/packages/editor/src/layouts/sidebar/Sidebar.vue
index 69333b9c..c6c6675e 100644
--- a/packages/editor/src/layouts/sidebar/Sidebar.vue
+++ b/packages/editor/src/layouts/sidebar/Sidebar.vue
@@ -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)"
>
(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 = {
- '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) => {
diff --git a/packages/editor/src/services/ui.ts b/packages/editor/src/services/ui.ts
index 373a1209..5bbffbed 100644
--- a/packages/editor/src/services/ui.ts
+++ b/packages/editor/src/services/ui.ts
@@ -48,6 +48,7 @@ const state = reactive({
propsPanelSize: 'small',
showAddPageButton: true,
hideSlideBar: false,
+ sideBarItems: [],
navMenuRect: {
left: 0,
top: 0,
diff --git a/packages/editor/src/theme/data-source-field.scss b/packages/editor/src/theme/data-source-field.scss
new file mode 100644
index 00000000..458ba55d
--- /dev/null
+++ b/packages/editor/src/theme/data-source-field.scss
@@ -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;
+ }
+}
diff --git a/packages/editor/src/theme/theme.scss b/packages/editor/src/theme/theme.scss
index c9ea6921..cb87ec37 100644
--- a/packages/editor/src/theme/theme.scss
+++ b/packages/editor/src/theme/theme.scss
@@ -24,3 +24,4 @@
@import "./tree.scss";
@import "./floating-box.scss";
@import "./page-fragment-select.scss";
+@import "./data-source-field.scss";
diff --git a/packages/editor/src/type.ts b/packages/editor/src/type.ts
index 1a281933..2958edce 100644
--- a/packages/editor/src/type.ts
+++ b/packages/editor/src/type.ts
@@ -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;
/** 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;
}
/** 可新增的数据源类型选项 */