深圳市燕川中学校友会公益数字平台
连接毕业校友、在校生与老师 · 非官方、无盈利 · 开源共建
你可能见过无数校友录网站。但 燕中校友数字母港 是一个面向深圳市燕川中学校友、在校师生与管理员的全栈数字化社区操作系统。V2.0 版本经历了从「能跑」到「生产级」的质变——我们重建了安全防线、实现了站内 CMS 审核闭环、赋予了系统星空紫暗黑玻璃拟态的设计灵魂,并以幂等性数据播种工作流兜底了零停机部署。
One-command to start. One pipeline to deploy. Zero OOM on the edge.
![]() |
![]() |
![]() |
| 百年燕中(学校介绍) | 校园公告与新闻资讯 | 校友活动 |
![]() |
![]() |
![]() |
| 在校生互助资源站 | 筑梦师长(教师频道) | 互通有无(联系我们) |
![]() |
![]() |
![]() |
| 星空通讯录(校友地图) | 校友成就墙 | 燕中故事专栏 (CMS) |
![]() |
![]() |
|
| 燕中记忆文化长廊 | 电子校友纪念卡 |
🛠️ 管理员后台(点击展开 14 张截图)
![]() |
![]() |
![]() |
| 控制台概览 | 新闻管理 | 活动管理 |
![]() |
![]() |
![]() |
| 校友名单管理 | 修改申请审核 | 燕中记忆管理 |
![]() |
![]() |
![]() |
| 燕中故事管理 | 待审核故事工作台 | 投稿管理 |
![]() |
![]() |
![]() |
| 用户管理 | 旧资料认领审核 | 校友成就墙管理 |
![]() |
![]() |
|
| 教师频道管理 | 页面内容管理 |
| 特性 | 描述 |
|---|---|
| 🛡️ 工业级安全防护 | HMAC-SHA256 + timingSafeEqual 防时序攻击 · 三层限流自动降级(Upstash → ioredis → Memory)· Payload 16KB 熔断器防 OOM · sessionVersion 即时全局踢出 |
| 🌌 星空紫暗黑玻璃拟态 | 全局 Tailwind 语义设计令牌 · backdrop-blur-xl 毛玻璃卡片 · 3 级阴影系统 · 暗黑主题贯穿前台与后台 |
| 🗺️ 多维校友地图聚合 | Leaflet 热力地图 · 城市/院校/专业三维聚合算法 · cityCoordinates 静态离线坐标系 · 实时校友搜索与分布统计 |
| 📝 站内 CMS 审核闭环 | DRAFT → PENDING → PUBLISHED/REJECTED 四态状态机 · 前台「我的投稿」面板支持状态追踪与撤销 · 后台审核工作台含完整审计日志 |
| ⚙️ 自动化全链路部署 | Prisma 幂等种子脚本 · build 命令自动建表+播种 · systemd + Nginx + Let's Encrypt · WAL 模式 SQLite 事务优化 |
| 🎨 前端工程化解耦 | useResource + CrudManager 数据层抽象 · 基础组件库(GlassCard/PageShell/Badge/PageHeader)· JoinRequestModal 全局单例弹窗 |
| 📤 智能图片管道 | Sharp 16:9 自动裁切 + WebP 转换 · 原子写入(tmp→rename)防文件损坏 · 上传 MIME 类型安全校验 |
| 📊 操作审计追溯 | 管理员所有关键操作自动写入 AuditLog · JSON before/after 快照 · 按目标类型 & 时间双索引检索 |
graph TD
U(("👤 用户 / 浏览器"))
U -->|"HTTPS :443"| NGINX["<b>Nginx</b><br/>SSL · 静态资源 · 反向代理"]
NGINX -->|"proxy_pass :3000"| MW["<b>Edge Middleware</b><br/>HMAC-SHA256 验签<br/>路由级角色分流"]
MW --> FRONT["<b>前台 21 页</b><br/>首页 · 地图 · 校友证<br/>故事投稿 · 个人中心"]
MW --> ADMIN["<b>后台 18 页</b><br/>CMS 审核 · 名单管理<br/>用户管理 · 内容配置"]
MW --> API["<b>60+ API Routes</b><br/>鉴权 → Payload 校验<br/>readJsonBody 熔断"]
FRONT --> PRISMA
ADMIN --> PRISMA
API --> PRISMA
PRISMA["<b>Prisma 7.x ORM</b><br/>16 Models · 50+ Index<br/>WAL · busy_timeout=5s"] --> SQLITE[("🗄️ SQLite")]
PRISMA --> CACHE
subgraph SAFE["🛡️ 安全层"]
MW
AUTH["<b>RBAC 鉴权</b><br/>GUEST / ALUMNI / ADMIN<br/>sessionVersion 即时踢出"]
LIMIT["<b>三层限流</b><br/>Upstash → ioredis<br/>→ Memory Map<br/>优雅降级"]
end
subgraph CACHE["⩛ 缓存层(可选)"]
REDIS["Upstash Redis"]
IOREDIS["自建 Redis"]
MEM["进程内内存"]
end
style U fill:#7C3AED,color:#fff,stroke:#A78BFA
style SQLITE fill:#003B57,color:#fff
style NGINX fill:#22C55E,color:#fff
style PRISMA fill:#2D3748,color:#fff
style SAFE fill:transparent,stroke:#EF4444,stroke-dasharray:4
style CACHE fill:transparent,stroke:#F59E0B,stroke-dasharray:4
技术选型哲学:SQLite 单文件数据库零运维;WAL + 事务批量写 +
busy_timeout三重优化保障并发可靠。Standalone 编译输出意味着 一台 2C2G Linux 服务器足以驱动数百校友日常访问。
- Node.js ≥ 20.x
- npm ≥ 10.x
- WSL / Linux(生产构建需 Unix 环境)
git clone https://github.com/yanchuaner/web_yanchuaner.git
cd web_yanchuaner
npm ci
cp .env.example .env # 编辑 .env 配置环境变量
npm run build # Prisma generate → db push → seed → next build
npm run dev浏览器访问 http://localhost:3000 即可预览。
npm run build做了什么?
prisma generate && prisma db push && prisma db seed && next build
一条命令完成:类型生成 → 数据库建表 → 种子数据注入 → 生产编译。这就是我们说的「幂等性数据播种工作流」——无论执行多少次,数据都安全无损。
npm run create-admin
# 按提示输入用户名和密码,即可获得后台管理权限| 变量 | 说明 |
|---|---|
DATABASE_URL |
SQLite 数据库路径(如 file:./prisma/dev.db) |
SESSION_SECRET |
Token 签名密钥 · 至少 32 字符随机串 |
ACCESS_PASSWORD_HASH |
访问口令(SHA256 哈希) |
ADMIN_USERNAME / ADMIN_PASSWORD_HASH |
管理员账号 |
UPLOAD_DIR |
图片上传目录,默认 public/uploads |
RESEND_API_KEY / RESEND_FROM_EMAIL |
邮件服务(Resend) |
UPSTASH_REDIS_REST_URL / UPSTASH_REDIS_REST_TOKEN |
云端限流(可选) |
REDIS_URL |
自建 Redis(可选) |
web_yanchuaner/
├── src/
│ ├── app/ # Next.js App Router 主阵地
│ │ ├── (front)/ # 前台路由组(21 页)
│ │ │ ├── page.tsx # 星空大堂(首页)
│ │ │ ├── about/ # 百年燕中
│ │ │ ├── alumni/ # 校友专属空间
│ │ │ │ ├── university-map/ # 🗺️ 校友城市热力地图
│ │ │ │ ├── stories/ # 📝 校友故事专栏
│ │ │ │ ├── certificate/ # 🎓 电子校友纪念卡
│ │ │ │ ├── achievements/ # 🏆 校友成就榜
│ │ │ │ ├── memories/ # 📸 青春记忆馆
│ │ │ │ └── correction/ # ✏️ 校友名录修正
│ │ │ ├── students/ # 在校生资源站
│ │ │ ├── teachers/ # 筑梦师长
│ │ │ ├── news/ # 新闻资讯
│ │ │ ├── events/ # 活动公告
│ │ │ └── me/ # 个人中心(资料+投稿管理)
│ │ ├── (admin)/admin/ # 后台路由组(18 页)
│ │ │ ├── page.tsx # 控制台概览
│ │ │ ├── stories/pending/ # 审核工作台
│ │ │ ├── alumni/ # 校友名册管理(含 CSV 导入)
│ │ │ ├── users/ # 用户管理
│ │ │ ├── user-claims/ # 校友认领审核
│ │ │ └── ... # 内容/活动/成就/记忆管理
│ │ └── api/ # 60+ API 端点(鉴权→校验→业务)
│ ├── components/
│ │ ├── ui/ # 原子级 UI 组件
│ │ │ ├── PageShell.tsx # 页面容器(导航+页脚包裹)
│ │ │ ├── GlassCard.tsx # 毛玻璃卡片基座
│ │ │ ├── PageHeader.tsx # 页面标题(eyebrow+描述)
│ │ │ ├── Button.tsx # 语义按钮(variant/size)
│ │ │ ├── Badge.tsx # 状态徽章
│ │ │ ├── EmptyState.tsx # 空状态占位
│ │ │ ├── RevealSection.tsx # 滚动渐入动画
│ │ │ └── InteractiveStarfield.tsx # 🎆 星空粒子背景
│ │ └── admin/ # 后台组件
│ │ ├── AdminPageShell.tsx # 后台页面壳
│ │ ├── AdminBreadcrumb.tsx # 面包屑导航
│ │ └── CrudManager.tsx # 通用 CRUD 表格组件
│ ├── hooks/
│ │ └── useResource.ts # 数据层抽象 Hook
│ ├── lib/ # 核心工具库
│ │ ├── db.ts # Prisma 客户端(WAL+timeout)
│ │ ├── verify-token.ts # HMAC-SHA256 Token 签名/校验
│ │ ├── admin-auth.ts # RBAC 鉴权中间件(API/Page 双模式)
│ │ ├── auth-utils.ts # 密码规范/Payload 熔断器/安全跳转
│ │ ├── rate-limit.ts # 三层限流器(Upstash→ioredis→Memory)
│ │ ├── cache.ts # Redis 缓存层(可选)
│ │ ├── image-pipeline.ts # Sharp 16:9 智能裁切管道
│ │ ├── tags.ts # Tags 解析/标准化工具
│ │ ├── email.ts # Resend 邮件服务
│ │ ├── apiClient.ts # 前台 fetch 客户端封装
│ │ └── memories.ts # 记忆数据工具
│ └── middleware.ts # Edge 路由守卫(Token 验签+路由分流)
├── prisma/
│ ├── schema.prisma # 16 个数据模型 + 50+ 索引
│ ├── seed.ts # 幂等性种子脚本
│ └── data/ # 种子数据源(CSV/JSON)
├── scripts/ # 运维脚本(备份/加载测试/数据迁移/种子)
├── docs/ # 技术文档矩阵
│ ├── architecture.md # 架构设计详解(请求生命周期、数据解耦、地图聚合)
│ ├── security.md # 安全防御指南(Payload 熔断、IDOR、Token 设计)
│ ├── deployment.md # 部署流水线指南(systemd、Nginx、CI/CD)
│ ├── ui-guide.md # UI 开发指南(设计令牌、组件库、星空紫主题)
│ ├── routes.md # 全量路由清单(60+ API + 状态机路由标注)
│ ├── admin-guide.md # 管理员手册(CMS 审核工作台、审计日志)
│ ├── operations-guide.md # 运营指南(SQLite WAL、幂等播种、限流架构)
│ └── troubleshooting.md # 故障排除(SQLITE_BUSY、429、构建问题)
├── tailwind.config.ts # 语义设计令牌定义
└── Dockerfile # 多阶段 Standalone 容器构建
| 命令 | 说明 |
|---|---|
npm run dev |
启动开发服务(热重载 · 0.0.0.0:3000) |
npm run build |
一站式生产构建(生成→建表→播种→编译) |
npm run start |
启动 Standalone 生产服务 |
npm run lint |
ESLint 静态检查 |
npm run smoke |
核心路由安全冒烟测试 |
npm run seed |
幂等种子注入(仅 prisma/seed.ts) |
npm run seed-all |
全量种子注入(名册+内容+记忆+故事) |
npm run create-admin |
交互式创建管理员账号 |
npm run fresh |
清理重建开发环境 |
npx prisma studio |
数据库可视化浏览器 |
本项目从 V2.0 起建立了防御性编程基线,核心安全机制包括:
- Payload 大小熔断:所有 JSON 请求体受
readJsonBody()限制(普适 16KB / 富文本 512KB),超限直接拒绝,杜绝内存炸弹 - CSV 导入多层防御:文件 ≤ 2MB · 智能列头检测 · 逐行字段校验 · 事务批量写入 · 错误上限 20 条即熔断
- 鉴权分层:Middleware(Edge Token 验签)→ API(
requireAdmin/requireVerifiedAlumni)→ 数据库层(select显式投射脱敏)——三层纵深 - Token 安全设计:
sessionVersion计数器 + HMAC-SHA256 +timingSafeEqual,支持即时全局踢出所有会话 - 限流自动降级:Upstash Redis → ioredis → Memory Map,任何一层故障均不阻断服务
- 图片安全:MIME 类型校验 + Sharp 重编码 + 原子写入(tmp→rename)
详见 docs/security.md。
本项目统一使用语义 CSS 类名,禁止裸写十六进制色值。
text-brand /* 主色 #7C3AED */ bg-surface /* 卡片白 */
bg-brand/10 /* 10% 透明主色 */ bg-surface-muted /* 页面底色 */
text-accent /* CTA 绿 */ border-line /* 统一描边 */完整的令牌定义见 src/app/globals.css 的 :root 块 + tailwind.config.ts。
欢迎所有校友共建者提交 Issue 或 Pull Request!
- Fork 本仓库,从
main分支创建 Feature 分支 - 修改后确保通过
npm run lint(零警告) - 提交 PR 指向
main分支,附上清晰的变更说明
| 禁止修改 | 说明 |
|---|---|
src/app/api/* |
后端 API 端点与数据契约 |
prisma/schema.prisma |
数据库模型定义 |
src/lib/db.ts / src/lib/admin-auth.ts / src/lib/verify-token.ts |
数据库连接与鉴权核心 |
src/middleware.ts |
路由安全中间件 |
所有路由的 folder 名与 href |
SEO 与外链稳定性 |
本项目采用 MIT License 授权,仅用于个人公益及非商业性校友联络平台构建。
Built with ❤️ for Yanzhong Alumni · V2.0 — June 2026
























