refactor(vimp): 重命名右侧面板为ConfigPanel并镜像左侧面板结构
- 删除 right-panel.vue,新建 config-panel.vue + config-panel.ts store - 接入 Pinia store 管理折叠状态,与 ResourcePanel store 结构镜像 - NTabs 改为纵向 placement=right + type=bar,Tab 标签加 lucide 图标 - 标题栏与 Tab 栏 72px 格纵向对齐,折叠后从右截断保留 Tab 标签 - 画布区域移除占位卡片,保留灰色斜纹 + drop 行为 - 删除未实现的"事件陷阱" Tab
This commit is contained in:
@@ -59,10 +59,6 @@ const onDrop = (e: DragEvent) => {
|
||||
}"
|
||||
@dragover="onDragover"
|
||||
@drop="onDrop"
|
||||
>
|
||||
<div :style="{ padding: '12px 24px', border: '1px solid #ddd', borderRadius: '4px', backgroundColor: '#fff', fontSize: '13px' }">
|
||||
{{ screens.find(s => s.id === activeScreen)?.name }} 画布(占位)
|
||||
</div>
|
||||
</div>
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -0,0 +1,131 @@
|
||||
<script setup lang="ts">
|
||||
import { NButton, NIcon, NTabPane, NTabs, NText } from 'naive-ui'
|
||||
import { ChevronRightIcon, DatabaseIcon, LayoutGridIcon, SlidersHorizontalIcon, ZapIcon, type Component } from 'lucide-vue-next'
|
||||
import { ref } from 'vue'
|
||||
import { useConfigPanelStore } from '../stores'
|
||||
import { storeToRefs } from 'pinia'
|
||||
|
||||
interface ControlTabPane {
|
||||
name: string
|
||||
tab: string
|
||||
icon: Component
|
||||
}
|
||||
|
||||
const tabs: ControlTabPane[] = [
|
||||
{ name: 'component', tab: '组件', icon: LayoutGridIcon },
|
||||
{ name: 'config', tab: '属性', icon: SlidersHorizontalIcon },
|
||||
{ name: 'data', tab: '数据', icon: DatabaseIcon },
|
||||
{ name: 'interaction', tab: '事件', icon: ZapIcon },
|
||||
]
|
||||
|
||||
const PANEL_WIDTH_EXPANDED = '320px'
|
||||
const PANEL_WIDTH_COLLAPSED = '72px'
|
||||
const TAB_WIDTH = '72px'
|
||||
|
||||
const activeTab = ref(tabs[0]?.name ?? '')
|
||||
|
||||
const configPanelStore = useConfigPanelStore()
|
||||
const { collapsed } = storeToRefs(configPanelStore)
|
||||
|
||||
const expandConfigPanel = () => {
|
||||
if (collapsed.value) {
|
||||
configPanelStore.toggleCollapsed()
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div
|
||||
:style="{
|
||||
width: collapsed ? PANEL_WIDTH_COLLAPSED : PANEL_WIDTH_EXPANDED,
|
||||
flexShrink: 0,
|
||||
height: '100%',
|
||||
display: 'flex',
|
||||
justifyContent: 'flex-end',
|
||||
overflow: 'hidden',
|
||||
transition: 'width 0.2s',
|
||||
}"
|
||||
>
|
||||
<div
|
||||
:style="{
|
||||
width: PANEL_WIDTH_EXPANDED,
|
||||
height: '100%',
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
}"
|
||||
>
|
||||
<div
|
||||
:style="{
|
||||
height: '42px',
|
||||
flexShrink: 0,
|
||||
padding: '8px 0',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
}"
|
||||
>
|
||||
<div
|
||||
:style="{
|
||||
display: 'grid',
|
||||
placeItems: 'center',
|
||||
width: '32px',
|
||||
marginRight: 'auto',
|
||||
}"
|
||||
>
|
||||
<NButton text @click="configPanelStore.toggleCollapsed()">
|
||||
<NIcon :component="ChevronRightIcon" />
|
||||
</NButton>
|
||||
</div>
|
||||
<div
|
||||
:style="{
|
||||
display: 'grid',
|
||||
placeItems: 'center',
|
||||
width: TAB_WIDTH,
|
||||
}"
|
||||
>
|
||||
<NText>控制</NText>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
:style="{
|
||||
flex: 1,
|
||||
minHeight: 0,
|
||||
overflow: 'hidden',
|
||||
}"
|
||||
>
|
||||
<NTabs
|
||||
v-model:value="activeTab"
|
||||
:type="'bar'"
|
||||
:placement="'right'"
|
||||
:size="'small'"
|
||||
:tab-style="{
|
||||
width: TAB_WIDTH,
|
||||
height: '64px',
|
||||
}"
|
||||
:style="{
|
||||
height: '100%',
|
||||
'--n-pane-padding-top': '0',
|
||||
'--n-tab-gap-vertical': '0',
|
||||
}"
|
||||
>
|
||||
<NTabPane
|
||||
v-for="t in tabs"
|
||||
:key="t.name"
|
||||
:name="t.name"
|
||||
:tab="t.tab"
|
||||
:tab-props="{ onClick: () => expandConfigPanel() }"
|
||||
>
|
||||
<template #tab>
|
||||
<div :style="{ width: '48px', display: 'flex', flexDirection: 'column', justifyContent: 'center', alignItems: 'center' }">
|
||||
<NIcon :size="18" :component="t.icon" />
|
||||
<div :style="{ fontSize: '12px' }">{{ t.tab }}</div>
|
||||
</div>
|
||||
</template>
|
||||
<div :style="{ padding: '20px', textAlign: 'center', fontSize: '12px' }">
|
||||
{{ t.tab }}面板(占位)
|
||||
</div>
|
||||
</NTabPane>
|
||||
</NTabs>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -1,40 +0,0 @@
|
||||
<script setup lang="ts">
|
||||
import { NTabPane, NTabs, NText } from 'naive-ui'
|
||||
import { ref } from 'vue'
|
||||
|
||||
const tabs = [
|
||||
{ name: 'component', tab: '组件' },
|
||||
{ name: 'config', tab: '属性' },
|
||||
{ name: 'data', tab: '数据' },
|
||||
{ name: 'interaction', tab: '事件' },
|
||||
{ name: 'event-trap', tab: '事件陷阱' },
|
||||
]
|
||||
|
||||
const activeTab = ref(tabs[0]?.name ?? '')
|
||||
const collapsed = ref(false)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div :style="{ width: collapsed ? '48px' : '320px', flexShrink: 0, transition: 'width 0.2s' }">
|
||||
<div :style="{ width: '320px', height: '100%', display: 'flex', flexDirection: 'column' }">
|
||||
<div :style="{ height: '42px', flexShrink: 0, display: 'flex', alignItems: 'center', justifyContent: 'space-between', padding: '0 8px' }">
|
||||
<NText>控制</NText>
|
||||
<button
|
||||
:style="{ border: 'none', background: 'transparent', cursor: 'pointer', fontSize: '16px', padding: '4px 8px' }"
|
||||
@click="collapsed = !collapsed"
|
||||
>
|
||||
{{ collapsed ? '›' : '‹' }}
|
||||
</button>
|
||||
</div>
|
||||
<div v-show="!collapsed" :style="{ flex: 1, minHeight: 0, overflow: 'auto', padding: '8px' }">
|
||||
<NTabs v-model:value="activeTab" type="line" size="small" animated>
|
||||
<NTabPane v-for="t in tabs" :key="t.name" :name="t.name" :tab="t.tab">
|
||||
<div :style="{ padding: '20px', textAlign: 'center', fontSize: '12px' }">
|
||||
{{ t.tab }}面板(占位)
|
||||
</div>
|
||||
</NTabPane>
|
||||
</NTabs>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -0,0 +1,15 @@
|
||||
import { defineStore } from 'pinia'
|
||||
import { ref } from 'vue'
|
||||
|
||||
export const useConfigPanelStore = defineStore('vimp-config-panel', () => {
|
||||
const collapsed = ref<boolean>(false)
|
||||
|
||||
const toggleCollapsed = () => {
|
||||
collapsed.value = !collapsed.value
|
||||
}
|
||||
|
||||
return {
|
||||
collapsed,
|
||||
toggleCollapsed,
|
||||
}
|
||||
})
|
||||
@@ -1,3 +1,4 @@
|
||||
export * from './alarm';
|
||||
export * from './camera';
|
||||
export * from './config-panel';
|
||||
export * from './resource-panel';
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<script setup lang="ts">
|
||||
import ResourcePanel from './components/resource-panel.vue'
|
||||
import RightPanel from './components/right-panel.vue'
|
||||
import ConfigPanel from './components/config-panel.vue'
|
||||
import CanvasArea from './components/canvas-area.vue'
|
||||
</script>
|
||||
|
||||
@@ -8,6 +8,6 @@ import CanvasArea from './components/canvas-area.vue'
|
||||
<div style="height: 100%; display: flex; overflow: hidden">
|
||||
<ResourcePanel />
|
||||
<CanvasArea />
|
||||
<RightPanel />
|
||||
<ConfigPanel />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
Reference in New Issue
Block a user