feat: 添加左侧侧边栏折叠功能,优化布局和样式以提升用户体验

This commit is contained in:
xudan 2025-09-15 15:50:22 +08:00
parent de1ffcdd16
commit 911a9fbe2f
5 changed files with 96 additions and 10 deletions

View File

@ -1 +1,2 @@
-Always reply to me in Chinese
文件编码使用 UTF8

Binary file not shown.

After

Width:  |  Height:  |  Size: 597 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 597 B

View File

@ -7,6 +7,8 @@ import { useRoute } from 'vue-router';
import type { RobotRealtimeInfo } from '../apis/robot';
import { getSceneByGroupId, getSceneById, monitorRealSceneById, monitorSceneById } from '../apis/scene';
import expandIcon from '../assets/icons/png/expand.png';
import foldIcon from '../assets/icons/png/fold.png';
import FollowViewNotification from '../components/follow-view-notification.vue';
import { autoDoorSimulationService, type AutoDoorWebSocketData } from '../services/auto-door-simulation.service';
import {
@ -35,6 +37,9 @@ const isMonitorMode = computed(() => route.path.includes('/monitor'));
//
const title = ref<string>('');
//
const leftCollapsed = ref<boolean>(false);
//
watch(
isMonitorMode,
@ -417,13 +422,15 @@ const focusFindKeydownHandler = (event: KeyboardEvent) => {
const isFindKey = event.key === 'f' || event.key === 'F';
if ((event.ctrlKey || event.metaKey) && isFindKey && !isTypingElement(event.target)) {
const raw: any = leftSiderEl.value as any;
const sider: HTMLElement | null = (raw && raw.$el) ? (raw.$el as HTMLElement) : (raw as HTMLElement | null);
const sider: HTMLElement | null = raw && raw.$el ? (raw.$el as HTMLElement) : (raw as HTMLElement | null);
if (sider) {
const input = sider.querySelector('.search input, .search .ant-input') as HTMLInputElement | null;
if (input) {
event.preventDefault();
input.focus();
try { input.select?.(); } catch {}
try {
input.select?.();
} catch {}
}
}
}
@ -454,9 +461,20 @@ const handleGlobalKeydown = (event: KeyboardEvent) => {
</a-flex>
</a-layout-header>
<a-layout class="p-16">
<a-layout-sider :width="320" ref="leftSiderEl">
<a-tabs type="card">
<a-layout class="p-16 main-layout">
<img
:src="leftCollapsed ? expandIcon : foldIcon"
class="sider-toggle"
alt="toggle-sider"
@click="leftCollapsed = !leftCollapsed"
/>
<a-layout-sider
class="left-sider"
:width="leftCollapsed ? 0 : 320"
:style="{ minWidth: leftCollapsed ? '0px' : '320px', overflow: 'hidden' }"
ref="leftSiderEl"
>
<a-tabs type="card" v-show="!leftCollapsed">
<a-tab-pane key="1" :tab="$t('机器人')">
<RobotGroups v-if="editor" :token="EDITOR_KEY" :sid="sid" :current="current?.id" @change="selectRobot" />
</a-tab-pane>
@ -532,4 +550,28 @@ const handleGlobalKeydown = (event: KeyboardEvent) => {
pointer-events: all;
}
}
.main-layout {
position: relative;
}
.left-sider {
position: relative;
left: 36px;
}
.sider-toggle {
position: absolute;
top: 20px;
left: 8px;
width: 36px;
height: 36px;
padding: 8px;
cursor: pointer;
z-index: 10;
background-color: #fff;
border-radius: 4px;
body[data-theme='dark'] & {
background-color: #000;
}
}
</style>

View File

@ -4,6 +4,8 @@ import { computed, onMounted, onUnmounted, provide, ref, type ShallowRef, shallo
import { useI18n } from 'vue-i18n';
import { getSceneById, importBinTaskExcel, pushSceneById, saveSceneById } from '../apis/scene';
import expandIcon from '../assets/icons/png/expand.png';
import foldIcon from '../assets/icons/png/fold.png';
import BatchEditToolbar from '../components/batch-edit-toolbar.vue';
import AutoCreateStorageModal from '../components/modal/auto-create-storage-modal.vue';
import { EditorService } from '../services/editor.service';
@ -111,13 +113,15 @@ const focusFindKeydownHandler = (event: KeyboardEvent) => {
const isFindKey = event.key === 'f' || event.key === 'F';
if ((event.ctrlKey || event.metaKey) && isFindKey && !isTypingElement(event.target)) {
const raw: any = leftSiderEl.value as any;
const sider: HTMLElement | null = (raw && raw.$el) ? (raw.$el as HTMLElement) : (raw as HTMLElement | null);
const sider: HTMLElement | null = raw && raw.$el ? (raw.$el as HTMLElement) : (raw as HTMLElement | null);
if (sider) {
const input = sider.querySelector('.search input, .search .ant-input') as HTMLInputElement | null;
if (input) {
event.preventDefault();
input.focus();
try { input.select?.(); } catch {}
try {
input.select?.();
} catch {}
}
}
}
@ -135,6 +139,9 @@ onUnmounted(() => {
const editable = ref<boolean>(false);
watch(editable, (v) => editor.value?.setState(v));
//
const leftCollapsed = ref<boolean>(false);
const toPush = () => {
Modal.confirm({
class: 'confirm',
@ -275,9 +282,20 @@ const handleAutoCreateStorageCancel = () => {
</a-flex>
</a-layout-header>
<a-layout class="p-16">
<a-layout-sider :width="320" ref="leftSiderEl">
<a-tabs type="card">
<a-layout class="p-16 main-layout">
<img
:src="leftCollapsed ? expandIcon : foldIcon"
class="sider-toggle"
alt="toggle-sider"
@click="leftCollapsed = !leftCollapsed"
/>
<a-layout-sider
class="left-sider"
:width="leftCollapsed ? 0 : 320"
:style="{ minWidth: leftCollapsed ? '0px' : '320px', overflow: 'hidden' }"
ref="leftSiderEl"
>
<a-tabs type="card" v-show="!leftCollapsed">
<a-tab-pane key="1" :tab="$t('机器人')">
<RobotGroups
v-if="editor"
@ -370,4 +388,29 @@ const handleAutoCreateStorageCancel = () => {
pointer-events: all;
}
}
.main-layout {
position: relative;
}
.left-sider {
position: relative;
left: 36px;
}
.sider-toggle {
position: absolute;
top: 20px;
left: 8px;
width: 36px;
height: 36px;
padding: 8px;
cursor: pointer;
z-index: 10;
background-color: #fff;
border-radius: 4px;
body[data-theme='dark'] & {
background-color: #000;
}
}
</style>