访问社区 · 项目结构 · [Java 业务](#Java 业务) · [AI 模块](#AI 模块) · 本地启动
萌部落是一个前后端分离的兴趣社区,把发帖、评论、收藏、聊天、成长、游戏和 AI 陪伴放在一套体系里。
核心功能展示











项目总览
#mermaid-svg-OFK9XZjOg6ff05dC{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-OFK9XZjOg6ff05dC .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-OFK9XZjOg6ff05dC .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-OFK9XZjOg6ff05dC .error-icon{fill:#552222;}#mermaid-svg-OFK9XZjOg6ff05dC .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-OFK9XZjOg6ff05dC .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-OFK9XZjOg6ff05dC .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-OFK9XZjOg6ff05dC .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-OFK9XZjOg6ff05dC .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-OFK9XZjOg6ff05dC .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-OFK9XZjOg6ff05dC .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-OFK9XZjOg6ff05dC .marker{fill:#333333;stroke:#333333;}#mermaid-svg-OFK9XZjOg6ff05dC .marker.cross{stroke:#333333;}#mermaid-svg-OFK9XZjOg6ff05dC svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-OFK9XZjOg6ff05dC p{margin:0;}#mermaid-svg-OFK9XZjOg6ff05dC .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-OFK9XZjOg6ff05dC .cluster-label text{fill:#333;}#mermaid-svg-OFK9XZjOg6ff05dC .cluster-label span{color:#333;}#mermaid-svg-OFK9XZjOg6ff05dC .cluster-label span p{background-color:transparent;}#mermaid-svg-OFK9XZjOg6ff05dC .label text,#mermaid-svg-OFK9XZjOg6ff05dC span{fill:#333;color:#333;}#mermaid-svg-OFK9XZjOg6ff05dC .node rect,#mermaid-svg-OFK9XZjOg6ff05dC .node circle,#mermaid-svg-OFK9XZjOg6ff05dC .node ellipse,#mermaid-svg-OFK9XZjOg6ff05dC .node polygon,#mermaid-svg-OFK9XZjOg6ff05dC .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-OFK9XZjOg6ff05dC .rough-node .label text,#mermaid-svg-OFK9XZjOg6ff05dC .node .label text,#mermaid-svg-OFK9XZjOg6ff05dC .image-shape .label,#mermaid-svg-OFK9XZjOg6ff05dC .icon-shape .label{text-anchor:middle;}#mermaid-svg-OFK9XZjOg6ff05dC .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-OFK9XZjOg6ff05dC .rough-node .label,#mermaid-svg-OFK9XZjOg6ff05dC .node .label,#mermaid-svg-OFK9XZjOg6ff05dC .image-shape .label,#mermaid-svg-OFK9XZjOg6ff05dC .icon-shape .label{text-align:center;}#mermaid-svg-OFK9XZjOg6ff05dC .node.clickable{cursor:pointer;}#mermaid-svg-OFK9XZjOg6ff05dC .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-OFK9XZjOg6ff05dC .arrowheadPath{fill:#333333;}#mermaid-svg-OFK9XZjOg6ff05dC .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-OFK9XZjOg6ff05dC .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-OFK9XZjOg6ff05dC .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-OFK9XZjOg6ff05dC .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-OFK9XZjOg6ff05dC .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-OFK9XZjOg6ff05dC .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-OFK9XZjOg6ff05dC .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-OFK9XZjOg6ff05dC .cluster text{fill:#333;}#mermaid-svg-OFK9XZjOg6ff05dC .cluster span{color:#333;}#mermaid-svg-OFK9XZjOg6ff05dC div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-OFK9XZjOg6ff05dC .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-OFK9XZjOg6ff05dC rect.text{fill:none;stroke-width:0;}#mermaid-svg-OFK9XZjOg6ff05dC .icon-shape,#mermaid-svg-OFK9XZjOg6ff05dC .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-OFK9XZjOg6ff05dC .icon-shape p,#mermaid-svg-OFK9XZjOg6ff05dC .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-OFK9XZjOg6ff05dC .icon-shape .label rect,#mermaid-svg-OFK9XZjOg6ff05dC .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-OFK9XZjOg6ff05dC .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-OFK9XZjOg6ff05dC .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-OFK9XZjOg6ff05dC :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} HTTPS / WSS
ai 域内部调用
用户 / 浏览器
forum-vue 用户端
Nginx
静态资源 + 反向代理
Spring Cloud Gateway
六个 Java 业务域
auth · content · im · game · economy · ai
Nacos
注册发现 / 配置
数据与消息
MySQL 六域库 · Redis · RabbitMQ
ai-server
审核 / 摘要 / 看板娘 / RAG
PostgreSQL
LangGraph 状态
外部模型与工具
请求路径是单向分层:用户端 → Nginx → Gateway → 对应业务域。六个 Java 域各自持有 api 契约和 server 实现,靠 Nacos 注册发现;MySQL 按域拆成六个库。AI 生成在 Python 服务,Java ai 域负责额度、会话和落库,普通社区功能不绑定具体模型。
项目结构
| 目录 | 负责什么 |
|---|---|
forum-vue |
用户端页面、编辑器、社区互动与看板娘界面 |
java-cloud-standalone |
Gateway + 六域 api/server + 公共 common |
ai-server |
发帖检查、摘要、写作、生图、站内检索与看板娘 |
nginx |
网站入口、Compose、打包和发布脚本 |
live2d |
看板娘模型资源 |
migrate-online-db.sh |
旧单库 forum_db 拆到六域库的迁移脚本 |
六域职责
| 域 | 进程 | 数据库 | 主要职责 |
|---|---|---|---|
| auth | forum-auth |
forum_auth_db |
登录注册、账号资料、权限快照 |
| content | forum-content |
forum_content_db |
帖子、板块、标签、评论、弹幕、推荐 |
| im | forum-im |
forum_im_db |
私信、群聊、通知、语音信令 |
| game | forum-game |
forum_game_db |
大厅、房间、对局、排行 |
| economy | forum-economy |
forum_economy_db |
积分、签到、抽奖、会员 |
| ai | forum-ai |
forum_ai_db |
AI 额度、会话、漂流瓶、看板娘业务落库 |
跨域只依赖对方的 xxx-api,通过本地 Feign 客户端调用;不共享 Entity、Mapper、Service 实现。
单域内部分层
#mermaid-svg-bxHdkNzqYwKkYDiC{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-bxHdkNzqYwKkYDiC .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-bxHdkNzqYwKkYDiC .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-bxHdkNzqYwKkYDiC .error-icon{fill:#552222;}#mermaid-svg-bxHdkNzqYwKkYDiC .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-bxHdkNzqYwKkYDiC .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-bxHdkNzqYwKkYDiC .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-bxHdkNzqYwKkYDiC .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-bxHdkNzqYwKkYDiC .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-bxHdkNzqYwKkYDiC .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-bxHdkNzqYwKkYDiC .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-bxHdkNzqYwKkYDiC .marker{fill:#333333;stroke:#333333;}#mermaid-svg-bxHdkNzqYwKkYDiC .marker.cross{stroke:#333333;}#mermaid-svg-bxHdkNzqYwKkYDiC svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-bxHdkNzqYwKkYDiC p{margin:0;}#mermaid-svg-bxHdkNzqYwKkYDiC .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-bxHdkNzqYwKkYDiC .cluster-label text{fill:#333;}#mermaid-svg-bxHdkNzqYwKkYDiC .cluster-label span{color:#333;}#mermaid-svg-bxHdkNzqYwKkYDiC .cluster-label span p{background-color:transparent;}#mermaid-svg-bxHdkNzqYwKkYDiC .label text,#mermaid-svg-bxHdkNzqYwKkYDiC span{fill:#333;color:#333;}#mermaid-svg-bxHdkNzqYwKkYDiC .node rect,#mermaid-svg-bxHdkNzqYwKkYDiC .node circle,#mermaid-svg-bxHdkNzqYwKkYDiC .node ellipse,#mermaid-svg-bxHdkNzqYwKkYDiC .node polygon,#mermaid-svg-bxHdkNzqYwKkYDiC .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-bxHdkNzqYwKkYDiC .rough-node .label text,#mermaid-svg-bxHdkNzqYwKkYDiC .node .label text,#mermaid-svg-bxHdkNzqYwKkYDiC .image-shape .label,#mermaid-svg-bxHdkNzqYwKkYDiC .icon-shape .label{text-anchor:middle;}#mermaid-svg-bxHdkNzqYwKkYDiC .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-bxHdkNzqYwKkYDiC .rough-node .label,#mermaid-svg-bxHdkNzqYwKkYDiC .node .label,#mermaid-svg-bxHdkNzqYwKkYDiC .image-shape .label,#mermaid-svg-bxHdkNzqYwKkYDiC .icon-shape .label{text-align:center;}#mermaid-svg-bxHdkNzqYwKkYDiC .node.clickable{cursor:pointer;}#mermaid-svg-bxHdkNzqYwKkYDiC .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-bxHdkNzqYwKkYDiC .arrowheadPath{fill:#333333;}#mermaid-svg-bxHdkNzqYwKkYDiC .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-bxHdkNzqYwKkYDiC .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-bxHdkNzqYwKkYDiC .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-bxHdkNzqYwKkYDiC .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-bxHdkNzqYwKkYDiC .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-bxHdkNzqYwKkYDiC .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-bxHdkNzqYwKkYDiC .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-bxHdkNzqYwKkYDiC .cluster text{fill:#333;}#mermaid-svg-bxHdkNzqYwKkYDiC .cluster span{color:#333;}#mermaid-svg-bxHdkNzqYwKkYDiC div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-bxHdkNzqYwKkYDiC .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-bxHdkNzqYwKkYDiC rect.text{fill:none;stroke-width:0;}#mermaid-svg-bxHdkNzqYwKkYDiC .icon-shape,#mermaid-svg-bxHdkNzqYwKkYDiC .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-bxHdkNzqYwKkYDiC .icon-shape p,#mermaid-svg-bxHdkNzqYwKkYDiC .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-bxHdkNzqYwKkYDiC .icon-shape .label rect,#mermaid-svg-bxHdkNzqYwKkYDiC .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-bxHdkNzqYwKkYDiC .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-bxHdkNzqYwKkYDiC .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-bxHdkNzqYwKkYDiC :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} HTTP 请求
Controller
Service
权限 / 状态 / 业务规则
Mapper
本域 MySQL
Redis
Feign
调用其他域 api
RabbitMQ
按需
每个业务域都是同一套分层,只是落在不同进程和不同库上。同一条帖子无论从首页、搜索、收藏夹还是看板娘进入,数据都回到 content;账号身份由 auth 提供快照,其他域按需读取。
Java 业务模块
帖子发布与审核
#mermaid-svg-y1w6oEzbtiEQef23{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-y1w6oEzbtiEQef23 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-y1w6oEzbtiEQef23 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-y1w6oEzbtiEQef23 .error-icon{fill:#552222;}#mermaid-svg-y1w6oEzbtiEQef23 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-y1w6oEzbtiEQef23 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-y1w6oEzbtiEQef23 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-y1w6oEzbtiEQef23 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-y1w6oEzbtiEQef23 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-y1w6oEzbtiEQef23 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-y1w6oEzbtiEQef23 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-y1w6oEzbtiEQef23 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-y1w6oEzbtiEQef23 .marker.cross{stroke:#333333;}#mermaid-svg-y1w6oEzbtiEQef23 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-y1w6oEzbtiEQef23 p{margin:0;}#mermaid-svg-y1w6oEzbtiEQef23 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-y1w6oEzbtiEQef23 .cluster-label text{fill:#333;}#mermaid-svg-y1w6oEzbtiEQef23 .cluster-label span{color:#333;}#mermaid-svg-y1w6oEzbtiEQef23 .cluster-label span p{background-color:transparent;}#mermaid-svg-y1w6oEzbtiEQef23 .label text,#mermaid-svg-y1w6oEzbtiEQef23 span{fill:#333;color:#333;}#mermaid-svg-y1w6oEzbtiEQef23 .node rect,#mermaid-svg-y1w6oEzbtiEQef23 .node circle,#mermaid-svg-y1w6oEzbtiEQef23 .node ellipse,#mermaid-svg-y1w6oEzbtiEQef23 .node polygon,#mermaid-svg-y1w6oEzbtiEQef23 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-y1w6oEzbtiEQef23 .rough-node .label text,#mermaid-svg-y1w6oEzbtiEQef23 .node .label text,#mermaid-svg-y1w6oEzbtiEQef23 .image-shape .label,#mermaid-svg-y1w6oEzbtiEQef23 .icon-shape .label{text-anchor:middle;}#mermaid-svg-y1w6oEzbtiEQef23 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-y1w6oEzbtiEQef23 .rough-node .label,#mermaid-svg-y1w6oEzbtiEQef23 .node .label,#mermaid-svg-y1w6oEzbtiEQef23 .image-shape .label,#mermaid-svg-y1w6oEzbtiEQef23 .icon-shape .label{text-align:center;}#mermaid-svg-y1w6oEzbtiEQef23 .node.clickable{cursor:pointer;}#mermaid-svg-y1w6oEzbtiEQef23 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-y1w6oEzbtiEQef23 .arrowheadPath{fill:#333333;}#mermaid-svg-y1w6oEzbtiEQef23 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-y1w6oEzbtiEQef23 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-y1w6oEzbtiEQef23 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-y1w6oEzbtiEQef23 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-y1w6oEzbtiEQef23 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-y1w6oEzbtiEQef23 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-y1w6oEzbtiEQef23 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-y1w6oEzbtiEQef23 .cluster text{fill:#333;}#mermaid-svg-y1w6oEzbtiEQef23 .cluster span{color:#333;}#mermaid-svg-y1w6oEzbtiEQef23 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-y1w6oEzbtiEQef23 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-y1w6oEzbtiEQef23 rect.text{fill:none;stroke-width:0;}#mermaid-svg-y1w6oEzbtiEQef23 .icon-shape,#mermaid-svg-y1w6oEzbtiEQef23 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-y1w6oEzbtiEQef23 .icon-shape p,#mermaid-svg-y1w6oEzbtiEQef23 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-y1w6oEzbtiEQef23 .icon-shape .label rect,#mermaid-svg-y1w6oEzbtiEQef23 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-y1w6oEzbtiEQef23 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-y1w6oEzbtiEQef23 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-y1w6oEzbtiEQef23 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 通过与摘要
拒绝或异常
作者
编辑器
富文本或 Markdown
登录、参数与内容基础校验
保存为草稿
提交审核
Java 写入待审核帖子
审核任务队列
AI 审核图
文本、图片、视频
审核结果队列
Java 更新审核状态
公开帖子
驳回,作者可修改
首页、板块、搜索、推荐
帖子、问答、视频和弹幕都建立在内容社区模块上。发布时先保存必要内容,再进行检查;最终是否公开由 Java 后端决定,AI 只给出内容检查结果。
帖子互动与通知
#mermaid-svg-004xPuU2slleoX7W{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-004xPuU2slleoX7W .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-004xPuU2slleoX7W .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-004xPuU2slleoX7W .error-icon{fill:#552222;}#mermaid-svg-004xPuU2slleoX7W .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-004xPuU2slleoX7W .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-004xPuU2slleoX7W .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-004xPuU2slleoX7W .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-004xPuU2slleoX7W .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-004xPuU2slleoX7W .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-004xPuU2slleoX7W .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-004xPuU2slleoX7W .marker{fill:#333333;stroke:#333333;}#mermaid-svg-004xPuU2slleoX7W .marker.cross{stroke:#333333;}#mermaid-svg-004xPuU2slleoX7W svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-004xPuU2slleoX7W p{margin:0;}#mermaid-svg-004xPuU2slleoX7W .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-004xPuU2slleoX7W .cluster-label text{fill:#333;}#mermaid-svg-004xPuU2slleoX7W .cluster-label span{color:#333;}#mermaid-svg-004xPuU2slleoX7W .cluster-label span p{background-color:transparent;}#mermaid-svg-004xPuU2slleoX7W .label text,#mermaid-svg-004xPuU2slleoX7W span{fill:#333;color:#333;}#mermaid-svg-004xPuU2slleoX7W .node rect,#mermaid-svg-004xPuU2slleoX7W .node circle,#mermaid-svg-004xPuU2slleoX7W .node ellipse,#mermaid-svg-004xPuU2slleoX7W .node polygon,#mermaid-svg-004xPuU2slleoX7W .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-004xPuU2slleoX7W .rough-node .label text,#mermaid-svg-004xPuU2slleoX7W .node .label text,#mermaid-svg-004xPuU2slleoX7W .image-shape .label,#mermaid-svg-004xPuU2slleoX7W .icon-shape .label{text-anchor:middle;}#mermaid-svg-004xPuU2slleoX7W .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-004xPuU2slleoX7W .rough-node .label,#mermaid-svg-004xPuU2slleoX7W .node .label,#mermaid-svg-004xPuU2slleoX7W .image-shape .label,#mermaid-svg-004xPuU2slleoX7W .icon-shape .label{text-align:center;}#mermaid-svg-004xPuU2slleoX7W .node.clickable{cursor:pointer;}#mermaid-svg-004xPuU2slleoX7W .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-004xPuU2slleoX7W .arrowheadPath{fill:#333333;}#mermaid-svg-004xPuU2slleoX7W .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-004xPuU2slleoX7W .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-004xPuU2slleoX7W .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-004xPuU2slleoX7W .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-004xPuU2slleoX7W .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-004xPuU2slleoX7W .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-004xPuU2slleoX7W .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-004xPuU2slleoX7W .cluster text{fill:#333;}#mermaid-svg-004xPuU2slleoX7W .cluster span{color:#333;}#mermaid-svg-004xPuU2slleoX7W div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-004xPuU2slleoX7W .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-004xPuU2slleoX7W rect.text{fill:none;stroke-width:0;}#mermaid-svg-004xPuU2slleoX7W .icon-shape,#mermaid-svg-004xPuU2slleoX7W .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-004xPuU2slleoX7W .icon-shape p,#mermaid-svg-004xPuU2slleoX7W .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-004xPuU2slleoX7W .icon-shape .label rect,#mermaid-svg-004xPuU2slleoX7W .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-004xPuU2slleoX7W .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-004xPuU2slleoX7W .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-004xPuU2slleoX7W :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 公开帖子
点赞或取消点赞
发布评论
回复与楼中楼
收藏到文件夹
视频弹幕
互动记录
通知中心
实时提醒或未读数
相关用户
互动数据和帖子数据分开保存,但展示时会组合在一起。这样既能显示每个人的点赞、收藏和回复状态,也能让通知中心准确告诉用户发生了什么。
搜索、热帖与推荐
#mermaid-svg-alrGCznKVIw53kwb{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-alrGCznKVIw53kwb .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-alrGCznKVIw53kwb .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-alrGCznKVIw53kwb .error-icon{fill:#552222;}#mermaid-svg-alrGCznKVIw53kwb .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-alrGCznKVIw53kwb .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-alrGCznKVIw53kwb .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-alrGCznKVIw53kwb .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-alrGCznKVIw53kwb .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-alrGCznKVIw53kwb .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-alrGCznKVIw53kwb .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-alrGCznKVIw53kwb .marker{fill:#333333;stroke:#333333;}#mermaid-svg-alrGCznKVIw53kwb .marker.cross{stroke:#333333;}#mermaid-svg-alrGCznKVIw53kwb svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-alrGCznKVIw53kwb p{margin:0;}#mermaid-svg-alrGCznKVIw53kwb .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-alrGCznKVIw53kwb .cluster-label text{fill:#333;}#mermaid-svg-alrGCznKVIw53kwb .cluster-label span{color:#333;}#mermaid-svg-alrGCznKVIw53kwb .cluster-label span p{background-color:transparent;}#mermaid-svg-alrGCznKVIw53kwb .label text,#mermaid-svg-alrGCznKVIw53kwb span{fill:#333;color:#333;}#mermaid-svg-alrGCznKVIw53kwb .node rect,#mermaid-svg-alrGCznKVIw53kwb .node circle,#mermaid-svg-alrGCznKVIw53kwb .node ellipse,#mermaid-svg-alrGCznKVIw53kwb .node polygon,#mermaid-svg-alrGCznKVIw53kwb .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-alrGCznKVIw53kwb .rough-node .label text,#mermaid-svg-alrGCznKVIw53kwb .node .label text,#mermaid-svg-alrGCznKVIw53kwb .image-shape .label,#mermaid-svg-alrGCznKVIw53kwb .icon-shape .label{text-anchor:middle;}#mermaid-svg-alrGCznKVIw53kwb .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-alrGCznKVIw53kwb .rough-node .label,#mermaid-svg-alrGCznKVIw53kwb .node .label,#mermaid-svg-alrGCznKVIw53kwb .image-shape .label,#mermaid-svg-alrGCznKVIw53kwb .icon-shape .label{text-align:center;}#mermaid-svg-alrGCznKVIw53kwb .node.clickable{cursor:pointer;}#mermaid-svg-alrGCznKVIw53kwb .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-alrGCznKVIw53kwb .arrowheadPath{fill:#333333;}#mermaid-svg-alrGCznKVIw53kwb .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-alrGCznKVIw53kwb .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-alrGCznKVIw53kwb .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-alrGCznKVIw53kwb .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-alrGCznKVIw53kwb .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-alrGCznKVIw53kwb .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-alrGCznKVIw53kwb .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-alrGCznKVIw53kwb .cluster text{fill:#333;}#mermaid-svg-alrGCznKVIw53kwb .cluster span{color:#333;}#mermaid-svg-alrGCznKVIw53kwb div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-alrGCznKVIw53kwb .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-alrGCznKVIw53kwb rect.text{fill:none;stroke-width:0;}#mermaid-svg-alrGCznKVIw53kwb .icon-shape,#mermaid-svg-alrGCznKVIw53kwb .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-alrGCznKVIw53kwb .icon-shape p,#mermaid-svg-alrGCznKVIw53kwb .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-alrGCznKVIw53kwb .icon-shape .label rect,#mermaid-svg-alrGCznKVIw53kwb .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-alrGCznKVIw53kwb .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-alrGCznKVIw53kwb .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-alrGCznKVIw53kwb :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 新帖子、浏览与互动
内容与行为数据
定时计算热度
Redis 热帖缓存
首页与板块
用户关键词
帖子标题、正文与标签检索
帖子结果
高相似度作者结果
生成帖子特征
更新兴趣画像
推荐候选与排序
用户发现内容
发现模块不是另外复制一份帖子,而是根据已有内容、互动和兴趣帮助用户更快找到想看的内容。搜索优先找帖子本身;需要时也能找到与关键词高度相关的作者。
私信、群聊与实时互动
#mermaid-svg-wft350bA9z1GYc3P{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-wft350bA9z1GYc3P .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-wft350bA9z1GYc3P .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-wft350bA9z1GYc3P .error-icon{fill:#552222;}#mermaid-svg-wft350bA9z1GYc3P .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-wft350bA9z1GYc3P .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-wft350bA9z1GYc3P .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-wft350bA9z1GYc3P .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-wft350bA9z1GYc3P .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-wft350bA9z1GYc3P .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-wft350bA9z1GYc3P .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-wft350bA9z1GYc3P .marker{fill:#333333;stroke:#333333;}#mermaid-svg-wft350bA9z1GYc3P .marker.cross{stroke:#333333;}#mermaid-svg-wft350bA9z1GYc3P svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-wft350bA9z1GYc3P p{margin:0;}#mermaid-svg-wft350bA9z1GYc3P .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-wft350bA9z1GYc3P .cluster-label text{fill:#333;}#mermaid-svg-wft350bA9z1GYc3P .cluster-label span{color:#333;}#mermaid-svg-wft350bA9z1GYc3P .cluster-label span p{background-color:transparent;}#mermaid-svg-wft350bA9z1GYc3P .label text,#mermaid-svg-wft350bA9z1GYc3P span{fill:#333;color:#333;}#mermaid-svg-wft350bA9z1GYc3P .node rect,#mermaid-svg-wft350bA9z1GYc3P .node circle,#mermaid-svg-wft350bA9z1GYc3P .node ellipse,#mermaid-svg-wft350bA9z1GYc3P .node polygon,#mermaid-svg-wft350bA9z1GYc3P .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-wft350bA9z1GYc3P .rough-node .label text,#mermaid-svg-wft350bA9z1GYc3P .node .label text,#mermaid-svg-wft350bA9z1GYc3P .image-shape .label,#mermaid-svg-wft350bA9z1GYc3P .icon-shape .label{text-anchor:middle;}#mermaid-svg-wft350bA9z1GYc3P .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-wft350bA9z1GYc3P .rough-node .label,#mermaid-svg-wft350bA9z1GYc3P .node .label,#mermaid-svg-wft350bA9z1GYc3P .image-shape .label,#mermaid-svg-wft350bA9z1GYc3P .icon-shape .label{text-align:center;}#mermaid-svg-wft350bA9z1GYc3P .node.clickable{cursor:pointer;}#mermaid-svg-wft350bA9z1GYc3P .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-wft350bA9z1GYc3P .arrowheadPath{fill:#333333;}#mermaid-svg-wft350bA9z1GYc3P .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-wft350bA9z1GYc3P .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-wft350bA9z1GYc3P .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-wft350bA9z1GYc3P .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-wft350bA9z1GYc3P .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-wft350bA9z1GYc3P .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-wft350bA9z1GYc3P .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-wft350bA9z1GYc3P .cluster text{fill:#333;}#mermaid-svg-wft350bA9z1GYc3P .cluster span{color:#333;}#mermaid-svg-wft350bA9z1GYc3P div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-wft350bA9z1GYc3P .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-wft350bA9z1GYc3P rect.text{fill:none;stroke-width:0;}#mermaid-svg-wft350bA9z1GYc3P .icon-shape,#mermaid-svg-wft350bA9z1GYc3P .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-wft350bA9z1GYc3P .icon-shape p,#mermaid-svg-wft350bA9z1GYc3P .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-wft350bA9z1GYc3P .icon-shape .label rect,#mermaid-svg-wft350bA9z1GYc3P .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-wft350bA9z1GYc3P .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-wft350bA9z1GYc3P .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-wft350bA9z1GYc3P :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 发起方
发送私信或群消息
接收方或群成员
身份与成员关系校验
会话和消息记录
WebSocket 实时推送
未读数、已读状态、历史分页
消息中心与通知
语音邀请
私信、群聊和语音功能共用"消息先保存,再实时送达"的思路。用户重新进入页面后仍能看到历史消息;多人同时在线时也能及时收到新消息。
游戏中心
#mermaid-svg-brDQS1aZxvGyUQ8L{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-brDQS1aZxvGyUQ8L .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-brDQS1aZxvGyUQ8L .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-brDQS1aZxvGyUQ8L .error-icon{fill:#552222;}#mermaid-svg-brDQS1aZxvGyUQ8L .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-brDQS1aZxvGyUQ8L .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-brDQS1aZxvGyUQ8L .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-brDQS1aZxvGyUQ8L .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-brDQS1aZxvGyUQ8L .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-brDQS1aZxvGyUQ8L .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-brDQS1aZxvGyUQ8L .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-brDQS1aZxvGyUQ8L .marker{fill:#333333;stroke:#333333;}#mermaid-svg-brDQS1aZxvGyUQ8L .marker.cross{stroke:#333333;}#mermaid-svg-brDQS1aZxvGyUQ8L svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-brDQS1aZxvGyUQ8L p{margin:0;}#mermaid-svg-brDQS1aZxvGyUQ8L .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-brDQS1aZxvGyUQ8L .cluster-label text{fill:#333;}#mermaid-svg-brDQS1aZxvGyUQ8L .cluster-label span{color:#333;}#mermaid-svg-brDQS1aZxvGyUQ8L .cluster-label span p{background-color:transparent;}#mermaid-svg-brDQS1aZxvGyUQ8L .label text,#mermaid-svg-brDQS1aZxvGyUQ8L span{fill:#333;color:#333;}#mermaid-svg-brDQS1aZxvGyUQ8L .node rect,#mermaid-svg-brDQS1aZxvGyUQ8L .node circle,#mermaid-svg-brDQS1aZxvGyUQ8L .node ellipse,#mermaid-svg-brDQS1aZxvGyUQ8L .node polygon,#mermaid-svg-brDQS1aZxvGyUQ8L .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-brDQS1aZxvGyUQ8L .rough-node .label text,#mermaid-svg-brDQS1aZxvGyUQ8L .node .label text,#mermaid-svg-brDQS1aZxvGyUQ8L .image-shape .label,#mermaid-svg-brDQS1aZxvGyUQ8L .icon-shape .label{text-anchor:middle;}#mermaid-svg-brDQS1aZxvGyUQ8L .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-brDQS1aZxvGyUQ8L .rough-node .label,#mermaid-svg-brDQS1aZxvGyUQ8L .node .label,#mermaid-svg-brDQS1aZxvGyUQ8L .image-shape .label,#mermaid-svg-brDQS1aZxvGyUQ8L .icon-shape .label{text-align:center;}#mermaid-svg-brDQS1aZxvGyUQ8L .node.clickable{cursor:pointer;}#mermaid-svg-brDQS1aZxvGyUQ8L .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-brDQS1aZxvGyUQ8L .arrowheadPath{fill:#333333;}#mermaid-svg-brDQS1aZxvGyUQ8L .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-brDQS1aZxvGyUQ8L .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-brDQS1aZxvGyUQ8L .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-brDQS1aZxvGyUQ8L .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-brDQS1aZxvGyUQ8L .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-brDQS1aZxvGyUQ8L .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-brDQS1aZxvGyUQ8L .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-brDQS1aZxvGyUQ8L .cluster text{fill:#333;}#mermaid-svg-brDQS1aZxvGyUQ8L .cluster span{color:#333;}#mermaid-svg-brDQS1aZxvGyUQ8L div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-brDQS1aZxvGyUQ8L .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-brDQS1aZxvGyUQ8L rect.text{fill:none;stroke-width:0;}#mermaid-svg-brDQS1aZxvGyUQ8L .icon-shape,#mermaid-svg-brDQS1aZxvGyUQ8L .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-brDQS1aZxvGyUQ8L .icon-shape p,#mermaid-svg-brDQS1aZxvGyUQ8L .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-brDQS1aZxvGyUQ8L .icon-shape .label rect,#mermaid-svg-brDQS1aZxvGyUQ8L .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-brDQS1aZxvGyUQ8L .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-brDQS1aZxvGyUQ8L .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-brDQS1aZxvGyUQ8L :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 玩家
游戏大厅
创建、加入或匹配房间
校验人数、状态与游戏类型
房间实时连接
落子、操作、聊天、重连
对应游戏规则
广播最新房间状态
胜负、认输或结算
保存战绩与回放
积分、排行与个人资料
五子棋、井字棋和俄罗斯方块复用大厅、房间、实时连接和结算这套基本流程;每种游戏只保留各自的规则和画面,不重复建立一整套社交和排行系统。
AI 模块
AI 模块采用"统一入口、模块化处理"的方式。Java 后端不直接调用某一张图或某个模型,而是把请求交给 AI 服务入口;AI 服务按 taskType + intent + version 路由到已注册模块。当前的八个 Python 模块目录承载内容审核、摘要、创作、生图、游戏、搜索、RAG、推荐和看板娘九类 Gateway 能力;Java 始终负责权限、额度、持久化与最终业务状态。
#mermaid-svg-NiJX3saLJMAkNxGL{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-NiJX3saLJMAkNxGL .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-NiJX3saLJMAkNxGL .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-NiJX3saLJMAkNxGL .error-icon{fill:#552222;}#mermaid-svg-NiJX3saLJMAkNxGL .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-NiJX3saLJMAkNxGL .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-NiJX3saLJMAkNxGL .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-NiJX3saLJMAkNxGL .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-NiJX3saLJMAkNxGL .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-NiJX3saLJMAkNxGL .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-NiJX3saLJMAkNxGL .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-NiJX3saLJMAkNxGL .marker{fill:#333333;stroke:#333333;}#mermaid-svg-NiJX3saLJMAkNxGL .marker.cross{stroke:#333333;}#mermaid-svg-NiJX3saLJMAkNxGL svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-NiJX3saLJMAkNxGL p{margin:0;}#mermaid-svg-NiJX3saLJMAkNxGL .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-NiJX3saLJMAkNxGL .cluster-label text{fill:#333;}#mermaid-svg-NiJX3saLJMAkNxGL .cluster-label span{color:#333;}#mermaid-svg-NiJX3saLJMAkNxGL .cluster-label span p{background-color:transparent;}#mermaid-svg-NiJX3saLJMAkNxGL .label text,#mermaid-svg-NiJX3saLJMAkNxGL span{fill:#333;color:#333;}#mermaid-svg-NiJX3saLJMAkNxGL .node rect,#mermaid-svg-NiJX3saLJMAkNxGL .node circle,#mermaid-svg-NiJX3saLJMAkNxGL .node ellipse,#mermaid-svg-NiJX3saLJMAkNxGL .node polygon,#mermaid-svg-NiJX3saLJMAkNxGL .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-NiJX3saLJMAkNxGL .rough-node .label text,#mermaid-svg-NiJX3saLJMAkNxGL .node .label text,#mermaid-svg-NiJX3saLJMAkNxGL .image-shape .label,#mermaid-svg-NiJX3saLJMAkNxGL .icon-shape .label{text-anchor:middle;}#mermaid-svg-NiJX3saLJMAkNxGL .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-NiJX3saLJMAkNxGL .rough-node .label,#mermaid-svg-NiJX3saLJMAkNxGL .node .label,#mermaid-svg-NiJX3saLJMAkNxGL .image-shape .label,#mermaid-svg-NiJX3saLJMAkNxGL .icon-shape .label{text-align:center;}#mermaid-svg-NiJX3saLJMAkNxGL .node.clickable{cursor:pointer;}#mermaid-svg-NiJX3saLJMAkNxGL .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-NiJX3saLJMAkNxGL .arrowheadPath{fill:#333333;}#mermaid-svg-NiJX3saLJMAkNxGL .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-NiJX3saLJMAkNxGL .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-NiJX3saLJMAkNxGL .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-NiJX3saLJMAkNxGL .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-NiJX3saLJMAkNxGL .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-NiJX3saLJMAkNxGL .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-NiJX3saLJMAkNxGL .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-NiJX3saLJMAkNxGL .cluster text{fill:#333;}#mermaid-svg-NiJX3saLJMAkNxGL .cluster span{color:#333;}#mermaid-svg-NiJX3saLJMAkNxGL div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-NiJX3saLJMAkNxGL .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-NiJX3saLJMAkNxGL rect.text{fill:none;stroke-width:0;}#mermaid-svg-NiJX3saLJMAkNxGL .icon-shape,#mermaid-svg-NiJX3saLJMAkNxGL .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-NiJX3saLJMAkNxGL .icon-shape p,#mermaid-svg-NiJX3saLJMAkNxGL .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-NiJX3saLJMAkNxGL .icon-shape .label rect,#mermaid-svg-NiJX3saLJMAkNxGL .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-NiJX3saLJMAkNxGL .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-NiJX3saLJMAkNxGL .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-NiJX3saLJMAkNxGL :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 用户端
Java AI 接口
校验用户、额度与内部密钥
AI Gateway
模块路由
taskType / intent / version
内容审核
帖子摘要
创作辅助
润色、封面提示
图片生成
五子棋 AI
站内搜索
RAG 索引
推荐特征与画像
看板娘 Agent
标准事件与结果
内容审核模块
#mermaid-svg-hJvt6mHtqfFVEOey{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-hJvt6mHtqfFVEOey .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-hJvt6mHtqfFVEOey .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-hJvt6mHtqfFVEOey .error-icon{fill:#552222;}#mermaid-svg-hJvt6mHtqfFVEOey .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-hJvt6mHtqfFVEOey .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-hJvt6mHtqfFVEOey .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-hJvt6mHtqfFVEOey .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-hJvt6mHtqfFVEOey .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-hJvt6mHtqfFVEOey .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-hJvt6mHtqfFVEOey .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-hJvt6mHtqfFVEOey .marker{fill:#333333;stroke:#333333;}#mermaid-svg-hJvt6mHtqfFVEOey .marker.cross{stroke:#333333;}#mermaid-svg-hJvt6mHtqfFVEOey svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-hJvt6mHtqfFVEOey p{margin:0;}#mermaid-svg-hJvt6mHtqfFVEOey .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-hJvt6mHtqfFVEOey .cluster-label text{fill:#333;}#mermaid-svg-hJvt6mHtqfFVEOey .cluster-label span{color:#333;}#mermaid-svg-hJvt6mHtqfFVEOey .cluster-label span p{background-color:transparent;}#mermaid-svg-hJvt6mHtqfFVEOey .label text,#mermaid-svg-hJvt6mHtqfFVEOey span{fill:#333;color:#333;}#mermaid-svg-hJvt6mHtqfFVEOey .node rect,#mermaid-svg-hJvt6mHtqfFVEOey .node circle,#mermaid-svg-hJvt6mHtqfFVEOey .node ellipse,#mermaid-svg-hJvt6mHtqfFVEOey .node polygon,#mermaid-svg-hJvt6mHtqfFVEOey .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-hJvt6mHtqfFVEOey .rough-node .label text,#mermaid-svg-hJvt6mHtqfFVEOey .node .label text,#mermaid-svg-hJvt6mHtqfFVEOey .image-shape .label,#mermaid-svg-hJvt6mHtqfFVEOey .icon-shape .label{text-anchor:middle;}#mermaid-svg-hJvt6mHtqfFVEOey .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-hJvt6mHtqfFVEOey .rough-node .label,#mermaid-svg-hJvt6mHtqfFVEOey .node .label,#mermaid-svg-hJvt6mHtqfFVEOey .image-shape .label,#mermaid-svg-hJvt6mHtqfFVEOey .icon-shape .label{text-align:center;}#mermaid-svg-hJvt6mHtqfFVEOey .node.clickable{cursor:pointer;}#mermaid-svg-hJvt6mHtqfFVEOey .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-hJvt6mHtqfFVEOey .arrowheadPath{fill:#333333;}#mermaid-svg-hJvt6mHtqfFVEOey .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-hJvt6mHtqfFVEOey .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-hJvt6mHtqfFVEOey .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-hJvt6mHtqfFVEOey .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-hJvt6mHtqfFVEOey .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-hJvt6mHtqfFVEOey .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-hJvt6mHtqfFVEOey .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-hJvt6mHtqfFVEOey .cluster text{fill:#333;}#mermaid-svg-hJvt6mHtqfFVEOey .cluster span{color:#333;}#mermaid-svg-hJvt6mHtqfFVEOey div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-hJvt6mHtqfFVEOey .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-hJvt6mHtqfFVEOey rect.text{fill:none;stroke-width:0;}#mermaid-svg-hJvt6mHtqfFVEOey .icon-shape,#mermaid-svg-hJvt6mHtqfFVEOey .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-hJvt6mHtqfFVEOey .icon-shape p,#mermaid-svg-hJvt6mHtqfFVEOey .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-hJvt6mHtqfFVEOey .icon-shape .label rect,#mermaid-svg-hJvt6mHtqfFVEOey .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-hJvt6mHtqfFVEOey .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-hJvt6mHtqfFVEOey .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-hJvt6mHtqfFVEOey :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 通过
拒绝
通过
拒绝
通过
拒绝
待审核帖子
Java 审核任务
审核任务队列
LangGraph 流程开始
validate_text
检查正文
validate_images
检查图片
reject_text
validate_video
检查视频
reject_image
summarize
Flash 摘要
reject_video
审核通过
finalize
汇总结果
审核结果队列
Java 更新帖子状态
内容审核走 RabbitMQ 异步链路,避免用户发帖时一直等待。审核模块也提供单独的文本、图片检查入口:文本优先命中语义缓存;图片先校验 Base64、体积与格式,再由视觉模型描述、文本模型判定。无论 AI 给出什么结论,Java 才能变更帖子审核状态。
帖子摘要模块
#mermaid-svg-K0Ww27twUJb15iem{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-K0Ww27twUJb15iem .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-K0Ww27twUJb15iem .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-K0Ww27twUJb15iem .error-icon{fill:#552222;}#mermaid-svg-K0Ww27twUJb15iem .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-K0Ww27twUJb15iem .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-K0Ww27twUJb15iem .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-K0Ww27twUJb15iem .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-K0Ww27twUJb15iem .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-K0Ww27twUJb15iem .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-K0Ww27twUJb15iem .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-K0Ww27twUJb15iem .marker{fill:#333333;stroke:#333333;}#mermaid-svg-K0Ww27twUJb15iem .marker.cross{stroke:#333333;}#mermaid-svg-K0Ww27twUJb15iem svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-K0Ww27twUJb15iem p{margin:0;}#mermaid-svg-K0Ww27twUJb15iem .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-K0Ww27twUJb15iem .cluster-label text{fill:#333;}#mermaid-svg-K0Ww27twUJb15iem .cluster-label span{color:#333;}#mermaid-svg-K0Ww27twUJb15iem .cluster-label span p{background-color:transparent;}#mermaid-svg-K0Ww27twUJb15iem .label text,#mermaid-svg-K0Ww27twUJb15iem span{fill:#333;color:#333;}#mermaid-svg-K0Ww27twUJb15iem .node rect,#mermaid-svg-K0Ww27twUJb15iem .node circle,#mermaid-svg-K0Ww27twUJb15iem .node ellipse,#mermaid-svg-K0Ww27twUJb15iem .node polygon,#mermaid-svg-K0Ww27twUJb15iem .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-K0Ww27twUJb15iem .rough-node .label text,#mermaid-svg-K0Ww27twUJb15iem .node .label text,#mermaid-svg-K0Ww27twUJb15iem .image-shape .label,#mermaid-svg-K0Ww27twUJb15iem .icon-shape .label{text-anchor:middle;}#mermaid-svg-K0Ww27twUJb15iem .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-K0Ww27twUJb15iem .rough-node .label,#mermaid-svg-K0Ww27twUJb15iem .node .label,#mermaid-svg-K0Ww27twUJb15iem .image-shape .label,#mermaid-svg-K0Ww27twUJb15iem .icon-shape .label{text-align:center;}#mermaid-svg-K0Ww27twUJb15iem .node.clickable{cursor:pointer;}#mermaid-svg-K0Ww27twUJb15iem .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-K0Ww27twUJb15iem .arrowheadPath{fill:#333333;}#mermaid-svg-K0Ww27twUJb15iem .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-K0Ww27twUJb15iem .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-K0Ww27twUJb15iem .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-K0Ww27twUJb15iem .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-K0Ww27twUJb15iem .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-K0Ww27twUJb15iem .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-K0Ww27twUJb15iem .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-K0Ww27twUJb15iem .cluster text{fill:#333;}#mermaid-svg-K0Ww27twUJb15iem .cluster span{color:#333;}#mermaid-svg-K0Ww27twUJb15iem div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-K0Ww27twUJb15iem .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-K0Ww27twUJb15iem rect.text{fill:none;stroke-width:0;}#mermaid-svg-K0Ww27twUJb15iem .icon-shape,#mermaid-svg-K0Ww27twUJb15iem .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-K0Ww27twUJb15iem .icon-shape p,#mermaid-svg-K0Ww27twUJb15iem .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-K0Ww27twUJb15iem .icon-shape .label rect,#mermaid-svg-K0Ww27twUJb15iem .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-K0Ww27twUJb15iem .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-K0Ww27twUJb15iem .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-K0Ww27twUJb15iem :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 否
是
详情页请求摘要
Java 校验登录、额度与可见性
POST_SUMMARY / GENERATE / v1
清理 HTML,校验正文
正文超过单段上限?
Flash 模型直接摘要
分块逐段摘要
合并各段结果
返回 summary / highlights / chunkCount
详情页展示,不修改原文
摘要模块使用 AiRuntime 调用快速文本模型;它仅输出内容理解结果,不修改帖子原文或审核状态。
创作与图片生成模块
#mermaid-svg-36yp413rEZHnuL00{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-36yp413rEZHnuL00 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-36yp413rEZHnuL00 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-36yp413rEZHnuL00 .error-icon{fill:#552222;}#mermaid-svg-36yp413rEZHnuL00 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-36yp413rEZHnuL00 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-36yp413rEZHnuL00 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-36yp413rEZHnuL00 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-36yp413rEZHnuL00 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-36yp413rEZHnuL00 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-36yp413rEZHnuL00 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-36yp413rEZHnuL00 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-36yp413rEZHnuL00 .marker.cross{stroke:#333333;}#mermaid-svg-36yp413rEZHnuL00 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-36yp413rEZHnuL00 p{margin:0;}#mermaid-svg-36yp413rEZHnuL00 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-36yp413rEZHnuL00 .cluster-label text{fill:#333;}#mermaid-svg-36yp413rEZHnuL00 .cluster-label span{color:#333;}#mermaid-svg-36yp413rEZHnuL00 .cluster-label span p{background-color:transparent;}#mermaid-svg-36yp413rEZHnuL00 .label text,#mermaid-svg-36yp413rEZHnuL00 span{fill:#333;color:#333;}#mermaid-svg-36yp413rEZHnuL00 .node rect,#mermaid-svg-36yp413rEZHnuL00 .node circle,#mermaid-svg-36yp413rEZHnuL00 .node ellipse,#mermaid-svg-36yp413rEZHnuL00 .node polygon,#mermaid-svg-36yp413rEZHnuL00 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-36yp413rEZHnuL00 .rough-node .label text,#mermaid-svg-36yp413rEZHnuL00 .node .label text,#mermaid-svg-36yp413rEZHnuL00 .image-shape .label,#mermaid-svg-36yp413rEZHnuL00 .icon-shape .label{text-anchor:middle;}#mermaid-svg-36yp413rEZHnuL00 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-36yp413rEZHnuL00 .rough-node .label,#mermaid-svg-36yp413rEZHnuL00 .node .label,#mermaid-svg-36yp413rEZHnuL00 .image-shape .label,#mermaid-svg-36yp413rEZHnuL00 .icon-shape .label{text-align:center;}#mermaid-svg-36yp413rEZHnuL00 .node.clickable{cursor:pointer;}#mermaid-svg-36yp413rEZHnuL00 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-36yp413rEZHnuL00 .arrowheadPath{fill:#333333;}#mermaid-svg-36yp413rEZHnuL00 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-36yp413rEZHnuL00 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-36yp413rEZHnuL00 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-36yp413rEZHnuL00 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-36yp413rEZHnuL00 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-36yp413rEZHnuL00 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-36yp413rEZHnuL00 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-36yp413rEZHnuL00 .cluster text{fill:#333;}#mermaid-svg-36yp413rEZHnuL00 .cluster span{color:#333;}#mermaid-svg-36yp413rEZHnuL00 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-36yp413rEZHnuL00 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-36yp413rEZHnuL00 rect.text{fill:none;stroke-width:0;}#mermaid-svg-36yp413rEZHnuL00 .icon-shape,#mermaid-svg-36yp413rEZHnuL00 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-36yp413rEZHnuL00 .icon-shape p,#mermaid-svg-36yp413rEZHnuL00 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-36yp413rEZHnuL00 .icon-shape .label rect,#mermaid-svg-36yp413rEZHnuL00 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-36yp413rEZHnuL00 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-36yp413rEZHnuL00 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-36yp413rEZHnuL00 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 作者
编辑器
Java 校验登录、额度与草稿归属
POST_CREATION / POLISH
POST_CREATION / COVER_HINTS
按体裁和编辑器模式
润色正文
从正文提取封面提示词
返回候选文本
IMAGE_GENERATION / GENERATE
校验提示词与质量参数
调用生图能力
图片地址与用量统计
用户确认后保存草稿或发布
创作模块只生成候选内容、提示词或图片 URL。草稿保存、发布、积分扣除与权限校验都留在 Java,AI 不会直接写入帖子状态。
游戏 AI 模块
#mermaid-svg-wVNferuT6IWcG2SH{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-wVNferuT6IWcG2SH .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-wVNferuT6IWcG2SH .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-wVNferuT6IWcG2SH .error-icon{fill:#552222;}#mermaid-svg-wVNferuT6IWcG2SH .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-wVNferuT6IWcG2SH .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-wVNferuT6IWcG2SH .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-wVNferuT6IWcG2SH .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-wVNferuT6IWcG2SH .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-wVNferuT6IWcG2SH .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-wVNferuT6IWcG2SH .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-wVNferuT6IWcG2SH .marker{fill:#333333;stroke:#333333;}#mermaid-svg-wVNferuT6IWcG2SH .marker.cross{stroke:#333333;}#mermaid-svg-wVNferuT6IWcG2SH svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-wVNferuT6IWcG2SH p{margin:0;}#mermaid-svg-wVNferuT6IWcG2SH .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-wVNferuT6IWcG2SH .cluster-label text{fill:#333;}#mermaid-svg-wVNferuT6IWcG2SH .cluster-label span{color:#333;}#mermaid-svg-wVNferuT6IWcG2SH .cluster-label span p{background-color:transparent;}#mermaid-svg-wVNferuT6IWcG2SH .label text,#mermaid-svg-wVNferuT6IWcG2SH span{fill:#333;color:#333;}#mermaid-svg-wVNferuT6IWcG2SH .node rect,#mermaid-svg-wVNferuT6IWcG2SH .node circle,#mermaid-svg-wVNferuT6IWcG2SH .node ellipse,#mermaid-svg-wVNferuT6IWcG2SH .node polygon,#mermaid-svg-wVNferuT6IWcG2SH .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-wVNferuT6IWcG2SH .rough-node .label text,#mermaid-svg-wVNferuT6IWcG2SH .node .label text,#mermaid-svg-wVNferuT6IWcG2SH .image-shape .label,#mermaid-svg-wVNferuT6IWcG2SH .icon-shape .label{text-anchor:middle;}#mermaid-svg-wVNferuT6IWcG2SH .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-wVNferuT6IWcG2SH .rough-node .label,#mermaid-svg-wVNferuT6IWcG2SH .node .label,#mermaid-svg-wVNferuT6IWcG2SH .image-shape .label,#mermaid-svg-wVNferuT6IWcG2SH .icon-shape .label{text-align:center;}#mermaid-svg-wVNferuT6IWcG2SH .node.clickable{cursor:pointer;}#mermaid-svg-wVNferuT6IWcG2SH .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-wVNferuT6IWcG2SH .arrowheadPath{fill:#333333;}#mermaid-svg-wVNferuT6IWcG2SH .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-wVNferuT6IWcG2SH .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-wVNferuT6IWcG2SH .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-wVNferuT6IWcG2SH .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-wVNferuT6IWcG2SH .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-wVNferuT6IWcG2SH .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-wVNferuT6IWcG2SH .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-wVNferuT6IWcG2SH .cluster text{fill:#333;}#mermaid-svg-wVNferuT6IWcG2SH .cluster span{color:#333;}#mermaid-svg-wVNferuT6IWcG2SH div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-wVNferuT6IWcG2SH .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-wVNferuT6IWcG2SH rect.text{fill:none;stroke-width:0;}#mermaid-svg-wVNferuT6IWcG2SH .icon-shape,#mermaid-svg-wVNferuT6IWcG2SH .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-wVNferuT6IWcG2SH .icon-shape p,#mermaid-svg-wVNferuT6IWcG2SH .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-wVNferuT6IWcG2SH .icon-shape .label rect,#mermaid-svg-wVNferuT6IWcG2SH .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-wVNferuT6IWcG2SH .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-wVNferuT6IWcG2SH .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-wVNferuT6IWcG2SH :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 是
否或调用失败
五子棋房间
Java 校验回合、玩家与棋盘
GAME / GOBANG_MOVE / v1
校验落子位置合法性
规则层生成候选步
启用大模型规划?
大模型评估候选步
规则兜底选步
返回落子位置与用量
二次校验后落子并广播
游戏模块只建议一步棋;房间状态、胜负结算与 WebSocket 广播由 Java 游戏服务控制,模型不可绕过游戏规则。
推荐画像模块
#mermaid-svg-KI4BeyyaS5iw0p8F{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-KI4BeyyaS5iw0p8F .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-KI4BeyyaS5iw0p8F .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-KI4BeyyaS5iw0p8F .error-icon{fill:#552222;}#mermaid-svg-KI4BeyyaS5iw0p8F .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-KI4BeyyaS5iw0p8F .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-KI4BeyyaS5iw0p8F .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-KI4BeyyaS5iw0p8F .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-KI4BeyyaS5iw0p8F .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-KI4BeyyaS5iw0p8F .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-KI4BeyyaS5iw0p8F .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-KI4BeyyaS5iw0p8F .marker{fill:#333333;stroke:#333333;}#mermaid-svg-KI4BeyyaS5iw0p8F .marker.cross{stroke:#333333;}#mermaid-svg-KI4BeyyaS5iw0p8F svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-KI4BeyyaS5iw0p8F p{margin:0;}#mermaid-svg-KI4BeyyaS5iw0p8F .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-KI4BeyyaS5iw0p8F .cluster-label text{fill:#333;}#mermaid-svg-KI4BeyyaS5iw0p8F .cluster-label span{color:#333;}#mermaid-svg-KI4BeyyaS5iw0p8F .cluster-label span p{background-color:transparent;}#mermaid-svg-KI4BeyyaS5iw0p8F .label text,#mermaid-svg-KI4BeyyaS5iw0p8F span{fill:#333;color:#333;}#mermaid-svg-KI4BeyyaS5iw0p8F .node rect,#mermaid-svg-KI4BeyyaS5iw0p8F .node circle,#mermaid-svg-KI4BeyyaS5iw0p8F .node ellipse,#mermaid-svg-KI4BeyyaS5iw0p8F .node polygon,#mermaid-svg-KI4BeyyaS5iw0p8F .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-KI4BeyyaS5iw0p8F .rough-node .label text,#mermaid-svg-KI4BeyyaS5iw0p8F .node .label text,#mermaid-svg-KI4BeyyaS5iw0p8F .image-shape .label,#mermaid-svg-KI4BeyyaS5iw0p8F .icon-shape .label{text-anchor:middle;}#mermaid-svg-KI4BeyyaS5iw0p8F .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-KI4BeyyaS5iw0p8F .rough-node .label,#mermaid-svg-KI4BeyyaS5iw0p8F .node .label,#mermaid-svg-KI4BeyyaS5iw0p8F .image-shape .label,#mermaid-svg-KI4BeyyaS5iw0p8F .icon-shape .label{text-align:center;}#mermaid-svg-KI4BeyyaS5iw0p8F .node.clickable{cursor:pointer;}#mermaid-svg-KI4BeyyaS5iw0p8F .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-KI4BeyyaS5iw0p8F .arrowheadPath{fill:#333333;}#mermaid-svg-KI4BeyyaS5iw0p8F .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-KI4BeyyaS5iw0p8F .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-KI4BeyyaS5iw0p8F .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-KI4BeyyaS5iw0p8F .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-KI4BeyyaS5iw0p8F .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-KI4BeyyaS5iw0p8F .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-KI4BeyyaS5iw0p8F .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-KI4BeyyaS5iw0p8F .cluster text{fill:#333;}#mermaid-svg-KI4BeyyaS5iw0p8F .cluster span{color:#333;}#mermaid-svg-KI4BeyyaS5iw0p8F div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-KI4BeyyaS5iw0p8F .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-KI4BeyyaS5iw0p8F rect.text{fill:none;stroke-width:0;}#mermaid-svg-KI4BeyyaS5iw0p8F .icon-shape,#mermaid-svg-KI4BeyyaS5iw0p8F .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-KI4BeyyaS5iw0p8F .icon-shape p,#mermaid-svg-KI4BeyyaS5iw0p8F .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-KI4BeyyaS5iw0p8F .icon-shape .label rect,#mermaid-svg-KI4BeyyaS5iw0p8F .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-KI4BeyyaS5iw0p8F .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-KI4BeyyaS5iw0p8F .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-KI4BeyyaS5iw0p8F :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 行为与内容信号
事务提交后异步
事务提交后异步
事务提交后异步
帖子审核通过
点赞、收藏、回复、兴趣设置
标记不感兴趣 / 恢复
帖子特征提取任务
用户画像更新任务
反馈记录表
RECOMMENDATION / ARTICLE_FEATURE
RECOMMENDATION / USER_PROFILE
Gateway → LangChain → 模型
forum_article_ai_feature
topics / summary / fingerprint
forum_user_ai_profile_snapshot
topics / avoidTopics / summary
请求推荐流
Java 推荐规则
召回、可见性、关注、热度
硬过滤不感兴趣
兴趣加分、回避降分、后端分页
推荐 AI 只异步提炼公开帖主题与用户的聚合兴趣/回避主题,模型失败时使用规则兜底。推荐候选、帖子可见性、不感兴趣硬过滤和最终排序始终由 Java 完成;该模块不经过 RabbitMQ,也不需要 LangGraph。
看板娘助手模块
#mermaid-svg-xz8C3cBXwiI6a8Bh{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-xz8C3cBXwiI6a8Bh .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-xz8C3cBXwiI6a8Bh .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-xz8C3cBXwiI6a8Bh .error-icon{fill:#552222;}#mermaid-svg-xz8C3cBXwiI6a8Bh .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-xz8C3cBXwiI6a8Bh .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-xz8C3cBXwiI6a8Bh .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-xz8C3cBXwiI6a8Bh .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-xz8C3cBXwiI6a8Bh .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-xz8C3cBXwiI6a8Bh .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-xz8C3cBXwiI6a8Bh .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-xz8C3cBXwiI6a8Bh .marker{fill:#333333;stroke:#333333;}#mermaid-svg-xz8C3cBXwiI6a8Bh .marker.cross{stroke:#333333;}#mermaid-svg-xz8C3cBXwiI6a8Bh svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-xz8C3cBXwiI6a8Bh p{margin:0;}#mermaid-svg-xz8C3cBXwiI6a8Bh .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-xz8C3cBXwiI6a8Bh .cluster-label text{fill:#333;}#mermaid-svg-xz8C3cBXwiI6a8Bh .cluster-label span{color:#333;}#mermaid-svg-xz8C3cBXwiI6a8Bh .cluster-label span p{background-color:transparent;}#mermaid-svg-xz8C3cBXwiI6a8Bh .label text,#mermaid-svg-xz8C3cBXwiI6a8Bh span{fill:#333;color:#333;}#mermaid-svg-xz8C3cBXwiI6a8Bh .node rect,#mermaid-svg-xz8C3cBXwiI6a8Bh .node circle,#mermaid-svg-xz8C3cBXwiI6a8Bh .node ellipse,#mermaid-svg-xz8C3cBXwiI6a8Bh .node polygon,#mermaid-svg-xz8C3cBXwiI6a8Bh .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-xz8C3cBXwiI6a8Bh .rough-node .label text,#mermaid-svg-xz8C3cBXwiI6a8Bh .node .label text,#mermaid-svg-xz8C3cBXwiI6a8Bh .image-shape .label,#mermaid-svg-xz8C3cBXwiI6a8Bh .icon-shape .label{text-anchor:middle;}#mermaid-svg-xz8C3cBXwiI6a8Bh .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-xz8C3cBXwiI6a8Bh .rough-node .label,#mermaid-svg-xz8C3cBXwiI6a8Bh .node .label,#mermaid-svg-xz8C3cBXwiI6a8Bh .image-shape .label,#mermaid-svg-xz8C3cBXwiI6a8Bh .icon-shape .label{text-align:center;}#mermaid-svg-xz8C3cBXwiI6a8Bh .node.clickable{cursor:pointer;}#mermaid-svg-xz8C3cBXwiI6a8Bh .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-xz8C3cBXwiI6a8Bh .arrowheadPath{fill:#333333;}#mermaid-svg-xz8C3cBXwiI6a8Bh .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-xz8C3cBXwiI6a8Bh .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-xz8C3cBXwiI6a8Bh .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-xz8C3cBXwiI6a8Bh .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-xz8C3cBXwiI6a8Bh .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-xz8C3cBXwiI6a8Bh .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-xz8C3cBXwiI6a8Bh .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-xz8C3cBXwiI6a8Bh .cluster text{fill:#333;}#mermaid-svg-xz8C3cBXwiI6a8Bh .cluster span{color:#333;}#mermaid-svg-xz8C3cBXwiI6a8Bh div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-xz8C3cBXwiI6a8Bh .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-xz8C3cBXwiI6a8Bh rect.text{fill:none;stroke-width:0;}#mermaid-svg-xz8C3cBXwiI6a8Bh .icon-shape,#mermaid-svg-xz8C3cBXwiI6a8Bh .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-xz8C3cBXwiI6a8Bh .icon-shape p,#mermaid-svg-xz8C3cBXwiI6a8Bh .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-xz8C3cBXwiI6a8Bh .icon-shape .label rect,#mermaid-svg-xz8C3cBXwiI6a8Bh .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-xz8C3cBXwiI6a8Bh .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-xz8C3cBXwiI6a8Bh .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-xz8C3cBXwiI6a8Bh :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 历史过长
生图
对话
需要
不需要
用户消息
读取会话、记忆与上下文
MASCOT / CONTEXT_COMPRESS
将历史压缩为摘要
route_skill
识别请求类型
supervisor
选择生图还是对话路径
image
结合上下文生成图片
assess
判断是否需要联网搜索
tavily_search
搜索文字与图片
agent
快速或深度回答
保存消息、图片与状态
流式推送文本、图集或帖子按钮
看板娘会参考正在进行的对话。多数问题优先快速回答;只有需要复杂推理、规划或多步骤处理时才使用更强模型。长会话先压缩为摘要,检索到的帖子结果会保存到当前会话中,用户关闭再打开仍可以继续查看。
站内搜索模块
#mermaid-svg-VYYzOT8wEU8hhtWS{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-VYYzOT8wEU8hhtWS .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-VYYzOT8wEU8hhtWS .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-VYYzOT8wEU8hhtWS .error-icon{fill:#552222;}#mermaid-svg-VYYzOT8wEU8hhtWS .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-VYYzOT8wEU8hhtWS .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-VYYzOT8wEU8hhtWS .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-VYYzOT8wEU8hhtWS .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-VYYzOT8wEU8hhtWS .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-VYYzOT8wEU8hhtWS .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-VYYzOT8wEU8hhtWS .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-VYYzOT8wEU8hhtWS .marker{fill:#333333;stroke:#333333;}#mermaid-svg-VYYzOT8wEU8hhtWS .marker.cross{stroke:#333333;}#mermaid-svg-VYYzOT8wEU8hhtWS svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-VYYzOT8wEU8hhtWS p{margin:0;}#mermaid-svg-VYYzOT8wEU8hhtWS .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-VYYzOT8wEU8hhtWS .cluster-label text{fill:#333;}#mermaid-svg-VYYzOT8wEU8hhtWS .cluster-label span{color:#333;}#mermaid-svg-VYYzOT8wEU8hhtWS .cluster-label span p{background-color:transparent;}#mermaid-svg-VYYzOT8wEU8hhtWS .label text,#mermaid-svg-VYYzOT8wEU8hhtWS span{fill:#333;color:#333;}#mermaid-svg-VYYzOT8wEU8hhtWS .node rect,#mermaid-svg-VYYzOT8wEU8hhtWS .node circle,#mermaid-svg-VYYzOT8wEU8hhtWS .node ellipse,#mermaid-svg-VYYzOT8wEU8hhtWS .node polygon,#mermaid-svg-VYYzOT8wEU8hhtWS .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-VYYzOT8wEU8hhtWS .rough-node .label text,#mermaid-svg-VYYzOT8wEU8hhtWS .node .label text,#mermaid-svg-VYYzOT8wEU8hhtWS .image-shape .label,#mermaid-svg-VYYzOT8wEU8hhtWS .icon-shape .label{text-anchor:middle;}#mermaid-svg-VYYzOT8wEU8hhtWS .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-VYYzOT8wEU8hhtWS .rough-node .label,#mermaid-svg-VYYzOT8wEU8hhtWS .node .label,#mermaid-svg-VYYzOT8wEU8hhtWS .image-shape .label,#mermaid-svg-VYYzOT8wEU8hhtWS .icon-shape .label{text-align:center;}#mermaid-svg-VYYzOT8wEU8hhtWS .node.clickable{cursor:pointer;}#mermaid-svg-VYYzOT8wEU8hhtWS .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-VYYzOT8wEU8hhtWS .arrowheadPath{fill:#333333;}#mermaid-svg-VYYzOT8wEU8hhtWS .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-VYYzOT8wEU8hhtWS .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-VYYzOT8wEU8hhtWS .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-VYYzOT8wEU8hhtWS .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-VYYzOT8wEU8hhtWS .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-VYYzOT8wEU8hhtWS .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-VYYzOT8wEU8hhtWS .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-VYYzOT8wEU8hhtWS .cluster text{fill:#333;}#mermaid-svg-VYYzOT8wEU8hhtWS .cluster span{color:#333;}#mermaid-svg-VYYzOT8wEU8hhtWS div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-VYYzOT8wEU8hhtWS .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-VYYzOT8wEU8hhtWS rect.text{fill:none;stroke-width:0;}#mermaid-svg-VYYzOT8wEU8hhtWS .icon-shape,#mermaid-svg-VYYzOT8wEU8hhtWS .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-VYYzOT8wEU8hhtWS .icon-shape p,#mermaid-svg-VYYzOT8wEU8hhtWS .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-VYYzOT8wEU8hhtWS .icon-shape .label rect,#mermaid-svg-VYYzOT8wEU8hhtWS .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-VYYzOT8wEU8hhtWS .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-VYYzOT8wEU8hhtWS .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-VYYzOT8wEU8hhtWS :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 是
否
搜索词
Java 提取公开候选与用户上下文
SEARCH / QUERY / v1
规范化搜索词与范围
向量检索帖子与用户
有向量命中?
候选 ID 与相关分数
关键词混合排序兜底
Java 过滤状态、作者与权限
后端分页返回
搜索模块只返回候选 ID 与分数,响应中明确标注仍需 Java 权限过滤。看板娘需要外部网页或地图信息时,才在自身 Agent 图中按需调用对应 MCP 工具。
RAG 索引模块
#mermaid-svg-cJZ9TVClf2me362a{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-cJZ9TVClf2me362a .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-cJZ9TVClf2me362a .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-cJZ9TVClf2me362a .error-icon{fill:#552222;}#mermaid-svg-cJZ9TVClf2me362a .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-cJZ9TVClf2me362a .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-cJZ9TVClf2me362a .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-cJZ9TVClf2me362a .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-cJZ9TVClf2me362a .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-cJZ9TVClf2me362a .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-cJZ9TVClf2me362a .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-cJZ9TVClf2me362a .marker{fill:#333333;stroke:#333333;}#mermaid-svg-cJZ9TVClf2me362a .marker.cross{stroke:#333333;}#mermaid-svg-cJZ9TVClf2me362a svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-cJZ9TVClf2me362a p{margin:0;}#mermaid-svg-cJZ9TVClf2me362a .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-cJZ9TVClf2me362a .cluster-label text{fill:#333;}#mermaid-svg-cJZ9TVClf2me362a .cluster-label span{color:#333;}#mermaid-svg-cJZ9TVClf2me362a .cluster-label span p{background-color:transparent;}#mermaid-svg-cJZ9TVClf2me362a .label text,#mermaid-svg-cJZ9TVClf2me362a span{fill:#333;color:#333;}#mermaid-svg-cJZ9TVClf2me362a .node rect,#mermaid-svg-cJZ9TVClf2me362a .node circle,#mermaid-svg-cJZ9TVClf2me362a .node ellipse,#mermaid-svg-cJZ9TVClf2me362a .node polygon,#mermaid-svg-cJZ9TVClf2me362a .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-cJZ9TVClf2me362a .rough-node .label text,#mermaid-svg-cJZ9TVClf2me362a .node .label text,#mermaid-svg-cJZ9TVClf2me362a .image-shape .label,#mermaid-svg-cJZ9TVClf2me362a .icon-shape .label{text-anchor:middle;}#mermaid-svg-cJZ9TVClf2me362a .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-cJZ9TVClf2me362a .rough-node .label,#mermaid-svg-cJZ9TVClf2me362a .node .label,#mermaid-svg-cJZ9TVClf2me362a .image-shape .label,#mermaid-svg-cJZ9TVClf2me362a .icon-shape .label{text-align:center;}#mermaid-svg-cJZ9TVClf2me362a .node.clickable{cursor:pointer;}#mermaid-svg-cJZ9TVClf2me362a .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-cJZ9TVClf2me362a .arrowheadPath{fill:#333333;}#mermaid-svg-cJZ9TVClf2me362a .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-cJZ9TVClf2me362a .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-cJZ9TVClf2me362a .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-cJZ9TVClf2me362a .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-cJZ9TVClf2me362a .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-cJZ9TVClf2me362a .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-cJZ9TVClf2me362a .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-cJZ9TVClf2me362a .cluster text{fill:#333;}#mermaid-svg-cJZ9TVClf2me362a .cluster span{color:#333;}#mermaid-svg-cJZ9TVClf2me362a div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-cJZ9TVClf2me362a .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-cJZ9TVClf2me362a rect.text{fill:none;stroke-width:0;}#mermaid-svg-cJZ9TVClf2me362a .icon-shape,#mermaid-svg-cJZ9TVClf2me362a .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-cJZ9TVClf2me362a .icon-shape p,#mermaid-svg-cJZ9TVClf2me362a .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-cJZ9TVClf2me362a .icon-shape .label rect,#mermaid-svg-cJZ9TVClf2me362a .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-cJZ9TVClf2me362a .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-cJZ9TVClf2me362a .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-cJZ9TVClf2me362a :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 帖子公开 / 作者资料更新
Java 确认业务状态已提交
RAG / INDEX_ARTICLE 或 INDEX_USER
规范化可检索字段
文本向量化
写入索引存储
帖子下架或删除
Java 触发删除
RAG / REMOVE_ARTICLE
供搜索模块召回
RAG 模块将文章与用户资料的索引写入、删除统一收敛到 Gateway;它不拥有帖子公开状态,索引命中后仍由 Java 过滤。
AI 使用的数据与记录
#mermaid-svg-CfMUZpWICpW74Xtt{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-CfMUZpWICpW74Xtt .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-CfMUZpWICpW74Xtt .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-CfMUZpWICpW74Xtt .error-icon{fill:#552222;}#mermaid-svg-CfMUZpWICpW74Xtt .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-CfMUZpWICpW74Xtt .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-CfMUZpWICpW74Xtt .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-CfMUZpWICpW74Xtt .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-CfMUZpWICpW74Xtt .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-CfMUZpWICpW74Xtt .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-CfMUZpWICpW74Xtt .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-CfMUZpWICpW74Xtt .marker{fill:#333333;stroke:#333333;}#mermaid-svg-CfMUZpWICpW74Xtt .marker.cross{stroke:#333333;}#mermaid-svg-CfMUZpWICpW74Xtt svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-CfMUZpWICpW74Xtt p{margin:0;}#mermaid-svg-CfMUZpWICpW74Xtt .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-CfMUZpWICpW74Xtt .cluster-label text{fill:#333;}#mermaid-svg-CfMUZpWICpW74Xtt .cluster-label span{color:#333;}#mermaid-svg-CfMUZpWICpW74Xtt .cluster-label span p{background-color:transparent;}#mermaid-svg-CfMUZpWICpW74Xtt .label text,#mermaid-svg-CfMUZpWICpW74Xtt span{fill:#333;color:#333;}#mermaid-svg-CfMUZpWICpW74Xtt .node rect,#mermaid-svg-CfMUZpWICpW74Xtt .node circle,#mermaid-svg-CfMUZpWICpW74Xtt .node ellipse,#mermaid-svg-CfMUZpWICpW74Xtt .node polygon,#mermaid-svg-CfMUZpWICpW74Xtt .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-CfMUZpWICpW74Xtt .rough-node .label text,#mermaid-svg-CfMUZpWICpW74Xtt .node .label text,#mermaid-svg-CfMUZpWICpW74Xtt .image-shape .label,#mermaid-svg-CfMUZpWICpW74Xtt .icon-shape .label{text-anchor:middle;}#mermaid-svg-CfMUZpWICpW74Xtt .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-CfMUZpWICpW74Xtt .rough-node .label,#mermaid-svg-CfMUZpWICpW74Xtt .node .label,#mermaid-svg-CfMUZpWICpW74Xtt .image-shape .label,#mermaid-svg-CfMUZpWICpW74Xtt .icon-shape .label{text-align:center;}#mermaid-svg-CfMUZpWICpW74Xtt .node.clickable{cursor:pointer;}#mermaid-svg-CfMUZpWICpW74Xtt .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-CfMUZpWICpW74Xtt .arrowheadPath{fill:#333333;}#mermaid-svg-CfMUZpWICpW74Xtt .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-CfMUZpWICpW74Xtt .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-CfMUZpWICpW74Xtt .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-CfMUZpWICpW74Xtt .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-CfMUZpWICpW74Xtt .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-CfMUZpWICpW74Xtt .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-CfMUZpWICpW74Xtt .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-CfMUZpWICpW74Xtt .cluster text{fill:#333;}#mermaid-svg-CfMUZpWICpW74Xtt .cluster span{color:#333;}#mermaid-svg-CfMUZpWICpW74Xtt div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-CfMUZpWICpW74Xtt .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-CfMUZpWICpW74Xtt rect.text{fill:none;stroke-width:0;}#mermaid-svg-CfMUZpWICpW74Xtt .icon-shape,#mermaid-svg-CfMUZpWICpW74Xtt .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-CfMUZpWICpW74Xtt .icon-shape p,#mermaid-svg-CfMUZpWICpW74Xtt .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-CfMUZpWICpW74Xtt .icon-shape .label rect,#mermaid-svg-CfMUZpWICpW74Xtt .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-CfMUZpWICpW74Xtt .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-CfMUZpWICpW74Xtt .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-CfMUZpWICpW74Xtt :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} Java 社区后端
MySQL
会话、额度、创作工作区、推荐结果
Redis
验证码、缓存、任务去重
RabbitMQ
审核任务与异步回调
AI Gateway
PostgreSQL
LangGraph 流程状态
向量检索与站内内容候选
Flash、深度推理与生图模型
搜索与地图工具
会话、额度和业务结果留在社区数据中;AI 流程本身保留必要的过程记录。这样既能让用户回到上次的对话,也能避免模型调用越过社区已有的账号和权限规则。
技术栈
Java 后端
| 依赖 | 版本 | 用途 |
|---|---|---|
| Spring Boot | 3.5.x | Web、AMQP、Mail、Validation、WebSocket |
| MyBatis-Plus | 3.5.15 | Lambda API 查询,自带分页插件 |
| JJWT | 0.11.5 | JWT 签发与解析 |
| springdoc-openapi | 2.8.0 | 开发期 Swagger UI |
| spring-security-crypto | 随 Spring Boot | BCrypt 密码加密,未引入完整 Security 框架 |
| tianai-captcha | 1.5.5 | 滑块拼图验证码 |
| ip2region | 2.7.0 | 离线 IP 归属地解析 |
| Apache POI / PDFBox | 5.2.5 / 3.0.5 | Word、PDF 题库文档解析 |
| 阿里云 OSS SDK | 3.17.4 | 图片、视频文件存储 |
| 阿里云短信 SDK | 1.2.2 | 手机号验证码 |
| thumbnailator | 0.4.20 | 上传图片压缩与缩略图 |
| Hutool | 5.8.x | 通用工具集 |
Python AI 服务
| 依赖 | 版本 | 用途 |
|---|---|---|
| Flask | 3.x | HTTP Gateway 入口 |
| LangChain Core | 0.3.x | 模型调用与链路封装 |
| LangGraph | 0.2.x | 审核、看板娘等有状态 Agent 图 |
| langgraph-checkpoint-postgres | 2.x | LangGraph 线程状态持久化到 PostgreSQL |
| dashscope | ≥1.20 | 通义系列模型,含文本、视觉和生图 |
| Pillow | ≥10 | 图片格式校验与处理 |
| pika | 1.3.2 | RabbitMQ 消费者,负责审核异步链路 |
| psycopg3 | ≥3.1 | PostgreSQL 驱动 |
| redis-py | ≥5.0 | 语义缓存与状态去重 |
| oss2 | ≥2.18 | 阿里云 OSS 写入 |
前端
| 依赖 | 用途 |
|---|---|
| Vue 3 + Vite | SPA 框架与构建工具 |
| Pinia + pinia-plugin-persistedstate | 状态管理,支持本地持久化 |
| Vue Router | 客户端路由 |
| Element Plus | UI 组件库,配置中文语言包 |
基础设施
| 服务 | 镜像版本 | 用途 |
|---|---|---|
| Nginx | 1.30.1 | 反向代理、HTTPS 终止、静态资源分发 |
| Nacos | 3.1.1 | 服务注册发现与配置中心 |
| MySQL | 9.7.0 | 六个业务域独立库 |
| Redis | 8.0 | 缓存与排行榜,allkeys-lru 策略,限 256 MB |
| RabbitMQ | 4.3-management | 审核任务的异步消息队列 |
| PostgreSQL | 17 | LangGraph checkpoint 持久化存储 |
本地启动
准备 Java 17、Python 3.11、Node.js、Docker Desktop。中间件(含与线上同镜像的 Nacos)由开发 Compose 拉起。
powershell
# 中间件(开发 Compose:Nacos / MySQL / Redis / RabbitMQ / PostgreSQL / FFmpeg)
cd nginx
docker compose -f docker-compose.dev.yaml up -d
# IDEA 连接 Nacos 客户端:127.0.0.1:8848;浏览器控制台:http://127.0.0.1:8080/index.html
# (勿再启动仓库内本机独立 Nacos,避免端口冲突)
# 用户端
cd ..\forum-vue\front
npm install
npm run dev
# Java 微服务(IDEA 推荐按模块启动,或根目录 reactor 打包后分别启动)
cd ..\..\java-cloud-standalone
mvn -DskipTests package
# 依次启动:gateway、auth、content、im、game、economy、ai
# AI 服务
cd ..\ai-server
python main.py
若本地仍是旧的单库 forum_db,可先执行:
bash
bash migrate-online-db.sh migrate-data
本地构建和 Docker 构建会通过本机 7897 代理访问外部依赖。密钥和环境差异只放在环境变量或本地配置中,不放入仓库。
分工 :nginx/.env 只给 Docker Compose / up.sh 部署用;本地 IDEA 启动的 Java 不再 读取该文件,只使用系统环境变量与各模块 application.yml 默认值。
环境变量说明
参考 nginx/.env.example(部署用),主要配置项:
| 变量 | 说明 |
|---|---|
JWT_SECRET |
JWT 签名密钥,生产必须替换 |
PII_CRYPTO_SECRET |
手机号等敏感字段对称加密密钥 |
MYSQL_ROOT_PASSWORD |
MySQL root 密码 |
FORUM_*_DB_USERNAME / FORUM_*_DB_PASSWORD |
六个业务域数据库账号 |
NACOS_ADDR |
Nacos 地址,生产默认 nacos:8848 |
REDIS_PASSWORD |
Redis 认证密码 |
RABBITMQ_USER / RABBITMQ_PASSWORD / RABBITMQ_VHOST |
MQ 账号与虚拟主机 |
DASHSCOPE_API_KEY |
通义大模型 API Key |
TAVILY_API_KEY |
看板娘联网搜索 Key |
HUANAPI_IMAGE_KEY |
图片生成服务 Key |
ALIYUN_ACCESS_KEY_ID/SECRET |
阿里云 OSS / 短信公共凭据 |
FORUM_MASCOT_INTERNAL_KEY |
Java ↔ Python 内部鉴权密钥,两侧须一致 |
FORUM_VOICE_TURN_* |
语音通话用的 TURN 服务器地址和凭据 |
打包发布
#mermaid-svg-MU3M8slIuUiVO32I{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-MU3M8slIuUiVO32I .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-MU3M8slIuUiVO32I .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-MU3M8slIuUiVO32I .error-icon{fill:#552222;}#mermaid-svg-MU3M8slIuUiVO32I .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-MU3M8slIuUiVO32I .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-MU3M8slIuUiVO32I .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-MU3M8slIuUiVO32I .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-MU3M8slIuUiVO32I .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-MU3M8slIuUiVO32I .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-MU3M8slIuUiVO32I .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-MU3M8slIuUiVO32I .marker{fill:#333333;stroke:#333333;}#mermaid-svg-MU3M8slIuUiVO32I .marker.cross{stroke:#333333;}#mermaid-svg-MU3M8slIuUiVO32I svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-MU3M8slIuUiVO32I p{margin:0;}#mermaid-svg-MU3M8slIuUiVO32I .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-MU3M8slIuUiVO32I .cluster-label text{fill:#333;}#mermaid-svg-MU3M8slIuUiVO32I .cluster-label span{color:#333;}#mermaid-svg-MU3M8slIuUiVO32I .cluster-label span p{background-color:transparent;}#mermaid-svg-MU3M8slIuUiVO32I .label text,#mermaid-svg-MU3M8slIuUiVO32I span{fill:#333;color:#333;}#mermaid-svg-MU3M8slIuUiVO32I .node rect,#mermaid-svg-MU3M8slIuUiVO32I .node circle,#mermaid-svg-MU3M8slIuUiVO32I .node ellipse,#mermaid-svg-MU3M8slIuUiVO32I .node polygon,#mermaid-svg-MU3M8slIuUiVO32I .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-MU3M8slIuUiVO32I .rough-node .label text,#mermaid-svg-MU3M8slIuUiVO32I .node .label text,#mermaid-svg-MU3M8slIuUiVO32I .image-shape .label,#mermaid-svg-MU3M8slIuUiVO32I .icon-shape .label{text-anchor:middle;}#mermaid-svg-MU3M8slIuUiVO32I .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-MU3M8slIuUiVO32I .rough-node .label,#mermaid-svg-MU3M8slIuUiVO32I .node .label,#mermaid-svg-MU3M8slIuUiVO32I .image-shape .label,#mermaid-svg-MU3M8slIuUiVO32I .icon-shape .label{text-align:center;}#mermaid-svg-MU3M8slIuUiVO32I .node.clickable{cursor:pointer;}#mermaid-svg-MU3M8slIuUiVO32I .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-MU3M8slIuUiVO32I .arrowheadPath{fill:#333333;}#mermaid-svg-MU3M8slIuUiVO32I .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-MU3M8slIuUiVO32I .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-MU3M8slIuUiVO32I .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-MU3M8slIuUiVO32I .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-MU3M8slIuUiVO32I .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-MU3M8slIuUiVO32I .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-MU3M8slIuUiVO32I .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-MU3M8slIuUiVO32I .cluster text{fill:#333;}#mermaid-svg-MU3M8slIuUiVO32I .cluster span{color:#333;}#mermaid-svg-MU3M8slIuUiVO32I div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-MU3M8slIuUiVO32I .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-MU3M8slIuUiVO32I rect.text{fill:none;stroke-width:0;}#mermaid-svg-MU3M8slIuUiVO32I .icon-shape,#mermaid-svg-MU3M8slIuUiVO32I .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-MU3M8slIuUiVO32I .icon-shape p,#mermaid-svg-MU3M8slIuUiVO32I .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-MU3M8slIuUiVO32I .icon-shape .label rect,#mermaid-svg-MU3M8slIuUiVO32I .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-MU3M8slIuUiVO32I .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-MU3M8slIuUiVO32I .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-MU3M8slIuUiVO32I :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 当前源码
make-package.ps1
Vite 构建用户端
构建 Java、AI、FFmpeg 镜像
nginx dist
离线镜像 tar
nginx package
sql 中的初始化与增量脚本
verify-package.ps1
仅上传 package 目录
up.sh 启动线上容器
在 nginx 目录执行:
powershell
.\scripts\make-package.ps1
默认只显示简洁的构建结果。需要查看镜像构建详情时,再使用:
powershell
.\scripts\make-package.ps1 -ShowBuildDetails
完整发布包会生成在 nginx\package\。上传前可校验:
powershell
.\scripts\verify-package.ps1
发布包以六个 server 模块各自的 src/main/resources/db/create.sql 作为独立数据库初始化基线。已有旧单库 forum_db 的环境,上线前用包内 migrate-online-db.sh migrate-data 建六域结构并搬迁数据,默认保留 forum_db。旧会话清理默认关闭,只有明确把脚本中的开关改为 1 才会执行清理。
核心设计思路
权限边界放在各 Java 业务域的 Service 层。前端的登录拦截只是减少无效请求;跨域调用通过 auth-api 等契约获取身份快照,AI 服务也只接受附带内部密钥的请求。
帖子有一套严格的状态流转:草稿 → 待审核 → 已发布,每一步只能由 Java Service 推进。审核期间字段锁定,前端拿不到直接改状态的入口。每次提交审核都会生成一个任务 ID 写入 article.audit_task_id,和 AI 侧 LangGraph 的 thread_id 对应,审核过程可以完整追溯。
AI 服务只管生成,不管写入。审核结论、摘要、推荐特征都由模型给出,但落库的动作始终在 Java 完成。这样换模型或 AI 服务临时挂掉,不会影响发帖、聊天这些核心功能。
消息的逻辑是先存后推。WebSocket 断线重连后,未读内容从数据库补全,不依赖连接状态。私信、群聊、语音邀请和系统通知走同一套流程,差别只在消息类型字段。
游戏的实时状态放在内存里,结束后再写库。对局中的每一步通过 WebSocket 广播给房间成员,游戏结束才把战绩和回放写进数据库,不做高频持久化。
站内搜索优先走向量召回,没命中再退回关键词排序。搜索模块只返回候选 ID 和相关分数,权限过滤和分页由 Java 完成,搜索结果不会泄露无权查看的内容。
数据表概览
业务表按六个独立库拆分:forum_auth_db、forum_content_db、forum_im_db、forum_game_db、forum_economy_db、forum_ai_db。每张表都有 create_time、update_time、delete_state 三个基础字段,主键统一用 BIGINT AUTO_INCREMENT。
| 分组 | 主要表 |
|---|---|
| 用户与账号 | user、user_login_log、user_follow、user_interest_preference |
| 帖子内容 | article、article_image、article_reply、article_sub_reply、article_video_danmaku、forum_article_tag |
| 互动行为 | article_like、article_reply_like、article_favorite、user_favorite_folder |
| 私信与群聊 | message、group_chat、group_chat_member、group_chat_message |
| 漂流瓶 | drift_bottle、drift_bottle_comment、drift_bottle_pick_log |
| 游戏 | game_definition、game_gobang_match_record、game_jinzi_match_record、game_tetris_pk_match_record、game_user_profile |
| 成长与积分 | user_growth_profile、growth_experience_log、growth_challenge、points_log |
| 抽奖 | lottery_activity、lottery_prize、lottery_draw_record |
| AI 相关 | forum_ai_task_session、forum_ai_usage_log、forum_ai_creation_workspace、forum_user_ai_profile_snapshot、forum_article_ai_feature、forum_companion_session |
| 通知 | forum_notice、system_message、forum_outbox_message |
容器服务说明
生产栈由 nginx/docker-compose.yaml 定义。服务都在 forum-net 内网互通,对外只开放 Nginx 的 80 / 443;Nacos 不对外暴露。
#mermaid-svg-40EMeppkF31HnJKu{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-40EMeppkF31HnJKu .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-40EMeppkF31HnJKu .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-40EMeppkF31HnJKu .error-icon{fill:#552222;}#mermaid-svg-40EMeppkF31HnJKu .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-40EMeppkF31HnJKu .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-40EMeppkF31HnJKu .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-40EMeppkF31HnJKu .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-40EMeppkF31HnJKu .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-40EMeppkF31HnJKu .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-40EMeppkF31HnJKu .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-40EMeppkF31HnJKu .marker{fill:#333333;stroke:#333333;}#mermaid-svg-40EMeppkF31HnJKu .marker.cross{stroke:#333333;}#mermaid-svg-40EMeppkF31HnJKu svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-40EMeppkF31HnJKu p{margin:0;}#mermaid-svg-40EMeppkF31HnJKu .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-40EMeppkF31HnJKu .cluster-label text{fill:#333;}#mermaid-svg-40EMeppkF31HnJKu .cluster-label span{color:#333;}#mermaid-svg-40EMeppkF31HnJKu .cluster-label span p{background-color:transparent;}#mermaid-svg-40EMeppkF31HnJKu .label text,#mermaid-svg-40EMeppkF31HnJKu span{fill:#333;color:#333;}#mermaid-svg-40EMeppkF31HnJKu .node rect,#mermaid-svg-40EMeppkF31HnJKu .node circle,#mermaid-svg-40EMeppkF31HnJKu .node ellipse,#mermaid-svg-40EMeppkF31HnJKu .node polygon,#mermaid-svg-40EMeppkF31HnJKu .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-40EMeppkF31HnJKu .rough-node .label text,#mermaid-svg-40EMeppkF31HnJKu .node .label text,#mermaid-svg-40EMeppkF31HnJKu .image-shape .label,#mermaid-svg-40EMeppkF31HnJKu .icon-shape .label{text-anchor:middle;}#mermaid-svg-40EMeppkF31HnJKu .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-40EMeppkF31HnJKu .rough-node .label,#mermaid-svg-40EMeppkF31HnJKu .node .label,#mermaid-svg-40EMeppkF31HnJKu .image-shape .label,#mermaid-svg-40EMeppkF31HnJKu .icon-shape .label{text-align:center;}#mermaid-svg-40EMeppkF31HnJKu .node.clickable{cursor:pointer;}#mermaid-svg-40EMeppkF31HnJKu .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-40EMeppkF31HnJKu .arrowheadPath{fill:#333333;}#mermaid-svg-40EMeppkF31HnJKu .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-40EMeppkF31HnJKu .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-40EMeppkF31HnJKu .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-40EMeppkF31HnJKu .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-40EMeppkF31HnJKu .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-40EMeppkF31HnJKu .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-40EMeppkF31HnJKu .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-40EMeppkF31HnJKu .cluster text{fill:#333;}#mermaid-svg-40EMeppkF31HnJKu .cluster span{color:#333;}#mermaid-svg-40EMeppkF31HnJKu div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-40EMeppkF31HnJKu .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-40EMeppkF31HnJKu rect.text{fill:none;stroke-width:0;}#mermaid-svg-40EMeppkF31HnJKu .icon-shape,#mermaid-svg-40EMeppkF31HnJKu .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-40EMeppkF31HnJKu .icon-shape p,#mermaid-svg-40EMeppkF31HnJKu .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-40EMeppkF31HnJKu .icon-shape .label rect,#mermaid-svg-40EMeppkF31HnJKu .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-40EMeppkF31HnJKu .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-40EMeppkF31HnJKu .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-40EMeppkF31HnJKu :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 浏览器
nginx :80 / :443
gateway
Java 业务容器
auth · content · im · game · economy · ai
中间件
nacos · mysql · redis · rabbitmq
ai-server
ffmpeg
postgres
Gateway 与六个 Java 业务容器共用 forum-backend 镜像,靠不同 jar 入口区分进程。ffmpeg 负责视频转码,经内部密钥与 Java / AI 通信。
开发约定
- 内容、权限和数据由对应业务域的 Java 服务决定,页面只负责展示和提交操作。
- AI 只通过统一入口接入,页面不直接调用具体模型。
- 新的数据库变更只追加新脚本,不修改已经执行过的历史脚本。
- 密码、密钥、验证码或本地环境配置不提交仓库。