diff --git a/course-web/package-lock.json b/course-web/package-lock.json
index fdfbf47..a2f8003 100644
--- a/course-web/package-lock.json
+++ b/course-web/package-lock.json
@@ -64,6 +64,7 @@
"integrity": "sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw==",
"dev": true,
"license": "MIT",
+ "peer": true,
"dependencies": {
"@babel/code-frame": "^7.27.1",
"@babel/generator": "^7.28.5",
@@ -1399,6 +1400,7 @@
"integrity": "sha512-MWtvHrGZLFttgeEj28VXHxpmwYbor/ATPYbBfSFZEIRK0ecCFLl2Qo55z52Hss+UV9CRN7trSeq1zbgx7YDWWg==",
"dev": true,
"license": "MIT",
+ "peer": true,
"dependencies": {
"csstype": "^3.2.2"
}
@@ -1440,6 +1442,7 @@
"integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
"dev": true,
"license": "MIT",
+ "peer": true,
"bin": {
"acorn": "bin/acorn"
},
@@ -1599,6 +1602,7 @@
}
],
"license": "MIT",
+ "peer": true,
"dependencies": {
"baseline-browser-mapping": "^2.9.0",
"caniuse-lite": "^1.0.30001759",
@@ -1912,6 +1916,7 @@
"integrity": "sha512-LEyamqS7W5HB3ujJyvi0HQK/dtVINZvd5mAAp9eT5S/ujByGjiZLCzPcHVzuXbpJDJF/cxwHlfceVUDZ2lnSTw==",
"dev": true,
"license": "MIT",
+ "peer": true,
"dependencies": {
"@eslint-community/eslint-utils": "^4.8.0",
"@eslint-community/regexpp": "^4.12.1",
@@ -3052,6 +3057,7 @@
"resolved": "https://registry.npmmirror.com/picomatch/-/picomatch-4.0.3.tgz",
"integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
"license": "MIT",
+ "peer": true,
"engines": {
"node": ">=12"
},
@@ -3078,6 +3084,7 @@
}
],
"license": "MIT",
+ "peer": true,
"dependencies": {
"nanoid": "^3.3.11",
"picocolors": "^1.1.1",
@@ -3125,6 +3132,7 @@
"resolved": "https://registry.npmmirror.com/react/-/react-19.2.3.tgz",
"integrity": "sha512-Ku/hhYbVjOQnXDZFv2+RibmLFGwFdeeKHFcOTlrt7xplBnya5OGn/hIRDsqDiSUcfORsDC7MPxwork8jBwsIWA==",
"license": "MIT",
+ "peer": true,
"engines": {
"node": ">=0.10.0"
}
@@ -3134,6 +3142,7 @@
"resolved": "https://registry.npmmirror.com/react-dom/-/react-dom-19.2.3.tgz",
"integrity": "sha512-yELu4WmLPw5Mr/lmeEpox5rw3RETacE++JgHqQzd2dg+YbJuat3jH4ingc+WPZhxaoFzdv9y33G+F7Nl5O0GBg==",
"license": "MIT",
+ "peer": true,
"dependencies": {
"scheduler": "^0.27.0"
},
@@ -3399,6 +3408,7 @@
"resolved": "https://registry.npmmirror.com/rolldown-vite/-/rolldown-vite-7.2.5.tgz",
"integrity": "sha512-u09tdk/huMiN8xwoiBbig197jKdCamQTtOruSalOzbqGje3jdHiV0njQlAW0YvzoahkirFePNQ4RYlfnRQpXZA==",
"license": "MIT",
+ "peer": true,
"dependencies": {
"@oxc-project/runtime": "0.97.0",
"fdir": "^6.5.0",
@@ -3521,6 +3531,7 @@
"integrity": "sha512-0wZ1IRqGGhMP76gLqz8EyfBXKk0J2qo2+H3fi4mcUP/KtTocoX08nmIAHl1Z2kJIZbZee8KOpBCSNPRgauucjw==",
"dev": true,
"license": "MIT",
+ "peer": true,
"funding": {
"url": "https://github.com/sponsors/colinhacks"
}
diff --git a/course-web/src/App.jsx b/course-web/src/App.jsx
index 535540e..64ad5ea 100644
--- a/course-web/src/App.jsx
+++ b/course-web/src/App.jsx
@@ -10,9 +10,31 @@ function App() {
// Logic is now in CurrentPage, App just provides layout
return (
- {/* Global Background */}
-
-
+ {/* Global Background with Gradient and Glow Effects - Similar to image */}
+
+ {/* Base Gradient Background - From blue (left) to dark brown (right) with blue gradient */}
+
+ {/* Blue gradient layer for left side */}
+
+ {/* Additional gradient layer for smoother transition */}
+
+ {/* Vertical gradient for depth */}
+
+
+ {/* Glow Effects - Enhanced blue on left */}
+ {/* Left side - Enhanced Blue glow */}
+
+
+
+
+ {/* Right side - Reddish-orange glow (bottom right prominent like in image) */}
+
+
+
+ {/* Central subtle glow */}
+
+
+
{/* Page Content */}
diff --git a/course-web/src/components/UserMenu.jsx b/course-web/src/components/UserMenu.jsx
new file mode 100644
index 0000000..cb63a19
--- /dev/null
+++ b/course-web/src/components/UserMenu.jsx
@@ -0,0 +1,283 @@
+import React, { useState, useRef, useEffect } from 'react';
+import { useStoreData } from '../hooks/useStoreData';
+import { Store } from '../utils/store';
+import { User, Settings, LogOut, X, Edit2 } from 'lucide-react';
+import { GlassCard } from './ui/GlassCard';
+import { Button } from './ui/Button';
+import clsx from 'clsx';
+
+/**
+ * 用户资料菜单组件
+ * 显示用户信息、编辑资料和退出登录选项
+ */
+export function UserMenu({ isOpen, onClose, onLogout }) {
+ const data = useStoreData();
+ const [showEditModal, setShowEditModal] = useState(false);
+ const menuRef = useRef(null);
+
+ // 每次打开菜单时,重置编辑模态框状态(模仿 PncyssD 的逻辑)
+ // 确保每次打开菜单都显示主菜单界面,而不是编辑界面
+ useEffect(() => {
+ if (isOpen) {
+ // 菜单打开时,确保编辑模态框是关闭的
+ setShowEditModal(false);
+ }
+ }, [isOpen]);
+
+ // 点击外部关闭菜单
+ useEffect(() => {
+ if (!isOpen) return;
+
+ const handleClickOutside = (event) => {
+ if (menuRef.current && !menuRef.current.contains(event.target)) {
+ onClose();
+ }
+ };
+
+ document.addEventListener('mousedown', handleClickOutside);
+ return () => document.removeEventListener('mousedown', handleClickOutside);
+ }, [isOpen, onClose]);
+
+ // 如果菜单未打开,不渲染任何内容(除非正在显示编辑模态框)
+ if (!isOpen && !showEditModal) return null;
+
+ // 如果正在显示编辑模态框,只渲染编辑模态框
+ if (showEditModal) {
+ return (
+
{
+ setShowEditModal(false);
+ // 编辑模态框关闭后,如果菜单是打开的,会显示主菜单
+ }}
+ userProfile={data.userProfile}
+ />
+ );
+ }
+
+ // 显示主菜单(isOpen 为 true 且 showEditModal 为 false)
+
+ // 显示主菜单
+ return (
+ <>
+ {/* 菜单遮罩层 */}
+
+
+ {/* 用户菜单 */}
+
+
+ {/* 用户信息头部 */}
+
+
+ {data.userProfile.nickname?.[0] || 'U'}
+
+
+
+ {data.userProfile.nickname || '旅人'}
+
+
+
+ {data.userProfile.mbti || '未知'} · {data.userProfile.zodiac || '未知'}
+
+
+
+
+ {/* 统计数据 */}
+
+
+
+ {data.lifeTimeline?.length || 0}
+
+
+ 生命足迹
+
+
+
+
+ {data.generatedScripts?.length || 0}
+
+
+ 剧本生成
+
+
+
+
+ {/* 操作按钮 */}
+
+ {
+ setShowEditModal(true);
+ // 不关闭主菜单,让编辑模态框显示在主菜单之上
+ // 这样关闭编辑模态框后,主菜单仍然可见
+ }}
+ >
+
+ 编辑资料
+
+ {
+ if (window.confirm('确定要退出登录并清除所有数据吗?此操作不可逆。')) {
+ Store.reset();
+ if (onLogout) onLogout();
+ }
+ }}
+ >
+
+ 退出登录
+
+
+
+
+ >
+ );
+}
+
+/**
+ * 编辑资料模态框组件
+ */
+function EditProfileModal({ onClose, userProfile }) {
+ const [formData, setFormData] = useState({
+ nickname: userProfile.nickname || '',
+ mbti: userProfile.mbti || '',
+ zodiac: userProfile.zodiac || '',
+ hobbies: userProfile.hobbies?.join(', ') || '',
+ gender: userProfile.gender || 'secret'
+ });
+ const [isSaving, setIsSaving] = useState(false);
+
+ const handleSave = () => {
+ setIsSaving(true);
+
+ // 更新用户资料
+ Store.updateProfile({
+ nickname: formData.nickname,
+ mbti: formData.mbti,
+ zodiac: formData.zodiac,
+ hobbies: formData.hobbies.split(',').map(s => s.trim()).filter(s => s),
+ gender: formData.gender
+ });
+
+ setTimeout(() => {
+ setIsSaving(false);
+ onClose();
+ }, 300);
+ };
+
+ return (
+
+
+ {/* 关闭按钮 */}
+
+
+
+
+ {/* 标题 */}
+
+
+ {/* 表单 */}
+
+
+ 昵称
+ setFormData({ ...formData, nickname: e.target.value })}
+ placeholder="你想被如何称呼?"
+ className="w-full px-4 py-3 bg-white/5 border border-white/10 rounded-xl text-white placeholder-white/30 focus:outline-none focus:ring-2 focus:ring-primary/50 focus:border-primary/50 transition-all"
+ />
+
+
+
+
+
+ 兴趣爱好
+ setFormData({ ...formData, hobbies: e.target.value })}
+ placeholder="让灵魂起舞的事物(用逗号分隔)"
+ className="w-full px-4 py-3 bg-white/5 border border-white/10 rounded-xl text-white placeholder-white/30 focus:outline-none focus:ring-2 focus:ring-primary/50 focus:border-primary/50 transition-all"
+ />
+
+
+
+ 性别
+ setFormData({ ...formData, gender: e.target.value })}
+ className="w-full px-4 py-3 bg-white/5 border border-white/10 rounded-xl text-white focus:outline-none focus:ring-2 focus:ring-primary/50 focus:border-primary/50 transition-all"
+ >
+ 保密
+ 男
+ 女
+
+
+
+
+ {/* 操作按钮 */}
+
+
+ 保存修改
+
+
+ 取消
+
+
+
+
+ );
+}
+
diff --git a/course-web/src/components/ui/GlassCard.jsx b/course-web/src/components/ui/GlassCard.jsx
index e347eef..d304b13 100644
--- a/course-web/src/components/ui/GlassCard.jsx
+++ b/course-web/src/components/ui/GlassCard.jsx
@@ -9,7 +9,7 @@ export function GlassCard({ children, className, ...props }) {
return (
-
-
+
+
实现路径
@@ -132,14 +132,14 @@ export function PathView({ onSwitchToScript }) {
将幻想落地为行动,AI为你定制专属计划。
-
-
-
你需要先有一个剧本,才能生成通往它的路径。
+
+
+
你需要先有一个剧本,才能生成通往它的路径。
- 去生成剧本
+ 去生成剧本
@@ -149,7 +149,7 @@ export function PathView({ onSwitchToScript }) {
return (
-
+
@@ -245,11 +245,11 @@ export function PathView({ onSwitchToScript }) {
onClick={() => setExpandedStep(expandedStep === idx ? null : idx)}
>
-
+
{idx + 1}
-
{step.phase}
+
{step.phase}
{step.time}
@@ -277,7 +277,7 @@ export function PathView({ onSwitchToScript }) {
handleStepEdit(idx, 'content', e.currentTarget.textContent)}
- className={`p-3 rounded-lg text-sm text-gray-300 leading-relaxed border transition-colors ${
+ className={`p-3 rounded-lg text-sm text-beige/90 leading-relaxed border transition-colors ${
isEditing
? 'bg-white/10 border-primary/50 ring-2 ring-primary/20'
: 'bg-white/5 border-white/5'
@@ -325,7 +325,7 @@ export function PathView({ onSwitchToScript }) {
{/* Habits */}
-
+
养成习惯
{step.habit}
diff --git a/course-web/src/components/views/ScriptView.jsx b/course-web/src/components/views/ScriptView.jsx
index 64a17de..1f45db5 100644
--- a/course-web/src/components/views/ScriptView.jsx
+++ b/course-web/src/components/views/ScriptView.jsx
@@ -81,9 +81,9 @@ export function ScriptView({ onSwitchToPath }) {
return (
-
+
- 剧本生成器
+ 爽文剧本
基于你的真实画像,编织平行时空的无限可能。
@@ -108,7 +108,7 @@ export function ScriptView({ onSwitchToPath }) {
{data.userProfile.nickname ? data.userProfile.nickname[0] : 'U'}
-
{data.userProfile.nickname || '未命名'}
+
{data.userProfile.nickname || '未命名'}
{data.userProfile.mbti}
{data.userProfile.zodiac || '星辰'}
@@ -116,12 +116,12 @@ export function ScriptView({ onSwitchToPath }) {
-
-
天赋
+
+ 天赋
{(data.userProfile.hobbies || []).join(' / ') || '暂无'}
-
-
愿景
+
+ 愿景
{data.userProfile.futureVision || '暂无'}
@@ -130,7 +130,7 @@ export function ScriptView({ onSwitchToPath }) {
{/* Input Form */}
-
+
1
你的渴望主题
@@ -170,7 +170,7 @@ export function ScriptView({ onSwitchToPath }) {
variant="primary"
onClick={handleGenerate}
disabled={loading}
- className="w-full py-3 shadow-[0_0_20px_rgba(16,185,129,0.2)] flex justify-center items-center gap-2 group"
+ className="w-full py-3 shadow-[0_0_20px_rgba(205,133,63,0.2)] flex justify-center items-center gap-2 group"
>
{loading ? <> 编织命运中...> : <> 生成平行人生>}
@@ -197,11 +197,11 @@ export function ScriptView({ onSwitchToPath }) {
className={clsx(
"group relative p-3 rounded-xl cursor-pointer transition-all border",
selectedScriptId === s.id
- ? "bg-primary/10 border-primary/30 shadow-[inset_0_0_10px_rgba(16,185,129,0.05)]"
+ ? "bg-primary/10 border-primary/30 shadow-[inset_0_0_10px_rgba(205,133,63,0.05)]"
: "bg-transparent border-transparent hover:bg-white/5 hover:border-white/10"
)}
>
-
+
{s.title}
@@ -233,8 +233,8 @@ export function ScriptView({ onSwitchToPath }) {
-
舞台已就绪
-
请在左侧输入设定,生成你的平行人生。
+
舞台已就绪
+
请在左侧设定需求,开启你的爽文人生。
) : (
@@ -251,11 +251,11 @@ export function ScriptView({ onSwitchToPath }) {
-
+
{selectedScript.style === 'career' ? '职场逆袭' : selectedScript.style === 'love' ? '情感圆满' : '玄幻觉醒'}
- {selectedScript.title}
+ {selectedScript.title}
生成于 {new Date(selectedScript.createdAt).toLocaleDateString()}
·
@@ -275,7 +275,7 @@ export function ScriptView({ onSwitchToPath }) {
1
序幕:低谷回响
-
+
{selectedScript.plot.intro}
@@ -283,11 +283,11 @@ export function ScriptView({ onSwitchToPath }) {
{/* Chapter 2 */}
-
2
-
转折:契机出现
+
2
+
转折:契机出现
-
+
{selectedScript.plot.turning}
@@ -297,9 +297,9 @@ export function ScriptView({ onSwitchToPath }) {
-
+
{selectedScript.plot.climax}
@@ -310,7 +310,7 @@ export function ScriptView({ onSwitchToPath }) {
4
结局:新的开始
-
+
{selectedScript.plot.ending}
diff --git a/course-web/src/components/views/TimelineView.jsx b/course-web/src/components/views/TimelineView.jsx
index 516484f..aafd830 100644
--- a/course-web/src/components/views/TimelineView.jsx
+++ b/course-web/src/components/views/TimelineView.jsx
@@ -44,11 +44,11 @@ export function TimelineView() {
return (
-
+
- 时空日记
+ 人生轨迹
- 记录每一个当下,让AI为你照见未来。
+ 塑造你的每一刻,都被星辰见证。
@@ -83,7 +83,7 @@ export function TimelineView() {
{events.length === 0 ? (
-
暂无记录,写下你的第一篇日记吧。
+
执笔写下,哪些经历让你成为了现在的自己。
) : (
events.map((item, index) => (
@@ -99,16 +99,16 @@ export function TimelineView() {
{/* Center Dot */}
-
+
{/* Content Card */}
-
+
- {item.title}
- {item.content}
+ {item.title}
+ {item.content}
{item.aiReply && (
diff --git a/course-web/src/index.css b/course-web/src/index.css
index 5072241..b7051b6 100644
--- a/course-web/src/index.css
+++ b/course-web/src/index.css
@@ -1,11 +1,16 @@
@import "tailwindcss";
@theme {
- --color-primary: #2A9D8F;
- --color-secondary: #264653;
- --color-accent: #E9C46A;
- --color-aurora-green: #4CC9F0;
- --color-deep-sea: #0f1c2e;
+ --color-primary: #CD853F;
+ --color-secondary: #0a0c10;
+ --color-accent: #DAA520;
+ --color-aurora-green: #FFD700;
+ --color-deep-sea: #1a1c2c;
+ --color-text-beige: #E8D5B7;
+ --color-text-warm: #E8D5B7;
+ --color-gold-dark: #CD853F;
+ --color-gold-medium: #DAA520;
+ --color-gold-light: #FFD700;
--font-sans: "Noto Sans SC", sans-serif;
@@ -30,9 +35,12 @@
100% { transform: translateY(0); opacity: 1; }
}
@keyframes float {
- 0%, 100% { transform: translateY(0); }
- 50% { transform: translateY(-10px); }
+ 0%, 100% { transform: translate(0, 0) scale(1); }
+ 50% { transform: translate(5%, 5%) scale(1.1); }
}
+
+.animate-float { animation: float 15s infinite ease-in-out; }
+.animate-float-delayed { animation: float 20s infinite ease-in-out reverse; }
@keyframes breathe {
0%, 100% { opacity: 0.8; transform: scale(1); }
50% { opacity: 1; transform: scale(1.02); }
@@ -42,9 +50,9 @@
to { transform: rotate(360deg); }
}
@keyframes pulse-ring {
- 0% { transform: scale(0.95); box-shadow: 0 0 0 0 rgba(42, 157, 143, 0.7); }
- 70% { transform: scale(1); box-shadow: 0 0 0 10px rgba(42, 157, 143, 0); }
- 100% { transform: scale(0.95); box-shadow: 0 0 0 0 rgba(42, 157, 143, 0); }
+ 0% { transform: scale(0.95); box-shadow: 0 0 0 0 rgba(255, 171, 145, 0.7); }
+ 70% { transform: scale(1); box-shadow: 0 0 0 10px rgba(255, 171, 145, 0); }
+ 100% { transform: scale(0.95); box-shadow: 0 0 0 0 rgba(255, 171, 145, 0); }
}
@keyframes audio-wave {
0%, 100% { height: 5px; }
@@ -55,7 +63,7 @@
body {
-webkit-tap-highlight-color: transparent;
font-family: 'Noto Sans SC', sans-serif;
- @apply bg-deep-sea text-gray-800 overflow-x-hidden selection:bg-primary selection:text-white;
+ @apply bg-deep-sea text-gray-100 overflow-x-hidden selection:bg-primary/30 selection:text-white;
}
/* Background Noise Utility */
@@ -76,14 +84,14 @@ body {
border-radius: 4px;
}
::-webkit-scrollbar-thumb:hover {
- background: rgba(42, 157, 143, 0.6);
+ background: rgba(255, 171, 145, 0.6);
}
.custom-scrollbar::-webkit-scrollbar-thumb {
background: rgba(0, 0, 0, 0.1);
}
.custom-scrollbar::-webkit-scrollbar-thumb:hover {
- background: rgba(42, 157, 143, 0.4);
+ background: rgba(255, 171, 145, 0.4);
}
/* Transitions */
@@ -128,8 +136,8 @@ body {
}
.input-field:focus {
- border-color: #2A9D8F;
- box-shadow: 0 0 0 4px rgba(42, 157, 143, 0.15);
+ border-color: #CD853F;
+ box-shadow: 0 0 0 4px rgba(205, 133, 63, 0.15);
background: white;
}
@@ -140,7 +148,7 @@ body {
}
.input-field-dark:focus {
background: rgba(255, 255, 255, 0.1);
- border-color: #2A9D8F;
+ border-color: #CD853F;
}
select.input-field {
@@ -172,6 +180,20 @@ select.input-field-dark option {
.audio-waves span:nth-child(3) { animation-delay: 0.2s; }
.audio-waves span:nth-child(4) { animation-delay: 0.3s; }
+/* Text Beige Color Utility - 浅米色文字 */
+.text-beige {
+ color: #E8D5B7;
+}
+
+/* Advanced Gold Gradient Text - 高级金色渐变文字(更白亮、更明显、降低饱和度) */
+.text-gold-gradient {
+ background: linear-gradient(135deg, #E8D5B7 0%, #F4D03F 30%, #FFD700 60%, #FFF8DC 100%);
+ -webkit-background-clip: text;
+ -webkit-text-fill-color: transparent;
+ background-clip: text;
+ filter: brightness(1.1) saturate(0.9);
+}
+
/* Utilities */
.scrollbar-hide::-webkit-scrollbar {
display: none;
diff --git a/course-web/src/pages/DashboardPage.jsx b/course-web/src/pages/DashboardPage.jsx
index b29d430..9a50e6d 100644
--- a/course-web/src/pages/DashboardPage.jsx
+++ b/course-web/src/pages/DashboardPage.jsx
@@ -5,6 +5,7 @@ import { AudioEngine } from '../utils/audioEngine';
import { TimelineView } from '../components/views/TimelineView';
import { ScriptView } from '../components/views/ScriptView';
import { PathView } from '../components/views/PathView';
+import { UserMenu } from '../components/UserMenu';
import {
Compass,
BookOpen,
@@ -24,6 +25,7 @@ export function DashboardPage() {
const [activeTab, setActiveTab] = useState('timeline');
const [isMusicPlaying, setIsMusicPlaying] = useState(false);
const [isMobileMenuOpen, setIsMobileMenuOpen] = useState(false);
+ const [isUserMenuOpen, setIsUserMenuOpen] = useState(false);
// Initialize Audio Engine state based on store
useEffect(() => {
@@ -55,32 +57,40 @@ export function DashboardPage() {
className={clsx(
"w-full text-left px-4 py-3 rounded-xl flex items-center gap-3 transition-all duration-300 relative overflow-hidden group",
activeTab === tab
- ? "bg-primary/20 text-primary font-bold shadow-[0_0_15px_rgba(16,185,129,0.1)] border border-primary/20"
- : "text-gray-400 hover:text-white hover:bg-white/5 border border-transparent"
+ ? "bg-primary/20 text-primary font-bold shadow-[0_0_15px_rgba(205,133,63,0.1)] border border-primary/20"
+ : "text-gray-400 hover:text-primary hover:bg-white/5 border border-transparent"
)}
>
-
+
{label}
{mobileLabel || label}
{activeTab === tab && (
-
+
)}
);
return (
- {/* Ambient Background */}
+ {/* Ambient Background - Additional Layer for Dashboard with Blue Gradient */}
-
-
+ {/* Blue gradient overlay on left */}
+
+ {/* Subtle radial gradient overlay */}
+
+
+ {/* Blue glow effects on left */}
+
+
+ {/* Subtle glow effects on right */}
+
{/* Mobile Header */}
-
+
- 人生轨迹
+ 人生OS
setIsMobileMenuOpen(!isMobileMenuOpen)}>
{isMobileMenuOpen ? : }
@@ -89,47 +99,50 @@ export function DashboardPage() {
{/* Sidebar (Desktop) / Drawer (Mobile) */}
{/* Background Decoration */}
-
- 人生轨迹
+
+ 人生OS
{/* User Card */}
-
+
setIsUserMenuOpen(!isUserMenuOpen)}
+ className="flex items-center gap-4 mb-8 p-4 bg-white/5 rounded-2xl backdrop-blur-sm border border-white/10 hover:bg-white/10 transition-colors cursor-pointer group w-full text-left"
+ >
{data.userProfile.nickname?.[0] || 'U'}
-
-
{data.userProfile.nickname || '旅人'}
+
+
{data.userProfile.nickname || '旅人'}
-
- {data.userProfile.mbti} · {data.userProfile.zodiac || '未知'}
+
+ {data.userProfile.mbti || '未知'} · {data.userProfile.zodiac || '未知'}
-
+
{/* Navigation */}
-
-
+
+
-
+
{/* Music Player */}
@@ -163,6 +176,16 @@ export function DashboardPage() {
{activeTab === 'script' &&
setActiveTab('path')} />}
{activeTab === 'path' && setActiveTab('script')} />}
+
+ {/* User Menu */}
+ setIsUserMenuOpen(false)}
+ onLogout={() => {
+ // 退出登录后,App.jsx 会检测到 onboardingComplete 变为 false,自动跳转到登录页
+ window.location.reload();
+ }}
+ />
);
}
diff --git a/course-web/src/pages/LandingPage.jsx b/course-web/src/pages/LandingPage.jsx
index 60a46f5..978e788 100644
--- a/course-web/src/pages/LandingPage.jsx
+++ b/course-web/src/pages/LandingPage.jsx
@@ -93,7 +93,7 @@ export function LandingPage({ onStart }) {
- 人生轨迹
+ 人生OS
Life Trajectory
@@ -113,7 +113,7 @@ export function LandingPage({ onStart }) {
variant="primary"
size="lg"
onClick={() => setShowLoginModal(true)}
- className="w-full shadow-[0_0_20px_rgba(16,185,129,0.3)] hover:shadow-[0_0_30px_rgba(16,185,129,0.5)] transition-all"
+ className="w-full shadow-[0_0_20px_rgba(205,133,63,0.3)] hover:shadow-[0_0_30px_rgba(205,133,63,0.5)] transition-all"
>
登录账号
diff --git a/course-web/src/pages/OnboardingPage.jsx b/course-web/src/pages/OnboardingPage.jsx
index 4712dab..43e4b0e 100644
--- a/course-web/src/pages/OnboardingPage.jsx
+++ b/course-web/src/pages/OnboardingPage.jsx
@@ -171,7 +171,7 @@ export function OnboardingPage({ onFinish }) {
{[0,1,2,3,4].map(i => (
))}
diff --git a/course-web/vite.config.js b/course-web/vite.config.js
index 92ff5ca..058285e 100644
--- a/course-web/vite.config.js
+++ b/course-web/vite.config.js
@@ -9,7 +9,8 @@ export default defineConfig({
server: {
proxy: {
'/api': {
- target: 'http://localhost:19089',
+ // target: 'http://localhost:19089',
+ target: 'http://101.200.208.45:19089',
changeOrigin: true,
}
}