feat(vimp): 在vimp-page中新增三栏布局占位(resource-panel + canvas-area + right-panel)
新增 components/canvas-area.vue(多屏NTabs + 灰色斜纹画布占位)。新增 components/right-panel.vue(5 NTabs 占位 + 折叠按钮)。改造 vimp-page.vue 为三栏 flex div + 内联样式。保留 ResourcePanel 与原有 drop 行为不动。
This commit is contained in:
@@ -0,0 +1,68 @@
|
||||
<script setup lang="ts">
|
||||
import { NTabs, NTabPane } from 'naive-ui'
|
||||
import { ref } from 'vue'
|
||||
|
||||
const screens = [
|
||||
{ id: 'screen-1', name: '屏幕 1' },
|
||||
{ id: 'screen-2', name: '屏幕 2' },
|
||||
{ id: 'screen-3', name: '屏幕 3' },
|
||||
{ id: 'screen-4', name: '屏幕 4' },
|
||||
]
|
||||
|
||||
const activeScreen = ref(screens[0]?.id ?? '')
|
||||
|
||||
const onDragover = (e: DragEvent) => {
|
||||
e.preventDefault()
|
||||
if (e.dataTransfer) e.dataTransfer.dropEffect = 'copy'
|
||||
}
|
||||
|
||||
const onDrop = (e: DragEvent) => {
|
||||
e.preventDefault()
|
||||
const type = e.dataTransfer?.getData('type')
|
||||
if (!type) return
|
||||
if (type === 'camera' || type === 'alarm') {
|
||||
const code = e.dataTransfer.getData('code')
|
||||
const name = e.dataTransfer.getData('name')
|
||||
window.$message?.info(`播放:${JSON.stringify({ code, name })}`)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div :style="{ flex: 1, minWidth: 0, display: 'flex', flexDirection: 'column' }">
|
||||
<div :style="{ flexShrink: 0, padding: '0 8px' }">
|
||||
<NTabs
|
||||
v-model:value="activeScreen"
|
||||
type="line"
|
||||
size="small"
|
||||
animated
|
||||
>
|
||||
<NTabPane
|
||||
v-for="s in screens"
|
||||
:key="s.id"
|
||||
:name="s.id"
|
||||
:tab="s.name"
|
||||
/>
|
||||
</NTabs>
|
||||
</div>
|
||||
<div
|
||||
:style="{
|
||||
flex: 1,
|
||||
minHeight: 0,
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
backgroundColor: '#f5f5f5',
|
||||
backgroundImage: 'linear-gradient(45deg, #e5e5e5 25%, transparent 25%), linear-gradient(-45deg, #e5e5e5 25%, transparent 25%), linear-gradient(45deg, transparent 75%, #e5e5e5 75%), linear-gradient(-45deg, transparent 75%, #e5e5e5 75%)',
|
||||
backgroundSize: '16px 16px',
|
||||
backgroundPosition: '0 0, 0 8px, 8px -8px, -8px 0',
|
||||
}"
|
||||
@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,40 @@
|
||||
<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>
|
||||
@@ -1,41 +1,13 @@
|
||||
<script setup lang="ts">
|
||||
import ResourcePanel from './components/resource-panel.vue';
|
||||
|
||||
const onDragover = (event: DragEvent) => {
|
||||
event.preventDefault();
|
||||
if (event.dataTransfer) {
|
||||
event.dataTransfer.dropEffect = 'copy';
|
||||
}
|
||||
};
|
||||
|
||||
const onDrop = (event: DragEvent) => {
|
||||
event.preventDefault();
|
||||
const type = event.dataTransfer?.getData('type');
|
||||
if (!type) return;
|
||||
if (type === 'camera') {
|
||||
const code = event.dataTransfer?.getData('code');
|
||||
if (!code) return;
|
||||
const name = event.dataTransfer?.getData('name');
|
||||
window.$message.info(`播放:${JSON.stringify({ code, name })}`);
|
||||
} else if (type === 'alarm') {
|
||||
const code = event.dataTransfer?.getData('code');
|
||||
if (!code) return;
|
||||
const name = event.dataTransfer?.getData('name');
|
||||
window.$message.info(`查看警报器:${JSON.stringify({ code, name })}`);
|
||||
} else {
|
||||
}
|
||||
};
|
||||
import ResourcePanel from './components/resource-panel.vue'
|
||||
import RightPanel from './components/right-panel.vue'
|
||||
import CanvasArea from './components/canvas-area.vue'
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div style="height: 100%; overflow: hidden; display: flex">
|
||||
<div style="height: 100%; display: flex; overflow: hidden">
|
||||
<ResourcePanel />
|
||||
<div style="flex: 1">
|
||||
<div style="height: 480px; background-color: #666; display: grid; place-items: center" @dragover="onDragover" @drop="onDrop">
|
||||
<div>这里是播放器</div>
|
||||
</div>
|
||||
</div>
|
||||
<CanvasArea />
|
||||
<RightPanel />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped></style>
|
||||
|
||||
Reference in New Issue
Block a user