Files
blog/write-server
2026-06-24 16:01:59 +08:00
..
2026-06-22 10:49:09 +00:00
2026-06-21 20:42:44 +08:00
2026-06-24 14:34:12 +08:00
2026-06-24 16:01:59 +08:00
2026-06-21 20:42:44 +08:00
2026-06-22 14:59:24 +08:00
2026-06-22 13:20:07 +08:00
2026-06-22 10:49:09 +00:00
2026-06-24 13:50:26 +08:00
2026-06-21 20:42:44 +08:00
2026-06-24 13:52:16 +08:00
2026-06-24 15:08:41 +08:00
2026-06-22 15:18:55 +08:00
2026-06-22 18:21:28 +08:00
2026-06-21 20:42:44 +08:00
2026-06-22 14:59:24 +08:00
2026-06-21 20:42:44 +08:00
2026-06-21 20:42:44 +08:00
2026-06-24 13:50:26 +08:00
2026-06-21 20:42:44 +08:00
2026-06-21 20:42:44 +08:00
2026-06-21 20:42:44 +08:00
2026-06-22 18:53:26 +08:00
2026-06-21 20:42:44 +08:00
2026-06-22 10:49:09 +00:00

Write Server

Hugo 博客的管理后台,基于 Next.js 16 + Tailwind CSS 4,Docker 容器化部署。

域名:https://post.usj.cc

功能模块

模块 路径 权限 说明
文章管理 / admin/user 列表、搜索、编辑、删除、预览(user 只看自己的文章)
撰写文章 /edit admin/user Markdown 编辑器,图片/视频上传,作者自动填充
评论管理 /comments admin/user Artalk 评论回复、删除
图片管理 /images admin/user 图片上传管理
回收站 /recycle admin/user 已删文章恢复(30 天)
订阅源 /feeds admin RSS 订阅源管理
友链管理 /links admin 友链增删改查
公众号 /wechat admin 微信公众号发布(自包含,直连微信 API)
Bot 管理 /bot admin Telegram Bot / Hugo 预览状态
用户管理 /users admin 添加/删除用户、修改密码

技术栈

  • 框架: Next.js 16 (Turbopack, standalone 输出)
  • 样式: Tailwind CSS 4, SEN 暖色系
  • 数据: 直接读写 Hugo Markdown 文件,无数据库
  • 认证: Service Worker + SHA-256 密码哈希,3 小时自动过期
  • 评论: Artalk API v2 + 新评论 Telegram 实时推送
  • Bot: Telegram Bot(长轮询,语音转文字,GIF/视频处理)
  • 公众号: 微信 API 直连(access_token 自动管理)
  • 视频: ffmpeg GIF 转换 + Amigo 风格自定义播放器
  • 反向代理: Nginx + HTTPS
  • Hugo 预览: 独立端口 1313,HTTPS 访问

Telegram Bot 功能

命令 说明
/new 新建文章
/edit 编辑文章
/delete 删除文章
/list 文章列表
/publish 保存发布
/draft 保存草稿
/deploy 推送到线上
/links 友链管理
/feeds 订阅管理
/stats 网站数据
语音消息 自动转文字写入文章(需配置 DeepSeek/OpenAI API)
图片 自动保存到文章目录
GIF 动画 ffmpeg 自动转换为 GIF 格式,透明背景
视频 保存为视频文件,自定义播放器
文档 根据类型自动处理

Bot 支持多用户,通过 TG_ALLOWED_CHAT_IDS 配置授权。

视频与 GIF 支持

Telegram Bot 自动处理

发送类型 处理方式 结果
GIF 动画 ffmpeg 转换为 .gif <img> 标签,自动循环播放
视频 直接保存 .mp4 自定义播放器(播放/暂停/进度条/静音/全屏)
图片 直接保存 Markdown 图片语法

Hugo Shortcode

{{< video src="xxx.mp4" >}}                        ← 普通视频
{{< video src="xxx.mp4" caption="视频说明" >}}      ← 带说明的视频
{{< video src="xxx.gif" loop="true" muted="true" >}} ← GIF 模式
{{< bilibili BV1xx411c7mD >}}                      ← B站视频
{{< youtube dQw4w9WgXcQ >}}                        ← YouTube 视频

播放器特性

  • Amigo 风格自定义播放器
  • 播放/暂停按钮(中央大按钮 + 底部控制栏)
  • 进度条拖拽
  • 时间显示
  • 静音切换
  • 全屏播放
  • 悬停显示控制栏
  • 暗黑模式适配

用户系统

用户配置文件:users.json(明文写入,容器启动时自动哈希)

{
  "users": [
    { "username": "admin", "password": "密码", "name": "昵称", "role": "admin" },
    { "username": "user1", "password": "密码", "name": "昵称", "role": "user" }
  ]
}
  • admin: 看所有文章,管理所有模块,可添加/删除用户
  • user: 只看自己写的文章,只能用文章/撰写/评论/图片/回收站

修改密码:

  • 网页端:侧边栏「用户管理」页面
  • 命令行:编辑 users.json → 重启容器

目录结构

write-server/
├── src/
│   ├── app/                    # Next.js 页面和 API
│   │   ├── api/auth/login/     # 登录认证
│   │   ├── api/posts/          # 文章 CRUD(按用户过滤)
│   │   ├── api/users/          # 用户管理
│   │   ├── api/rss/wechat/     # 微信公众号发布
│   │   ├── api/recycle/        # 回收站
│   │   ├── login/              # 登录页面
│   │   └── users/              # 用户管理页面
│   ├── components/             # React 组件
│   │   ├── AppShell.tsx        # 布局(登录页/主界面切换)
│   │   ├── AuthGuard.tsx       # 登录状态检查
│   │   ├── PostEditor.tsx      # 文章编辑器
│   │   ├── ShortcutPanel.tsx   # 快捷插入(视频/B站/YouTube)
│   │   └── Sidebar.tsx         # 侧边栏(按角色显示菜单)
│   └── lib/
│       ├── auth.ts             # 认证(SHA-256 哈希)
│       ├── posts.ts            # 文章读写
│       ├── recycle.ts          # 回收站
│       ├── wechat.ts           # 微信 API 直连
│       ├── voice.ts            # 语音转文字
│       ├── hugo.ts             # Hugo Server 管理
│       └── bot/                # Telegram Bot
│           ├── poll.ts         # 消息轮询 + GIF/视频处理
│           ├── handlers.ts     # 命令处理
│           └── notify.ts       # 新评论推送
├── nginx/
│   ├── conf.d/
│   │   ├── write-server.conf   # 主站配置
│   │   └── hugo-preview.conf   # Hugo 预览 HTTPS
│   ├── login.html              # 登录页(备用)
│   └── sw.js                   # Service Worker(认证)
├── scripts/
│   ├── hash-users.js           # 密码哈希脚本
│   └── ...
├── users.json                  # 用户配置
├── entrypoint.sh               # Docker 入口(权限修复 + 密码哈希 + ffmpeg)
├── Dockerfile
└── docker-compose.yml

端口说明

端口 用途 协议
80 HTTP → HTTPS 重定向 HTTP
443 写作后台(nginx → 8016) HTTPS
1313 Hugo 预览(nginx 代理) HTTPS

环境变量 (.env)

# 评论系统
ARTALK_SERVER=https://artalk.usj.cc
ARTALK_SITE=优世界

# Telegram Bot
TG_BOT_TOKEN=your-bot-token
TG_ALLOWED_CHAT_IDS=7499586710,123456789

# 微信公众号(自包含)
WECHAT_APP_ID=your-app-id
WECHAT_APP_SECRET=your-app-secret

# RSS/友链 API
RSS_API_BASE=https://api.usj.cc
RSS_API_TOKEN=your-token

# AI / 语音转文字
DEEPSEEK_API_KEY=your-key
DEEPSEEK_BASE_URL=https://api.deepseek.com

# 其他
DEFAULT_AUTHOR=小赵
PREFER_IFACE=eth0

注意: BLOG_ROOT 不要写在 .env 里!Docker 部署通过 docker-compose.yml 的 volume 映射自动处理。

常用命令

# 启动
docker compose up -d

# 停止
docker compose down

# 重建(代码变更后)
docker compose down && docker compose build --no-cache && docker compose up -d

# 查看日志
docker logs write-server -f
docker logs write-nginx -f

# 重启单个服务
docker compose restart write-server
docker compose restart nginx

# 重启 Hugo 预览
curl -X DELETE http://127.0.0.1:8016/api/hugo
curl http://127.0.0.1:8016/api/hugo

# 清除 Hugo 缓存
rm -rf /path/to/blog/resources/_gen
docker compose restart write-server

迁移到新服务器

1. 安装 Docker

curl -fsSL https://get.docker.com | sh
systemctl enable docker && systemctl start docker
apt install -y docker-compose-plugin git certbot

2. 克隆项目

cd ~ && mkdir -p hugo && cd hugo
git clone <repo-url> blog
cd blog/write-server

3. 配置

# 环境变量
cp .env.example .env && nano .env

# 用户(明文密码,启动时自动哈希)
cat > users.json << 'EOF'
{
  "users": [
    { "username": "admin", "password": "你的密码", "name": "小赵", "role": "admin" },
    { "username": "test", "password": "她的密码", "name": "辣辣", "role": "user" }
  ]
}
EOF

4. DNS + SSL

# DNS: post.usj.cc → 新服务器 IP

# SSL 证书
docker compose up -d nginx
docker compose stop nginx
certbot certonly --standalone -d post.usj.cc --agree-tos --email you@email.com
mkdir -p nginx/ssl
cp /etc/letsencrypt/live/post.usj.cc/fullchain.pem nginx/ssl/
cp /etc/letsencrypt/live/post.usj.cc/privkey.pem nginx/ssl/

5. 防火墙 + 启动

ufw allow 22,80,443,1313/tcp && ufw enable
git config --global --add safe.directory /root/hugo/blog
docker compose up -d

6. 自动续期 SSL

crontab -e
# 添加: 0 3 1 * * certbot renew --quiet && docker compose restart nginx

迁移清单

类型 内容 说明
必须 博客源码 git clone
必须 .env 手动填写 Token
必须 users.json 手动创建,明文密码(启动时自动哈希)
必须 SSL 证书 新服务器重新申请
可选 recycle/ 30 天过期,可不迁移
不需要 Docker 镜像 重新构建
不需要 node_modules 自动安装

Hugo 主题集成

write-server 依赖 Hugo 主题(Ying)的以下功能:

  • 视频 shortcode (layouts/shortcodes/video.html) - 支持本地视频、B站、YouTube
  • 视频渲染钩子 (layouts/_default/_markup/render-video.html) - Markdown 视频标签
  • 视频 CSS (assets/css/main.css) - Amigo 风格播放器样式
  • 暗黑模式 - 纯色背景,无背景图

已知限制

  • Hugo 预览(1313 端口)导航链接独立,和主站不互通
  • 博客目录 owner 会被 entrypoint 改为 uid 1001
  • 语音转文字需要配置 DEEPSEEK_API_KEY 或 WHISPER_API_KEY
  • 新评论推送每 60 秒检查一次
  • GIF 转换需要 ffmpeg(Docker 镜像已内置)

License

MIT