11<template>
22 <div class="h-screen flex overflow-hidden" style="background-color: #EDEDED">
33 <!-- 左侧边栏 -->
4- <div class="w-16 border-r border-gray-200 flex flex-col" style="background-color: #e8e7e7">
5- <div class="flex-1 flex flex-col justify-start pt-0">
4+ <div class="border-r border-gray-200 flex flex-col" style="background-color: #e8e7e7; width: 60px; min-width: 60px; max-width: 60px">
5+ <div class="flex-1 flex flex-col justify-start pt-0 gap-0">
6+ <!-- 头像(类似微信侧边栏) -->
7+ <div class="w-full h-[60px] flex items-center justify-center">
8+ <div class="w-[40px] h-[40px] rounded-md overflow-hidden bg-gray-300 flex-shrink-0">
9+ <img v-if="selfAvatarUrl" :src="selfAvatarUrl" alt="avatar" class="w-full h-full object-cover" />
10+ <div
11+ v-else
12+ class="w-full h-full flex items-center justify-center text-white text-xs font-bold"
13+ style="background-color: #4B5563"
14+ >
15+ 我
16+ </div>
17+ </div>
18+ </div>
19+
620 <!-- 聊天图标 (与 oh-my-wechat 一致) -->
7- <div class="w-16 h-16 flex items-center justify-center chat-tab selected text-[#07b75b]">
8- <div class="w-7 h-7">
9- <svg class="w-full h-full" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true">
10- <path d="M12 19.8C17.52 19.8 22 15.99 22 11.3C22 6.6 17.52 2.8 12 2.8C6.48 2.8 2 6.6 2 11.3C2 13.29 2.8 15.12 4.15 16.57C4.6 17.05 4.82 17.29 4.92 17.44C5.14 17.79 5.21 17.99 5.23 18.4C5.24 18.59 5.22 18.81 5.16 19.26C5.1 19.75 5.07 19.99 5.13 20.16C5.23 20.49 5.53 20.71 5.87 20.72C6.04 20.72 6.27 20.63 6.72 20.43L8.07 19.86C8.43 19.71 8.61 19.63 8.77 19.59C8.95 19.55 9.04 19.54 9.22 19.54C9.39 19.53 9.64 19.57 10.14 19.65C10.74 19.75 11.37 19.8 12 19.8Z"/>
11- </svg>
21+ <div class="w-full h-[var(--sidebar-rail-step)] flex items-center justify-center group">
22+ <div class="w-[var(--sidebar-rail-btn)] h-[var(--sidebar-rail-btn)] rounded-md bg-transparent group-hover:bg-[#E1E1E1] flex items-center justify-center transition-colors">
23+ <div class="w-[var(--sidebar-rail-icon)] h-[var(--sidebar-rail-icon)] text-[#07b75b]">
24+ <svg class="w-full h-full" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true">
25+ <path d="M12 19.8C17.52 19.8 22 15.99 22 11.3C22 6.6 17.52 2.8 12 2.8C6.48 2.8 2 6.6 2 11.3C2 13.29 2.8 15.12 4.15 16.57C4.6 17.05 4.82 17.29 4.92 17.44C5.14 17.79 5.21 17.99 5.23 18.4C5.24 18.59 5.22 18.81 5.16 19.26C5.1 19.75 5.07 19.99 5.13 20.16C5.23 20.49 5.53 20.71 5.87 20.72C6.04 20.72 6.27 20.63 6.72 20.43L8.07 19.86C8.43 19.71 8.61 19.63 8.77 19.59C8.95 19.55 9.04 19.54 9.22 19.54C9.39 19.53 9.64 19.57 10.14 19.65C10.74 19.75 11.37 19.8 12 19.8Z" />
26+ </svg>
27+ </div>
28+ </div>
29+ </div>
30+
31+ <!-- 朋友圈图标(Aperture 风格) -->
32+ <div
33+ class="w-full h-[var(--sidebar-rail-step)] flex items-center justify-center cursor-pointer group"
34+ title="朋友圈"
35+ @click="goSns"
36+ >
37+ <div
38+ class="w-[var(--sidebar-rail-btn)] h-[var(--sidebar-rail-btn)] rounded-md flex items-center justify-center transition-colors bg-transparent group-hover:bg-[#E1E1E1]"
39+ >
40+ <div class="w-[var(--sidebar-rail-icon)] h-[var(--sidebar-rail-icon)]" :class="isSnsRoute ? 'text-[#07b75b]' : 'text-[#5d5d5d]'">
41+ <svg
42+ class="w-full h-full"
43+ viewBox="0 0 24 24"
44+ fill="none"
45+ stroke="currentColor"
46+ stroke-width="1.5"
47+ stroke-linecap="round"
48+ stroke-linejoin="round"
49+ aria-hidden="true"
50+ >
51+ <circle cx="12" cy="12" r="10" />
52+ <line x1="14.31" y1="8" x2="20.05" y2="17.94" />
53+ <line x1="9.69" y1="8" x2="21.17" y2="8" />
54+ <line x1="7.38" y1="12" x2="13.12" y2="2.06" />
55+ <line x1="9.69" y1="16" x2="3.95" y2="6.06" />
56+ <line x1="14.31" y1="16" x2="2.83" y2="16" />
57+ <line x1="16.62" y1="12" x2="10.88" y2="21.94" />
58+ </svg>
59+ </div>
1260 </div>
1361 </div>
1462
1563 <!-- 隐私模式按钮 -->
1664 <div
17- class="w-16 h-12 flex items-center justify-center cursor-pointer transition-colors"
18- :class="privacyMode ? 'text-[#03C160]' : 'text-gray-500 hover:text-gray-700'"
65+ class="w-full h-[var(--sidebar-rail-step)] flex items-center justify-center cursor-pointer group"
1966 @click="privacyMode = !privacyMode"
2067 :title="privacyMode ? '关闭隐私模式' : '开启隐私模式'"
2168 >
22- <svg class="w-6 h-6" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
23- <path v-if="privacyMode" stroke-linecap="round" stroke-linejoin="round" d="M3.98 8.223A10.477 10.477 0 001.934 12C3.226 16.338 7.244 19.5 12 19.5c.993 0 1.953-.138 2.863-.395M6.228 6.228A10.45 10.45 0 0112 4.5c4.756 0 8.773 3.162 10.065 7.498a10.523 10.523 0 01-4.293 5.774M6.228 6.228L3 3m3.228 3.228l3.65 3.65m7.894 7.894L21 21m-3.228-3.228l-3.65-3.65m0 0a3 3 0 10-4.243-4.243m4.242 4.242L9.88 9.88" />
24- <path v-else stroke-linecap="round" stroke-linejoin="round" d="M2.036 12.322a1.012 1.012 0 010-.639C3.423 7.51 7.36 4.5 12 4.5c4.638 0 8.573 3.007 9.963 7.178.07.207.07.431 0 .639C20.577 16.49 16.64 19.5 12 19.5c-4.638 0-8.573-3.007-9.963-7.178z" />
25- <circle v-if="!privacyMode" cx="12" cy="12" r="3" />
26- </svg>
69+ <div
70+ class="w-[var(--sidebar-rail-btn)] h-[var(--sidebar-rail-btn)] rounded-md flex items-center justify-center transition-colors bg-transparent group-hover:bg-[#E1E1E1]"
71+ >
72+ <svg class="w-[var(--sidebar-rail-icon)] h-[var(--sidebar-rail-icon)]" :class="privacyMode ? 'text-[#07b75b]' : 'text-[#5d5d5d]'" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">
73+ <path v-if="privacyMode" stroke-linecap="round" stroke-linejoin="round" d="M3.98 8.223A10.477 10.477 0 001.934 12C3.226 16.338 7.244 19.5 12 19.5c.993 0 1.953-.138 2.863-.395M6.228 6.228A10.45 10.45 0 0112 4.5c4.756 0 8.773 3.162 10.065 7.498a10.523 10.523 0 01-4.293 5.774M6.228 6.228L3 3m3.228 3.228l3.65 3.65m7.894 7.894L21 21m-3.228-3.228l-3.65-3.65m0 0a3 3 0 10-4.243-4.243m4.242 4.242L9.88 9.88" />
74+ <path v-else stroke-linecap="round" stroke-linejoin="round" d="M2.036 12.322a1.012 1.012 0 010-.639C3.423 7.51 7.36 4.5 12 4.5c4.638 0 8.573 3.007 9.963 7.178.07.207.07.431 0 .639C20.577 16.49 16.64 19.5 12 19.5c-4.638 0-8.573-3.007-9.963-7.178z" />
75+ <circle v-if="!privacyMode" cx="12" cy="12" r="3" />
76+ </svg>
77+ </div>
2778 </div>
2879
2980 <!-- 设置按钮(仅桌面端) -->
3081 <div
3182 v-if="isDesktopEnv"
32- class="w-16 h-12 flex items-center justify-center cursor-pointer transition-colors text-gray-500 hover:text-gray-700 "
83+ class="w-full h-[var(--sidebar-rail-step)] flex items-center justify-center cursor-pointer group "
3384 @click="openDesktopSettings"
3485 title="设置"
3586 >
36- <svg class="w-6 h-6" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
37- <path
38- stroke-linecap="round"
39- stroke-linejoin="round"
40- d="M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z"
41- />
42- <path stroke-linecap="round" stroke-linejoin="round" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z" />
43- </svg>
87+ <div class="w-[var(--sidebar-rail-btn)] h-[var(--sidebar-rail-btn)] rounded-md flex items-center justify-center transition-colors bg-transparent group-hover:bg-[#E1E1E1]">
88+ <svg class="w-[var(--sidebar-rail-icon)] h-[var(--sidebar-rail-icon)] text-[#5d5d5d]" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">
89+ <path
90+ stroke-linecap="round"
91+ stroke-linejoin="round"
92+ d="M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z"
93+ />
94+ <path stroke-linecap="round" stroke-linejoin="round" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z" />
95+ </svg>
96+ </div>
4497 </div>
4598 </div>
4699 </div>
@@ -1714,6 +1767,7 @@ useHead({
17141767})
17151768
17161769const route = useRoute()
1770+ const isSnsRoute = computed(() => route.path?.startsWith('/sns'))
17171771
17181772const routeUsername = computed(() => {
17191773 const raw = route.params.username
@@ -1729,6 +1783,24 @@ const selectedContact = ref(null)
17291783
17301784// 隐私模式
17311785const privacyMode = ref(false)
1786+ const PRIVACY_MODE_KEY = 'ui.privacy_mode'
1787+
1788+ onMounted(() => {
1789+ if (!process.client) return
1790+ try {
1791+ privacyMode.value = localStorage.getItem(PRIVACY_MODE_KEY) === '1'
1792+ } catch {}
1793+ })
1794+
1795+ watch(
1796+ () => privacyMode.value,
1797+ (v) => {
1798+ if (!process.client) return
1799+ try {
1800+ localStorage.setItem(PRIVACY_MODE_KEY, v ? '1' : '0')
1801+ } catch {}
1802+ }
1803+ )
17321804
17331805// 桌面端设置(仅 Electron 环境可见)
17341806const isDesktopEnv = ref(false)
@@ -1880,6 +1952,18 @@ const selectedAccount = ref(null)
18801952
18811953const availableAccounts = ref([])
18821954
1955+ const sidebarMediaBase = process.client ? 'http://localhost:8000' : ''
1956+
1957+ const selfAvatarUrl = computed(() => {
1958+ const acc = String(selectedAccount.value || '').trim()
1959+ if (!acc) return ''
1960+ return `${sidebarMediaBase}/api/chat/avatar?account=${encodeURIComponent(acc)}&username=${encodeURIComponent(acc)}`
1961+ })
1962+
1963+ const goSns = async () => {
1964+ await navigateTo('/sns')
1965+ }
1966+
18831967// 实时更新(WCDB DLL + db_storage watcher)
18841968const realtimeEnabled = ref(false)
18851969const realtimeAvailable = ref(false)
0 commit comments