27 KiB
AI 数字销售助手 — AI 开发者快速指南
本文档面向 AI 编程助手,帮助你在最短时间内理解项目全貌并高效开发。 完整接口清单与数据模型详见根目录
README.md。
🎯 项目终极目标(最重要,务必理解)
构建一个能完全模仿真人销售在微信上与客户对话的 AI 系统。
这不是一个普通的客服机器人。它的核心差异在于:
-
数字销售分身:通过上传销售本人的真实聊天记录,AI 提取其个人风格(方言、句式、语气、性格),构建一个"数字分身"——回复风格与销售本人高度一致。
-
四大维度画像驱动:AI 不是简单回复,而是基于四大维度画像(销售风格 / 项目资料 / 聊天技巧 / 客户画像)综合理解场景后生成回复,就像一个真正的销售在思考。
-
自主运营能力:
- 自动回复:根据客户等级(熟客/意向/沉睡/非客户)采取不同策略
- 主动触达:生日祝福、活动推送、新盘推荐
- 画像自迭代:每次对话后自动分析并完善客户画像
- 等级评估:定期重新评估客户等级,动态调整运营策略
-
最终愿景:销售人员只需处理 AI 搞不定的关键对话,日常客户维护、跟进、促单全部由 AI 代劳——让一个销售能有效服务 10 倍于现在的客户数量。
理解这个目标后,你写的每一行代码都应该服务于:让 AI 更像那个销售、更懂那个客户、更专业地推进销售进程。
项目目录结构
ai_scheduler/
├── cmd/server/ # 程序入口
│ ├── main.go # 启动入口
│ ├── wire.go # Wire DI 声明(//go:build wireinject)
│ └── wire_gen.go # Wire 自动生成(禁止手动编辑)
├── config/ # 配置文件
│ ├── config.yaml # 主配置(MySQL/Mongo/Redis/JWT/微信协议地址等)
│ └── config_env.yaml # 环境变量覆盖
├── internal/
│ ├── biz/ # ★ 业务逻辑层(最核心的开发区域)
│ │ ├── advice_wx.go # 微信回调处理 + 消息流水 + 会话聚合查询
│ │ ├── advice_wx_send.go # 微信消息发送
│ │ ├── advice_strategy.go # 智能策略(四级回复/主动对话)
│ │ ├── advice_client.go # 客户管理 + 等级评估 + 互动时间
│ │ ├── advice_advicer.go # 销售管理
│ │ ├── advice_project.go # 项目管理
│ │ ├── advice_skill.go # 聊天技巧
│ │ ├── advice_chat.go # AI 对话(LLM 调用)
│ │ ├── advice_evaluate.go # 客户等级评估
│ │ ├── advice_iterate.go # 画像自迭代
│ │ ├── advice_proactive.go # 主动触达(生日/活动推送)
│ │ ├── advice_activity.go # 产品活动
│ │ ├── advice_model_sup.go # LLM 模型配置
│ │ ├── advice_customer_new.go # ★ 微信好友 CRUD + 差集对比(ai_advice_customer)
│ │ ├── advicer_admin.go # 管理员账号
│ │ ├── advicer_industry.go # 行业模板
│ │ ├── provider_set.go # Wire Provider 集合
│ │ ├── handle/ # ⚠️ 历史遗留死代码,可忽略
│ │ └── llm_service/ # ⚠️ 历史遗留死代码,可忽略
│ ├── services/advice/ # ★ HTTP Handler 适配层
│ │ ├── wxhook.go # 回调 + 会话接口 Handler
│ │ ├── wx_proxy.go # 微信 API 代理(分发到 wxDispatchMap)
│ │ ├── wx_ws_hub.go # WebSocket Hub(实时推送新消息/在线状态)
│ │ ├── customer_new.go # ★ 微信好友 CRUD Handler(Add/List/Del/Diff/BatchAdd)
│ │ ├── advicer.go # 销售/项目/技巧等 Handler
│ │ ├── client.go # 客户 Handler
│ │ ├── smart.go # 智能策略 Handler
│ │ └── provider_set.go # Wire Provider 集合
│ ├── server/ # HTTP 服务器
│ │ ├── router/
│ │ │ ├── router.go # ★ 路由总装 + registerCommon 响应包装中间件 + WebSocket 路由
│ │ │ └── advicer.go # ★ 全部业务路由注册(~80 个接口)
│ │ ├── http.go # Fiber 服务器创建(NewHTTPServer 参数列表需同步)
│ │ └── server.go # 服务器生命周期
│ ├── entitys/ # ★ 请求/响应 DTO
│ │ ├── advicer_data.go # ★ 核心 DTO(~500 行,最频繁修改)
│ │ ├── advicer.go # 销售相关 DTO
│ │ ├── advicer_admin.go # 管理员 DTO
│ │ └── response.go # 通用响应结构
│ ├── data/
│ │ ├── mongo_model/ # ★ MongoDB 集合模型
│ │ │ ├── advicer_wx_msg.go # 微信消息流水
│ │ │ ├── advicer_version.go # 销售版本(画像维度)
│ │ │ ├── advicer_client.go # 客户(MongoDB 侧)
│ │ │ ├── advicer_project.go # 项目资料
│ │ │ ├── advicer_talk_skill.go # 聊天技巧
│ │ │ ├── advicer_activity.go # 活动
│ │ │ ├── advicer_proactive_log.go # 主动触达记录
│ │ │ ├── advicer_chat_his.go # AI 对话历史
│ │ │ ├── advicer_project_data.go # 项目资料(新版)
│ │ │ ├── common.go # 公共结构(*Item 包装)
│ │ │ └── provider_set.go # Wire Provider
│ │ ├── model/ # MySQL GORM 模型(*.gen.go 禁止手动编辑)
│ │ │ └── ai_advice_customer.gen.go # ★ 微信好友表模型
│ │ ├── impl/ # MySQL GORM 数据访问实现
│ │ │ ├── advice_customer_impl.go # ★ 微信好友 Impl(含 BatchInsert)
│ │ │ └── provider_set.go # Wire Provider 集合
│ │ ├── constants/ # 常量(Prompt 模板、模型映射)
│ │ └── error/ # 错误码
│ ├── config/config.go # 配置结构体
│ ├── middleware/ # JWT 认证中间件
│ ├── jobs/advice_task.go # 定时任务(cron)
│ └── pkg/ # 工具包
│ ├── wx/ # ★ 微信协议封装
│ │ ├── api.go # API 端点注册
│ │ ├── request.go # HTTP 请求封装
│ │ ├── callback.go # 回调报文解析(CallbackEvent 结构 + 消息过滤)
│ │ ├── qs_*.go # 各类型请求/响应结构体
│ │ └── apidoc/ # 上游 API 文档
│ ├── utils_mongo/ # MongoDB 工具
│ ├── utils_oss/ # OSS 文件存储
│ └── ... # 其他工具包
├── web/ # ★ 前端(零构建,静态托管)
│ ├── project.html # 项目后台入口(★ 版本号管理)
│ ├── admin.html # 管理后台入口
│ ├── index.html # 首页
│ └── assets/
│ ├── css/theme.css # 深色科技风设计系统
│ └── js/
│ ├── core.js # ★ 核心库(API/Toast/Modal/Store)
│ ├── wx.js # ★ 微信工作台-核心(状态/生命周期/通讯录/WS/AI设置)
│ ├── wx_login.js # ★ 微信工作台-登录模块(二维码/在线检测/登出)
│ ├── wx_chat.js # ★ 微信工作台-聊天模块(会话/消息/联系人详情)
│ ├── project.js # 项目后台主入口(VIEWS 注册表)
│ ├── project_data.js # 数据中心(销售/项目/技巧/客户编辑)
│ ├── project_detail.js # 项目设置
│ ├── project_list.js # 项目列表
│ ├── project_analysis.js # 聊天记录分析
│ ├── project_activity.js # 活动管理
│ ├── project_drill.js # AI 演练
│ ├── project_smart.js # 智能策略
│ ├── project_modelsup.js # 模型配置
│ ├── admin.js # 管理后台主入口
│ ├── admin_admin.js # 管理员管理
│ ├── admin_industry.js # 行业模板管理
│ └── admin_modelsup.js # 模型配置管理
├── sql/ # 数据库初始化脚本
│ ├── 01_ai_advice_project_template.sql
│ ├── 02_advicer_mongo_init.js
│ ├── 03_advicer_join_date.sql
│ ├── 03_advicer_wx_token.sql
│ └── 04_ai_advice_customer.sql # ★ 微信好友表 DDL
├── tmpl/ # Excel 模板文件
├── go.mod / go.sum # Go 模块依赖
├── Makefile # 构建命令
└── Dockerfile # Docker 部署
技术栈
Go 1.26 + Fiber v2 + GORM(MySQL) + MongoDB + Redis + Wire DI + 原生前端(零构建)
调用链
HTTP → Fiber中间件(CORS/JWT) → Router(Vali校验) → Service → Biz → Impl/Mongo → LLM
↓
registerCommon 统一包装 {code, message, data}
Wire 依赖注入
cmd/server/wire.go声明依赖关系(//go:build wireinject)cmd/server/wire_gen.go由wire工具自动生成(禁止手动编辑)- 各层通过
provider_set.go暴露 Wire Provider - 新增模块后必须:
- 在各层
provider_set.go添加新 Provider - 在
http.go的NewHTTPServer参数列表添加新 Service - 在
router.go的SetupRoutes参数列表添加新 Service - 在
advicer.go的AdvicerRouterRegist参数列表添加新 Service - 执行
wire命令重新生成wire_gen.go
- 在各层
数据库概览
MySQL 表(GORM 管理,*.gen.go 禁止手动编辑)
| 表名 | 说明 |
|---|---|
ai_advice_admin |
管理员账号 |
ai_advice_advicer |
销售基本信息(含 wx_device_id 微信设备标识) |
ai_advice_advicer_version |
销售版本(画像维度 JSON) |
ai_advice_client |
客户基本信息 |
ai_advice_customer |
★ 微信好友列表(self_wxid + user_name 联合唯一键) |
ai_advice_industry_temp |
行业模板 |
ai_advice_model_sup |
LLM 模型配置 |
ai_advice_project |
项目信息(含项目级 wx_token) |
ai_advice_session |
AI 对话会话 |
ai_advice_talk |
聊天技巧 |
MongoDB 集合
| 集合名 | 说明 | 关键字段 |
|---|---|---|
advicer_wx_msg |
★ 微信消息流水(回调+发送) | appId, wxid, selfWxid, direction, msgType, content, read, createAt |
advicer_version |
销售画像维度 | dialectFeatures, sentencePatterns, toneTags, personalityTags |
advicer_project |
项目资料维度 | regionValue, competitionComparison, coreSellingPoints |
advicer_talk_skill |
聊天技巧维度 | needsMining, painPointResponse, valueBuilding, closingTechniques |
advicer_client |
客户画像 | clientLevel, personalInfo, purchasePurpose, coreDemands |
advicer_activity |
产品活动 | name, content, startAt, endAt, status |
advicer_proactive_log |
主动触达记录 | clientId, wxid, type, content |
advicer_chat_his |
AI 对话历史 | sessionId, messages |
advicer_project_data |
项目资料(新版) | sections[] |
命名差异
| 层 | 命名风格 | 示例 |
|---|---|---|
| MySQL | 蛇形 | project_id |
| MongoDB | 驼峰(bson tag) | projectId |
| 前端 JS | 驼峰 | projectId |
核心数据模型:四大维度
系统的一切围绕四个独立维度展开,每个维度有独立的 MySQL 配置 + MongoDB 数据:
| 维度 | 含义 | MongoDB 集合 | 关键字段 |
|---|---|---|---|
| advicer (销售) | 个人风格:方言/句式/语气/性格/标志性对话 | advicer_version |
dialectFeatures, sentencePatterns, toneTags, personalityTags, signatureDialogues |
| project (项目) | 产品资料:区域价值/竞品对比/卖点/配套/背书 | advicer_project |
regionValue, competitionComparison, coreSellingPoints... |
| skill (技巧) | 聊天策略:需求挖掘/痛点应对/价值塑造/促单/节奏 | advicer_talk_skill |
needsMining, painPointResponse, valueBuilding, closingTechniques... |
| client (客户) | 客户画像:身份/需求/顾虑/等级/决策链 | advicer_client |
clientLevel, personalInfo, purchasePurpose, coreDemands, concerns[] |
客户等级:unknown → regular(熟客) / intent(意向) / sleeping(沉睡) / non(非客户) — 等级决定 AI 行为策略。
前端架构
页面结构
| 页面 | 文件 | 用途 |
|---|---|---|
| 首页 | index.html |
登录 + 项目选择 |
| 管理后台 | admin.html |
全局配置(管理员/行业模板/LLM模型) |
| 项目后台 | project.html |
★ 主要工作区(项目管理/微信工作台/智能策略等) |
前端模块加载机制
- 零构建:所有 JS 通过
<script>标签在 HTML 中按序引入,无打包工具 - IIFE 模式:每个 JS 文件用
(function(global){...})(window)包裹 - 版本号缓存:
<script src="assets/js/xxx.js?v=42">— 修改 JS 后必须更新版本号 - 全局命名空间:
window.Core(核心库)、window.WxN(微信模块共享)、window.Wx(微信挂载点)
微信工作台模块拆分(WxN 命名空间模式)
微信工作台拆分为三个文件,通过 window.WxN 共享命名空间交互:
| 文件 | 职责 | 导出(WxN.xxx) |
|---|---|---|
wx.js |
核心:state 管理/生命周期/通讯录/WebSocket/AI 设置/好友差集同步 | loadProfile, loadContacts, renderContacts, connectWs, openAiConfig |
wx_login.js |
登录:二维码/在线检测/登出/回调设置 | renderLoginCard, checkOnline, checkOnlineLoop, doLogout, resetToOffline |
wx_chat.js |
聊天:会话列表/消息渲染/发送/联系人详情 | loadConversations, openConversationChat, renderChat, doSend, handleNewMessage |
架构要点:
wx.js创建WxN命名空间并通过Object.defineProperty暴露stategetter- 子模块通过
WxN.state访问最新状态(避免闭包捕获旧 state 引用) - 子模块通过
WxN.xxx = fn导出函数供其他模块调用 - 加载顺序:
wx.js→wx_login.js→wx_chat.js
Core.js API 速查
// HTTP 请求
Core.api(path, params) // 管理后台 API(POST JSON,自动 JWT,自动解包 data)
// 完整路径:/api/v1/admin/advice/admin/{path}
Core.wxApi(path, params) // 微信代理 API(自动注入 projectId,解包 {code, data})
// 完整路径:/api/v1/admin/advice/admin/wx/{path}
// UI
Core.toast(msg, type) // 提示(type: "ok"|"err"|"warn"|"info")
Core.modal({title, body, footer, width}) // 模态框,返回 {root, body, close}
Core.confirm(msg, title) // 确认对话框,返回 Promise<boolean>
Core.loading(show, text) // 全屏加载遮罩
// 工具
Core.esc(str) // HTML 转义
Core.store(key, val) // localStorage 读写
Core.initial(name) // 取姓名首字
Core.nowTime() // 当前时间字符串
Core.sleep(ms) // Promise 延迟
Core.splitBubbles(text) // 拆分长消息为多条气泡
// 常量
Core.KEYS.wxApp // localStorage key: 微信登录态
Core.KEYS.wxBrief // localStorage key: 联系人简要信息缓存
Core.KEYS.token // localStorage key: JWT token
项目后台视图注册
新增模块在 project_*.js 定义 renderXxx(),在 project.js 的 VIEWS 中用延迟包装注册:
render: function () { renderXxx(); } // ✓ 正确
render: renderXxx // ✗ 错误(函数提升时序问题)
后端开发约定
响应格式
普通 API: 前端 Core.api() → 后端 HandleResponse → registerCommon 包装 → {code:0, data:..., message:"success"}
微信代理 API:前端 Core.wxApi() → wx_proxy.Proxy → c.Locals("skip_response_wrap", true) → {code:0, data:..., message:"ok"}
⚠️ 重要:registerCommon 中间件会包装所有响应。微信代理已自行包装,必须设置 skip_response_wrap 避免双层嵌套。
- 成功:
{code: 0, message: "success", data: <业务数据>} - 成功兼容:
{code: 200, ...}(前端同时接受 0 和 200) - 分页:
data内含{list, total, page, pageSize} - 失败:
{code: <错误码>, message: <错误信息>, data: null}
DataTemp 通用 CRUD 基类模式
MySQL CRUD 模块遵循 DataTemp 模板模式:
impl继承dataTemp.DataTempBase[T],自动获得Add/Update/Del/GetListToStruct/GetRangeToMapStruct等方法- 查询条件使用
*builder.Cond指针参数(不是接口值) - 分页使用
dataTemp.ReqPageBo{Page: n, Limit: n}(注意字段是Limit不是PageSize)
Mongo 列表接口必须用 *Item 包装
type XxxItem struct {
Id primitive.ObjectID `bson:"_id" json:"id"`
XxxMongo `bson:",inline"`
}
前端编辑/删除依赖此 id 字段。
微信代理新增 API
- 在
internal/pkg/wx/qs_*.go定义 Req/Res 结构体 - 在
internal/pkg/wx/api.go注册端点var Xxx = Api[XxxReq, XxxResData]{Path: "xxx/yyy"} - 在
internal/services/advice/wx_proxy.go的wxDispatchMap添加映射 - 前端通过
Core.wxApi("xxx/yyy", payload)调用
微信工作台模块(当前活跃开发区域)
架构要点
- 前端:
wx.js+wx_login.js+wx_chat.js,通过WxN命名空间协作 - 后端代理:
wx_proxy.go将前端请求分发到上游微信协议服务(100+ API 端点) - 消息回调:上游推送客户消息 →
/api/v1/advicer/wx/callback→advice_wx.go处理入库 MongoDB - 实时通信:WebSocket(
/api/v1/advicer/ws)推送新消息和在线状态变化 - 好友同步:前端
syncCustomerDiff()→ 后端customer/diff+customer/batch_add→ MySQLai_advice_customer
初始化流程(重要)
页面加载/刷新 → mount() → freshState()
→ 从 URL hash 解析 wx-advicer=advicerId
→ fetchDeviceAndCheck(advicerId)
→ Core.api("advicer/info", {advicerId}) 获取最新 wx_device_id
→ state.app = { appId: wx_device_id } ← 始终从 API 获取,不缓存
→ checkOnline()
→ 在线 → checkOnlineLoop() ← 内部调用 connectWs() 建立 WebSocket
loadProfile() ← 获取 wxid/nickName 等
.then(loadConversations()) ← 需要 wxid 作为 selfWxid
loadContacts() ← 拉取通讯录
.then(syncCustomerDiff()) ← 好友差集同步
→ 离线 → getQrCode() 显示二维码
关键要点:
state.app.appId始终从 advicer/info API 实时获取,不使用 localStorage 缓存checkOnlineLoop()内部已调用connectWs(),不要额外调用loadProfile()先于loadConversations()完成,因为会话查询需要selfWxidloadProfile()返回 Promise,依赖state.app.wxid的操作必须在其.then()中执行
QR 码登录流程
getQrCode() → 选择地区 → login/getLoginQrCode → 返回 {uuid, appId, qrImgBase64}
→ 更新销售 wx_device_id(Core.api("advicer/wx_device/update"))
→ startLoginPolling() 每 10 秒轮询 login/checkLogin
→ status=2(登录成功)→ state.app = {appId, wxid, nickName, ...}
→ checkOnlineLoop() ← 内部调用 connectWs()
→ loadProfile().then(loadConversations())
→ loadContacts()
WebSocket 实时通信机制
前端 connectWs()
→ 创建 WebSocket 到 /api/v1/advicer/ws?token=JWT
→ onopen 发送 {"action":"subscribe","appId": state.app.appId}
→ 后端 WxWsHub 设置 client.appId = 订阅的 appId
后端 Broadcast(appId, event, data)
→ 遍历所有已连接 client
→ 匹配 client.appId == appId → 推送 JSON 事件
前端 onmessage → handleWsEvent(msg)
→ "new_message" → WxN.handleNewMessage(data) ← 定义在 wx_chat.js
→ "online_status" → WxN.handleOnlineStatus(data) ← 定义在 wx_login.js
appId 匹配:前端订阅的 appId = wx_device_id(来自 advicer/info API),后端广播的 appId = 回调事件中的 Appid 字段(来自上游微信协议服务)。两者必须一致。
消息回调处理流程
上游协议服务 → POST /api/v1/advicer/wx/callback
→ advice_wx.go.HandleCallback()
→ 解析 AddMsg 事件 → 提取消息字段
→ 过滤:gh_ 开头的 wxid(公众号消息)→ 忽略
→ 过滤:msgType 为 "other" → 忽略
→ 去重(AppId + NewMsgId)
→ 入库 MongoDB advicer_wx_msg
→ WebSocket 广播 new_message 事件(按 appId 匹配推送)
→ 触发智能策略(客户文本消息异步 AI 决策)
会话查询流程
前端 loadConversations()
→ POST wx/conversation/list { selfWxid } ← 不再传 appId
→ MongoDB 聚合管道:$match(selfWxid) → $sort → $group by wxid → 分页
→ 返回会话列表(每个 wxid 的最新消息预览 + 未读数)
前端 openConversationChat(wxid)
→ POST wx/conversation/msgs { selfWxid, wxid } ← 不再传 appId
→ MongoDB 查询:filter(selfWxid+wxid) → sort(createAt:1) → 分页
→ 返回消息列表 → 渲染聊天气泡
前端 markConvAsRead(wxid)
→ POST wx/conversation/read { selfWxid, wxid } ← 不再传 appId
→ MongoDB 更新:filter(wxid+direction=customer+read=false) → set read=true
好友差集同步流程
前端 loadContacts() 获取通讯录 {friends, chatrooms}
→ syncCustomerDiff()
→ POST advicer/customer/diff { selfWxid, userNames: friends }
→ 后端返回 { list: [已有好友记录], diff: [缺失的 userName] }
→ 用 list 填充 state.brief(联系人简要信息)
→ diff 不为空时:
→ 分批(每批 20 个)调用 getBriefInfo(带 3 次重试,间隔 2 秒)
→ 组装入库数据 → POST advicer/customer/batch_add { list: records }
→ 同时更新 state.brief 并刷新渲染
群聊仍通过 loadBriefInfoForChatrooms() 单独拉取 brief info
定时任务概览
| 任务 | 频率 | 作用 |
|---|---|---|
| 客户等级评估 | 每天凌晨 | 重新评估所有客户等级 |
| 熟客超时兜底 | 每 2 分钟 | 熟客消息超 10 分钟无人工回复 → AI 礼貌回复 |
| 画像自迭代 | 每 10 分钟 | 对话闲置超 30 分钟 → 分析新消息完善画像 |
| 主动触达 | 每小时 | 生日祝福 / 活动推送(9:00-21:00,受 auto_reply 总开关控制) |
所有任务使用 cron.SkipIfStillRunning 防堆积。
常见开发场景速查
新增一个 MySQL CRUD 模块(参考 ai_advice_customer 模块):
sql/04_xxx.sql建表 DDLdata/model/xxx.gen.go定义 GORM 模型data/impl/xxx_impl.go继承 DataTemp 实现数据访问data/impl/provider_set.go注册 Wire Providerentitys/advicer_data.go定义请求/响应结构体biz/xxx.go实现业务逻辑biz/provider_set.go注册 Wire Providerservices/advice/xxx.go实现 Handlerservices/advice/provider_set.go注册 Wire Providerserver/http.go+router/router.go+router/advicer.go添加参数 + 注册路由- 执行
wire重新生成wire_gen.go go build ./cmd/server编译验证
新增一个 MongoDB 集合:
data/mongo_model/xxx.go定义模型 +*Item包装data/mongo_model/provider_set.go注册 Wire Providerbiz/advice_xxx.go实现 CRUD 业务- 前端
project_data.js添加编辑界面
新增一个微信代理 API:
pkg/wx/qs_*.go定义 Req/Respkg/wx/api.go注册端点services/advice/wx_proxy.go的wxDispatchMap添加映射- 前端
Core.wxApi("path", payload)调用
修改 AI 分析提示词:
data/constants/prompt.go(BasePrompt 基础提示词)data/constants/advicer.go(Prompt 模板 + 维度映射)
修改前端微信工作台:
- 核心状态/通讯录/WS →
wx.js - 登录/在线检测/登出 →
wx_login.js - 会话/消息/发送/详情 →
wx_chat.js - 样式 →
theme.css - 修改后必须更新
project.html中的?v=N版本号
⚠️ 避坑清单
*.gen.go和wire_gen.go禁止手动编辑——它们由工具自动生成- Mongo 全量更新是
$set语义——务必"先读后合并再写",否则清空未提交字段 - 微信代理响应必须设
skip_response_wrap——否则被registerCommon二次包装 - 前端修改必须更新版本号——
?v=N控制浏览器缓存,不更新则浏览器用旧缓存 - 历史遗留代码(
internal/biz/handle、llm_service等)是死代码,可忽略 - 新增无需登录的接口须在
router.go的AuthMiddleware白名单中追加 loadProfile()返回 Promise——依赖state.app.wxid的操作必须在其.then()回调中执行- 子模块通过
WxN.state访问状态——不要在闭包中缓存 state 引用,始终通过 getter 获取最新值 state.app.appId不缓存——每次进入工作台都从advicer/infoAPI 实时获取wx_device_idcheckOnlineLoop()已内含connectWs()——不要在其外部再调connectWs(),否则导致连接级联断开builder.Cond查询用指针——DataTemp 方法接受*builder.Cond指针参数,传&cond而非conddataTemp.ReqPageBo分页字段是Limit——不是PageSize- 新增 Service 后需同步三个文件——
http.go、router.go、advicer.go的函数签名都要加参数 - 会话/消息查询不传
appId——appId会变,用selfWxid作为筛选依据 - WebSocket 订阅 appId 必须与广播 appId 一致——前端订阅用
wx_device_id,后端广播用回调的Appid字段
编译与部署
# 编译(忽略历史死代码)
go build ./cmd/server/
# 仅验证业务代码
go build ./internal/entitys/ ./internal/services/advice/
# 本地运行
go run cmd/server/main.go
# Wire 重新生成(修改依赖后执行)
cd cmd/server && wire
# Docker 部署
docker-compose up -d
最后更新:2026-09-24 · 完整文档见 README.md