Files
ndm-web-platform/src/pages/vimp/components/config-panel.vue
T
yangsy b6fb767928 feat(vimp): 新增ScreenPanel和screen-store支持多屏增删与重命名
- 新建 stores/screen.ts(id用 crypto.randomUUID 唯一生成、addScreen/removeScreen/renameScreen actions)
- 新建 screen-panel.vue 替换 canvas-area.vue(NTab + NTabs type=card + addable/closable)
- 添加屏幕增删的二次确认弹窗(window.$dialog.warning/info)
- 双击Tab弹出重命名输入框(沿用删除dialog的交互风格)
- 调整 onClose 入参命名为 id,语义与 store 一致
- 包裹 Tab 区域加 user-select: none,防止双击/拖动时文字被选中
- 附带:config-panel.vue 同步 Prettier 格式化(无逻辑改动)
2026-06-23 14:01:27 +08:00

124 lines
3.3 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<script setup lang="ts">
import { NButton, NIcon, NTabPane, NTabs, NText } from 'naive-ui';
import { ChevronRightIcon, DatabaseIcon, LayoutGridIcon, SlidersHorizontalIcon, ZapIcon } from 'lucide-vue-next';
import { ref, type Component } 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>