refactor(vimp): 提取资源面板为独立组件并添加pinia存储
- 将原内嵌的资源标签页逻辑提取为独立组件 - 新增专用pinia存储管理资源面板的折叠和搜索状态 - 统一折叠展开与搜索交互的逻辑实现
This commit is contained in:
@@ -0,0 +1,62 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { NButton, NFlex, NIcon, NInput, NPageHeader, NTabPane, NTabs, type TabPaneProps } from 'naive-ui';
|
||||||
|
import { ref, type Component } from 'vue';
|
||||||
|
import AlarmTree from './alarm-tree.vue';
|
||||||
|
import CameraTree from './camera-tree.vue';
|
||||||
|
import { ChevronLeftIcon } from 'lucide-vue-next';
|
||||||
|
import { useResourcePanelStore } from '../stores';
|
||||||
|
import { watchImmediate } from '@vueuse/core';
|
||||||
|
import { storeToRefs } from 'pinia';
|
||||||
|
|
||||||
|
interface ResourceTabPane extends TabPaneProps {
|
||||||
|
name: string;
|
||||||
|
tab: string;
|
||||||
|
component?: Component;
|
||||||
|
}
|
||||||
|
|
||||||
|
const resourceTabPanes: ResourceTabPane[] = [
|
||||||
|
{ name: 'camera', tab: '摄像头', component: CameraTree },
|
||||||
|
{ name: 'alarm', tab: '警报器', component: AlarmTree },
|
||||||
|
{ name: 'monitor', tab: '监视器' },
|
||||||
|
];
|
||||||
|
|
||||||
|
const activeTabName = ref(resourceTabPanes.at(0)?.name ?? '');
|
||||||
|
|
||||||
|
const resourcePanelStore = useResourcePanelStore();
|
||||||
|
const { collapsed, searchInput } = storeToRefs(resourcePanelStore);
|
||||||
|
|
||||||
|
const collapseResourcePanel = () => {
|
||||||
|
if (!collapsed.value) {
|
||||||
|
resourcePanelStore.toggleCollapsed();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const expandResourcePanel = () => {
|
||||||
|
if (collapsed.value) {
|
||||||
|
resourcePanelStore.toggleCollapsed();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<NFlex vertical :size="0" style="width: 480px; height: 100%; overflow: hidden">
|
||||||
|
<NFlex style="width: 100%; min-height: 38px; padding: 8px 16px" :align="'center'">
|
||||||
|
<div @click="expandResourcePanel">资源</div>
|
||||||
|
<template v-if="!collapsed">
|
||||||
|
<NInput clearable :size="'tiny'" :placeholder="'搜索'" style="width: 360px; margin-left: auto" />
|
||||||
|
<NButton text @click="collapseResourcePanel">
|
||||||
|
<NIcon :component="ChevronLeftIcon"></NIcon>
|
||||||
|
</NButton>
|
||||||
|
</template>
|
||||||
|
</NFlex>
|
||||||
|
<NTabs :type="'line'" :placement="'left'" style="height: 100%; flex: 1" v-model:value="activeTabName">
|
||||||
|
<NTabPane v-for="{ name: resourceName, tab: resourceTab, component } in resourceTabPanes" :key="resourceName" :tab="resourceTab" :name="resourceName">
|
||||||
|
<template v-if="!!component && !collapsed">
|
||||||
|
<component :is="component" />
|
||||||
|
</template>
|
||||||
|
</NTabPane>
|
||||||
|
</NTabs>
|
||||||
|
</NFlex>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped></style>
|
||||||
@@ -1,12 +1,28 @@
|
|||||||
import { defineStore } from 'pinia';
|
import { defineStore } from 'pinia';
|
||||||
import { ref } from 'vue';
|
import { ref } from 'vue';
|
||||||
|
|
||||||
|
export interface ResourcePanelSearchInput {
|
||||||
|
enabled: boolean; // 是否启用搜索输入框 (只有在资源面板展开且选择摄像机或警报器时才启用)
|
||||||
|
show: boolean; // 是否显示搜索输入框 (只有当enabled为true时才允许控制显示)
|
||||||
|
value: string; // 搜索输入框的值
|
||||||
|
}
|
||||||
|
|
||||||
export const useResourcePanelStore = defineStore('vimp-resource-panel', () => {
|
export const useResourcePanelStore = defineStore('vimp-resource-panel', () => {
|
||||||
const showSearch = ref<boolean>(false);
|
const collapsed = ref<boolean>(false);
|
||||||
const searchText = ref<string>('');
|
const searchInput = ref<ResourcePanelSearchInput>({
|
||||||
|
enabled: false,
|
||||||
|
show: false,
|
||||||
|
value: '',
|
||||||
|
});
|
||||||
|
|
||||||
|
const toggleCollapsed = () => {
|
||||||
|
collapsed.value = !collapsed.value;
|
||||||
|
};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
showSearch,
|
collapsed,
|
||||||
searchText,
|
searchInput,
|
||||||
|
|
||||||
|
toggleCollapsed,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,19 +1,5 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { NTabPane, NTabs, type TabPaneProps } from 'naive-ui';
|
import ResourcePanel from './components/resource-pannel.vue';
|
||||||
import { ref, type Component } from 'vue';
|
|
||||||
import CameraTree from './components/camera-tree.vue';
|
|
||||||
import AlarmTree from './components/alarm-tree.vue';
|
|
||||||
|
|
||||||
interface ResourceTabPane extends TabPaneProps {
|
|
||||||
name: string;
|
|
||||||
tab: string;
|
|
||||||
component?: Component;
|
|
||||||
}
|
|
||||||
|
|
||||||
const resourceTabPanes: ResourceTabPane[] = [
|
|
||||||
{ name: 'camera', tab: '摄像头', component: CameraTree },
|
|
||||||
{ name: 'alarm', tab: '警报器', component: AlarmTree },
|
|
||||||
];
|
|
||||||
|
|
||||||
const onDragover = (event: DragEvent) => {
|
const onDragover = (event: DragEvent) => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
@@ -43,15 +29,7 @@ const onDrop = (event: DragEvent) => {
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div style="height: 100%; overflow: hidden; display: flex">
|
<div style="height: 100%; overflow: hidden; display: flex">
|
||||||
<div style="width: 540px; height: 100%; overflow: hidden">
|
<ResourcePanel />
|
||||||
<NTabs :type="'line'" :placement="'left'" style="height: 100%">
|
|
||||||
<NTabPane v-for="{ name: resourceName, tab: resourceTab, component } in resourceTabPanes" :key="resourceName" :tab="resourceTab" :name="resourceName">
|
|
||||||
<template v-if="!!component">
|
|
||||||
<component :is="component" />
|
|
||||||
</template>
|
|
||||||
</NTabPane>
|
|
||||||
</NTabs>
|
|
||||||
</div>
|
|
||||||
<div style="flex: 1">
|
<div style="flex: 1">
|
||||||
<div style="height: 480px; background-color: #666; display: grid; place-items: center" @dragover="onDragover" @drop="onDrop">
|
<div style="height: 480px; background-color: #666; display: grid; place-items: center" @dragover="onDragover" @drop="onDrop">
|
||||||
<div>这里是播放器</div>
|
<div>这里是播放器</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user