diff --git a/packages/editor/src/Editor.vue b/packages/editor/src/Editor.vue index 279d5c5d..930e7911 100644 --- a/packages/editor/src/Editor.vue +++ b/packages/editor/src/Editor.vue @@ -134,7 +134,7 @@ import type { MApp } from '@tmagic/core'; import Framework from './layouts/Framework.vue'; import TMagicNavMenu from './layouts/NavMenu.vue'; -import PropsPanel from './layouts/PropsPanel.vue'; +import PropsPanel from './layouts/props-panel/PropsPanel.vue'; import Sidebar from './layouts/sidebar/Sidebar.vue'; import Workspace from './layouts/workspace/Workspace.vue'; import codeBlockService from './services/codeBlock'; diff --git a/packages/editor/src/index.ts b/packages/editor/src/index.ts index 99965775..043abec9 100644 --- a/packages/editor/src/index.ts +++ b/packages/editor/src/index.ts @@ -91,7 +91,8 @@ export { default as KeyValue } from './fields/KeyValue.vue'; export { default as CodeBlockList } from './layouts/sidebar/code-block/CodeBlockList.vue'; export { default as CodeBlockListPanel } from './layouts/sidebar/code-block/CodeBlockListPanel.vue'; export { default as DataSourceConfigPanel } from './layouts/sidebar/data-source/DataSourceConfigPanel.vue'; -export { default as PropsPanel } from './layouts/PropsPanel.vue'; +export { default as PropsPanel } from './layouts/props-panel/PropsPanel.vue'; +export { default as PropsFormPanel } from './layouts/props-panel/FormPanel.vue'; export { default as ToolButton } from './components/ToolButton.vue'; export { default as ContentMenu } from './components/ContentMenu.vue'; export { default as Icon } from './components/Icon.vue'; diff --git a/packages/editor/src/layouts/Framework.vue b/packages/editor/src/layouts/Framework.vue index 7a4aa641..60cbb7d3 100644 --- a/packages/editor/src/layouts/Framework.vue +++ b/packages/editor/src/layouts/Framework.vue @@ -20,7 +20,7 @@ v-model:left="columnWidth.left" v-model:right="columnWidth.right" :min-left="65" - :min-right="20" + :min-right="320" :min-center="100" :width="frameworkRect?.width || 0" @change="columnWidthChange" @@ -50,9 +50,7 @@ @@ -65,7 +63,6 @@ import { computed, inject, onBeforeUnmount, onMounted, ref, useTemplateRef, watch } from 'vue'; import type { MPage, MPageFragment } from '@tmagic/core'; -import { TMagicScrollbar } from '@tmagic/design'; import SplitView from '@editor/components/SplitView.vue'; import type { FrameworkSlots, GetColumnWidth, PageBarSortOptions, Services } from '@editor/type'; diff --git a/packages/editor/src/layouts/PropsPanel.vue b/packages/editor/src/layouts/PropsPanel.vue deleted file mode 100644 index 18b94881..00000000 --- a/packages/editor/src/layouts/PropsPanel.vue +++ /dev/null @@ -1,140 +0,0 @@ - - - diff --git a/packages/editor/src/layouts/props-panel/FormPanel.vue b/packages/editor/src/layouts/props-panel/FormPanel.vue new file mode 100644 index 00000000..a1782094 --- /dev/null +++ b/packages/editor/src/layouts/props-panel/FormPanel.vue @@ -0,0 +1,123 @@ + + + diff --git a/packages/editor/src/layouts/props-panel/PropsPanel.vue b/packages/editor/src/layouts/props-panel/PropsPanel.vue new file mode 100644 index 00000000..9e62327a --- /dev/null +++ b/packages/editor/src/layouts/props-panel/PropsPanel.vue @@ -0,0 +1,142 @@ + + + diff --git a/packages/editor/src/layouts/props-panel/use-style-panel.ts b/packages/editor/src/layouts/props-panel/use-style-panel.ts new file mode 100644 index 00000000..03737bc1 --- /dev/null +++ b/packages/editor/src/layouts/props-panel/use-style-panel.ts @@ -0,0 +1,29 @@ +import { computed } from 'vue'; + +import { Protocol } from '@editor/services/storage'; +import { Services } from '@editor/type'; + +export const useStylePanel = (services?: Services) => { + const showStylePanelStorageKey = 'props-panel-show-style-panel'; + const showStylePanelStorageValue = services?.storageService.getItem(showStylePanelStorageKey, { + protocol: Protocol.BOOLEAN, + }); + if (typeof showStylePanelStorageValue === 'boolean') { + services?.uiService.set('showStylePanel', showStylePanelStorageValue); + } + const showStylePanel = computed(() => services?.uiService.get('showStylePanel') ?? true); + const showStylePanelHandler = () => { + services?.uiService.set('showStylePanel', true); + services?.storageService.setItem(showStylePanelStorageKey, true, { protocol: Protocol.BOOLEAN }); + }; + const closeStylePanelHandler = () => { + services?.uiService.set('showStylePanel', false); + services?.storageService.setItem(showStylePanelStorageKey, false, { protocol: Protocol.BOOLEAN }); + }; + + return { + showStylePanel, + showStylePanelHandler, + closeStylePanelHandler, + }; +}; diff --git a/packages/editor/src/services/storage.ts b/packages/editor/src/services/storage.ts index 4a197d40..f15e2361 100644 --- a/packages/editor/src/services/storage.ts +++ b/packages/editor/src/services/storage.ts @@ -82,7 +82,8 @@ export class WebStorage extends BaseService { case Protocol.NUMBER: return Number(item); case Protocol.BOOLEAN: - return Boolean(item); + if (item === 'true') return true; + if (item === 'false') return false; default: return item; } diff --git a/packages/editor/src/services/ui.ts b/packages/editor/src/services/ui.ts index 5088b97c..537d25b2 100644 --- a/packages/editor/src/services/ui.ts +++ b/packages/editor/src/services/ui.ts @@ -29,6 +29,7 @@ import BaseService from './BaseService'; const state = reactive({ uiSelectMode: false, showSrc: false, + showStylePanel: true, zoom: 1, stageContainerRect: { width: 0, diff --git a/packages/editor/src/theme/common/var.scss b/packages/editor/src/theme/common/var.scss index eddbe735..38379675 100644 --- a/packages/editor/src/theme/common/var.scss +++ b/packages/editor/src/theme/common/var.scss @@ -12,3 +12,5 @@ $sidebar-heder-background-color: $theme-color; $sidebar-content-background-color: #ffffff; $page-bar-height: 32px; + +$props-style-panel-width: 300px; diff --git a/packages/editor/src/theme/props-panel.scss b/packages/editor/src/theme/props-panel.scss index 58b58ada..9241c73d 100644 --- a/packages/editor/src/theme/props-panel.scss +++ b/packages/editor/src/theme/props-panel.scss @@ -1,5 +1,78 @@ +@use "common/var" as *; + .m-editor-props-panel { - padding: 0 10px 50px 10px; + height: 100%; + position: relative; + + --props-style-panel-width: 300px; + + .m-editor-props-form-panel { + padding-bottom: 10px; + position: relative; + height: 100%; + box-sizing: border-box; + + .tmagic-design-scrollbar { + height: 100%; + } + } + + .m-editor-props-property-panel { + &.show-style-panel { + padding-right: var(--props-style-panel-width); + + .m-editor-props-panel-src-icon { + right: calc(15px + var(--props-style-panel-width)); + } + } + + .tmagic-design-form { + padding-right: 10px; + padding-left: 10px; + + > .m-container-tab { + > .tmagic-design-tabs { + > .el-tabs__content { + padding-top: 55px; + } + > .el-tabs__header.is-top { + position: absolute; + top: 0; + width: 100%; + background: #fff; + z-index: 2; + } + } + } + } + } + + .m-editor-props-style-panel { + position: absolute; + width: var(--props-style-panel-width); + right: 0; + top: 0; + background: #fff; + z-index: 12; + + $style-panel-title-height: 38px; + + .tmagic-design-scrollbar { + height: calc(100% - $style-panel-title-height - 1px); + } + + .m-editor-props-style-panel-title { + text-align: center; + font-size: 14px; + font-weight: 600; + padding: 0 5px; + height: $style-panel-title-height; + display: flex; + justify-content: space-between; + align-items: center; + border-bottom: 2px solid $border-color; + } + } .m-editor-props-panel-src-icon { position: absolute; @@ -8,6 +81,13 @@ z-index: 30; } + .m-editor-props-panel-style-icon { + position: absolute; + right: 15px; + bottom: 60px; + z-index: 30; + } + .m-editor-props-panel-src-code.magic-code-editor { position: absolute; left: 0; diff --git a/packages/editor/src/type.ts b/packages/editor/src/type.ts index d87c6172..7bfe258e 100644 --- a/packages/editor/src/type.ts +++ b/packages/editor/src/type.ts @@ -231,6 +231,8 @@ export interface UiState { uiSelectMode: boolean; /** 是否显示整个配置源码, true: 显示, false: 不显示,默认为false */ showSrc: boolean; + /** 是否将样式配置单独一列显示, true: 显示, false: 不显示,默认为true */ + showStylePanel: boolean; /** 画布显示放大倍数,默认为 1 */ zoom: number; /** 画布容器的宽高 */ diff --git a/packages/editor/src/utils/props.ts b/packages/editor/src/utils/props.ts index e61deae2..e68c0737 100644 --- a/packages/editor/src/utils/props.ts +++ b/packages/editor/src/utils/props.ts @@ -18,6 +18,7 @@ */ import { NODE_CONDS_KEY } from '@tmagic/core'; +import { tMagicMessage } from '@tmagic/design'; import type { FormConfig, FormState, TabPaneConfig } from '@tmagic/form'; export const arrayOptions = [ @@ -41,6 +42,7 @@ export const numberOptions = [ export const styleTabConfig: TabPaneConfig = { title: '样式', + display: ({ services }: any) => !(services.uiService.get('showStylePanel') ?? true), items: [ { name: 'style', @@ -53,6 +55,7 @@ export const styleTabConfig: TabPaneConfig = { type: 'data-source-field-select', name: 'position', text: '固定定位', + labelPosition: 'left', checkStrictly: false, dataSourceFieldType: ['string'], fieldConfig: { @@ -213,7 +216,7 @@ export const styleTabConfig: TabPaneConfig = { checkStrictly: false, dataSourceFieldType: ['string'], fieldConfig: { - type: 'text', + type: 'img-upload', }, }, { @@ -344,11 +347,13 @@ export const advancedTabConfig: TabPaneConfig = { { name: 'created', text: 'created', + labelPosition: 'top', type: 'code-select', }, { name: 'mounted', text: 'mounted', + labelPosition: 'top', type: 'code-select', }, ], @@ -389,8 +394,21 @@ export const fillConfig = (config: FormConfig = [], labelWidth = '80px'): FormCo // 组件id,必须要有 { name: 'id', - type: 'display', - text: 'id', + text: 'ID', + type: 'text', + disabled: true, + append: { + type: 'button', + text: '复制', + handler: async (vm, { model }) => { + try { + await navigator.clipboard.writeText(`${model.id}`); + tMagicMessage.success('已复制'); + } catch (err) { + tMagicMessage.error('复制失败'); + } + }, + }, }, { name: 'name',