# 无标题
# 🚀 萌喵写作网 · 全站重设计 · 终端粘贴执行版
> 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 (<>
{messages.map((msg) => (
))}
>);
}
TSXEOF
echo "✅ Step 6 · ModuleChat.tsx 完成"
```
---
## Step 7 · 主应用对话首页
```bash
cat > /home/ubuntu/feimao-platform/src/app/app/page.tsx << 'TSXEOF'
"use client";
import { useState, useEffect } from "react";
interface Message { id: number; text: string; sender: "user" | "persona"; }
export default function AppHome() {
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: "嗨~欢迎回来!今天想创作什么?", sender: "persona" }]);
}, []);
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 (<>
{messages.map((msg) => (
))}
>);
}
TSXEOF
echo "✅ Step 7 · 对话首页 完成"
```
---
## Step 8 · 五个模块页面
**一条一条粘,粘完一条等提示再粘下一条:**
### 8.1 学习
```bash
cat > /home/ubuntu/feimao-platform/src/app/app/learn/page.tsx << 'TSXEOF'
"use client"; import ModuleChat from "../../components/ModuleChat";
export default function P() { return (); }
TSXEOF
echo "✅ 学习模块"
```
### 8.2 写作
```bash
cat > /home/ubuntu/feimao-platform/src/app/app/write/page.tsx << 'TSXEOF'
"use client"; import ModuleChat from "../../components/ModuleChat";
export default function P() { return (); }
TSXEOF
echo "✅ 写作模块"
```
### 8.3 剧本
```bash
cat > /home/ubuntu/feimao-platform/src/app/app/script/page.tsx << 'TSXEOF'
"use client"; import ModuleChat from "../../components/ModuleChat";
export default function P() { return (); }
TSXEOF
echo "✅ 剧本模块"
```
### 8.4 创意
```bash
cat > /home/ubuntu/feimao-platform/src/app/app/create/page.tsx << 'TSXEOF'
"use client"; import ModuleChat from "../../components/ModuleChat";
export default function P() { return (); }
TSXEOF
echo "✅ 创意模块"
```
### 8.5 论坛
```bash
cat > /home/ubuntu/feimao-platform/src/app/app/forum/page.tsx << 'TSXEOF'
"use client"; import ModuleChat from "../../components/ModuleChat";
export default function P() { return (); }
TSXEOF
echo "✅ 论坛模块"
```
---
## Step 9 · 作品库
```bash
cat > /home/ubuntu/feimao-platform/src/app/app/works/page.tsx << 'TSXEOF'
"use client";
import { useState } from "react";
type Work = { id: number; title: string; words: number; status: string; updated: string };
export default function WorksPage() {
const [works] = useState([]);
const [selectedId, setSelectedId] = useState(null);
const selected = works.find((w) => w.id === selectedId);
const muted = { color: "var(--gl-text-muted)" };
const primary = { color: "var(--gl-text-primary)" };
return (
{works.length === 0 && (
📝
还没有作品
点击「新建作品」开始创作
或「导入文档」上传已有作品
)}
{works.map((w) => (
))}
已用 0 字 / 总额度 50万字
{selected ? (
{selected.title}
{(selected.words / 10000).toFixed(1)}万字{selected.status}最后更新:{selected.updated}
📑 章节目录
{Array.from({ length: 8 }, (_, i) => (
第{i + 1}章
{Math.floor(Math.random() * 5000 + 2000)} 字
))}
) : (
)}
);
}
TSXEOF
echo "✅ Step 9 · 作品库 完成"
```
---
## Step 10 · 🔨 构建 & 重启
```bash
cd /home/ubuntu/feimao-platform && npm run build && pm2 restart feimao-platform && echo "" && echo "==========================================" && echo "🚀 部署完成!" && echo " 🔐 门禁: http://43.133.36.90" && echo " 🌊 引导: http://43.133.36.90/onboarding" && echo " 💬 主应用: http://43.133.36.90/app" && echo "==========================================" && echo "" && echo "🔐 团队通道测试:" && echo " 冰朔: TCS-0002∞ / ICE-GL∞" && echo " 肥猫: TCS-GL-0007∞" && echo ""
```
---
## ✅ 全部完成
所有 10 个 Step 执行完,打开 `http://43.133.36.90` 验证:
| 地址 | 内容 |
| --- | --- |
| `/` | 🔐 邀请码门禁 + 团队入口 |
| `/onboarding` | 🌊 人格体引导 |
| `/app` | 💬 主对话 |
| `/app/learn` | 📚 学习 |
| `/app/write` | ✍️ 写作 |
| `/app/script` | 🎬 剧本 |
| `/app/create` | 💡 创意 |
| `/app/forum` | 💬 论坛 |
| `/app/works` | 📁 作品库 |