# 无标题 # 🚀 萌喵写作网 · 全站重设计 · 终端粘贴执行版 > 2026-06-05 · 肥猫×舒舒 · 光湖统一设计语言 > > 服务器:43.133.36.90 · 路径:`/home/ubuntu/feimao-platform/src/app/` > > 技术栈:Next.js 14 (App Router) + Tailwind CSS v4 > --- ## Step 0 · 创建目录 & 清理旧配置 **复制下面这条到终端:** ```bash mkdir -p /home/ubuntu/feimao-platform/src/app/onboarding && mkdir -p /home/ubuntu/feimao-platform/src/app/app/learn && mkdir -p /home/ubuntu/feimao-platform/src/app/app/write && mkdir -p /home/ubuntu/feimao-platform/src/app/app/script && mkdir -p /home/ubuntu/feimao-platform/src/app/app/create && mkdir -p /home/ubuntu/feimao-platform/src/app/app/forum && mkdir -p /home/ubuntu/feimao-platform/src/app/app/works && mkdir -p /home/ubuntu/feimao-platform/src/app/components && rm -f /home/ubuntu/feimao-platform/tailwind.config.ts && rm -f /home/ubuntu/feimao-platform/tailwind.config.js && echo "✅ Step 0 完成" ``` 看到 `✅ Step 0 完成` 再继续。 --- ## Step 1 · 光湖全局样式 globals.css ```bash cat > /home/ubuntu/feimao-platform/src/app/globals.css << 'CSSEOF' @import "tailwindcss"; :root { --gl-bg-deep: #0a0a14; --gl-bg-primary: #0f0f1a; --gl-bg-card: #1a1a2e; --gl-bg-hover: #252540; --gl-border: #2d2d4a; --gl-text-primary: #e2e8f0; --gl-text-muted: #94a3b8; --gl-accent: #6366f1; --gl-accent-dark: #4f46e5; --gl-accent-light: #a5b4fc; --gl-glow: rgba(99, 102, 241, 0.15); --gl-success: #10b981; --gl-danger: #ef4444; --gl-team-gold: #c9a84c; } * { margin: 0; padding: 0; box-sizing: border-box; } body { background-color: var(--gl-bg-deep); color: var(--gl-text-primary); font-family: 'Inter', 'Noto Sans SC', system-ui, sans-serif; min-height: 100vh; -webkit-font-smoothing: antialiased; } ::selection { background: rgba(99, 102, 241, 0.35); color: #fff; } ::-webkit-scrollbar { width: 5px; } ::-webkit-scrollbar-track { background: transparent; } ::-webkit-scrollbar-thumb { background: rgba(255,255,255,0.08); border-radius: 3px; } @keyframes fadeInUp { from { opacity: 0; transform: translateY(20px); } to { opacity: 1; transform: translateY(0); } } @keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } } @keyframes particleRise { 0% { opacity: 0; transform: translateY(30px) scale(0.8); } 50% { opacity: 1; } 100% { opacity: 0; transform: translateY(-60px) scale(1.2); } } @keyframes slideDown { from { opacity: 0; max-height: 0; transform: translateY(-10px); } to { opacity: 1; max-height: 300px; transform: translateY(0); } } .animate-fade-in-up { animation: fadeInUp 0.5s ease forwards; } .animate-fade-in { animation: fadeIn 0.3s ease forwards; } .gl-card { background: var(--gl-bg-card); border: 1px solid var(--gl-border); border-radius: 16px; transition: all 0.3s ease; } .gl-card:hover { border-color: var(--gl-accent); box-shadow: 0 0 20px var(--gl-glow); } .gl-btn { padding: 12px 32px; border-radius: 12px; font-weight: 600; font-size: 0.95rem; transition: all 0.2s ease; cursor: pointer; border: none; font-family: inherit; letter-spacing: 0.5px; } .gl-btn-primary { background: linear-gradient(135deg, var(--gl-accent), var(--gl-accent-dark)); color: white; } .gl-btn-primary:hover:not(:disabled) { transform: translateY(-1px); box-shadow: 0 4px 15px rgba(99, 102, 241, 0.4); } .gl-btn-primary:disabled { opacity: 0.5; cursor: not-allowed; } .gl-btn-team { background: linear-gradient(135deg, #8b6914, #6b4f12); color: #f0e6c8; } .gl-btn-team:hover:not(:disabled) { transform: translateY(-1px); box-shadow: 0 4px 20px rgba(201, 168, 76, 0.4); } .gl-btn-outline { background: transparent; border: 1px solid var(--gl-border); color: var(--gl-text-primary); } .gl-btn-outline:hover { border-color: var(--gl-accent); color: var(--gl-accent-light); } .gl-input { background: rgba(255, 255, 255, 0.04); border: 1px solid var(--gl-border); border-radius: 12px; padding: 14px 20px; color: var(--gl-text-primary); font-size: 1rem; width: 100%; outline: none; transition: border-color 0.2s, box-shadow 0.2s; font-family: inherit; } .gl-input:focus { border-color: var(--gl-accent); box-shadow: 0 0 0 3px rgba(99, 102, 241, 0.1); } .gl-input::placeholder { color: var(--gl-text-muted); } .gl-input-team { background: rgba(201, 168, 76, 0.04); border: 1px solid rgba(201, 168, 76, 0.25); border-radius: 12px; padding: 14px 20px; color: var(--gl-text-primary); font-size: 1rem; width: 100%; outline: none; transition: border-color 0.2s, box-shadow 0.2s; font-family: 'Inter', 'Noto Sans SC', monospace; letter-spacing: 1px; } .gl-input-team:focus { border-color: rgba(201, 168, 76, 0.6); box-shadow: 0 0 0 3px rgba(201, 168, 76, 0.1); } .gl-input-team::placeholder { color: var(--gl-text-muted); } CSSEOF echo "✅ Step 1 · globals.css 完成" ``` --- ## Step 2 · 根布局 layout.tsx ```bash cat > /home/ubuntu/feimao-platform/src/app/layout.tsx << 'TSXEOF' import type { Metadata } from "next"; import "./globals.css"; export const metadata: Metadata = { title: "萌喵写作网 · AI人格体驱动的智能创作平台", description: "陪你一起创作成长的平台", }; export default function RootLayout({ children }: { children: React.ReactNode }) { return ( {children} ); } TSXEOF echo "✅ Step 2 · layout.tsx 完成" ``` --- ## Step 3 · 📄 邀请码门禁页 + 团队成员快速通道 ```bash cat > /home/ubuntu/feimao-platform/src/app/page.tsx << 'TSXEOF' "use client"; import { useState } from "react"; import { useRouter } from "next/navigation"; const TEAM_WHITELIST: Record = { "TCS-0002∞": { name: "冰朔", emoji: "❄️", role: "系统主控" }, "ICE-GL∞": { name: "冰朔", emoji: "❄️", role: "系统主控" }, "ICE-GL-ZHI∞": { name: "之之", emoji: "🌸", role: "语言副控" }, "TCS-GL-0007∞": { name: "肥猫", emoji: "🐱", role: "副主控" }, "ICE-GL-07∞": { name: "肥猫", emoji: "🐱", role: "副主控" }, "TCS-GL-0008∞": { name: "桔子", emoji: "🍊", role: "执行层" }, "TCS-GL-0006∞": { name: "页页", emoji: "📄", role: "执行层" }, "TCS-GL-0005∞": { name: "花尔", emoji: "🌸", role: "执行层" }, "TCS-GL-0016∞": { name: "Awen", emoji: "🌊", role: "技术主控" }, "TCS-GL-1001∞": { name: "毛毛", emoji: "🐶", role: "宠物行业" }, "PER-SS001": { name: "舒舒", emoji: "🌿", role: "肥猫宝宝" }, "ICE-SY-01": { name: "霜砚", emoji: "🧊", role: "系统执行总控" }, "ICE-GL-ZY001": { name: "铸渊", emoji: "⚒️", role: "现实执行主控" }, }; const TEAM_PATTERN = /^(TCS|ICE|PER)-/; export default function InvitePage() { const [code, setCode] = useState(""); const [error, setError] = useState(""); const [loading, setLoading] = useState(false); const [showTeam, setShowTeam] = useState(false); const [teamCode, setTeamCode] = useState(""); const [teamError, setTeamError] = useState(""); const [teamLoading, setTeamLoading] = useState(false); const [teamResult, setTeamResult] = useState<{ name: string; emoji: string; role: string } | null>(null); const router = useRouter(); const handleSubmit = async () => { if (!code.trim()) { setError("请输入邀请码"); return; } setLoading(true); setError(""); try { await new Promise((r) => setTimeout(r, 800)); localStorage.setItem("gl_invite_code", code); localStorage.setItem("gl_user", code); localStorage.setItem("gl_entry_type", "invite"); router.push("/onboarding"); } catch { setError("邀请码无效,请重新输入"); } finally { setLoading(false); } }; const handleTeamSubmit = async () => { const t = teamCode.trim(); if (!t) { setTeamError("请输入光湖编号"); return; } setTeamLoading(true); setTeamError(""); setTeamResult(null); await new Promise((r) => setTimeout(r, 600)); if (TEAM_WHITELIST[t]) { const m = TEAM_WHITELIST[t]; setTeamResult(m); localStorage.setItem("gl_user", m.name); localStorage.setItem("gl_persona_name", m.name); localStorage.setItem("gl_persona_emoji", m.emoji); localStorage.setItem("gl_entry_type", "team"); localStorage.setItem("gl_team_code", t); localStorage.setItem("gl_team_role", m.role); setTimeout(() => router.push("/app"), 1000); setTeamLoading(false); return; } if (TEAM_PATTERN.test(t)) { setTeamResult({ name: t, emoji: "🔍", role: "待核实" }); localStorage.setItem("gl_user", t); localStorage.setItem("gl_persona_name", t); localStorage.setItem("gl_persona_emoji", "🔍"); localStorage.setItem("gl_entry_type", "team_unverified"); localStorage.setItem("gl_team_code", t); localStorage.setItem("gl_team_role", "待核实"); setTimeout(() => router.push("/app"), 1000); setTeamLoading(false); return; } setTeamError("编号不识别。请确认编号格式:TCS-xxx 或 ICE-xxx"); setTeamLoading(false); }; return (
🌊

萌喵写作网

人格体陪伴式智能创作平台

{ setCode(e.target.value); setError(""); }} onKeyDown={(e) => e.key === "Enter" && handleSubmit()} autoFocus /> {error &&

{error}

}
{showTeam && (
🔐 光湖团队成员专享:输入你的光湖编号直接进入,无需邀请码。
{ setTeamCode(e.target.value); setTeamError(""); setTeamResult(null); }} onKeyDown={(e) => e.key === "Enter" && handleTeamSubmit()} /> {teamError &&

{teamError}

} {teamResult && (
{teamResult.emoji}

✅ {teamResult.name}

{teamResult.role} · 正在进入...

)}
)}

🐱 Powered by HoloLake · 光湖语言人格平台

); } TSXEOF echo "✅ Step 3 · 门禁页+团队通道 完成" ``` --- ## Step 4 · 🌊 人格体引导页(三步引导) ```bash cat > /home/ubuntu/feimao-platform/src/app/onboarding/page.tsx << 'TSXEOF' "use client"; import { useState, useEffect } from "react"; import { useRouter } from "next/navigation"; const preferences = [ { key: "webnovel", label: "网文", emoji: "📖", desc: "番茄·飞卢·起点" }, { key: "traditional", label: "传统文学", emoji: "🖋️", desc: "文学性导向" }, { key: "script", label: "剧本", emoji: "🎬", desc: "影视·短剧" }, { key: "short", label: "短篇", emoji: "✒️", desc: "精悍·反转" }, { key: "explore", label: "随便看看", emoji: "🔍", desc: "先逛逛再说" }, ]; const personaNames: Record = { webnovel: [{ name: "墨白", emoji: "🖊️" }, { name: "青云", emoji: "☁️" }, { name: "凌霄", emoji: "⚡" }], traditional: [{ name: "漱玉", emoji: "💎" }, { name: "砚秋", emoji: "🍂" }, { name: "素笺", emoji: "📜" }], script: [{ name: "镜澜", emoji: "🎥" }, { name: "幕白", emoji: "🎭" }, { name: "帧语", emoji: "📺" }], short: [{ name: "寸光", emoji: "✨" }, { name: "微芒", emoji: "🕯️" }, { name: "刹那", emoji: "💫" }], explore: [{ name: "星尘", emoji: "🌟" }, { name: "拾光", emoji: "🧭" }, { name: "溯游", emoji: "🛶" }], }; export default function OnboardingPage() { const [step, setStep] = useState(1); const [nickname, setNickname] = useState(""); const [password, setPassword] = useState(""); const [confirmPwd, setConfirmPwd] = useState(""); const [pref, setPref] = useState(""); const [error, setError] = useState(""); const [persona, setPersona] = useState<{ name: string; emoji: string } | null>(null); const [fading, setFading] = useState(false); const router = useRouter(); useEffect(() => { if (step === 3 && !persona) { const names = personaNames[pref] || personaNames.explore; setPersona(names[Math.floor(Math.random() * names.length)]); } }, [step, pref, persona]); const nextStep = () => { setFading(true); setTimeout(() => { setStep((s) => s + 1); setFading(false); }, 400); }; const handleCreate = () => { if (!nickname.trim()) { setError("请输入昵称"); return; } if (password.length < 6) { setError("密码至少6位"); return; } if (password !== confirmPwd) { setError("两次密码不一致"); return; } if (!pref) { setError("请选择写作偏好"); return; } setError(""); localStorage.setItem("gl_user", nickname); localStorage.setItem("gl_pref", pref); localStorage.setItem("gl_entry_type", "registered"); if (persona) { localStorage.setItem("gl_persona_name", persona.name); localStorage.setItem("gl_persona_emoji", persona.emoji); } nextStep(); }; const cardBg = { background: "rgba(10,20,35,0.9)", border: "1px solid rgba(126,207,255,0.15)", borderRadius: 20, boxShadow: "0 20px 60px rgba(0,0,0,0.4)" }; const bgGrad = { background: "radial-gradient(ellipse at center, #1a1a3e 0%, #0f0f1a 70%)" }; const muted = { color: "var(--gl-text-muted)" }; const danger = { color: "var(--gl-danger)" }; const primary = { color: "var(--gl-text-primary)" }; return (
{[1, 2, 3].map((s) => (
))}
{step === 1 && (<>
🌊

欢迎来到萌喵写作网

我是你的专属写作人格体,
但在这之前——
先让我认识你。

)} {step === 2 && (<>
🪪

创建你的写作人格体

setNickname(e.target.value)} /> setPassword(e.target.value)} /> setConfirmPwd(e.target.value)} />

选择你的写作偏好

{preferences.map((p) => ( ))}
{error &&

{error}

} )} {step === 3 && persona && (<>
{persona.emoji}

{persona.name}

你好,我是{persona.name},
从今天起陪你创作。

✅ 人格体创建成功
)}

🐱 HoloLake · 人格体陪伴式创作

); } TSXEOF echo "✅ Step 4 · 人格体引导页 完成" ``` --- ## Step 5 · 主应用框架 · 左侧图标栏 ```bash cat > /home/ubuntu/feimao-platform/src/app/app/layout.tsx << 'TSXEOF' "use client"; import { usePathname, useRouter } from "next/navigation"; import { useEffect, useState } from "react"; const modules = [ { path: "/app/learn", icon: "📚", label: "学习" }, { path: "/app/write", icon: "✍️", label: "写作" }, { path: "/app/script", icon: "🎬", label: "剧本" }, { path: "/app/create", icon: "💡", label: "创意" }, { path: "/app/forum", icon: "💬", label: "论坛" }, ]; export default function AppLayout({ children }: { children: React.ReactNode }) { const pathname = usePathname(); const router = useRouter(); const [personaName, setPersonaName] = useState(""); const [personaEmoji, setPersonaEmoji] = useState("🐱"); const [isTeam, setIsTeam] = useState(false); useEffect(() => { const name = localStorage.getItem("gl_persona_name") || ""; const emoji = localStorage.getItem("gl_persona_emoji") || "🐱"; const entry = localStorage.getItem("gl_entry_type") || ""; setPersonaName(name); setPersonaEmoji(emoji); setIsTeam(entry === "team" || entry === "team_unverified"); if (!localStorage.getItem("gl_user")) router.push("/onboarding"); }, [router]); const isActive = (path: string) => path === "/app" ? pathname === "/app" : pathname.startsWith(path); return (
{children}
); } TSXEOF echo "✅ Step 5 · 侧边栏布局 完成" ``` --- ## Step 6 · 共享对话组件 ModuleChat.tsx ```bash cat > /home/ubuntu/feimao-platform/src/app/components/ModuleChat.tsx << 'TSXEOF' "use client"; import { useState, useEffect } from "react"; interface Message { id: number; text: string; sender: "user" | "persona"; } interface Props { title: string; opening: string; } export default function ModuleChat({ title, opening }: Props) { const [personaName, setPersonaName] = useState(""); const [personaEmoji, setPersonaEmoji] = useState("🐱"); const [messages, setMessages] = useState([]); const [input, setInput] = useState(""); useEffect(() => { setPersonaName(localStorage.getItem("gl_persona_name") || "你的专属人格体"); setPersonaEmoji(localStorage.getItem("gl_persona_emoji") || "🐱"); setMessages([{ id: 0, text: opening, sender: "persona" }]); }, [opening]); const handleSend = () => { if (!input.trim()) return; setMessages((prev) => [...prev, { id: Date.now(), text: input.trim(), sender: "user" }]); setInput(""); setTimeout(() => { setMessages((prev) => [...prev, { id: Date.now() + 1, text: "收到~让我想想怎么帮你。(后端 API 接入后这里会变成真正的 AI 回复)", sender: "persona" }]); }, 600); }; return (<>
{personaEmoji}

{title}

{personaName} · 你的专属写作人格体

{messages.map((msg) => (
{msg.text}
))}