萌部落社区 v1.6

本项目出于个人兴趣爱好搭建;线上地址仅供学习交流。

部分界面演示

image-20260618112324233

image-20260620132214399

image-20260620132229021

image-20260620132244567

image-20260620132313826

image-20260620132340560

image-20260620132355767

image-20260620132418922

image-20260620132431965

管理界面还没完全做好,目前比较糙

image-20260605175951669

image-20260605180011517


线上地址:

  • 用户端:https://www.nuonuoya.cn

前后端分离技术社区:发帖(图文 / 视频)、评论楼中楼、视频弹幕、私信、关注、收藏夹、抽奖、搜索、帖子标签;发布前 AI 审核;多实例部署时私信支持跨实例实时推送;看板娘支持 RAG 推荐帖子、MCP 联网与出行工具;游戏中心已接入 WebSocket 五子棋、井字棋与俄罗斯方块(单人 + PK)。


v1.6 更新摘要

相对 v1.3(上一版 README),本版在保留游戏中心三套玩法的基础上,重点补齐社区互动、视频体验、登录引导与前端工程化。相对 上一 Git 提交(422802d,本版另含大规模代码整理与仓库瘦身(约 566 个文件变更,移除独立管理端目录等)。

v1.6 能力版图

社区互动
楼中楼 / 点赞 / 发图 / 关注

视频体验
弹幕 / 播放器 / 音量控制

游戏中心
五子棋 / 井字棋 / 方块单人+PK

AI 能力
审核 / 看板娘 / 语义搜索

体验与工程
登录引导 / Vue 外置脚本 / 部署包

v1.3 基线

维度 v1.3 v1.6(本版)
游戏 五子棋、井字棋 + 俄罗斯方块单人 / PK;匹配与观战规则修复
视频帖 播放、上传 + 弹幕(样式 / 密度 / 区域);播放器控件优化
评论 楼中楼 + 回复刷新、发图进度、回复点赞、表情卡片统一
私信 文本 / 表情 + 上传分页、左侧列表跳主页、表情 UI 统一
个人中心 资料 / 收藏 + 收藏夹分页与重命名、详情页返回定位钩子
社交 + 用户关注 / 粉丝列表
登录 路由守卫 + 未登录统一弹窗引导;验证码交互优化
仓库 forum-vue-admin 精简为用户端 + 后端 + AI + Nginx 四件套

社区与内容

  • 楼中楼回复:主评 / 子评回复后局部刷新,不再整页重载。
  • 评论互动:回复点赞(空心 / 实心红心);评论发图保留上传提示直至全部完成;表情包封面与标题同行展示。
  • 视频弹幕:视频帖支持滚动 / 顶部 / 底部弹幕,可配置颜色、字号、模式、密度、显示区域与彩色过滤;发送与播放器控件分层布局。
  • 视频播放器:音量改为喇叭图标(静音显示带斜线喇叭);弹幕层底部高于控制栏,避免遮挡。
  • 用户关注:关注 / 取关、粉丝与关注列表;个人主页展示关注关系。
  • 收藏夹与个人主页:收藏夹分页(每页 10 条)、名称编辑(≤25 字);从帖子详情返回时恢复收藏夹 / 个人主页原滚动位置;笔记与点赞列表分页(每页 12 条)。

私信与表情

  • 私信:左侧会话列表点击头像 / 昵称可跳转对方主页;我的上传表情支持分页,上传按钮与表情格同尺寸并排。
  • 表情卡片:评论、私信、游戏房间复用统一「封面 + 标题」布局;移除表情后不再自动关闭弹层。

游戏中心(在 v1.3 基础上加固)

  • 五子棋 / 井字棋:修复双人在线匹配不到的问题;观战席禁止聊天与表情;终局卡片仅展示胜负与倒计时。
  • 俄罗斯方块:单人 canvas 循环 + 后端成绩中心;PK 后端权威棋盘、垃圾行、观战只读;结算卡星空蓝主题;PK 观战禁输入。
  • 房间聊天:表情包入口在输入框内侧,发送按钮统一星空蓝色调。

AI 与搜索

  • 语义搜索:AI 向量搜索时过滤无关用户结果。
  • 看板娘:关闭对话面板不中断进行中的回复或生图;GPT 生图请求参数与帖子封面图生成对齐。
  • Python 服务:补齐 oss2 等依赖;内部鉴权与客户端模块拆分。

登录与安全体验

  • 未登录引导:首页搜索、创作中心、私信、设置、积分、签到、抽奖、看板娘等操作统一 弹窗确认 → 去登录,不直接硬跳转。
  • 会员中心:未登录访问 /vip 弹窗引导,而非静默跳转登录页。
  • 行为验证码:滑块 / 点击验证失败自动关闭弹窗;发码按钮展示 loading;验证码错误码静默避免重复 toast。

工程与仓库

  • Vue 规范:持续推进「.vue 仅模板 + 外置 .js / .scss」;抽取 VideoVolumeIconPurchasedEmojiPackPopover 等公共组件。
  • 仓库精简:移除独立 forum-vue-admin 目录,聚焦用户端交付;管理端能力保留在后端 API,界面待完善。
  • 部署:仍遵循「本机 make-package.ps1 打整包 → 服务器 bash up.sh」,避免 index.htmlassets 版本错位。

v1.3 历史摘要(保留)

  • 游戏中心 / 五子棋:新增独立游戏大厅、五子棋匹配页和蓝黑主题对局页,支持真人匹配、观战、房间聊天 / 表情、棋谱回放、天梯榜和战绩统计。
  • 游戏中心 / 井字棋:复用游戏中心通用表与结算链路,新增 3×3 井字棋匹配页与对局页;支持快速匹配、AI 对手、房间聊天 / 表情、棋谱回放、天梯榜和战绩统计(不开放观战)。
  • 游戏中心 / 俄罗斯方块:新增 canvas 单人模式与双人 PK 模式;单人模式支持成绩结算、历史记录、排行榜与回放,PK 模式支持双人匹配、后端权威房间状态、垃圾行攻击、观战与终局结算。
  • 三层 WebSocket:大厅在线、游戏在线、房间对局拆成独立连接,服务端主动推送在线状态、匹配结果、落子、终局胜线和观战席变化。
  • 论坛积分联动:五子棋 / 井字棋胜负直接进入论坛积分流水,玩家段位、胜率、总局数和排行榜复用论坛账号体系。
  • 单人成绩型游戏接入:俄罗斯方块单人模式采用“前端本地权威游戏循环 + 后端成绩中心”的方案,避免把单人玩法硬套成棋类房间模型。
  • 局时 / 步时:五子棋支持 10 分钟局时、60 秒步时;井字棋支持 2 分钟局时、20 秒步时;超时、认输、成线 / 五连均走统一结算链路。
  • AI 对手:长时间无人匹配时自动进入 AI 房间;低水平玩家使用 deepseek-v4-flash,高水平玩家使用 deepseek-v4-pro,DeepSeek 不可用时展示本地策略兜底(井字棋 AI 局积分变化更小)。
  • 局部责任链:五子棋动作 / 匹配、私信发送、发帖提交审核、抽奖准入已抽成 Guard Chain;结算、扣分、库存、MQ、WebSocket 广播仍保留在 Service 主流程。
  • 多实例准备:在线状态、匹配队列、房间快照、房间事件广播和对局结束事件已按 Redis / RabbitMQ 拆出扩展点。

项目概览

目录 说明
backend Java 后端(Spring Boot):业务 API、鉴权、MQ、WebSocket、审核状态、五子棋 / 井字棋 / 俄罗斯方块
ai-server Python:AI 审核 / 写作 / 看板娘 / 语义搜索 / RAG
forum-vue 用户端(Vue 3 + Vite 6)
nginx Nginx 配置、Docker Compose、打包脚本、ffmpeg 视频服务

整体架构

用户端 Web

Nginx

Java 后端 backend

FFmpeg 视频服务

MySQL

Redis

RabbitMQ

Python AI ai-server

Game WebSocket: 大厅 / 游戏 / 房间

PostgreSQL

阿里云 OSS

  • 用户端 → Nginx(静态 dist/ + 反代 API)
  • Java → MySQL / Redis / RabbitMQ / FFmpeg / ai-server
  • 五子棋 / 井字棋 / 俄罗斯方块 PK 实时链路 → Java WebSocket(大厅在线、游戏在线、房间对局三类连接)
  • 局部责任链 → Java 后端 Guard Chain,只拦截前置准入规则,不接管事务核心流程
  • ai-server → PostgreSQL(LangGraph checkpoint)、DashScope、OSS 签名读私有媒体

功能一览

用户端

  • 发帖 / 评论 / 楼中楼(富文本 / Markdown)
  • 图文帖 / 视频帖、封面、相册(最多 15 张)
  • 视频弹幕(滚动 / 顶 / 底、颜色 / 字号 / 密度 / 区域可配)
  • 帖子标签(版块内申请 / 绑定)
  • 发帖 AI 异步审核(通过才发布)
  • 图片压缩 + AI 审核 + OSS;视频 FFmpeg 处理后上传 OSS
  • 评论 / 楼中楼回复点赞、评论发图与表情包
  • 私信 WebSocket、积分 / 签到 / 商城 / 抽奖、热帖榜
  • 用户关注、个人主页、收藏夹(分页 / 重命名 / 返回定位)
  • 智能搜索(DB 快搜 + AI 语义增强)
  • 看板娘:多模型、会话历史、站内帖子 RAG、联网与地图工具、GPT 生图
  • 未登录操作统一弹窗引导登录;会员中心 / 关键功能需登录
  • 游戏中心:五子棋实时匹配、观战、房间聊天 / 表情、棋谱回放、战绩统计、天梯榜、AI 对手
  • 游戏中心:井字棋快速匹配、房间聊天 / 表情、棋谱回放、战绩统计、天梯榜、AI 对手(平局不扣积分)
  • 游戏中心:俄罗斯方块单人模式(canvas 棋盘、成绩结算、历史记录、排行榜、回放)
  • 游戏中心:俄罗斯方块 PK 模式(双人匹配、后端权威状态、垃圾行攻击、观战、胜负结算)

核心流程

1) 游戏中心 / 五子棋(WebSocket 实时对战)

游戏中心目前先接入 五子棋,实时链路分成三层 WebSocket:大厅连接用于展示大厅在线与玩家状态;游戏连接用于匹配页在线人数、房间总数和最近对局;房间连接用于落子、计时、观战、聊天和终局同步。HTTP 只负责历史记录、统计、天梯榜、回放等非实时数据查询。

五子棋能力

  • 快速匹配:真人优先,长时间无人时自动创建 AI 房间
  • AI 对手:Java 调 Python AI Hub;低水平玩家使用 deepseek-v4-flash,高水平玩家使用 deepseek-v4-pro;DeepSeek 不可用或返回非法坐标时才走本地规则兜底
  • 实时对局:服务端维护权威棋盘,校验回合、坐标、棋色和观战身份;落子结果通过房间 WebSocket 主动推送
  • 计时规则:支持 10 分钟局时、60 秒步时,任一玩家超时直接结算
  • 观战与聊天:观众只读棋局,不能落子 / 认输;房间内支持文本和已购表情包,终局后禁止继续发送消息或表情
  • 棋谱与回放:每手落子写入 MySQL,前端支持历史对局回放和自动播放
  • 积分结算:胜负同步论坛积分流水,战绩统计、胜率、天梯榜与论坛用户体系共享
  • 多实例准备:在线状态、匹配队列、房间快照与房间事件可走 Redis;对局结束事件可投递 RabbitMQ 做补偿与异步处理
RabbitMQ Redis MySQL Python AI Java 后端 房间 WS 游戏 WS 大厅 WS 前端 RabbitMQ Redis MySQL Python AI Java 后端 房间 WS 游戏 WS 大厅 WS 前端 alt [匹配真人] [长时间无人] 进入游戏中心 建立大厅在线连接 更新大厅在线、段位、胜率快照 进入五子棋匹配页 开始匹配 创建真人房间 创建 AI 房间 请求 DeepSeek 落子 玩家落子 / 认输 / 聊天 校验回合、坐标、计时、观战权限 写落子、战绩、积分流水 投递对局结束事件 推送棋盘、胜线、结果与倒计时

1b) 游戏中心 / 井字棋(WebSocket 轻量对战)

井字棋作为游戏中心第二款对战游戏,复用 game_definition / game_user_profile / game_match_record / game_room_move 等通用表,以 game_code = jinzi 区分数据。实时链路同样拆成三层 WebSocket:大厅连接展示游戏中心在线;游戏连接负责井字棋匹配页在线人数与匹配队列;房间连接负责 3×3 落子、计时、聊天和终局同步。HTTP 负责个人资料、历史战绩、天梯榜与棋谱回放查询。

井字棋能力

  • 快速匹配:按论坛积分分桶(青铜 / 白银 / 黄金 / 大师),同桶内真人优先配对
  • 入场门槛:开始匹配前须至少有 3 论坛积分;真人胜局 ±3 分,AI 胜局 ±1 分,平局不结算积分
  • AI 对手:队列等待约 15 秒无人匹配时自动创建 AI 房间;积分低于 1600 走 deepseek-v4-flash,达到 1600 及以上走 deepseek-v4-pro;DeepSeek 不可用或返回非法坐标时走本地 Minimax 兜底
  • 实时对局:服务端维护权威 3×3 棋盘,校验回合、坐标、棋色;三连成线推送 winningLine,平局走 END_DRAW
  • 计时规则:支持 2 分钟局时、20 秒步时;断线保留 30 秒重连窗口,超时判负
  • 房间聊天:对局双方支持文本和已购表情包;不开放观战席,终局后禁止继续落子 / 认输 / 聊天
  • 棋谱与回放:每手落子写入 game_room_move,匹配页支持历史对局回放
  • 积分结算:胜负同步论坛积分流水;战绩、胜率、天梯榜与论坛用户体系共享
  • 多实例准备:在线状态、匹配队列、房间快照与结算事件复用 Redis / RabbitMQ 扩展点
RabbitMQ Redis MySQL Python AI Java 后端 房间 WS 游戏 WS 大厅 WS 前端 RabbitMQ Redis MySQL Python AI Java 后端 房间 WS 游戏 WS 大厅 WS 前端 alt [匹配真人] [约 15 秒无人] 进入游戏中心 建立大厅在线连接 更新大厅在线、战绩快照 进入井字棋匹配页 开始匹配 创建真人房间 创建 AI 房间 请求 DeepSeek 落子 玩家落子 / 认输 / 聊天 校验回合、坐标、计时 写落子、战绩、积分流水 投递对局结束事件 推送棋盘、胜线、平局或终局结果

1c) 游戏中心 / 俄罗斯方块(单人 + PK)

俄罗斯方块分成两套玩法。单人模式采用 canvas 主棋盘,前端本地运行游戏循环,后端只负责资料、结算、排行榜与回放;双人 PK 模式则回到后端权威房间状态,双方输入通过 WebSocket 上送,服务端推进棋盘、处理垃圾行并广播最新状态。这样既保留了单人模式的流畅度,也保证了 PK 模式的公平性。

俄罗斯方块能力

  • 单人模式:10x20 经典玩法,支持移动、旋转、软降 / 硬降、消行、成绩结算、历史记录、排行榜与回放
  • PK 模式:双人匹配、双棋盘实时同步、基础垃圾行攻击、终局胜负结算
  • 观战:第三名及以上用户可以进入 PK 房间实时观看双方棋盘,但不能发送输入控制
  • 数据分层:单人模式不硬套棋类房间语义;PK 模式保留游戏级 / 房间级连接与观战列表
  • 积分联动:单人模式按成绩档位发放论坛积分,PK 模式按胜负发放论坛积分
MySQL Java 后端 房间 WS 游戏 WS 前端 MySQL Java 后端 房间 WS 游戏 WS 前端 alt [单人模式] [PK 模式] 本地运行游戏循环 提交单局结算与回放 写单局记录、资料、排行榜 开始匹配 创建 PK 房间 发送输入操作 推进双方棋盘、计算垃圾行 写对局记录与结算 广播双方棋盘、垃圾行与终局结果

1d) 视频帖弹幕

视频帖在播放器层叠加弹幕引擎:前端按视频时间轴渲染滚动 / 顶部 / 底部弹幕;用户可在播放条旁设置颜色、字号、模式与显示区域,发送时写入 article_video_danmaku 表。弹幕层高度受控,底部不低于播放器控制栏。

MySQL Java 后端 播放器 用户 MySQL Java 后端 播放器 用户 编辑样式并发送弹幕 POST 弹幕(文章 ID / 时间点 / 样式) 持久化弹幕 返回弹幕条目 按 currentTime 渲染到弹幕层

2) 发帖审核(异步 + 幂等)

  1. 用户提交 → Java 状态改为「审核中」,生成 taskId,投递 q-audit-article
  2. Python worker 消费:validate_textvalidate_imagesvalidate_video(有视频时)→ summarize
  3. 结果回 MQ → Java 条件更新状态并通知用户

视频审核要点

  • DashScope 需能访问视频 URL;私有 OSS 由 ai-server 用 ALIYUN_* / OSS_* 生成签名 URL
  • 视频 >100MB 或 DashScope 拉取失败时:FFmpeg 抽帧 → 走图片审核兜底
  • ai-server 容器须配置与 Java 相同的 OSS 环境变量(见 docker-compose.yaml
DashScope ai-server RabbitMQ Java 前端 DashScope ai-server RabbitMQ Java 前端 提交审核 审核任务(含 videoUrl) worker 消费 文本/图片审核 OSS 签名 videoUrl 视频审核(或抽帧兜底) 审核结果 更新帖子状态

3) 视频上传

用户选择视频后,前端可后台上传并展示进度;后端按体积分流,大文件经 FFmpeg 再写入 OSS。Nginx /file/ 代理超时 3600s,避免长视频压缩卡住。

  • ≤200MB:Java 直传 OSS
  • >200MB:Java → FFmpeg(H.264+AAC 则 remux 不重编码,否则 ultrafast 重编码)→ 回传字节流 → OSS
  • 绑定帖子:保存草稿 / 提交时调用 setArticleVideo(视频帖不调相册接口)

用户选择视频

前端后台上传 + 进度条

Nginx /file/ 反代

Java FileService

体积 ≤ 200MB?

直传 OSS

FFmpeg 服务

H.264 + AAC?

remux -c copy

ultrafast 重编码

上传 OSS

返回 videoUrl

setArticleVideo 绑定帖子

4) 行为验证码 + 一次性票据

短信 / 邮件有成本,注册与找回密码不能裸奔。滑块验证通过后签发 Redis 短 TTL 票据;后续发码 / 注册须携带票据,校验成功即 删除(一次性)。

Redis Java 后端 前端 Redis Java 后端 前端 alt [票据有效且未用过] [无效 / 已用 / 过期] 1) 提交滑块验证结果 SET ticket(UUID, purpose, TTL≈2min) 返回 ticket 2) 注册 / 发码(带 ticket) GET + DEL ticket(用一次即失效) 继续业务(发码 / 注册) 拒绝

5) 积分抽奖防超卖

抽奖最怕 积分扣成负数限量奖品发超。关键扣减在事务内用 带条件的 UPDATE 保证原子性;并发抽奖对用户行 SELECT FOR UPDATE 串行化。

  • 扣积分:WHERE points >= cost,影响行数为 0 则失败
  • 扣库存:WHERE stock > 0,失败则换奖品重抽(有上限)
  • 硬保底:连续 N 次未中头奖 → 下次走保底池
  • 软保底:十连最后一抽兜底,保证至少一个稀有

0 行

成功

失败

成功

开始抽奖

事务: SELECT user FOR UPDATE

扣积分 UPDATE points>=cost

余额不足

单抽 / 十连

触发硬保底?

保底奖池

按权重抽奖品

扣库存 UPDATE stock>0

换奖品重试

写中奖记录 / 发奖

提交事务

十连: 末抽软保底检查

6) 私信跨实例推送

多实例时,接收方的 WebSocket 连接落在哪台机器不确定。写库后向 Redis PubSub 广播推送事件;只有持有目标连接的那台实例真正下发,其余实例忽略。

本机有 B 的连接

无 B 连接

用户 A 发私信

Java 实例 1

用户 B 的 WS

Java 实例 2

MySQL 持久化消息

Redis PubSub 广播

WebSocket 推送给 B

忽略

7) 热帖榜(Redis ZSet)

热帖榜用 Redis ZSet:member 为帖子 ID,score 为热度。点赞 / 浏览 / 回复 / 收藏等行为触发 ZINCRBY;删帖、驳回、下线时 ZREM。定时任务可从 DB 全量重算做兜底。

用户行为: 浏览 / 点赞 / 回复 / 收藏

Redis ZSet hot_rank

ZINCRBY 加分

删帖 / 审核驳回 / 下线

ZREM 移除

定时兜底任务

从 MySQL 重算热度

首页 / 热榜接口 ZREVRANGE

8) 智能搜索(快搜 + 语义增强)

搜索分层:先数据库 LIKE 快搜(低成本、稳定);结果过少或相关性不足时,再调 ai-server 做语义排序 / RAG 召回,把更相关的帖子排到前面。

用户输入关键词

MySQL 标题 LIKE 快搜

结果数量 / 质量够用?

直接返回列表

拉取候选: 标题 + 摘要 + 标签

ai-server 语义排序 / RAG

返回重排后的结果

9) 局部责任链(Guard Chain)

后端只在前置准入校验上使用局部责任链,避免业务入口继续堆叠大量重复 if。责任链只回答“能不能继续”,失败时返回统一错误;真正的落库、扣积分、库存扣减、MQ 投递、WebSocket 广播和状态流转仍由原 Service 主流程负责。

已接入的 Guard Chain:

  • 五子棋房间动作:MOVE / CHAT / SURRENDER,校验房间存在、进行中、玩家身份、回合、坐标、空位和聊天内容
  • 五子棋匹配入口:校验用户存在、积分足够、未在对局中、未重复入队
  • 井字棋房间动作:在 JinziRoomService 内校验房间存在、进行中、玩家身份、回合、坐标、空位和聊天内容(不开放观战)
  • 井字棋匹配入口:校验用户存在、积分 ≥ 3、未在对局中、未重复入队
  • 私信发送:校验文本 / 图片 / GIF / 回复消息的内容、发送者状态、接收者、不能给自己发、媒体 URL 来源
  • 发帖提交审核:校验作者、禁言、帖子可见、状态允许、审核重试次数
  • 抽奖准入:校验用户 ID、抽数、活动可用、用户可用

明确不放进责任链的核心流程:

  • 五子棋终局结算:对局记录、胜负统计、积分流水、玩家状态、结算事件和广播
  • 井字棋终局结算:对局记录、胜负统计、积分流水(平局 scoreDelta=0)、玩家状态、结算事件和广播
  • 发帖审核结果应用:PENDING_AUDIT + taskId 的 DB CAS、Redis dedup、通过 / 拒绝 / 异常状态落库
  • 抽奖执行:积分扣减、库存扣减、中奖记录、软保底 / 硬保底计数
  • 文件上传:当前私有方法校验已足够集中,拆链收益不明显

失败

通过

业务请求

构造 Context

Guard Chain 前置校验

返回业务错误 / WebSocket 友好提示

Service 主流程

MySQL / Redis

RabbitMQ 事件

WebSocket 推送


本地开发

启动顺序

# 1. 中间件
cd nginx
docker compose -f docker-compose.dev.yaml up -d --build

# 2. 用户端
cd ..\forum-vue\front
npm install
npm run dev

# 3. 后端
cd ..\..\backend
mvn spring-boot:run

# 4. Python AI
cd ..\ai-server
python main.py
模块 默认地址 / 端口
用户端 http://localhost:5173
后端 http://localhost:10086
AI 服务 http://localhost:5000
MySQL localhost:33061
Redis localhost:63790
RabbitMQ AMQP localhost:56690
RabbitMQ 管理台 localhost:25672
PostgreSQL localhost:54320
FFmpeg localhost:8099

开发者

forum-vue/front:5173

backend:10086

MySQL:33061

Redis:63790

RabbitMQ:56690

ai-server:5000

FFmpeg:8099

PostgreSQL:54320

IDEA 打开后端:File → Open → 选 backend 文件夹或 pom.xml,Maven Reload,开启 Lombok Annotation Processors。

五子棋本地调试

  • 游戏入口:用户端登录后访问 /games,再进入 /games/gobang
  • WebSocket 入口:/ws/game-center/lobby/ws/games/gobang/ws/games/gobang/rooms/{roomId}
  • 对局结果依赖 MySQL;在线、匹配与多实例房间事件依赖 Redis;异步结算事件依赖 RabbitMQ
  • AI 对手依赖 ai-serverDEEPSEEK_API_KEY;Python 服务不可用时 Java 会使用本地规则兜底,但界面会展示兜底标识

井字棋本地调试

  • 游戏入口:用户端登录后访问 /games,再进入 /games/jinzi
  • WebSocket 入口:/ws/game-center/lobby/ws/games/jinzi/ws/games/jinzi/rooms/{roomId}
  • 匹配门槛:论坛积分至少 3 分;真人胜局 ±3 分,AI 胜局 ±1 分,平局不结算
  • 计时:2 分钟局时、20 秒步时;断线 30 秒内可重连,否则判负
  • AI 对手约 15 秒无人匹配后触发;同样依赖 ai-serverDEEPSEEK_API_KEY,不可用时走本地 Minimax 兜底

本地密钥

copy scripts\dev-secrets.ps1.example scripts\dev-secrets.ps1
. .\scripts\load-dev-env.ps1

真实 .envscripts/dev-secrets.ps1ai-server/config.local.yaml 不提交。数据库全量结构在 backend/src/main/resources/sql/create.sql,增量 SQL 放在 backend/src/main/resources/sql/

快速验收

cd backend
mvn clean test

cd ..\forum-vue\front
npm run build

生产部署

生产部署遵循“本机构建完整包,服务器只加载完整包”的原则,避免前端 index.htmlassets 版本不一致。

本地 make-package.ps1

nginx/package

上传整包到服务器

确认 package/.env 与 ssl

bash up.sh

docker load 镜像

compose up --force-recreate

healthz / 前端资源校验

日常更新

cd nginx
.\scripts\make-package.ps1

服务器:

cd ~/package
bash up.sh
curl -s http://127.0.0.1/healthz
./verify-frontend-dist.sh .

首次部署

cd ~/package
cp .env.example .env
nano .env
bash start.sh

up.sh 保留数据卷;docker compose down -v 会删除数据库数据,线上慎用。需要排查时优先执行 bash collect-logs.sh 收集日志包。


配置说明

nginx/.env 和服务器 package/.env 为准,真实值只来自环境变量或本地忽略文件。

类别 变量
安全 JWT_SECRETPII_CRYPTO_SECRETFORUM_MASCOT_INTERNAL_KEYFORUM_AI_INTERNAL_KEY
数据 MYSQL_*REDIS_PASSWORDRABBITMQ_*POSTGRES_*
AI DASHSCOPE_API_KEYDEEPSEEK_API_KEY(须来自 platform.deepseek.com勿与 DashScope 混用)、HUANAPI_*TAVILY_API_KEYBAIDU_MAP_API_KEY
OSS ALIYUN_ACCESS_KEY_IDALIYUN_ACCESS_KEY_SECRETOSS_BUCKET_NAMEOSS_URL_PREFIXOSS_ROOT_PREFIX
OSS → ai-server 同上 OSS 变量须注入 forum-ai-server(视频审核签名读私有桶)
邮件 MAIL_USERNAMEMAIL_PASSWORD

五子棋 / 井字棋 AI 使用 DeepSeek:低水平对手走 deepseek-v4-flash,高水平对手走 deepseek-v4-pro;模型名称配置在 ai-server/config.yaml / config.docker.yamldeepseek.model_flashdeepseek.model_pro。看板娘 MCP 内置 tavily_searchget_current_datetimemap_*,需要对应 API Key。


常见问题

1) 五子棋对局结束后还能发消息导致异常

结束后房间会清理内存状态,但前端还会停留 60 秒展示胜负和胜线。后端必须把这段窗口里的聊天、表情、落子、认输都拦截成友好提示:当前对战已经结束,不能发送消息或表情包。如果又出现堆栈,优先看 GobangGuardChain 中的房间存在、进行中和玩家动作准入校验。

2) 五子棋 WebSocket 已连接但棋盘不刷新

检查三层连接是否连对:大厅 /ws/games/lobby,游戏 /ws/games/gobang,房间 /ws/games/gobang/rooms/{roomId}。落子后不应该依赖 HTTP 刷新,前端应直接应用 move_accepted / game_finished 的 payload。

没有

move_accepted

game_finished

room_error

棋盘没刷新

房间 WS 有消息?

检查 token、roomId、Nginx WS 代理

消息类型正确?

检查前端 applyMove

检查胜线和结束态渲染

按后端提示修权限 / 状态

3) 井字棋 WebSocket 已连接但棋盘不刷新

检查游戏连接与房间连接是否连对:大厅 /ws/game-center/lobby,游戏 /ws/games/jinzi,房间 /ws/games/jinzi/rooms/{roomId}。落子后应直接应用 move_accepted / game_finished 的 payload,不要依赖 HTTP 轮询刷新。

4) AI 对手一直显示本地策略兜底

说明 Java 没拿到 Python / DeepSeek 的合法坐标。依次检查:ai-server 是否在 5000 端口;FORUM_AI_INTERNAL_KEY 是否一致;DEEPSEEK_API_KEY 是否有效;Python 返回坐标是否为空位。兜底不是错误,但如果 Python 已启动仍长期兜底,优先查 Python 日志里的 DeepSeek 调用失败原因。

5) 前端 403 / 白屏

通常是生产包没整体更新,导致 index.html 指向的 assets 不存在。不要只传单个 JS 文件;重新上传完整 nginx/package,服务器执行 bash up.sh,再跑 ./verify-frontend-dist.sh .

6) 审核一直显示异常

视频审核最常见是私有 OSS 导致 DashScope 无法拉取媒体,确认 ai-server 注入 OSS 变量并生成签名 URL。RabbitMQ 队列短暂 NOT_FOUND 多数是启动竞态,Java / Python 都起来后会恢复;持续存在时检查交换机和队列声明。

7) Redis / RabbitMQ 在游戏里分别负责什么

Redis 更适合短生命周期实时状态:大厅在线、游戏在线、匹配队列、房间快照、跨实例房间事件广播。RabbitMQ 更适合“必须最终处理”的事件:对局结束后异步结算、补偿任务、统计刷新和通知扩展。不要把实时棋盘权威状态只放进 MQ,棋盘最终裁决仍由 Java 房间服务完成。

8) 本地 RabbitMQ 端口对不上

开发 Compose 默认把 RabbitMQ AMQP 映射到 56690,而后端配置如果没有加载本地环境变量,可能仍按 56720 连接。启动后端前确认 SPRING_RABBITMQ_PORT=56690,或在本机显式启动与 application.yml 一致的 RabbitMQ 端口。

9) 未登录点击功能直接跳转登录页

v1.6 起首页搜索、创作中心、私信、看板娘等交互应弹出「需要登录」确认框。若仍直接跳转,检查 loginPrompt.js 与路由 meta.requiresAuth 是否被绕过。

10) 行为验证码失败后弹窗不关闭

验证失败(业务码 1168)须自动关闭弹窗,由用户下次手动触发。检查 BehaviorCaptchaDialog.failAndClosecheckCaptchasilentBizCodes 配置。


仓库结构

luntan/
  backend/                 # Java 后端:API、WebSocket、积分、弹幕、关注、五子棋 / 井字棋 / 俄罗斯方块
  ai-server/               # Python AI(审核 / 看板娘 / RAG)
  forum-vue/               # 用户端前端
  nginx/                   # Compose、Nginx、FFmpeg、打包脚本
    scripts/
      make-package.ps1     # 一键打包
      build-all.ps1        # 构建前后端与镜像
      export-images.ps1    # 组装 package/
      verify-package.ps1   # 打包自检
      server-up.sh         # → package/up.sh
    ffmpeg/                # 视频压缩 / 审核抽帧
  scripts/
    dev-secrets.ps1.example
    load-dev-env.ps1       # 本地加载密钥到当前 PowerShell 会话
  luntan.code-workspace    # 多根工作区(可选)

Git 忽略要点.env.codex/nginx/package/nginx/dist/target/node_modules/ssl/*.pemscripts/dev-secrets.ps1、本地 ai-server/config.local.yaml 等,见根目录 .gitignore

Logo

中国智能体开发者社区,聚焦智能体与大模型开发,提供前沿资讯、实用工具链、开源项目及行业案例。通过技术沙龙、开发者大赛等活动,促进经验交流与协作,助力开发者快速构建创新智能应用。

更多推荐