From abddcae659b235e78a50668aab46bea51683095d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E8=B0=A2=E4=BA=9A=E6=98=95?= <1549469775@qq.com>
Date: Sat, 22 Feb 2025 19:40:47 +0800
Subject: [PATCH] =?UTF-8?q?feat:=20=E6=B5=8F=E8=A7=88=E5=99=A8?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 src/main/commands/BasicCommand.ts          |  7 ++-
 src/main/commands/TabsCommand.ts           |  4 ++
 src/main/modules/tabs/index.ts             | 18 ++++--
 src/renderer/src/assets/style/_common.scss |  4 ++
 src/renderer/src/pages/[...all].vue        |  2 +-
 src/renderer/src/pages/_ui/App.vue         |  5 ++
 src/renderer/src/pages/_ui/Browser.vue     |  1 +
 src/renderer/src/pages/index.vue           | 92 ++++++++++++++++++++++++++++--
 8 files changed, 120 insertions(+), 13 deletions(-)
 create mode 100644 src/renderer/src/pages/_ui/App.vue

diff --git a/src/main/commands/BasicCommand.ts b/src/main/commands/BasicCommand.ts
index de5608d..44ebb6d 100644
--- a/src/main/commands/BasicCommand.ts
+++ b/src/main/commands/BasicCommand.ts
@@ -1,9 +1,13 @@
 import { app, dialog } from "electron"
 import { inject } from "inversify"
+import Tabs from "main/modules/tabs"
 import WindowManager from "main/modules/window-manager"
 
 export default class BasicCommand {
-    constructor(@inject(WindowManager) private _WindowManager: WindowManager) {
+    constructor(
+        @inject(WindowManager) private _WindowManager: WindowManager,
+        @inject(Tabs) private _Tabs: Tabs
+    ) {
         //
     }
 
@@ -53,6 +57,7 @@ export default class BasicCommand {
                 return
             }
         }
+        this._Tabs.closeAll()
         focusedWindow!.reload()
     }
 }
diff --git a/src/main/commands/TabsCommand.ts b/src/main/commands/TabsCommand.ts
index da022bd..044ceba 100644
--- a/src/main/commands/TabsCommand.ts
+++ b/src/main/commands/TabsCommand.ts
@@ -39,6 +39,10 @@ class TabsCommand {
         this._Tabs.navigate(+index, url)
     }
 
+    closeAll() {
+        this._Tabs.closeAll()
+    }
+
     setActive(index) {
         this._Tabs.changeActive(index)
     }
diff --git a/src/main/modules/tabs/index.ts b/src/main/modules/tabs/index.ts
index 7e933af..2e62f6d 100644
--- a/src/main/modules/tabs/index.ts
+++ b/src/main/modules/tabs/index.ts
@@ -23,11 +23,11 @@ class Tabs extends BaseClass {
 
     private curRect:
         | {
-              x: number
-              y: number
-              width: number
-              height: number
-          }
+            x: number
+            y: number
+            width: number
+            height: number
+        }
         | undefined = undefined
 
     constructor() {
@@ -99,6 +99,14 @@ class Tabs extends BaseClass {
         this.events.emit("update")
     }
 
+    closeAll() {
+        this._tabs = this._tabs.filter(tab => {
+            tab.destroy()
+        })
+        this._tabs = []
+        this.events.emit("update")
+    }
+
     removeAll(index: number[]) {
         index
             .map(v => {
diff --git a/src/renderer/src/assets/style/_common.scss b/src/renderer/src/assets/style/_common.scss
index 651c752..f47851c 100644
--- a/src/renderer/src/assets/style/_common.scss
+++ b/src/renderer/src/assets/style/_common.scss
@@ -20,3 +20,7 @@ body {
 #app {
     height: 100%;
 }
+
+* {
+    user-select: none;
+}
diff --git a/src/renderer/src/pages/[...all].vue b/src/renderer/src/pages/[...all].vue
index 6dbd617..991be30 100644
--- a/src/renderer/src/pages/[...all].vue
+++ b/src/renderer/src/pages/[...all].vue
@@ -1,3 +1,3 @@
 <template>
-    <div>Not Found</div>
+    <div @click="$router.back()">Not Found</div>
 </template>
diff --git a/src/renderer/src/pages/_ui/App.vue b/src/renderer/src/pages/_ui/App.vue
new file mode 100644
index 0000000..101f062
--- /dev/null
+++ b/src/renderer/src/pages/_ui/App.vue
@@ -0,0 +1,5 @@
+<template>
+    <div>
+        app
+    </div>
+</template>
\ No newline at end of file
diff --git a/src/renderer/src/pages/_ui/Browser.vue b/src/renderer/src/pages/_ui/Browser.vue
index 35971ee..225fa4d 100644
--- a/src/renderer/src/pages/_ui/Browser.vue
+++ b/src/renderer/src/pages/_ui/Browser.vue
@@ -28,6 +28,7 @@ const { stop } = useResizeObserver(PlaceHolder, () => {
 
 onBeforeUnmount(() => {
     stop()
+    api.call("TabsCommand.closeAll")
 })
 
 const list = ref<any[]>([])
diff --git a/src/renderer/src/pages/index.vue b/src/renderer/src/pages/index.vue
index dc280d9..9ceb9e6 100644
--- a/src/renderer/src/pages/index.vue
+++ b/src/renderer/src/pages/index.vue
@@ -1,18 +1,98 @@
 <script setup lang="ts">
-import Browser from "./_ui/Browser.vue"
+import { defineAsyncComponent } from "vue"
+
+const active = ref()
+const allApp = [
+    { label: "浏览器", comp: defineAsyncComponent(() => import("./_ui/Browser.vue")) },
+    { label: "观山", comp: defineAsyncComponent(() => import("./_ui/App.vue")) },
+    { label: "听雨", comp: defineAsyncComponent(() => import("./_ui/App.vue")) },
+    { label: "赏月", comp: defineAsyncComponent(() => import("./_ui/App.vue")) },
+    { label: "抚琴", comp: defineAsyncComponent(() => import("./_ui/App.vue")) },
+    { label: "望云", comp: defineAsyncComponent(() => import("./_ui/App.vue")) },
+    { label: "踏雪", comp: defineAsyncComponent(() => import("./_ui/App.vue")) },
+    { label: "卧松", comp: defineAsyncComponent(() => import("./_ui/App.vue")) },
+    { label: "泛舟", comp: defineAsyncComponent(() => import("./_ui/App.vue")) },
+    { label: "弈星", comp: defineAsyncComponent(() => import("./_ui/App.vue")) },
+    { label: "垂钓", comp: defineAsyncComponent(() => import("./_ui/App.vue")) },
+    { label: "采菊", comp: defineAsyncComponent(() => import("./_ui/App.vue")) },
+    { label: "倚栏", comp: defineAsyncComponent(() => import("./_ui/App.vue")) },
+    { label: "望霞", comp: defineAsyncComponent(() => import("./_ui/App.vue")) },
+    { label: "枕风", comp: defineAsyncComponent(() => import("./_ui/App.vue")) },
+    { label: "沐泉", comp: defineAsyncComponent(() => import("./_ui/App.vue")) },
+    { label: "汲露", comp: defineAsyncComponent(() => import("./_ui/App.vue")) },
+    { label: "步竹", comp: defineAsyncComponent(() => import("./_ui/App.vue")) },
+    { label: "剪烛", comp: defineAsyncComponent(() => import("./_ui/App.vue")) },
+    { label: "拾阶", comp: defineAsyncComponent(() => import("./_ui/App.vue")) },
+    { label: "撷兰", comp: defineAsyncComponent(() => import("./_ui/App.vue")) },
+    { label: "访柳", comp: defineAsyncComponent(() => import("./_ui/App.vue")) },
+    { label: "谒梅", comp: defineAsyncComponent(() => import("./_ui/App.vue")) },
+    { label: "拨荷", comp: defineAsyncComponent(() => import("./_ui/App.vue")) },
+    { label: "望鹤", comp: defineAsyncComponent(() => import("./_ui/App.vue")) },
+]
 </script>
 
 <template>
     <div h-full flex>
-        <div w="200px" relative>
-            <div p="8px 10px" text="12px" @click="$router.push('/_ui/Browser')" border border-b cursor="pointer" hover:bg-gray-100>浏览器</div>
-            <div p="8px 10px" text="12px" border border-b cursor="pointer" hover:bg-gray-100>浏览器</div>
+        <div w="100px" relative max-w="200px" min-w="80px">
+            <div overflow-hidden>
+                <div
+                    v-for="(app, index) in allApp"
+                    p="8px 10px"
+                    text="12px"
+                    border
+                    border-b
+                    h="30px"
+                    cursor="pointer"
+                    @click="active = index"
+                    hover:bg-gray-50
+                    class="item"
+                    transition-all
+                    :class="{ active: active === index }"
+                >
+                    <div class="text" transition-all position="absolute" left="10px">{{ app.label }}</div>
+                </div>
+            </div>
             <AdjustLine></AdjustLine>
         </div>
         <div b-l="1px solid #E5E5E5" flex-1 w-0 overflow-auto flex flex-col>
-            <Browser></Browser>
+            <component v-if="allApp[active]" :is="allApp[active].comp"></component>
         </div>
     </div>
 </template>
 
-<style lang="scss" scoped></style>
+<style lang="scss" scoped>
+.item {
+    position: relative;
+    &::before {
+        content: "";
+        position: absolute;
+        left: 0;
+        top: 0;
+        height: 100%;
+        width: 6px;
+        background-color: #f3f4f6;
+        transition: all linear 300ms;
+    }
+    &:hover {
+        &::before {
+            width: 30px;
+        }
+        .text {
+            left: 20px;
+        }
+    }
+    &.active {
+        @apply: text-black;
+        &::before {
+            width: 100%;
+        }
+        .text {
+            left: 50%;
+            transform: translateX(-50%);
+        }
+    }
+    .text {
+        transition-duration: 300ms;
+    }
+}
+</style>