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 { ref } from 'vue';
|
||||
|
||||
export interface ResourcePanelSearchInput {
|
||||
enabled: boolean; // 是否启用搜索输入框 (只有在资源面板展开且选择摄像机或警报器时才启用)
|
||||
show: boolean; // 是否显示搜索输入框 (只有当enabled为true时才允许控制显示)
|
||||
value: string; // 搜索输入框的值
|
||||
}
|
||||
|
||||
export const useResourcePanelStore = defineStore('vimp-resource-panel', () => {
|
||||
const showSearch = ref<boolean>(false);
|
||||
const searchText = ref<string>('');
|
||||
const collapsed = ref<boolean>(false);
|
||||
const searchInput = ref<ResourcePanelSearchInput>({
|
||||
enabled: false,
|
||||
show: false,
|
||||
value: '',
|
||||
});
|
||||
|
||||
const toggleCollapsed = () => {
|
||||
collapsed.value = !collapsed.value;
|
||||
};
|
||||
|
||||
return {
|
||||
showSearch,
|
||||
searchText,
|
||||
collapsed,
|
||||
searchInput,
|
||||
|
||||
toggleCollapsed,
|
||||
};
|
||||
});
|
||||
|
||||
@@ -1,19 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import { NTabPane, NTabs, type TabPaneProps } from 'naive-ui';
|
||||
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 },
|
||||
];
|
||||
import ResourcePanel from './components/resource-pannel.vue';
|
||||
|
||||
const onDragover = (event: DragEvent) => {
|
||||
event.preventDefault();
|
||||
@@ -43,15 +29,7 @@ const onDrop = (event: DragEvent) => {
|
||||
|
||||
<template>
|
||||
<div style="height: 100%; overflow: hidden; display: flex">
|
||||
<div style="width: 540px; height: 100%; overflow: hidden">
|
||||
<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>
|
||||
<ResourcePanel />
|
||||
<div style="flex: 1">
|
||||
<div style="height: 480px; background-color: #666; display: grid; place-items: center" @dragover="onDragover" @drop="onDrop">
|
||||
<div>这里是播放器</div>
|
||||
|
||||
Reference in New Issue
Block a user