From bb2a5cdb399ff78ae7abef7b91bcf4615824fa62 Mon Sep 17 00:00:00 2001
From: npmrun <1549469775@qq.com>
Date: Thu, 20 Feb 2025 23:41:29 +0800
Subject: [PATCH] fix bug

---
 .vscode/settings.json                      |   2 +-
 src/main/commands/BasicCommand.ts          |  57 ++++-
 src/renderer/index.html                    |  30 +--
 src/renderer/src/components/AdjustLine.vue | 292 +++++++++++++++++++---
 src/renderer/src/components/NavBar.vue     |  39 ++-
 src/renderer/src/pages/index.vue           | 387 +++++++++++++++++++++++++----
 6 files changed, 707 insertions(+), 100 deletions(-)

diff --git a/.vscode/settings.json b/.vscode/settings.json
index 0d09930..7e74831 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -1,6 +1,6 @@
 {
     "[typescript]": {
-        "editor.defaultFormatter": "esbenp.prettier-vscode"
+        "editor.defaultFormatter": "vscode.typescript-language-features"
     },
     "[javascript]": {
         "editor.defaultFormatter": "esbenp.prettier-vscode"
diff --git a/src/main/commands/BasicCommand.ts b/src/main/commands/BasicCommand.ts
index eb3889b..de5608d 100644
--- a/src/main/commands/BasicCommand.ts
+++ b/src/main/commands/BasicCommand.ts
@@ -1,5 +1,58 @@
+import { app, dialog } from "electron"
+import { inject } from "inversify"
+import WindowManager from "main/modules/window-manager"
+
 export default class BasicCommand {
-    log() {
-        console.log("1231")
+    constructor(@inject(WindowManager) private _WindowManager: WindowManager) {
+        //
+    }
+
+    toggleDevTools() {
+        const focusedWindow = this._WindowManager.getFocusWindow()
+        if (focusedWindow) {
+            // @ts-ignore ...
+            focusedWindow.toggleDevTools()
+        }
+    }
+    fullscreen() {
+        const focusedWindow = this._WindowManager.getFocusWindow()
+        const isFullScreen = focusedWindow!.isFullScreen()
+        focusedWindow!.setFullScreen(!isFullScreen)
+        return !isFullScreen
+    }
+    isFullscreen() {
+        const focusedWindow = this._WindowManager.getFocusWindow()
+        return focusedWindow!.isFullScreen()
+    }
+
+    relunch() {
+        app.relaunch()
+        app.exit()
+    }
+
+    reload() {
+        const focusedWindow = this._WindowManager.getFocusWindow()
+        // 重载之后, 刷新并关闭所有的次要窗体
+        if (this._WindowManager.length() > 1 && focusedWindow && focusedWindow.$$opts!.name === this._WindowManager.mainInfo.name) {
+            const choice = dialog.showMessageBoxSync(focusedWindow, {
+                type: "question",
+                buttons: ["取消", "是的,继续", "不,算了"],
+                title: "警告",
+                defaultId: 2,
+                cancelId: 0,
+                message: "警告",
+                detail: "重载主窗口将关闭所有子窗口,是否继续",
+            })
+            if (choice == 1) {
+                this._WindowManager.getWndows().forEach(win => {
+                    if (win.$$opts!.name !== this._WindowManager.mainInfo.name) {
+                        win.close()
+                    }
+                })
+            } else {
+                return
+            }
+        }
+        focusedWindow!.reload()
     }
 }
diff --git a/src/renderer/index.html b/src/renderer/index.html
index 82eacab..2cf2727 100644
--- a/src/renderer/index.html
+++ b/src/renderer/index.html
@@ -1,17 +1,19 @@
 <!doctype html>
 <html>
-    <head>
-        <meta charset="UTF-8" />
-        <title>Electron</title>
-        <!-- https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP -->
-        <meta
-            http-equiv="Content-Security-Policy"
-            content="default-src 'self' api: 'unsafe-inline'; script-src 'self' api:; style-src 'self' 'unsafe-inline'; img-src 'self' data:;"
-        />
-    </head>
 
-    <body>
-        <div id="app"></div>
-        <script type="module" src="/src/main.ts"></script>
-    </body>
-</html>
+<head>
+    <meta charset="UTF-8" />
+    <title>Electron</title>
+    <!-- https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP -->
+    <meta http-equiv="Content-Security-Policy" content="default-src 'self' api: 'unsafe-inline'; 
+             script-src 'self' api:; 
+             style-src 'self' 'unsafe-inline'; 
+             img-src 'self' data: *;" />
+</head>
+
+<body>
+    <div id="app"></div>
+    <script type="module" src="/src/main.ts"></script>
+</body>
+
+</html>
\ No newline at end of file
diff --git a/src/renderer/src/components/AdjustLine.vue b/src/renderer/src/components/AdjustLine.vue
index d0d31a1..d399061 100644
--- a/src/renderer/src/components/AdjustLine.vue
+++ b/src/renderer/src/components/AdjustLine.vue
@@ -1,17 +1,29 @@
 <template>
-    <div class="adjust-line" :class="['adjust-line__' + direction]" ref="adjustLineEL"></div>
+    <div ref="adjustLineEL" :class="['adjust-line', `adjust-line--${direction}`, { 'adjust-line--dragging': isDragging }]">
+        <div class="adjust-line__handle">
+            <div class="adjust-line__grip">
+                <span class="grip-line"></span>
+                <span class="grip-line"></span>
+            </div>
+        </div>
+    </div>
 </template>
 
 <script setup lang="ts">
-import { nextTick, onMounted, ref, watch } from "vue"
+import { nextTick, onMounted, ref, watch, computed, onBeforeUnmount, onErrorCaptured } from "vue"
+import { useDebounceFn } from "@vueuse/core"
 
 const adjustLineEL = ref<HTMLElement>()
 
-type IProps = {
+// 定义方向类型
+type Direction = "left" | "right" | "top" | "bottom"
+
+// 优化Props接口
+interface AdjustLineProps {
     /**
      * 所在方向 'left' | 'right' | 'top' | 'bottom'
      */
-    direction?: "left" | "right" | "top" | "bottom"
+    direction?: Direction
     /**
      * 需要调整的元素
      */
@@ -24,14 +36,86 @@ type IProps = {
      * 唯一ID
      */
     mid?: string
+    minSize?: number
+    maxSize?: number
+    defaultSize?: number
+    onChange?: (size: number) => void
 }
 
-const props = withDefaults(defineProps<IProps>(), {
+const props = withDefaults(defineProps<AdjustLineProps>(), {
     direction: "right",
+    minSize: 100,
+    maxSize: 800,
 })
 
+// 定义事件
+const emit = defineEmits<{
+    (e: "resize", size: number): void
+    (e: "resizeStart"): void
+    (e: "resizeEnd", size: number): void
+}>()
+
 let curTarget: HTMLElement | undefined | null
 
+const isDragging = ref(false)
+const currentSize = ref(props.defaultSize || 0)
+
+// 使用computed优化方向判断
+const isHorizontal = computed(() => props.direction === "left" || props.direction === "right")
+
+// 使用computed获取光标样式
+const cursorStyle = computed(() => (isHorizontal.value ? "ew-resize" : "ns-resize"))
+
+// 保存状态到localStorage的优化
+const storageKey = computed(() => `adjust-line-${props.mid}`)
+
+function saveSize(size: number) {
+    if (props.mid) {
+        try {
+            localStorage.setItem(storageKey.value, String(size))
+        } catch (error) {
+            console.warn("Failed to save size to localStorage:", error)
+        }
+    }
+}
+
+function loadSavedSize(): number | null {
+    if (props.mid) {
+        try {
+            const saved = localStorage.getItem(storageKey.value)
+            return saved ? Number(saved) : null
+        } catch (error) {
+            console.warn("Failed to load size from localStorage:", error)
+            return null
+        }
+    }
+    return null
+}
+
+// 使用防抖优化resize事件
+const emitResize = useDebounceFn((size: number) => {
+    emit("resize", size)
+}, 16)
+
+// 使用ResizeObserver监听容器大小变化
+const observeResize = () => {
+    if (!adjustLineEL.value) return
+
+    const observer = new ResizeObserver(() => {
+        if (curTarget) {
+            const size = isHorizontal.value ? curTarget.clientWidth : curTarget.clientHeight
+            currentSize.value = size
+            emitResize(size)
+        }
+    })
+
+    observer.observe(adjustLineEL.value)
+
+    onBeforeUnmount(() => {
+        observer.disconnect()
+    })
+}
+
 onMounted(async () => {
     await nextTick()
     if (!props.target) {
@@ -51,6 +135,7 @@ onMounted(async () => {
             }
         },
     )
+    observeResize()
 })
 
 function handle(target: HTMLElement) {
@@ -231,49 +316,198 @@ function handle(target: HTMLElement) {
         }
     }
 }
+
+function handleDrag(e: MouseEvent, target: HTMLElement) {
+    const startPos = isHorizontal.value ? e.clientX : e.clientY
+    const startSize = isHorizontal.value ? target.clientWidth : target.clientHeight
+
+    const handleMouseMove = (e: MouseEvent) => {
+        const currentPos = isHorizontal.value ? e.clientX : e.clientY
+        const diff = props.direction === "right" || props.direction === "bottom" ? startPos - currentPos : currentPos - startPos
+
+        let newSize = startSize - diff
+
+        // 限制大小范围
+        newSize = Math.max(props.minSize, Math.min(props.maxSize, newSize))
+
+        // 应用新尺寸
+        if (isHorizontal.value) {
+            target.style.width = `${newSize}px`
+        } else {
+            target.style.height = `${newSize}px`
+        }
+
+        currentSize.value = newSize
+        emit("resize", newSize)
+    }
+
+    const handleMouseUp = () => {
+        document.removeEventListener("mousemove", handleMouseMove)
+        document.removeEventListener("mouseup", handleMouseUp)
+        document.body.style.userSelect = ""
+        isDragging.value = false
+        saveSize(currentSize.value)
+        emit("resizeEnd", currentSize.value)
+    }
+
+    document.addEventListener("mousemove", handleMouseMove)
+    document.addEventListener("mouseup", handleMouseUp)
+    document.body.style.userSelect = "none"
+    isDragging.value = true
+    emit("resizeStart")
+}
+
+const debug = {
+    log: (...args: any[]) => {
+        if (process.env.NODE_ENV === "development") {
+            console.log("[AdjustLine]", ...args)
+        }
+    },
+    error: (...args: any[]) => {
+        console.error("[AdjustLine]", ...args)
+    },
+}
+
+function handleError(error: Error, context: string) {
+    debug.error(`Error in ${context}:`, error)
+    // 可以添加错误上报逻辑
+}
+
+// 错误边界处理
+onErrorCaptured((err, instance, info) => {
+    handleError(err as Error, info)
+    return false
+})
 </script>
 
 <style lang="scss" scoped>
 .adjust-line {
     position: absolute;
     z-index: 999;
-    transition: background-color 0.5s ease;
 
-    &:hover,
-    &:active {
-        background: #1976d2;
+    &__handle {
+        position: absolute;
+        display: flex;
+        align-items: center;
+        justify-content: center;
+        background: transparent;
+        transition: all 0.2s ease;
+    }
+
+    &__grip {
+        display: flex;
+        gap: 3px;
+        opacity: 0;
+        transition: opacity 0.2s;
+
+        .adjust-line:hover &,
+        .adjust-line--dragging & {
+            opacity: 1;
+        }
+    }
+
+    .grip-line {
+        background-color: #999;
+        border-radius: 1px;
+
+        .adjust-line:hover &,
+        .adjust-line--dragging & {
+            background-color: #666;
+        }
     }
 
-    &__left {
-        left: -2px;
+    // 水平方向的调整线
+    &--left,
+    &--right {
         top: 0;
         bottom: 0;
-        width: 4px;
-        cursor: ew-resize;
+        width: 10px; // 增加可点击区域
+        cursor: col-resize;
+
+        .adjust-line__handle {
+            left: 0;
+            top: 0;
+            bottom: 0;
+            width: 100%;
+        }
+
+        .adjust-line__grip {
+            flex-direction: column;
+        }
+
+        .grip-line {
+            width: 2px;
+            height: 16px;
+        }
+
+        &:hover .adjust-line__handle {
+            background-color: rgba(0, 0, 0, 0.05);
+        }
     }
 
-    &__top {
-        top: -2px;
+    // 垂直方向的调整线
+    &--top,
+    &--bottom {
         left: 0;
         right: 0;
-        height: 4px;
-        cursor: n-resize;
+        height: 10px; // 增加可点击区域
+        cursor: row-resize;
+
+        .adjust-line__handle {
+            top: 0;
+            left: 0;
+            right: 0;
+            height: 100%;
+        }
+
+        .adjust-line__grip {
+            flex-direction: row;
+        }
+
+        .grip-line {
+            width: 16px;
+            height: 2px;
+        }
+
+        &:hover .adjust-line__handle {
+            background-color: rgba(0, 0, 0, 0.05);
+        }
     }
 
-    &__bottom {
-        bottom: -2px;
-        left: 0;
-        right: 0;
-        height: 4px;
-        cursor: n-resize;
+    // 调整位置以居中
+    &--left {
+        left: -5px;
+    }
+    &--right {
+        right: -5px;
+    }
+    &--top {
+        top: -5px;
+    }
+    &--bottom {
+        bottom: -5px;
     }
 
-    &__right {
-        right: -2px;
-        top: 0;
-        bottom: 0;
-        width: 4px;
-        cursor: ew-resize;
+    // 拖动时的全局遮罩
+    &--dragging {
+        &::after {
+            content: "";
+            position: fixed;
+            top: 0;
+            left: 0;
+            right: 0;
+            bottom: 0;
+            z-index: -1;
+            cursor: inherit;
+        }
+
+        .adjust-line__handle {
+            background-color: rgba(0, 0, 0, 0.08);
+        }
+
+        .grip-line {
+            background-color: #666;
+        }
     }
 }
 </style>
diff --git a/src/renderer/src/components/NavBar.vue b/src/renderer/src/components/NavBar.vue
index a8f6ac4..90d8706 100644
--- a/src/renderer/src/components/NavBar.vue
+++ b/src/renderer/src/components/NavBar.vue
@@ -1,5 +1,14 @@
 <template>
-    <div relative h="30px" leading="29px" pr="137px" select-none border-b="1px solid #E5E5E5" bg="#F8F8F8">
+    <div
+        relative
+        h="30px"
+        leading="29px"
+        pr="137px"
+        :style="{ paddingRight: isFullScreen ? '0' : '' }"
+        select-none
+        border-b="1px solid #E5E5E5"
+        bg="#F8F8F8"
+    >
         <div absolute top-0 right-0 bottom-0 left-0 style="-webkit-app-region: drag"></div>
         <div h-full px-2 flex items-center gap-1 justify-between>
             <div flex items-center gap-1>
@@ -21,17 +30,39 @@ import icon from "@res/icon.png"
 import config from "config"
 import { PopupMenu } from "@/bridge/PopupMenu"
 
+const isFullScreen = ref(false)
+onBeforeMount(async () => {
+    isFullScreen.value = await api.call("BasicCommand.isFullscreen")
+})
 const onClickMenu = () => {
     const menu = new PopupMenu([
         {
-            label: "关于",
-            click() {
-                fetch("api://fuck/BasicService/showAbout")
+            label: "全屏",
+            async click() {
+                isFullScreen.value = await api.call("BasicCommand.fullscreen")
+            },
+        },
+        {
+            label: "切换开发者工具",
+            async click() {
+                isFullScreen.value = await api.call("BasicCommand.toggleDevTools")
             },
         },
         {
             type: "separator",
         },
+        {
+            label: "重载",
+            click() {
+                api.call("BasicCommand.reload")
+            },
+        },
+        {
+            label: "重启",
+            click() {
+                api.call("BasicCommand.relunch")
+            },
+        },
     ])
     menu.show()
 }
diff --git a/src/renderer/src/pages/index.vue b/src/renderer/src/pages/index.vue
index 3cfd35a..31d6727 100644
--- a/src/renderer/src/pages/index.vue
+++ b/src/renderer/src/pages/index.vue
@@ -1,5 +1,5 @@
 <script setup lang="ts">
-import { onBeforeMount, onBeforeUnmount, onMounted, ref, useTemplateRef } from "vue"
+import { onBeforeMount, onBeforeUnmount, onMounted, ref, useTemplateRef, nextTick } from "vue"
 import { PopupMenu } from "@/bridge/PopupMenu"
 
 // const PlaceHolderRef = useTemplateRef("PlaceHolder")
@@ -25,6 +25,7 @@ const { stop } = useResizeObserver(PlaceHolder, () => {
         api.call("TabsCommand.bindElement", rect)
     }
 })
+
 onBeforeUnmount(() => {
     stop()
 })
@@ -89,8 +90,19 @@ function handleTabContextMenu(_, index) {
     menu.show()
 }
 
-function changeTab(_, index) {
-    api.call("TabsCommand.setActive", index)
+function scrollTabIntoView(index: number) {
+    nextTick(() => {
+        const tabList = document.querySelector('.tab-list')
+        const tabItems = tabList?.querySelectorAll('.tab-item')
+        if (tabList && tabItems && tabItems[index]) {
+            tabItems[index].scrollIntoView({ behavior: 'smooth', block: 'nearest', inline: 'nearest' })
+        }
+    })
+}
+
+async function changeTab(_, index) {
+    await api.call("TabsCommand.setActive", index)
+    scrollTabIntoView(index)
 }
 
 function addTabInput() {
@@ -102,8 +114,10 @@ function addTabInput() {
         }
     }
 }
-function addTab() {
-    api.call("TabsCommand.add", "about:blank")
+
+async function addTab() {
+    await api.call("TabsCommand.add", "about:blank")
+    scrollTabIntoView(list.value.length - 1)
 }
 
 async function closeTab(_, index) {
@@ -135,57 +149,330 @@ function onClickDevTool() {
             <AdjustLine></AdjustLine>
         </div>
         <div b-l="1px solid #E5E5E5" flex-1 w-0 overflow-auto flex flex-col>
-            <div h="100px" flex flex-col b-b="1px solid #E5E5E5">
-                <div flex gap-1 my-1 px-1 w-full>
-                    <div
-                        v-for="(item, index) in list"
-                        :key="index"
-                        p-1
-                        b-b="1px solid gray"
-                        b-l="1px solid gray"
-                        b-r="1px solid gray"
-                        :b-t="item.isActive ? '1px solid red' : '1px solid gray'"
-                        flex
-                        flex-1
-                        w-0
-                        items-center
-                        cursor="pointer"
-                        gap="5px"
-                        max-w="200px"
-                        @contextmenu="handleTabContextMenu(item, index)"
-                        @click="changeTab(item, index)"
-                    >
-                        <div flex-1 w-0 line-1 text-normal>{{ item.title || "加载中..." }}</div>
-                        <span p-1 rounded hover="bg-gray-2 text-hover" @click.stop="closeTab(item, index)">X</span>
+            <!-- Tab栏 -->
+            <div h="100px" flex flex-col b-b="1px solid var(--border-color)" class="tab-container">
+                <!-- Tab列表 -->
+                <div class="tab-list-container">
+                    <div class="tab-list">
+                        <div
+                            v-for="(item, index) in list"
+                            :key="index"
+                            :class="{
+                                'tab-item': true,
+                                'active': item.isActive
+                            }"
+                            @contextmenu="handleTabContextMenu(item, index)"
+                            @click="changeTab(item, index)"
+                        >
+                            <div class="tab-content">
+                                <!-- 网站图标 -->
+                                <img 
+                                    v-if="item.favicons?.length" 
+                                    :src="item.favicons[0]" 
+                                    class="tab-icon"
+                                    alt=""
+                                />
+                                <div v-else class="tab-icon-placeholder"></div>
+                                
+                                <!-- 标题 -->
+                                <div class="tab-title">{{ item.title || "加载中..." }}</div>
+                                
+                                <!-- 关闭按钮 -->
+                                <div class="tab-close" @click.stop="closeTab(item, index)">
+                                    <svg width="16" height="16" viewBox="0 0 16 16">
+                                        <path d="M12.81 4.36l-1.17-1.17L8 6.83 4.36 3.19 3.19 4.36 6.83 8l-3.64 3.64 1.17 1.17L8 9.17l3.64 3.64 1.17-1.17L9.17 8z" 
+                                            fill="currentColor"/>
+                                    </svg>
+                                </div>
+                            </div>
+                        </div>
                     </div>
-                    <div
-                        p-1
-                        b-b="1px solid gray"
-                        b-l="1px solid gray"
-                        b-r="1px solid gray"
-                        b-t="1px solid gray"
-                        flex
-                        items-center
-                        cursor="pointer"
-                        gap="5px"
-                        hover="bg-gray-2 text-hover"
-                    >
-                        <span p-1 rounded @click.stop="addTab()">+</span>
+                    
+                    <!-- 新建标签页按钮移到容器外部 -->
+                    <div class="new-tab-button-container">
+                        <div class="new-tab-button" @click.stop="addTab()">
+                            <svg width="20" height="20" viewBox="0 0 20 20">
+                                <path d="M10 4v12M4 10h12" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/>
+                            </svg>
+                        </div>
                     </div>
                 </div>
-                <div mx="5px" overflow="auto" flex-1 h-0 flex items-center gap-x="5px">
-                    <div flex-1 w-0 h="35px" px-3 rounded="35px" b="1px solid gray-4" flex items-center>
-                        <input v-model="curUrl" placeholder="输入点什么" w-full text="16px" b-0 leading="25px" outline-0 type="text" />
-                    </div>
-                    <div inline-block hover="bg-gray-2 text-hover" px-1 py-1 rounded cursor="pointer" @click="addTabInput()">
-                        <button text="14px" bg-transparent b-0 cursor="pointer">前往</button>
-                    </div>
-                    <div inline-block hover="bg-gray-2 text-hover" px-1 py-1 rounded cursor="pointer" @click="onClickDevTool()">
-                        <button text="14px" bg-transparent b-0 cursor="pointer">DevTool</button>
+
+                <!-- 地址栏 -->
+                <div class="address-bar">
+                    <div class="url-input-container">
+                        <input 
+                            v-model="curUrl" 
+                            placeholder="输入网址" 
+                            type="text"
+                            class="url-input"
+                        />
                     </div>
+                    <button class="action-button" @click="addTabInput()">前往</button>
+                    <button class="action-button" @click="onClickDevTool()">DevTool</button>
                 </div>
             </div>
-            <div ref="PlaceHolder" ml="1px" flex-1 h-0 flex items-center justify-center>fuck</div>
+
+            <!-- 内容区域 -->
+            <div ref="PlaceHolder" ml="1px" flex-1 h-0 flex items-center justify-center>
+                <!-- 保持原有内容 -->
+            </div>
         </div>
     </div>
 </template>
+
+<style scoped>
+.tab-container {
+    background: var(--tab-bar-bg, #f3f3f3);
+    border-bottom: none;
+    padding-top: 4px;
+    height: auto;
+    min-height: 80px;
+}
+
+.tab-list-container {
+    position: relative;
+    display: flex;
+    align-items: flex-end;
+    height: 32px;
+    padding: 0;
+    margin-bottom: 0;
+    width: 100%;
+    overflow: auto;
+}
+
+.tab-list {
+    height: 32px;
+    display: flex;
+    align-items: flex-end;
+    gap: 0;
+    margin-bottom: 0;
+    overflow-x: auto;
+    overflow-y: hidden;
+    padding: 0 4px;
+    /* 隐藏滚动条但保持功能 */
+    scrollbar-width: none; /* Firefox */
+    -ms-overflow-style: none; /* IE and Edge */
+    &::-webkit-scrollbar {
+        display: none; /* Chrome, Safari and Opera */
+    }
+}
+
+.tab-item {
+    position: relative;
+    min-width: 160px;
+    max-width: 240px;
+    height: 29px;
+    margin-right: -6px;
+    border-radius: 6px 6px 0 0;
+    background: var(--tab-bg, #dee1e6);
+    transition: all 0.15s ease;
+    z-index: 1;
+    display: flex;
+    align-items: center;
+    flex-shrink: 0; /* 防止标签被压缩 */
+    cursor: pointer;
+}
+
+.tab-item::after {
+    content: '';
+    position: absolute;
+    right: 0;
+    top: 6px;
+    height: 16px;
+    width: 1px;
+    background: var(--tab-separator-color, #bdc1c6);
+    opacity: 0.3;
+}
+
+.tab-item:hover {
+    background: var(--tab-hover-bg, #e9ebee);
+}
+
+.tab-item.active {
+    background: var(--tab-active-bg, #fff);
+    z-index: 2;
+    height: 32px;
+    margin-bottom: -1px;
+}
+
+.tab-item.active::before {
+    content: '';
+    position: absolute;
+    left: 0;
+    right: 0;
+    top: 0;
+    height: 2px;
+    background: var(--primary-color, #1a73e8);
+    border-radius: 2px 2px 0 0;
+}
+
+.tab-content {
+    display: flex;
+    align-items: center;
+    padding: 0 8px;
+    height: 100%;
+    gap: 6px;
+    width: 100%;
+}
+
+.tab-icon {
+    width: 16px;
+    height: 16px;
+    flex-shrink: 0;
+    border-radius: 3px;
+}
+
+.tab-icon-placeholder {
+    width: 16px;
+    height: 16px;
+    background: #bdc1c6;
+    border-radius: 50%;
+    flex-shrink: 0;
+    opacity: 0.7;
+}
+
+.tab-title {
+    flex: 1;
+    overflow: hidden;
+    text-overflow: ellipsis;
+    white-space: nowrap;
+    font-size: 12px;
+    color: var(--text-color, #5f6368);
+    line-height: 1.2;
+    padding-right: 4px;
+}
+
+.tab-item.active .tab-title {
+    color: var(--active-text-color, #202124);
+}
+
+.tab-close {
+    width: 16px;
+    height: 16px;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    border-radius: 50%;
+    color: var(--icon-color, #5f6368);
+    opacity: 0;
+    transition: opacity 0.15s ease;
+    flex-shrink: 0;
+}
+
+.tab-item:hover .tab-close {
+    opacity: 0.6;
+}
+
+.tab-close:hover {
+    background: var(--close-hover-bg, rgba(0, 0, 0, 0.08));
+    opacity: 1;
+}
+
+.new-tab-button-container {
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    width: 40px;
+    height: 32px;
+    background: var(--tab-bar-bg);
+}
+
+.new-tab-button {
+    width: 32px;
+    height: 32px;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    border-radius: 6px;
+    color: var(--icon-color, #5f6368);
+    transition: all 0.15s ease;
+    cursor: pointer;
+    opacity: 0.8;
+    background: transparent;
+}
+
+.new-tab-button:hover {
+    background: var(--tab-hover-bg, rgba(0, 0, 0, 0.06));
+    opacity: 1;
+}
+
+.address-bar {
+    padding: 8px 12px;
+    margin: 0;
+    background: var(--address-bar-bg, #fff);
+    display: flex;
+    align-items: center;
+    gap: 8px;
+    width: 100%;
+    border-top: 1px solid var(--tab-separator-color, rgba(0, 0, 0, 0.1));
+}
+
+.url-input-container {
+    flex: 1;
+    height: 36px;
+    background: var(--input-bg, #f1f3f4);
+    border-radius: 18px;
+    padding: 0 16px;
+    display: flex;
+    align-items: center;
+    margin: 0;
+    min-width: 0;
+}
+
+.url-input {
+    width: 100%;
+    height: 100%;
+    border: none;
+    background: transparent;
+    outline: none;
+    font-size: 14px;
+    color: var(--text-color, #333);
+}
+
+.action-button {
+    flex-shrink: 0;
+    height: 36px;
+    padding: 0 16px;
+    border: none;
+    border-radius: 18px;
+    background: transparent;
+    color: var(--text-color, #333);
+    font-size: 14px;
+    cursor: pointer;
+    transition: all 0.2s;
+}
+
+.action-button:hover {
+    background: var(--button-hover-bg, #f1f3f4);
+}
+
+/* 修改CSS变量 */
+:root {
+    --tab-bar-bg: #f1f3f4;
+    --tab-bg: rgba(32, 33, 36, 0.1);
+    --tab-hover-bg: rgba(32, 33, 36, 0.08);
+    --tab-active-bg: #fff;
+    --tab-separator-color: rgba(0, 0, 0, 0.2);
+    --text-color: #5f6368;
+    --active-text-color: #202124;
+    --icon-color: #5f6368;
+    --close-hover-bg: rgba(0, 0, 0, 0.08);
+    --primary-color: #1a73e8;
+    --new-tab-shadow: 0 -8px 12px -6px rgba(0, 0, 0, 0.1);
+}
+
+[data-theme="dark"] {
+    --tab-bar-bg: #202124;
+    --tab-bg: rgba(255, 255, 255, 0.1);
+    --tab-hover-bg: rgba(255, 255, 255, 0.08);
+    --tab-active-bg: #292a2d;
+    --tab-separator-color: rgba(255, 255, 255, 0.2);
+    --text-color: #9ba0a5;
+    --active-text-color: #e8eaed;
+    --icon-color: #9ba0a5;
+    --close-hover-bg: rgba(255, 255, 255, 0.08);
+    --primary-color: #8ab4f8;
+    --new-tab-shadow: 0 -8px 12px -6px rgba(0, 0, 0, 0.3);
+}
+</style>