Files
gochat/docs/product/03-design-project-structure.md
T
Rogee 92f0d51375 refactor: 统一 DB/Redis 配置为 DSN 模式 + 移除 Helm/K8s 部署
- DatabaseConfig: Host/Port/User/Password/Name/DBName/SSLMode → 单个 DSN 字段
- RedisConfig: Host/Port/Password/DB/URL → 单个 DSN 字段
- 环境变量: GOCHAT_DATABASE_* (7个) → GOCHAT_DATABASE_DSN, GOCHAT_REDIS_* (5个) → GOCHAT_REDIS_DSN
- validator.go: DSN URL 解析校验 (scheme + host)
- redis.go: redis.ParseURL(cfg.DSN) 直连
- 所有 docker-compose / CI / shell 脚本 / .env 同步更新
- 删除 deploy/helm/ 整个目录 (20个文件)
- CI 删除 helm-validate / deploy-staging / deploy-production 三个 job
- 文档同步更新 (README, 架构设计, PRD, 滚动升级)
2026-07-29 20:58:10 +08:00

43 KiB
Raw Blame History

P2A GoChat 项目结构与模块划分

版本:v1.1 产出日期:2026-05-22(设计阶段)/ 2026-07-09 更新 项目定位:Go语言 1:1 重写 Chatwoot(开源多渠道客服平台) 状态:设计文档,项目结构已实际落地。当前实际结构参见 02-architecture.md 或 AGENTS.md。 架构模式:单体架构(保证渠道扩展方便性)
第一阶段优先渠道:Web Widget + Telegram
第一阶段企业功能:Captain AI助手 + Copilot


1. 设计原则

1.1 Go语言特有的架构决策

决策维度 Chatwoot Rails 实现 GoChat 实现 原因
代码组织 Rails MVC(按技术层分层) 按业务域分包(domain-driven Go惯例是按业务功能组织包,而非按MVC角色
依赖注入 无(Rails自动加载) 手动DI + 构造函数注入 Go无自动DI容器,显式依赖更清晰
实时推送 ActionCableWebSocket Redis Pub/Sub + WebSocket handler Go更适合用Redis Pub/Sub做跨进程事件分发
异步任务 SidekiqRuby进程) Goroutine + Worker池 Go原生并发,无需外部Job队列
数据库迁移 ActiveRecord Migration GORM AutoMigrate + 手动Migration 首版用AutoMigrate快速迭代,后续迁移用golang-migrate
配置管理 InstallationConfig表 + ENV Viper配置层 + DB配置表 Go项目用Viper统一管理env/file/DB配置
中间件 Rails before_action Gin/Chi中间件链 Go HTTP中间件是显式链式调用
权限校验 Pundit Policy类 中间件 + 内联权限函数 Go没有class继承,用组合模式实现权限检查
多态关联 polymorphicowner_type+owner_id 独立关联表 + JSON字段 Go ORM对多态支持弱,用独立表更清晰
文件存储 ActiveStorage 本地存储抽象 + S3可选 Go无ActiveStorage,自建存储抽象层
事件分发 Dispatcher + Listener EventBus接口 + Redis Pub/Sub Go用channel/Redis实现事件分发,更高效

1.2 单体架构下的模块化策略

GoChat采用单仓库、多模块策略:

  • 所有代码在一个Git仓库中
  • 每个业务域是独立的Go包(package)
  • 包之间通过接口(interface)解耦,不直接引用内部实现
  • 渠道(Channel)通过插件接口注册,保证扩展方便性
  • 企业版功能通过enterprise子包提供,社区版编译时可选排除

2. 顶层目录结构

gochat/
├── cmd/                          # 应用入口
│   ├── server/                   # 主HTTP服务器
│   │   └── main.go              # 启动入口
│   ├── worker/                   # 后台Worker进程(可选独立部署)
│   │   └── main.go
│   ├── migrate/                  # 数据库迁移工具
│   │   └── main.go
│   └── seed/                     # 数据填充工具
│   │   └── main.go
│
├── internal/                     # 核心业务代码(不可外部引用)
│   ├── domain/                   # 业务域定义
│   │   ├── account/              # 账户管理(M1)
│   │   ├── user/                 # 用户管理(M1)
│   │   ├── inbox/                # 收件箱管理(M2)
│   │   ├── channel/              # 渠道抽象层(M2)
│   │   │   ├── webwidget/        # Web Widget渠道
│   │   │   ├── telegram/         # Telegram渠道
│   │   │   ├── facebook/         # Facebook渠道(第二阶段)
│   │   │   ├── whatsapp/         # WhatsApp渠道(第二阶段)
│   │   │   ├── email/            # Email渠道(第二阶段)
│   │   │   ├── twilio/           # Twilio SMS渠道(第二阶段)
│   │   │   ├── api/              # API渠道(第二阶段)
│   │   │   └── registry.go      # 渠道注册器
│   │   ├── conversation/         # 对话管理(M3
│   │   ├── message/              # 消息管理(M3)
│   │   ├── contact/              # 联系人管理(M4)
│   │   ├── team/                 # 团队管理(M5)
│   │   ├── assignment/           # 分配策略(M5)
│   │   ├── automation/           # 自动化规则(M6)
│   │   ├── macro/                # 宏操作(M6)
│   │   ├── canned/               # 模板消息(M6)
│   │   ├── reporting/            # 报告与CSATM7
│   │   ├── notification/         # 通知系统(M8
│   │   ├── webhook/              # Webhook系统(M8
│   │   ├── knowledgebase/        # 知识库(M9
│   │   ├── captain/              # Captain AI助手(M10企业版)
│   │   ├── copilot/              # Copilot副驾驶(M10企业版)
│   │   ├── sla/                  # SLA策略(M11企业版)
│   │   ├── auditlog/             # 审计日志(M11企业版)
│   │   ├── customrole/           # 自定义角色(M11企业版)
│   │   ├── company/              # 公司管理(M11企业版)
│   │   ├── agentcapacity/        # 坐席容量(M11企业版)
│   │   ├── call/                 # 语音通话(M11企业版)
│   │   ├── saml/                 # SAML SSOM11企业版)
│   │   ├── platform/             # 平台APIM12
│   │   ├── agentbot/             # AgentBotM12
│   │   ├── dashboardapp/         # Dashboard AppM12
│   │   ├── dataimport/           # 数据导入(M12)
│   │   ├── label/                # 标签系统
│   │   ├── note/                 # 笔记
│   │   └── customattr/           # 自定义属性
│   │
│   ├── model/                    # GORM数据模型定义(所有表)
│   │   ├── account.go
│   │   ├── user.go
│   │   ├── account_user.go
│   │   ├── inbox.go
│   │   ├── channel_web_widget.go
│   │   ├── channel_telegram.go
│   │   ├── conversation.go
│   │   ├── message.go
│   │   ├── contact.go
│   │   ├── contact_inbox.go
│   │   ├── team.go
│   │   ├── team_member.go
│   │   ├── assignment_policy.go
│   │   ├── automation_rule.go
│   │   ├── macro.go
│   │   ├── canned_response.go
│   │   ├── csat_survey_response.go
│   │   ├── reporting_event.go
│   │   ├── notification.go
│   │   ├── notification_setting.go
│   │   ├── notification_subscription.go
│   │   ├── webhook.go
│   │   ├── integrations_hook.go
│   │   ├── portal.go
│   │   ├── category.go
│   │   ├── folder.go
│   │   ├── article.go
│   │   ├── captain_assistant.go
│   │   ├── captain_assistant_response.go
│   │   ├── captain_custom_tool.go
│   │   ├── captain_document.go
│   │   ├── captain_inbox.go
│   │   ├── captain_scenario.go
│   │   ├── copilot_thread.go
│   │   ├── copilot_message.go
│   │   ├── sla_policy.go
│   │   ├── applied_sla.go
│   │   ├── sla_event.go
│   │   ├── audit.go
│   │   ├── custom_role.go
│   │   ├── company.go
│   │   ├── agent_capacity_policy.go
│   │   ├── inbox_capacity_limit.go
│   │   ├── call.go
│   │   ├── account_saml_settings.go
│   │   ├── platform_app.go
│   │   ├── platform_app_permissible.go
│   │   ├── agent_bot.go
│   │   ├── agent_bot_inbox.go
│   │   ├── dashboard_app.go
│   │   ├── data_import.go
│   │   ├── label.go
│   │   ├── tagging.go
│   │   ├── note.go
│   │   ├── custom_attribute_definition.go
│   │   ├── custom_filter.go
│   │   ├── campaign.go
│   │   ├── inbox_member.go
│   │   ├── conversation_participant.go
│   │   ├── mention.go
│   │   ├── attachment.go
│   │   ├── working_hour.go
│   │   ├── installation_config.go
│   │   ├── access_token.go
│   │   ├── email_template.go
│   │   ├── dashboard_app.go
│   │   ├── leave.go
│   │   ├── platform_banner.go
│   │   ├── article_embedding.go       # 企业版
│   │   ├── related_category.go
│   │   ├── inbox_assignment_policy.go
│   │   └── user_serializer.go         # JSON序列化辅助
│   │
│   ├── handler/                  # HTTP请求处理器(相当于Controller
│   │   ├── api/                  # API v1 处理器
│   │   │   ├── v1/
│   │   │   │   ├── account_handler.go
│   │   │   │   ├── agent_handler.go
│   │   │   │   ├── inbox_handler.go
│   │   │   │   ├── conversation_handler.go
│   │   │   │   ├── message_handler.go
│   │   │   │   ├── contact_handler.go
│   │   │   │   ├── team_handler.go
│   │   │   │   ├── assignment_handler.go
│   │   │   │   ├── automation_handler.go
│   │   │   │   ├── macro_handler.go
│   │   │   │   ├── canned_handler.go
│   │   │   │   ├── csat_handler.go
│   │   │   │   ├── reporting_handler.go
│   │   │   │   ├── notification_handler.go
│   │   │   │   ├── webhook_handler.go
│   │   │   │   ├── integration_handler.go
│   │   │   │   ├── portal_handler.go
│   │   │   │   ├── category_handler.go
│   │   │   │   ├── article_handler.go
│   │   │   │   ├── captain_handler.go
│   │   │   │   ├── copilot_handler.go
│   │   │   │   ├── sla_handler.go
│   │   │   │   ├── audit_handler.go
│   │   │   │   ├── customrole_handler.go
│   │   │   │   ├── company_handler.go
│   │   │   │   ├── agentcapacity_handler.go
│   │   │   │   ├── call_handler.go
│   │   │   │   ├── saml_handler.go
│   │   │   │   ├── platform_handler.go
│   │   │   │   ├── agentbot_handler.go
│   │   │   │   ├── label_handler.go
│   │   │   │   ├── note_handler.go
│   │   │   │   ├── customattr_handler.go
│   │   │   │   ├── customfilter_handler.go
│   │   │   │   ├── campaign_handler.go
│   │   │   │   ├── dashboardapp_handler.go
│   │   │   │   ├── dataimport_handler.go
│   │   │   │   ├── search_handler.go
│   │   │   │   └── upload_handler.go
│   │   │   ├── v2/               # API v2 处理器(报告等)
│   │   │   │   ├── report_handler.go
│   │   │   │   ├── summary_report_handler.go
│   │   │   │   └── live_report_handler.go
│   │   │   └── platform/         # Platform API 处理器
│   │   │       ├── platform_handler.go
│   │   │       ├── user_handler.go
│   │   │       ├── agentbot_handler.go
│   │   │       └── account_handler.go
│   │   ├── auth/                 # 认证处理器
│   │   │   ├── auth_handler.go
│   │   │   ├── oauth_handler.go
│   │   │   └── saml_handler.go
│   │   ├── public/               # 公开API(面向客户)
│   │   │   ├── inbox_handler.go
│   │   │   ├── contact_handler.go
│   │   │   ├── conversation_handler.go
│   │   │   ├── message_handler.go
│   │   │   ├── csat_handler.go
│   │   │   └── portal_handler.go
│   │   ├── widget/               # Widget API
│   │   │   ├── config_handler.go
│   │   │   ├── message_handler.go
│   │   │   ├── conversation_handler.go
│   │   │   ├── contact_handler.go
│   │   │   ├── event_handler.go
│   │   │   └── label_handler.go
│   │   ├── superadmin/           # 超级管理员
│   │   │   ├── dashboard_handler.go
│   │   │   ├── account_handler.go
│   │   │   ├── user_handler.go
│   │   │   ├── installation_handler.go
│   │   │   └── agentbot_handler.go
│   │   ├── webhook/              # 渠道Webhook处理器
│   │   │   ├── telegram_handler.go
│   │   │   ├── facebook_handler.go
│   │   │   ├── whatsapp_handler.go
│   │   │   ├── twilio_handler.go
│   │   │   ├── line_handler.go
│   │   │   └── instagram_handler.go
│   │   └── enterprise/           # 企业版Webhook
│   │       ├── stripe_handler.go
│   │       └── firecrawl_handler.go
│   │
│   ├── service/                  # 业务逻辑层(相当于Rails的Service/Builder
│   │   ├── account_service.go
│   │   ├── user_service.go
│   │   ├── inbox_service.go
│   │   ├── conversation_service.go
│   │   ├── message_service.go
│   │   ├── contact_service.go
│   │   ├── team_service.go
│   │   ├── assignment_service.go
│   │   ├── auto_assignment_service.go
│   │   ├── automation_service.go
│   │   ├── automation_executor.go
│   │   ├── macro_service.go
│   │   ├── canned_service.go
│   │   ├── csat_service.go
│   │   ├── reporting_service.go
│   │   ├── reporting_rollup_service.go
│   │   ├── notification_service.go
│   │   ├── webhook_service.go
│   │   ├── webhook_trigger_service.go
│   │   ├── integration_hook_service.go
│   │   ├── portal_service.go
│   │   ├── article_service.go
│   │   ├── captain_service.go
│   │   ├── captain_assistant_chat_service.go
│   │   ├── captain_agent_runner_service.go
│   │   ├── copilot_service.go
│   │   ├── sla_service.go
│   │   ├── sla_evaluator_service.go
│   │   ├── audit_service.go
│   │   ├── customrole_service.go
│   │   ├── company_service.go
│   │   ├── agentcapacity_service.go
│   │   ├── call_service.go
│   │   ├── saml_service.go
│   │   ├── platform_service.go
│   │   ├── agentbot_service.go
│   │   ├── dataimport_service.go
│   │   ├── contact_merge_service.go
│   │   ├── contact_import_service.go
│   │   ├── search_service.go
│   │   ├── campaign_service.go
│   │   ├── label_service.go
│   │   ├── note_service.go
│   │   ├── customattr_service.go
│   │   ├── upload_service.go
│   │   ├── branding_service.go
│   │   └── email_validation_service.go
│   │
│   ├── repository/               # 数据访问层(GORM查询封装)
│   │   ├── account_repo.go
│   │   ├── user_repo.go
│   │   ├── inbox_repo.go
│   │   ├── conversation_repo.go
│   │   ├── message_repo.go
│   │   ├── contact_repo.go
│   │   ├── team_repo.go
│   │   ├── assignment_policy_repo.go
│   │   ├── automation_rule_repo.go
│   │   ├── macro_repo.go
│   │   ├── canned_response_repo.go
│   │   ├── csat_repo.go
│   │   ├── reporting_repo.go
│   │   ├── notification_repo.go
│   │   ├── webhook_repo.go
│   │   ├── integration_hook_repo.go
│   │   ├── portal_repo.go
│   │   ├── article_repo.go
│   │   ├── captain_repo.go
│   │   ├── copilot_repo.go
│   │   ├── sla_repo.go
│   │   ├── audit_repo.go
│   │   ├── customrole_repo.go
│   │   ├── company_repo.go
│   │   ├── agentcapacity_repo.go
│   │   ├── call_repo.go
│   │   ├── platform_repo.go
│   │   ├── agentbot_repo.go
│   │   ├── label_repo.go
│   │   ├── note_repo.go
│   │   ├── customattr_repo.go
│   │   ├── customfilter_repo.go
│   │   ├── campaign_repo.go
│   │   ├── dashboardapp_repo.go
│   │   ├── dataimport_repo.go
│   │   ├── search_repo.go          # 全文搜索(PostgreSQL pg_trgm
│   │   └── base_repo.go            # 基础CRUD泛型封装
│   │
│   ├── middleware/                # HTTP中间件
│   │   ├── auth.go                # JWT/Token认证中间件
│   │   ├── account_scope.go       # 账户范围中间件(注入account_id
│   │   ├── permission.go          # 权限校验中间件
│   │   ├── rate_limit.go          # 速率限制
│   │   ├── cors.go                # CORS
│   │   ├── logger.go              # 请求日志
│   │   ├── recovery.go            # 异常恢复
│   │   ├── platform_auth.go       # Platform API认证
│   │   ├── super_admin_auth.go    # 超级管理员认证
│   │   ├── public_auth.go         # 公开API认证(contact token
│   │   ├── widget_auth.go         # Widget API认证(widget token
│   │   └── enterprise_check.go    # 企业版功能检查中间件
│   │
│   ├── eventbus/                  # 事件分发系统
│   │   ├── bus.go                 # EventBus核心
│   │   ├── redis_pubsub.go        # Redis Pub/Sub实现
│   │   ├── local.go               # 本地事件分发(goroutine
│   │   ├── events.go              # 事件类型定义
│   │   └── listeners.go           # Listener注册
│   │
│   ├── realtime/                  # 实时通信层
│   │   ├── hub.go                 # WebSocket连接管理器
│   │   ├── client.go              # WebSocket客户端
│   │   ├── handler.go             # WebSocket处理器
│   │   ├── channel.go             # 订阅频道
│   │   └── redis_subscriber.go    # Redis消息订阅转发WebSocket
│   │
│   ├── worker/                    # 后台异步任务
│   │   ├── pool.go                # Worker池管理
│   │   ├── scheduler.go           # 定时任务调度
│   │   ├── jobs.go                # Job定义
│   │   ├── branding_job.go        # 品牌信息异步获取
│   │   ├── notification_job.go    # 通知投递Job
│   │   ├── webhook_job.go         # Webhook投递Job
│   │   ├── csat_job.go            # CSAT发送Job
│   │   ├── reporting_job.go       # 报告聚合Job
│   │   ├── sla_job.go             # SLA评估Job
│   │   ├── auto_resolve_job.go    # 自动解决Job
│   │   ├── campaign_job.go        # Campaign执行Job
│   │   ├── dataimport_job.go      # 数据导入Job
│   │   └── contact_merge_job.go   # 联系人合并Job
│   │
│   ├── mailer/                    # 邮件发送
│   │   ├── mailer.go              # 邮件发送器
│   │   ├── templates/             # 邮件模板
│   │   │   ├── confirmation.html
│   │   │   ├── reset_password.html
│   │   │   ├── invitation.html
│   │   │   ├── csat_survey.html
│   │   │   └── dns_instructions.html
│   │   └── smtp.go                # SMTP配置
│   │
│   ├── push/                      # Push通知
│   │   ├── fcm.go                 # Firebase Cloud Messaging
│   │   └ push_subscription.go    # Push订阅管理
│   │
│   ├── validator/                 # 数据校验
│   │   ├── email.go               # 邮箱校验(disposable domain检测)
│   │   ├── json_schema.go         # JSON Schema校验
│   │   ├── captcha.go             # CAPTCHA校验
│   │   └── custom_attr.go         # 自定义属性校验
│   │
│   ├── storage/                   # 文件存储抽象
│   │   ├── storage.go             # Storage接口定义
│   │   ├── local.go               # 本地文件存储
│   │   ├── s3.go                  # S3存储
│   │   └── upload.go              # 上传处理
│   │
│   ├── serializer/                # JSON序列化层
│   │   ├── account_serializer.go
│   │   ├── user_serializer.go
│   │   ├── inbox_serializer.go
│   │   ├── conversation_serializer.go
│   │   ├── message_serializer.go
│   │   ├── contact_serializer.go
│   │   ├── team_serializer.go
│   │   ├── notification_serializer.go
│   │   └── common.go              # 通用序列化辅助
│   │
│   ├── featureflag/               # Feature Flag系统
│   │   ├── flags.go               # Feature Flag定义
│   │   ├── manager.go             # Flag管理器
│   │   └── checker.go             # Flag检查器
│   │
│   └── config/                    # 配置管理
│       ├── config.go              # Viper配置加载
│       ├── database.go            # 数据库配置
│       ├── redis.go               # Redis配置
│       ├── smtp.go                # SMTP配置
│       └── storage.go             # 存储配置
│
├── pkg/                           # 可外部引用的公共包
│   ├── errors/                    # 错误定义
│   │   ├── errors.go
│   │   └── codes.go
│   ├── response/                  # HTTP响应封装
│   │   ├── response.go
│   │   └── pagination.go
│   ├── crypto/                    # 加密工具
│   │   ├── hash.go
│   │   ├── jwt.go
│   │   └ token.go
│   ├── utils/                     # 通用工具
│   │   ├── time.go
│   │   ├── slug.go
│   │   ├── uuid.go
│   │   └── string.go
│   └── validator/                 # 公共校验
│       └ validator.go
│
├── migrations/                    # 数据库迁移文件
│   ├── 000001_init_schema.up.sql
│   ├── 000001_init_schema.down.sql
│   └── ...
│
├── docs/                          # 文档
│   ├── requirements/              # 需求文档(M1-M12
│   ├── architecture/              # 架构文档(本目录)
│   └── api/                       # API文档(Swagger/OpenAPI
│
├── scripts/                       # 辅助脚本
│   ├── setup.sh                   # 开发环境设置
│   └── seed.sh                    # 数据填充
│
├── deploy/                        # 部署配置
│   ├── docker/
│   │   ├── Dockerfile
│   │   └── docker-compose.yaml
│   └── quickstart/                  # 一键启动 Compose 栈
│
├── go.mod                         # Go模块定义
├── go.sum                         # Go依赖锁定
├── Makefile                       # 构建脚本
├── .env.example                   # 环境变量示例
├── README.md                      # 项目说明
└── LICENSE                        # MIT许可证

3. 包依赖关系图

3.1 核心分层架构

┌──────────────────────────────────────────────────┐
│                    cmd/                           │  ← 应用入口
│         (server, worker, migrate, seed)           │
└──────────────────────┬───────────────────────────┘
                       │
                       ↓
┌──────────────────────────────────────────────────┐
│                  handler/                         │  ← HTTP处理层
│   (api/v1, api/v2, auth, widget, public,          │
│    superadmin, webhook, platform, enterprise)     │
└──────────────────────┬───────────────────────────┘
                       │
                       ↓
┌──────────────────────────────────────────────────┐
│                  middleware/                       │  ← 中间件层
│  (auth, account_scope, permission, rate_limit,    │
│   cors, logger, enterprise_check)                 │
└──────────────────────┬───────────────────────────┘
                       │
                       ↓
┌──────────────────────────────────────────────────┐
│                  service/                          │  ← 业务逻辑层
│  (account_service, conversation_service,           │
│   message_service, captain_service, ...)           │
└──────────┬───────────┬──────────────────────────┘
           │           │
           ↓           ↓
┌──────────────┐  ┌──────────────────────────────────┐
│   model/      │  │          repository/              │  ← 数据层
│  (GORM模型)   │  │  (account_repo, conversation_repo │
│               │  │   message_repo, ...)              │
└──────────────┘  └──────────────────────────────────┘
                       │
                       ↓
┌──────────────────────────────────────────────────┐
│               基础设施层                            │
│  ┌────────────┐ ┌──────────┐ ┌────────────┐       │
│  │  eventbus/  │ │ realtime/│ │   worker/   │       │
│  │(Redis Pub/  │ │(WebSocket│ │ (goroutine  │       │
│  │   Sub)      │ │  hub)    │ │  pool)      │       │
│  └────────────┘ └──────────┘ └────────────┘       │
│  ┌────────────┐ ┌──────────┐ ┌────────────┐       │
│  │  mailer/    │ │  push/   │ │  storage/   │       │
│  │ (SMTP)     │ │ (FCM)    │ │ (Local/S3)  │       │
│  └────────────┘ └──────────┘ └────────────┘       │
│  ┌────────────┐ ┌──────────┐ ┌────────────┐       │
│  │  config/    │ │validator/│ │featureflag/ │       │
│  │  (Viper)    │ │(校验)    │ │(FlagShihTzu)│       │
│  └────────────┘ └──────────┘ └────────────┘       │
└──────────────────────────────────────────────────┘

3.2 模块间依赖规则

规则 说明
handler → service handler调用service,不直接访问repository
service → repository service调用repository,不直接写GORM查询
service → model service引用model做类型转换,不直接做CRUD
service → eventbus service发布事件,通过eventbus通知其他模块
service → worker service可触发异步Job
service → realtime service通过realtime推送WebSocket消息
repository → model repository操作model,执行GORM查询
domain包互不引用 各domain包通过eventbus解耦,不直接调用其他domain的service
handler互不引用 各handler独立,通过路由组织

3.3 渠道(Channel)扩展架构

                    ┌─────────────────┐
                    │  ChannelRegistry │  ← 渠道注册器
                    │  (registry.go)    │
                    └─────────┬────────┘
                              │
              ┌───────────────┼───────────────┐
              │               │               │
              ↓               ↓               ↓
     ┌──────────────┐ ┌──────────────┐ ┌──────────────┐
     │ WebWidget    │ │  Telegram    │ │  (更多渠道)   │
     │ Channel      │ │  Channel     │ │  Facebook    │
     │              │ │              │ │  WhatsApp    │
     │ - HandleIn() │ │ - HandleIn() │ │  Email       │
     │ - HandleOut()│ │ - HandleOut()│ │  Twilio      │
     │ - Validate() │ │ - Validate() │ │  ...         │
     │ - Config()   │ │ - Config()   │ │              │
     └──────────────┘ └──────────────┘ └──────────────┘

所有渠道实现 ChannelInterface:
  HandleInbound(ctx, message) → 创建Contact/Conversation/Message
  HandleOutbound(ctx, message) → 向渠道发送消息
  ValidateConfig(config) → 校验渠道配置
  GetConfig() → 返回渠道配置模板
  RegisterWebhook(router) → 注册渠道Webhook路由

关键设计决策

  • Chatwoot用Rails的多态关联(channel_type + channel_id)实现渠道扩展
  • GoChat改为接口+注册器模式,每个渠道是一个独立package实现ChannelInterface
  • 新增渠道只需:①实现ChannelInterface ②在registry.go注册 ③在路由中添加Webhook端点
  • 无需修改任何已有代码,完全符合开闭原则

4. 与Chatwoot原实现的对比说明

4.1 保留的设计

功能 Chatwoot实现 GoChat保留原因
多账户隔离 Account + AccountUser 多租户 核心需求,多账户隔离是客服平台基础
多态渠道 Channelable concern 改为接口模式,但多渠道概念保留
对话生命周期 open/resolved/pending/snoozed 核心业务状态机,必须保留
自动分配 RoundRobin + AssignmentPolicy 保留算法逻辑,Go实现更高效
Feature Flag FlagShihTzu位运算 保留位运算方式,Go用int64位掩码
事件驱动 Dispatcher + Listener 保留事件驱动架构,改为Redis Pub/Sub
CSAT调查 CsatSurveyService 保留CSAT完整流程
知识库 Portal + Category + Article 保留知识库结构
Webhook投递 Webhooks::TriggerJob 保留Webhook投递机制

4.2 简化的设计

功能 Chatwoot实现 GoChat简化 原因
ActiveStorage 3表(blobs+attachments+variants 1个Attachment模型+Storage接口 Go无ActiveStorage,自建更简洁
ActionMailbox 独立表+IMAP处理 集成到email渠道内 第一阶段不优先,简化合并
Pundit Policy 独立Policy类 middleware+内联权限函数 Go无class继承,中间件更自然
Devise认证 5个Controller+Omniauth JWT Token+OAuth2中间件 Go无DeviseJWT更主流
Sidekiq Cron 外部依赖 内置scheduler包 Go原生并发,无需Sidekiq
Rails Concern 25+个Concern模块 接口组合+embed struct Go用struct embedding替代Concern
polymorphic关联 owner_type+owner_id 独立关联表或JSON字段 GORM多态支持弱,独立表更清晰
93表全部实现 全部93表 分阶段实现,第一阶段约45表 渠道分阶段,不优先的渠道表延后
327路由全部实现 全部327路由 简化到约150路由 合理去重、合并RESTful风格

4.3 新增的设计

功能 说明 原因
ChannelInterface接口 渠道统一接口定义 Go接口比Rails多态更规范
ChannelRegistry注册器 渠道动态注册 便于渠道扩展,开闭原则
repository层 数据访问抽象 Go惯例分层,隔离GORM细节
serializer层 JSON序列化独立 Go JSON序列化与模型分离
EventBus + Redis Pub/Sub 跨进程事件分发 Go单体多实例部署需要跨进程通信
Worker池 + goroutine Go原生并发替代Sidekiq 更高效,无外部依赖
Viper配置层 统一配置管理 Go项目标准做法
Storage接口 文件存储抽象 支持Local/S3切换
enterprise_check中间件 企业版功能守卫 编译时/运行时企业版功能控制

5. 关键接口定义

5.1 ChannelInterface(渠道接口)

// internal/domain/channel/registry.go
package channel

// ChannelType 渠道类型枚举
type ChannelType string
const (
    ChannelWebWidget  ChannelType = "web_widget"
    ChannelTelegram   ChannelType = "telegram"
    ChannelFacebook   ChannelType = "facebook"
    ChannelWhatsApp   ChannelType = "whatsapp"
    ChannelEmail      ChannelType = "email"
    ChannelTwilio     ChannelType = "twilio_sms"
    ChannelAPI        ChannelType = "api"
)

// ChannelInterface 渠道必须实现的接口
type ChannelInterface interface {
    // HandleInbound 处理渠道入站消息
    HandleInbound(ctx context.Context, inboxID uint, params InboundParams) (*ConversationResult, error)
    // HandleOutbound 通过渠道发送出站消息
    HandleOutbound(ctx context.Context, conversation *Conversation, message *Message) error
    // ValidateConfig 校验渠道配置参数
    ValidateConfig(config map[string]interface{}) error
    // GetConfigTemplate 返回渠道配置模板
    GetConfigTemplate() *ChannelConfigTemplate
    // RegisterWebhook 注册渠道Webhook路由到HTTP router
    RegisterWebhook(router gin.IRouter)
    // RefreshOAuth 刷新OAuth令牌(可选,如Facebook/Instagram
    RefreshOAuth(ctx context.Context, channelModel *ChannelModel) error
}

// ChannelRegistry 渠道注册器
type ChannelRegistry struct {
    channels map[ChannelType]ChannelInterface
}

func (r *ChannelRegistry) Register(ct ChannelType, ch ChannelInterface) { ... }
func (r *ChannelRegistry) Get(ct ChannelType) (ChannelInterface, bool) { ... }
func (r *ChannelRegistry) AllTypes() []ChannelType { ... }

5.2 EventBus接口(事件分发)

// internal/eventbus/bus.go
package eventbus

type EventName string
const (
    ConversationCreated    EventName = "conversation_created"
    ConversationUpdated    EventName = "conversation_updated"
    ConversationOpened     EventName = "conversation_opened"
    ConversationResolved   EventName = "conversation_resolved"
    MessageCreated         EventName = "message_created"
    MessageUpdated         EventName = "message_updated"
    ContactCreated         EventName = "contact_created"
    ContactUpdated         EventName = "contact_updated"
    AssignmentChanged      EventName = "assignment_changed"
)

type Event struct {
    Name      EventName
    AccountID uint
    Data      map[string]interface{}
    Timestamp time.Time
}

type EventBus interface {
    Publish(ctx context.Context, event Event) error
    Subscribe(name EventName, handler EventHandler) error
}

type EventHandler func(ctx context.Context, event Event) error

5.3 Repository接口(数据访问)

// internal/repository/base_repo.go
package repository

// BaseRepository 泛型基础CRUD接口
type BaseRepository[T any] interface {
    Create(ctx context.Context, entity *T) error
    GetByID(ctx context.Context, id uint) (*T, error)
    Update(ctx context.Context, entity *T) error
    Delete(ctx context.Context, id uint) error
    List(ctx context.Context, filter Filter, page Pagination) ([]T, int64, error)
}

type Filter struct {
    AccountID  uint
    Conditions []Condition
    OrderBy    string
}

type Pagination struct {
    Page     int
    PerPage  int
}

type Condition struct {
    Field    string
    Operator string  // eq, ne, gt, lt, in, like, between
    Value    interface{}
}

6. 第一阶段与第二阶段模块划分

6.1 第一阶段(Web Widget + Telegram + Captain/Copilot

优先级 核心功能
P0 account 账户CRUD + 设置
P0 user 用户CRUD + 认证 + AccountUser
P0 inbox 收件箱CRUD + InboxMember
P0 channel/webwidget Web Widget渠道入站/出站
P0 channel/telegram Telegram渠道入站/出站
P0 conversation 对话CRUD + 状态流转
P0 message 消息CRUD + 附件
P0 contact 联系人CRUD + ContactInbox
P0 realtime WebSocket实时推送
P0 eventbus Redis Pub/Sub事件分发
P1 team 团队管理 + TeamMember
P1 assignment 自动分配 + RoundRobin
P1 notification 通知 + NotificationSetting
P1 webhook Webhook投递
P1 label 标签系统
P1 note 笔记
P1 canned 模板消息
P1 automation 自动化规则(基础版)
P1 reporting 报告 + CSAT
P1 campaign Campaign(基础版)
P1 customattr 自定义属性
P1 search 全文搜索(pg_trgm
P2-企业版 captain Captain AI助手 + Playground
P2-企业版 copilot Copilot副驾驶 + Thread
P2-企业版 sla SLA策略
P2-企业版 customrole 自定义角色权限
P2-企业版 auditlog 审计日志
P2-企业版 agentcapacity 坐席容量策略

6.2 第二阶段(更多渠道 + 更多企业功能)

新增渠道/功能
channel/facebook Facebook Messenger渠道
channel/whatsapp WhatsApp渠道
channel/email Email渠道
channel/twilio Twilio SMS渠道
channel/api API渠道
company 公司管理(企业版)
call 语音通话(企业版)
saml SAML SSO(企业版)
macro 宏操作
knowledgebase 知识库 + Help Center
platform Platform API
agentbot AgentBot
dashboardapp Dashboard App
dataimport 数据导入
assignment_v2 AssignmentPolicy V2

7. Go模块依赖(go.mod

module github.com/gochat/gochat

go 1.23

require (
    // HTTP框架
    github.com/gin-gonic/gin v1.10+
    // ORM
    gorm.io/gorm v1.25+
    gorm.io/driver/postgres v1.5+
    // Redis
    github.com/redis/go-redis/v9 v9.7+
    // 配置
    github.com/spf13/viper v1.19+
    // JWT
    github.com/golang-jwt/jwt/v5 v5.2+
    // WebSocket
    github.com/gorilla/websocket v1.5+
    // 数据库迁移
    github.com/golang-migrate/migrate/v4 v4.18+
    // 日志
    go.uber.org/zap v1.27+
    // 校验
    github.com/go-playground/validator/v10 v10.22+
    // 邮件
    github.com/wneessen/go-mail v0.5+
    // 加密
    golang.org/x/crypto v0.31+
    // UUID
    github.com/google/uuid v1.6+
    // S3存储(可选)
    github.com/aws/aws-sdk-go-v2 v1.32+
    // LLM SDK(企业版Captain
    github.com/sashabaranov/go-openai v1.32+
    // Telegram Bot SDK
    github.com/go-telegram-bot-api/telegram-bot-api/v5 v5.5+
)

8. 编译与部署架构

8.1 编译目标

# 社区版编译(不含企业版功能)
go build -tags community -o gochat-server cmd/server/main.go

# 企业版编译(含全部功能)
go build -tags enterprise -o gochat-server cmd/server/main.go

# Worker独立部署(可选)
go build -o gochat-worker cmd/worker/main.go

8.2 企业版功能隔离策略

GoChat使用Go的build tags实现企业版功能隔离:

// internal/domain/captain/captain_service.go
// +build enterprise

package captain

func NewCaptainService(...) *CaptainService { ... }
// internal/domain/captain/captain_stub.go
// +build !enterprise

package captain

func NewCaptainService(...) *CaptainService {
    // 返回stub实现,提示需要企业版许可
    return nil
}

enterprise_check中间件在运行时也做二次校验:

  • 编译时:build tags控制代码是否编译
  • 运行时:中间件检查Account的feature flags或License

9. 与Chatwoot目录结构的完整对比

Chatwoot目录 GoChat对应 说明
app/controllers/ internal/handler/ Go用handler命名
app/models/ internal/model/ GORM模型集中定义
app/models/channel/ internal/domain/channel/各渠道子包/ 按渠道分包
app/models/concerns/ 接口+struct embedding Go无Concern,用组合
app/services/ internal/service/ 业务逻辑层
app/builders/ internal/service/(合并) Builder在Go中合并到service
app/finders/ internal/repository/ Finder合并到repository
app/policies/ internal/middleware/permission.go 权限检查用中间件
app/presenters/ internal/serializer/ 序列化层
app/listeners/ internal/eventbus/listeners.go Listener注册到EventBus
app/dispatchers/ internal/eventbus/bus.go 事件分发
app/jobs/ internal/worker/ Go goroutine替代Sidekiq
app/mailers/ internal/mailer/ 邮件发送
app/dashboards/ 删除 Go无Administrate
app/channels/ (ActionCable) internal/realtime/ WebSocket
app/views/ (Jbuilder) internal/serializer/ JSON序列化
enterprise/ internal/domain/各企业版子包/ 企业版包(build tags
config/routes.rb internal/handler/路由注册函数/ Go显式路由注册
config/ internal/config/ + .env Viper + ENV
db/schema.rb internal/model/ + migrations/ GORM + golang-migrate
db/migrate/ migrations/ SQL迁移文件
spec/ tests/(待创建) Go测试
swagger/ docs/api/ OpenAPI文档

文档结束。下一步:产出 04-design-database.md 和 05-design-routing-and-api.md