File size: 4,129 Bytes
a0dfc48
2204456
395e9dc
2204456
 
395e9dc
 
 
 
1f4cfcb
2204456
395e9dc
2204456
a0dfc48
395e9dc
 
d971f9f
 
1f4cfcb
395e9dc
d971f9f
2204456
 
395e9dc
1f4cfcb
2204456
395e9dc
d971f9f
 
395e9dc
2204456
d971f9f
1f4cfcb
2204456
 
395e9dc
d971f9f
 
1f4cfcb
2204456
 
395e9dc
d971f9f
 
a0dfc48
f9ce30c
 
395e9dc
2204456
f9ce30c
 
395e9dc
2204456
395e9dc
1f4cfcb
2204456
395e9dc
f9ce30c
 
a0dfc48
 
 
2204456
 
 
 
 
 
 
 
 
 
 
 
a0dfc48
 
d971f9f
 
a0dfc48
d971f9f
a0dfc48
2204456
a0dfc48
2204456
 
 
 
 
 
 
 
a0dfc48
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
<template>
  <!-- 桌面端侧边栏 — round-12 F1 Bright v1 -->
  <nav class="hidden md:flex w-56 shrink-0 min-h-screen flex-col p-4 relative
              border-r border-hairline bg-surface">
    <!-- 顶部装饰条 -->
    <div class="absolute top-0 left-0 right-0 h-px bg-gradient-to-r from-transparent via-indigo-400/40 to-transparent"></div>

    <div class="mb-8 px-2">
      <div class="flex items-center gap-2 mb-1">
        <span class="inline-block w-2 h-2 rounded-sm bg-indigo-600"></span>
        <h1 class="text-lg font-extrabold text-ink-950 tracking-tight">AutoTeam</h1>
      </div>
      <p class="text-[10px] uppercase tracking-[0.2em] text-ink-400 ml-4">Operations Console</p>
    </div>

    <div class="space-y-0.5 flex-1">
      <button v-for="item in items" :key="item.key"
        @click="$emit('navigate', item.key)"
        class="w-full text-left px-3 py-2 rounded-lg text-sm transition-all flex items-center gap-2.5
               relative group focus-ring"
        :class="active === item.key
          ? 'bg-indigo-50 text-indigo-700'
          : 'text-ink-600 hover:bg-ink-100 hover:text-ink-950'">
        <span v-if="active === item.key" class="absolute left-0 top-2 bottom-2 w-0.5 rounded-r-full
          bg-indigo-600"></span>
        <component :is="item.icon" class="w-4 h-4 shrink-0" :stroke-width="2" />
        <span class="font-medium">{{ item.label }}</span>
      </button>
    </div>

    <div class="space-y-0.5 pt-4 border-t border-hairline">
      <button @click="$emit('refresh')" :disabled="loading"
        class="w-full text-left px-3 py-2 rounded-lg text-sm transition flex items-center gap-2.5
               text-ink-600 hover:bg-ink-100 hover:text-ink-950 disabled:opacity-50 focus-ring">
        <RefreshCw class="w-4 h-4 shrink-0" :class="loading ? 'animate-spin' : ''" :stroke-width="2" />
        <span class="font-medium">{{ loading ? '刷新中…' : '刷新数据' }}</span>
      </button>
      <button v-if="authRequired" @click="$emit('logout')"
        class="w-full text-left px-3 py-2 rounded-lg text-sm transition flex items-center gap-2.5
               text-ink-600 hover:bg-rose-50 hover:text-rose-700 focus-ring">
        <LogOut class="w-4 h-4 shrink-0" :stroke-width="2" />
        <span class="font-medium">登出</span>
      </button>
    </div>
  </nav>

  <!-- 移动端底部 tab 栏 -->
  <nav class="md:hidden fixed bottom-0 left-0 right-0 z-50 flex
              border-t border-hairline backdrop-blur-md bg-surface/95">
    <button v-for="item in items" :key="item.key"
      @click="$emit('navigate', item.key)"
      class="flex-1 flex flex-col items-center py-2 text-[10px] transition relative"
      :class="active === item.key ? 'text-indigo-700' : 'text-ink-500 hover:text-ink-700'">
      <span v-if="active === item.key"
        class="absolute top-0 left-1/4 right-1/4 h-0.5 rounded-b-full bg-indigo-600"></span>
      <component :is="item.icon" class="w-5 h-5" :stroke-width="2" />
      <span class="mt-0.5 font-medium">{{ item.mobileLabel || item.label }}</span>
    </button>
  </nav>
</template>

<script setup>
import {
  ChartPie,
  Users,
  RefreshCw,
  RotateCw,
  KeyRound,
  Scroll,
  ClipboardList,
  Settings,
  LogOut,
} from 'lucide-vue-next'

defineProps({
  active: String,
  loading: Boolean,
  authRequired: Boolean,
})
defineEmits(['navigate', 'refresh', 'logout'])

// round-12 F1 — emoji → lucide-vue-next 命名一致性
const items = [
  { key: 'dashboard', icon: ChartPie, label: '仪表盘', mobileLabel: '仪表盘' },
  { key: 'team', icon: Users, label: 'Team 成员', mobileLabel: '成员' },
  { key: 'pool', icon: RotateCw, label: '账号池操作', mobileLabel: '账号池' },
  { key: 'sync', icon: RefreshCw, label: '同步中心', mobileLabel: '同步' },
  { key: 'oauth', icon: KeyRound, label: 'OAuth 登录', mobileLabel: 'OAuth' },
  { key: 'tasks', icon: Scroll, label: '任务历史', mobileLabel: '任务' },
  { key: 'logs', icon: ClipboardList, label: '日志', mobileLabel: '日志' },
  { key: 'settings', icon: Settings, label: '设置', mobileLabel: '设置' },
]
</script>