Skip to content

Commit d0fcdf3

Browse files
committed
feat(frontend): refactor theme to support dark/light mode and fix IDE export warnings
1 parent bc3741c commit d0fcdf3

16 files changed

Lines changed: 3371 additions & 1689 deletions

frontend/src/App.vue

Lines changed: 264 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,55 +1,269 @@
11
<template>
2-
<div id="app" :class="{ 'sidebar-collapsed': sidebarCollapsed }">
2+
<div
3+
id="app"
4+
:class="{ 'sidebar-collapsed': sidebarCollapsed }"
5+
>
36
<!-- 侧边栏 Sidebar -->
4-
<aside class="layout-sidebar" :class="{ collapsed: sidebarCollapsed }">
7+
<aside
8+
class="layout-sidebar"
9+
:class="{ collapsed: sidebarCollapsed }"
10+
>
511
<div class="logo-area">
6-
<img src="/logo-banner.png" alt="渲染AI" class="logo-icon" />
12+
<img
13+
src="/logo-banner.png"
14+
alt="渲染AI"
15+
class="logo-icon"
16+
/>
717
</div>
818

919
<nav class="nav-menu">
10-
<RouterLink to="/" class="nav-item" active-class="active" exact>
11-
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m3 9 9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"></path><polyline points="9 22 9 12 15 12 15 22"></polyline></svg>
20+
<RouterLink
21+
to="/"
22+
class="nav-item"
23+
active-class="active"
24+
exact
25+
>
26+
<svg
27+
width="20"
28+
height="20"
29+
viewBox="0 0 24 24"
30+
fill="none"
31+
stroke="currentColor"
32+
stroke-width="2"
33+
stroke-linecap="round"
34+
stroke-linejoin="round"
35+
>
36+
<path d="m3 9 9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"></path>
37+
<polyline points="9 22 9 12 15 12 15 22"></polyline>
38+
</svg>
1239
<span class="nav-text">首页</span>
1340
</RouterLink>
14-
<RouterLink to="/redbook" class="nav-item" active-class="active">
15-
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="3" width="18" height="18" rx="2" ry="2"></rect><circle cx="8.5" cy="8.5" r="1.5"></circle><polyline points="21 15 16 10 5 21"></polyline></svg>
41+
<RouterLink
42+
to="/redbook"
43+
class="nav-item"
44+
active-class="active"
45+
>
46+
<svg
47+
width="20"
48+
height="20"
49+
viewBox="0 0 24 24"
50+
fill="none"
51+
stroke="currentColor"
52+
stroke-width="2"
53+
stroke-linecap="round"
54+
stroke-linejoin="round"
55+
>
56+
<rect
57+
x="3"
58+
y="3"
59+
width="18"
60+
height="18"
61+
rx="2"
62+
ry="2"
63+
></rect>
64+
<circle
65+
cx="8.5"
66+
cy="8.5"
67+
r="1.5"
68+
></circle>
69+
<polyline points="21 15 16 10 5 21"></polyline>
70+
</svg>
1671
<span class="nav-text">小红书图文</span>
1772
</RouterLink>
18-
<RouterLink to="/templates" class="nav-item" active-class="active">
19-
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 7h-9"></path><path d="M14 17H5"></path><circle cx="17" cy="17" r="3"></circle><circle cx="7" cy="7" r="3"></circle></svg>
73+
<RouterLink
74+
to="/templates"
75+
class="nav-item"
76+
active-class="active"
77+
>
78+
<svg
79+
width="20"
80+
height="20"
81+
viewBox="0 0 24 24"
82+
fill="none"
83+
stroke="currentColor"
84+
stroke-width="2"
85+
stroke-linecap="round"
86+
stroke-linejoin="round"
87+
>
88+
<path d="M20 7h-9"></path>
89+
<path d="M14 17H5"></path>
90+
<circle
91+
cx="17"
92+
cy="17"
93+
r="3"
94+
></circle>
95+
<circle
96+
cx="7"
97+
cy="7"
98+
r="3"
99+
></circle>
100+
</svg>
20101
<span class="nav-text">模板市集</span>
21102
</RouterLink>
22-
<RouterLink to="/concept" class="nav-item" active-class="active">
23-
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="3"></circle><circle cx="4" cy="6" r="2"></circle><circle cx="20" cy="6" r="2"></circle><line x1="6" y1="6" x2="9.5" y2="10"></line><line x1="18" y1="6" x2="14.5" y2="10"></line></svg>
103+
<RouterLink
104+
to="/concept"
105+
class="nav-item"
106+
active-class="active"
107+
>
108+
<svg
109+
width="20"
110+
height="20"
111+
viewBox="0 0 24 24"
112+
fill="none"
113+
stroke="currentColor"
114+
stroke-width="2"
115+
stroke-linecap="round"
116+
stroke-linejoin="round"
117+
>
118+
<circle
119+
cx="12"
120+
cy="12"
121+
r="3"
122+
></circle>
123+
<circle
124+
cx="4"
125+
cy="6"
126+
r="2"
127+
></circle>
128+
<circle
129+
cx="20"
130+
cy="6"
131+
r="2"
132+
></circle>
133+
<line
134+
x1="6"
135+
y1="6"
136+
x2="9.5"
137+
y2="10"
138+
></line>
139+
<line
140+
x1="18"
141+
y1="6"
142+
x2="14.5"
143+
y2="10"
144+
></line>
145+
</svg>
24146
<span class="nav-text">概念可视化</span>
25147
</RouterLink>
26148
<div class="nav-divider"></div>
27-
<RouterLink to="/history" class="nav-item" active-class="active">
28-
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path><polyline points="14 2 14 8 20 8"></polyline><line x1="16" y1="13" x2="8" y2="13"></line><line x1="16" y1="17" x2="8" y2="17"></line></svg>
149+
<RouterLink
150+
to="/history"
151+
class="nav-item"
152+
active-class="active"
153+
>
154+
<svg
155+
width="20"
156+
height="20"
157+
viewBox="0 0 24 24"
158+
fill="none"
159+
stroke="currentColor"
160+
stroke-width="2"
161+
stroke-linecap="round"
162+
stroke-linejoin="round"
163+
>
164+
<path
165+
d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"
166+
></path>
167+
<polyline points="14 2 14 8 20 8"></polyline>
168+
<line
169+
x1="16"
170+
y1="13"
171+
x2="8"
172+
y2="13"
173+
></line>
174+
<line
175+
x1="16"
176+
y1="17"
177+
x2="8"
178+
y2="17"
179+
></line>
180+
</svg>
29181
<span class="nav-text">历史记录</span>
30182
</RouterLink>
31-
<RouterLink to="/knowledge" class="nav-item" active-class="active">
32-
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M4 19.5A2.5 2.5 0 0 1 6.5 17H20"></path><path d="M6.5 2H20v20H6.5A2.5 2.5 0 0 1 4 19.5v-15A2.5 2.5 0 0 1 6.5 2z"></path></svg>
183+
<RouterLink
184+
to="/knowledge"
185+
class="nav-item"
186+
active-class="active"
187+
>
188+
<svg
189+
width="20"
190+
height="20"
191+
viewBox="0 0 24 24"
192+
fill="none"
193+
stroke="currentColor"
194+
stroke-width="2"
195+
stroke-linecap="round"
196+
stroke-linejoin="round"
197+
>
198+
<path d="M4 19.5A2.5 2.5 0 0 1 6.5 17H20"></path>
199+
<path
200+
d="M6.5 2H20v20H6.5A2.5 2.5 0 0 1 4 19.5v-15A2.5 2.5 0 0 1 6.5 2z"
201+
></path>
202+
</svg>
33203
<span class="nav-text">知识库</span>
34204
</RouterLink>
35-
<RouterLink to="/settings" class="nav-item" active-class="active">
36-
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="3"></circle><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z"></path></svg>
205+
<RouterLink
206+
to="/settings"
207+
class="nav-item"
208+
active-class="active"
209+
>
210+
<svg
211+
width="20"
212+
height="20"
213+
viewBox="0 0 24 24"
214+
fill="none"
215+
stroke="currentColor"
216+
stroke-width="2"
217+
stroke-linecap="round"
218+
stroke-linejoin="round"
219+
>
220+
<circle
221+
cx="12"
222+
cy="12"
223+
r="3"
224+
></circle>
225+
<path
226+
d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z"
227+
></path>
228+
</svg>
37229
<span class="nav-text">系统设置</span>
38230
</RouterLink>
39231
</nav>
40232

41233
<!-- 折叠按钮 -->
42-
<button class="collapse-btn" @click="toggleSidebar" :title="sidebarCollapsed ? '展开侧边栏' : '收起侧边栏'">
43-
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
44-
<polyline v-if="sidebarCollapsed" points="9 18 15 12 9 6"></polyline>
45-
<polyline v-else points="15 18 9 12 15 6"></polyline>
234+
<button
235+
class="collapse-btn"
236+
@click="toggleSidebar"
237+
:title="sidebarCollapsed ? '展开侧边栏' : '收起侧边栏'"
238+
>
239+
<svg
240+
width="16"
241+
height="16"
242+
viewBox="0 0 24 24"
243+
fill="none"
244+
stroke="currentColor"
245+
stroke-width="2"
246+
stroke-linecap="round"
247+
stroke-linejoin="round"
248+
>
249+
<polyline
250+
v-if="sidebarCollapsed"
251+
points="9 18 15 12 9 6"
252+
></polyline>
253+
<polyline
254+
v-else
255+
points="15 18 9 12 15 6"
256+
></polyline>
46257
</svg>
47258
</button>
48259

49260
<div class="sidebar-footer">
50261
<div class="brand-badge">
51262
<div class="brand-icon">R</div>
52-
<div class="brand-info" v-show="!sidebarCollapsed">
263+
<div
264+
class="brand-info"
265+
v-show="!sidebarCollapsed"
266+
>
53267
<div class="brand-name">渲染AI</div>
54268
<div class="brand-sub">RenderAI</div>
55269
</div>
@@ -63,16 +277,21 @@
63277
<component :is="Component" />
64278

65279
<!-- 全局页脚版权信息(首页除外) -->
66-
<footer v-if="route.path !== '/'" class="global-footer">
280+
<footer
281+
v-if="route.path !== '/'"
282+
class="global-footer"
283+
>
67284
<div class="footer-content">
68-
<div class="footer-tip">
69-
渲染AI - AI驱动的图文创作工具
70-
</div>
71-
<div class="footer-text">
72-
© 2025 渲染AI (RenderAI)
73-
</div>
285+
<div class="footer-tip">渲染AI - AI驱动的图文创作工具</div>
286+
<div class="footer-text">© 2025 渲染AI (RenderAI)</div>
74287
<div class="footer-license">
75-
Licensed under <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/" target="_blank" rel="noopener noreferrer">CC BY-NC-SA 4.0</a>
288+
Licensed under
289+
<a
290+
href="https://creativecommons.org/licenses/by-nc-sa/4.0/"
291+
target="_blank"
292+
rel="noopener noreferrer"
293+
>CC BY-NC-SA 4.0</a
294+
>
76295
</div>
77296
</div>
78297
</footer>
@@ -82,27 +301,30 @@
82301
</template>
83302

84303
<script setup lang="ts">
85-
import { RouterView, RouterLink } from 'vue-router'
86-
import { ref, onMounted } from 'vue'
87-
import { setupAutoSave } from './stores/generator'
304+
import { RouterView, RouterLink } from "vue-router";
305+
import { ref, onMounted } from "vue";
306+
import { setupAutoSave } from "./stores/generator";
307+
import { useTheme } from "./composables/useTheme";
88308
89309
// 侧边栏折叠状态
90-
const sidebarCollapsed = ref(false)
310+
const sidebarCollapsed = ref(false);
91311
92312
// 切换侧边栏折叠状态
93313
const toggleSidebar = () => {
94-
sidebarCollapsed.value = !sidebarCollapsed.value
314+
sidebarCollapsed.value = !sidebarCollapsed.value;
95315
// 保存状态到 localStorage
96-
localStorage.setItem('sidebarCollapsed', String(sidebarCollapsed.value))
97-
}
316+
localStorage.setItem("sidebarCollapsed", String(sidebarCollapsed.value));
317+
};
98318
99319
// 启用自动保存到 localStorage
100320
onMounted(() => {
101-
setupAutoSave()
321+
setupAutoSave();
322+
// 初始化主题
323+
useTheme();
102324
// 恢复侧边栏状态
103-
const saved = localStorage.getItem('sidebarCollapsed')
104-
if (saved === 'true') {
105-
sidebarCollapsed.value = true
325+
const saved = localStorage.getItem("sidebarCollapsed");
326+
if (saved === "true") {
327+
sidebarCollapsed.value = true;
106328
}
107-
})
329+
});
108330
</script>

0 commit comments

Comments
 (0)