You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

9.7 KiB

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

项目概览

yunyan-sas 是一个从单产品服务 deep_server(Go 模块名 earphone)迁移而来的 monorepo SaaS 平台,目标是把单产品后端改造成可托管多个应用/产品的 SaaS。迁移时 Go 模块名 earphone → yunyan,所有 import 前缀随之变更。回复一律用中文。

仓库结构

yunyan-sas/
├── go.work                  # Go workspace:use ./apps/services
├── build.sh                 # 构建/推送镜像(被 deploy.sh 调用,也可单用)
├── apps/
│   ├── proto/               # .proto 源文件(按业务域分目录)
│   ├── services/            # Go 后端(module: yunyan, go 1.25.0)
│   │   ├── lego/            #   内部服务框架(IService/IModule/Comp + sys 子系统)
│   │   ├── sys/             #   第三方集成(aliyun/tencentyun/openai/coze/nats/...)
│   │   ├── comm/            #   跨模块公共:常量、ErrorCode、IUserSession、NATS key
│   │   ├── modules/         #   业务模块(每个 = 一组 Comp)
│   │   ├── services/        #   各服务的 main.go 入口 + conf/*.yaml
│   │   ├── pb/              #   protoc 生成的 *.pb.go(DO NOT EDIT)
│   │   ├── swagger/、utils/
│   ├── admin/               # 管理后台前端(Nuxt 4 SSR + Tailwind + DaisyUI 4 + Pinia)
│   └── web/                 # 用户侧前端骨架(Nuxt 4)
└── deploy/<service>/        # 每服务一份 deploy.sh + docker-compose.yml + env/

常用命令

Go 后端(在 apps/services/ 下执行)

go build ./...                              # 编译全部
go vet ./...                               # 静态检查
go test ./...                             # 跑全部测试(测试集中在 sys/* 与 utils/)
go test ./sys/sms/ -run TestXxx -v        # 跑单个测试
go build -o /tmp/console ./services/console/   # 编译单个服务
go run ./services/console -conf ./services/console/conf/console.yaml   # 本地起服务

服务列表:api、gateway、home、mcp、migu、timer(集群服务,走 ETCD/rpcx)、console(单例服务,不接 ETCD)。每个服务 main.go 用 -conf 指向自己的 conf/*.yaml,默认相对路径 ./conf/<svc>.yaml。

Admin 前端(在 apps/admin/ 下执行)

pnpm install
pnpm dev        # 开发,默认 :3000
pnpm build      # 产出 .output/(SSR)

本地开发需同时起 console 后端(默认代理到 127.0.0.1:8080,见下文 proxy)。超管账号见各 console.yaml 的 AdminAccount/AdminPassword。

构建镜像与部署

./build.sh console          # 构建 registry.voitrans.net/starpivot-console:latest(PUSH=0 只构建不推)
./build.sh admin

# 测试环境发布(在 deploy/<服务>/ 下,服务 = app | console | admin)
cd deploy/console && ./dev-deploy.sh yunyan      # 云雁测试环境(广州阿里云 8.138.86.223)
cd deploy/console && ./dev-deploy.sh along       # 阿龙测试环境(阿里云 8.133.166.29)
cd deploy/console && ./dev-deploy.sh             # 不带参数 → 交互选环境:lingpu | yunyan | along

# 生产:先构建带版本号的镜像,再部署
cd deploy/console && ./prod-build.sh 0.2.1 yunyan   # 第 2 个参数选公司(yunyan|lingpu),省略则交互选
cd deploy/console && ./prod-deploy.sh 0.2.1 yunyan  # 第 2 个参数选生产环境,须与构建时所选公司一致;省略则交互选

镜像仓库按公司区分,地址/账号统一在 deploy/registry-profiles.sh(换仓库只改这一处,各脚本 source 它):

  • yunyan → registry.voitrans.net(仓库实体在广州机 8.138.86.223)
  • lingpu → registry.lingpu.net(灵谱香港机)
  • along → ym-registry.voitrans.net(仓库实体就在阿龙机 8.133.166.29 上,账号是 admin 不是 liwei);只用于测试环境,不在生产 COMPANIES 菜单里

测试环境档案在各 dev-deploy.sh 的 env_profile():

  • along → 8.133.166.29(阿里云,x86_64/Docker 24.0.9),目录 /home/work/starpivot/{app,admin,console},密钥 ~/.ssh/along.pem 该机已自带 postgres:16 / redis:7 / mysql / NPM / gitea / docker-registry,配 .env 时优先复用,别另起一套

生产镜像名也按公司区分,映射同在 registry-profiles.sh 的 prod_image_name()(build 与 deploy 共用一份,防漂移): admin/console 两家都用 starpivot-*(与 docker-compose.yml 里写死的 image/container_name 一致); 只有云雁的 app 仍是 voitrans-a11(上海机正跑着 7 个该镜像的容器,改名 compose 会认不出)。

admin/console 的 prod-deploy.sh 已改为多生产环境档案(env_profile(),同 dev-deploy.sh 的写法):

  • yunyan → 139.224.212.237(上海阿里云,与业务后端 app 同机),目录 /home/work/starpivot/{admin,console},密钥 ~/Documents/key/aliyun_shanghai.pem (2026-08-05 由美国机 47.253.88.66 迁来;美国机上的 yunyan-admin/console-a11 容器仍在跑,待验证后停,脚本已不再指向它)
  • lingpu → 8.166.114.65(广州阿里云),目录 /home/work/starpivot/{admin,console},密钥 ~/.ssh/lingpu-gz.pem

dev-deploy.sh <环境> 只做镜像部署:构建推送 → 远端 pull 重启,不上传 服务器上的真实 .env / confs/*.yaml(只下发 *.example 模板)。

后端架构(lego 框架)

整套后端围绕 lego 自研框架,核心是 Service → Module → Comp 三层 + 反射注册路由。

  • 启动:lego.Run(service, modules...)(lego/lego.go)依次 Init → Start → Run → Destroy。
  • 两种 Service 基类:
    • lego/base/rpcx(集群服务):接 ETCD 做服务发现,服务间用 rpcx RPC 互调。api/gateway/home/mcp/migu/timer 用它,且 OnInstallComp 装 services.NewHttpRouteComp()。
    • lego/base/single(单例服务):不接 ETCD/集群,只驱动单个模块。console 用它,主库 Supabase Postgres + 独立 Redis + NATS,维护 app_registry 注册表,按"选中应用"动态建到目标应用库的连接。
  • Module → Comp:模块(如 modules/api)在 OnInstallComp 里 RegisterComp 一组组件:apiComp(HTTP 入口)、modelComp(数据访问)、各种 consumer/interceptor。见 modules/api/module.go。
  • HTTP 路由靠反射自动注册(modules/comp_httpgate.go):继承 modules.MCompHttpGate 的组件,其每个导出方法只要签名是
    func (c *apiComp) MethodName(session comm.IUserSession, req *pb.XxxReq) (*pb.XxxResp, *pb.ErrorData)
    

    就会被注册成路由 <module>_<methodname小写>(如 api_getfactorys)。新增接口 = 新建 modules/<mod>/api_xxx.go 加一个符合签名的方法即可,无需手动注册。后缀 Check 的方法不注册。

  • 错误处理约定:成功填 resp;失败构造 &pb.ErrorData{Code: pb.ErrorCode_XXX, Message: ...} 并 return。
  • pb 包:pb/*.pb.go 由 apps/proto/ 下 .proto 经 protoc + protoc-gen-go v1.36 生成,手动改 .pb.go 无效;改协议要改 .proto 再重新生成。注意 console 模块有本地 gorm struct(非 pb)的 model 文件,见 modules/console/model_*.go。

Admin 前端约定(关键,易踩坑)

  • API 代理:server/middleware/proxy.ts 把 /web/api/* 和 /console/api/* 代理到 CONSOLE_BACKEND(容器内由 env 注入,本地默认 http://127.0.0.1:8080)。
  • useApi().webApi(method, data)(app/composables/useApi.ts):
    • 已自动拼成 /web/api/api_${method} 并已解包 data(成功返回 data 本体;失败 throw;code:18 自动登出)。
    • ⚠️ 调用时 method 不要带 api_ 前缀,否则变成 api_api_xxx → code:11。
    • 方法名以 get/list/load/query/fetch/search/count/stat/export/check 开头视为只读,不弹全屏遮罩;其余(add/update/del/save/create…)视为写操作,请求期间套遮罩防重复提交。
    • 选中应用通过请求头 X-App-Id 传给后端。
  • 后端返回常多包一层:如 getfactorys → {factorys}、getproducts → {products}、getproduct → {product};保存 payload 也常包一层(厂家 {Factory:{...}}、产品 {product:{...}});统计 trend 日期字段是 stat_day。列表 ID 多以十六进制展示(id.toString(16).toUpperCase())。
  • 样式:app/assets/css/console.css 由 nuxt.config 引用;DaisyUI 固定 4.x。

配置与密钥约定(重要)

  • 各 conf/*.yaml 与 deploy/<svc>/deploy.sh 中写死了真实的 DSN / 密钥 / 服务器 IP / 仓库密码,且纳入 git——这是用户在私有仓库下明确接受的取舍。修改这些文件时注意它们会随仓库提交。
  • ⚠️ 本仓库若要公开,必须先清理 deploy.sh 的 deploy_profile(DEPLOY_HOST/REGISTRY_PASS)与各 *.yaml 里的真实凭据。
  • 改部署逻辑要同步两份 deploy/console/deploy.sh 和 deploy/admin/deploy.sh(内容相同,建议改一份再 cp 覆盖)。

迁移上下文

源项目在 /Users/liwei/work/go/yunyan/deep_server_up/(及 go_earphone/server/deep_server/)。从旧代码移植接口时,注意 import 路径由 earphone/... 改为 yunyan/...,并核对接口签名是否符合上文反射注册约定。