1
This commit is contained in:
29
controller/archive_controller.go
Normal file
29
controller/archive_controller.go
Normal file
@@ -0,0 +1,29 @@
|
||||
// Package controller - 归档控制器
|
||||
// 功能:手动触发对话记录从MongoDB归档到Elasticsearch
|
||||
package controller
|
||||
|
||||
import (
|
||||
"context"
|
||||
"customer-server/model/dto"
|
||||
"customer-server/service"
|
||||
)
|
||||
|
||||
var Archive = new(archive)
|
||||
|
||||
type archive struct{}
|
||||
|
||||
// RunNow 手动触发归档
|
||||
// 参数: req - 归档请求(可选参数)
|
||||
// 返回: res - 归档执行结果信息
|
||||
// 功能: 手动触发月度归档任务,将MongoDB对话记录迁移到Elasticsearch
|
||||
// 路由: POST /archive/run
|
||||
func (c *archive) RunNow(ctx context.Context, req *dto.ArchiveRunReq) (res *dto.ArchiveRunRes, err error) {
|
||||
err = service.ArchiveService.RunNow(ctx)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
res = &dto.ArchiveRunRes{
|
||||
Message: "归档任务执行完成",
|
||||
}
|
||||
return
|
||||
}
|
||||
87
controller/customer_service_account_controller.go
Normal file
87
controller/customer_service_account_controller.go
Normal file
@@ -0,0 +1,87 @@
|
||||
// Package controller - 客服账号控制器
|
||||
// 功能:客服账号的增删改查
|
||||
package controller
|
||||
|
||||
import (
|
||||
"context"
|
||||
"customer-server/model/dto"
|
||||
"customer-server/service"
|
||||
|
||||
"gitea.com/red-future/common/beans"
|
||||
)
|
||||
|
||||
var CustomerServiceAccount = new(customerServiceAccount)
|
||||
|
||||
type customerServiceAccount struct{}
|
||||
|
||||
// Add 添加客服账号
|
||||
// 参数: req - 添加客服账号请求,包含账号名、平台、开场白等信息
|
||||
// 返回: res - 添加成功后的账号ID等信息
|
||||
// 功能: 创建客服账号并自动创建对应的RAGFlow配置(Dataset、Chat)
|
||||
func (c *customerServiceAccount) Add(ctx context.Context, req *dto.AddCustomerServiceAccountReq) (res *dto.AddCustomerServiceAccountRes, err error) {
|
||||
res, err = service.CustomerServiceAccount.Add(ctx, req)
|
||||
return
|
||||
}
|
||||
|
||||
// Update 更新客服账号
|
||||
// 参数: req - 更新客服账号请求,包含账号ID和待更新字段
|
||||
// 返回: res - 空响应(成功则err为nil)
|
||||
// 功能: 更新客服账号基本信息(不包含开场白和RAGFlow配置)
|
||||
func (c *customerServiceAccount) Update(ctx context.Context, req *dto.UpdateCustomerServiceAccountReq) (res *beans.ResponseEmpty, err error) {
|
||||
err = service.CustomerServiceAccount.Update(ctx, req)
|
||||
return
|
||||
}
|
||||
|
||||
// ToggleStatus 切换客服账号状态(启用/禁用)
|
||||
// 参数: req - 状态切换请求,包含账号ID
|
||||
// 返回: res - 空响应(成功则err为nil)
|
||||
// 功能: 在启用和禁用状态之间切换,禁用后不再接收用户消息
|
||||
func (c *customerServiceAccount) ToggleStatus(ctx context.Context, req *dto.ToggleCustomerServiceAccountStatusReq) (res *beans.ResponseEmpty, err error) {
|
||||
err = service.CustomerServiceAccount.ToggleStatus(ctx, req)
|
||||
return
|
||||
}
|
||||
|
||||
// List 获取客服账号列表
|
||||
// 参数: req - 列表查询请求,支持分页、平台筛选、状态筛选
|
||||
// 返回: res - 客服账号列表及分页信息
|
||||
// 功能: 分页查询客服账号,支持按平台、状态筛选
|
||||
func (c *customerServiceAccount) List(ctx context.Context, req *dto.ListCustomerServiceAccountReq) (res *dto.ListCustomerServiceAccountRes, err error) {
|
||||
res, err = service.CustomerServiceAccount.List(ctx, req)
|
||||
return
|
||||
}
|
||||
|
||||
// Delete 删除客服账号
|
||||
// 参数: req - 删除客服账号请求,包含账号ID
|
||||
// 返回: res - 删除结果信息
|
||||
// 功能: 逻辑删除客服账号,同时删除关联的RAGFlow配置
|
||||
func (c *customerServiceAccount) Delete(ctx context.Context, req *dto.DeleteCustomerServiceAccountReq) (res *dto.DeleteCustomerServiceAccountRes, err error) {
|
||||
res, err = service.CustomerServiceAccount.Delete(ctx, req)
|
||||
return
|
||||
}
|
||||
|
||||
// GetAccessibleSpeechcrafts 获取客服账号可访问的话术列表
|
||||
// 参数: req - 查询请求,包含账号名
|
||||
// 返回: res - 该账号可访问的话术列表
|
||||
// 功能: 查询绑定到该客服账号的所有话术
|
||||
func (c *customerServiceAccount) GetAccessibleSpeechcrafts(ctx context.Context, req *dto.GetAccessibleSpeechcraftsReq) (res *dto.GetAccessibleSpeechcraftsRes, err error) {
|
||||
res, err = service.CustomerServiceAccount.GetAccessibleSpeechcrafts(ctx, req)
|
||||
return
|
||||
}
|
||||
|
||||
// RecreateRAGFlowConfig 重新创建RAGFlow配置
|
||||
// 参数: req - 重建请求,包含账号名
|
||||
// 返回: res - 空响应(成功则err为nil)
|
||||
// 功能: 删除旧配置并重新创建Dataset和Chat,用于修复配置异常
|
||||
func (c *customerServiceAccount) RecreateRAGFlowConfig(ctx context.Context, req *dto.RecreateRAGFlowConfigReq) (res *beans.ResponseEmpty, err error) {
|
||||
err = service.CustomerServiceAccount.RecreateRAGFlowConfig(ctx, req)
|
||||
return
|
||||
}
|
||||
|
||||
// UpdateGreeting 更新开场白
|
||||
// 参数: req - 更新开场白请求,包含账号名和新开场白内容
|
||||
// 返回: res - 空响应(成功则err为nil)
|
||||
// 功能: 更新客服账号的开场白,用户连接WebSocket时推送
|
||||
func (c *customerServiceAccount) UpdateGreeting(ctx context.Context, req *dto.UpdateGreetingReq) (res *beans.ResponseEmpty, err error) {
|
||||
err = service.CustomerServiceAccount.UpdateGreeting(ctx, req)
|
||||
return
|
||||
}
|
||||
52
controller/data_controller.go
Normal file
52
controller/data_controller.go
Normal file
@@ -0,0 +1,52 @@
|
||||
// Package controller - 对话数据控制器
|
||||
// 功能:对话记录的查询、导出
|
||||
package controller
|
||||
|
||||
import (
|
||||
"context"
|
||||
"customer-server/model/dto"
|
||||
"customer-server/service"
|
||||
|
||||
"gitea.com/red-future/common/beans"
|
||||
)
|
||||
|
||||
var Data = new(data)
|
||||
|
||||
type data struct{}
|
||||
|
||||
// Add 添加数据
|
||||
// 参数: req - 添加数据请求,包含日期和数据内容
|
||||
// 返回: res - 添加成功后的数据ID等信息
|
||||
// 功能: 创建新的数据记录
|
||||
func (c *data) Add(ctx context.Context, req *dto.AddDataReq) (res *dto.AddDataRes, err error) {
|
||||
res, err = service.Data.Add(ctx, req)
|
||||
return
|
||||
}
|
||||
|
||||
// Update 更新数据
|
||||
// 参数: req - 更新数据请求,包含数据ID和待更新字段
|
||||
// 返回: res - 空响应(成功则err为nil)
|
||||
// 功能: 更新数据记录内容
|
||||
func (c *data) Update(ctx context.Context, req *dto.UpdateDataReq) (res *beans.ResponseEmpty, err error) {
|
||||
err = service.Data.Update(ctx, req)
|
||||
return
|
||||
}
|
||||
|
||||
// // Delete 删除数据
|
||||
// func (c *data) Delete(ctx context.Context, req *dto.DeleteDataReq) (res *beans.ResponseEmpty, err error) {
|
||||
// err = service.Data.Delete(ctx, req)
|
||||
// if err != nil {
|
||||
// return
|
||||
// }
|
||||
// res = &beans.ResponseEmpty{}
|
||||
// return
|
||||
// }
|
||||
|
||||
// List 获取数据列表
|
||||
// 参数: req - 列表查询请求,支持分页、日期范围筛选
|
||||
// 返回: res - 数据列表及分页信息
|
||||
// 功能: 分页查询数据记录,支持按日期范围筛选
|
||||
func (c *data) List(ctx context.Context, req *dto.ListDataReq) (res *dto.ListDataRes, err error) {
|
||||
res, err = service.Data.List(ctx, req)
|
||||
return
|
||||
}
|
||||
62
controller/data_statistics_controller.go
Normal file
62
controller/data_statistics_controller.go
Normal file
@@ -0,0 +1,62 @@
|
||||
// Package controller - 数据统计控制器
|
||||
// 功能:对话数据的统计分析、报表导出
|
||||
package controller
|
||||
|
||||
import (
|
||||
"context"
|
||||
"customer-server/model/dto"
|
||||
"customer-server/service"
|
||||
|
||||
"gitea.com/red-future/common/beans"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/util/gconv"
|
||||
)
|
||||
|
||||
var DataStatistics = new(dataStatistics)
|
||||
|
||||
type dataStatistics struct{}
|
||||
|
||||
// Add 添加数据统计
|
||||
// 参数: req - 添加数据统计请求,包含日期和统计数据
|
||||
// 返回: res - 添加成功后的统计ID等信息
|
||||
// 功能: 创建新的数据统计记录
|
||||
func (c *dataStatistics) Add(ctx context.Context, req *dto.AddDataStatisticsReq) (res *dto.AddDataStatisticsRes, err error) {
|
||||
res, err = service.DataStatistics.Add(ctx, req)
|
||||
return
|
||||
}
|
||||
|
||||
// Update 更新数据统计
|
||||
// 参数: req - 更新数据统计请求,包含统计ID和待更新字段
|
||||
// 返回: res - 空响应(成功则err为nil)
|
||||
// 功能: 更新数据统计记录内容
|
||||
func (c *dataStatistics) Update(ctx context.Context, req *dto.UpdateDataStatisticsReq) (res *beans.ResponseEmpty, err error) {
|
||||
err = service.DataStatistics.Update(ctx, req)
|
||||
return
|
||||
}
|
||||
|
||||
// List 获取数据统计列表
|
||||
// 参数: req - 列表查询请求,支持分页、日期范围筛选
|
||||
// 返回: res - 数据统计列表及分页信息
|
||||
// 功能: 分页查询数据统计记录,支持按日期范围筛选
|
||||
func (c *dataStatistics) List(ctx context.Context, req *dto.ListDataStatisticsReq) (res *dto.ListDataStatisticsRes, err error) {
|
||||
res, err = service.DataStatistics.List(ctx, req)
|
||||
return
|
||||
}
|
||||
|
||||
// Export 导出数据统计
|
||||
// 参数: req - 导出请求,包含筛选条件
|
||||
// 返回: res - 空响应(直接写入Response流)
|
||||
// 功能: 将数据统计导出为ZIP文件,包含Excel文件
|
||||
func (c *dataStatistics) Export(ctx context.Context, req *dto.ExportDataStatisticsReq) (res *beans.ResponseEmpty, err error) {
|
||||
zipData, filename, err := service.DataStatistics.Export(ctx, req)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
r := g.RequestFromCtx(ctx)
|
||||
r.Response.Header().Set("Content-Type", "application/zip")
|
||||
r.Response.Header().Set("Content-Disposition", "attachment; filename=\""+filename+"\"")
|
||||
r.Response.Header().Set("Content-Length", gconv.String(len(zipData)))
|
||||
r.Response.Write(zipData)
|
||||
return
|
||||
}
|
||||
35
controller/health_controller.go
Normal file
35
controller/health_controller.go
Normal file
@@ -0,0 +1,35 @@
|
||||
// Package controller - 健康检查控制器
|
||||
// 功能:服务健康状态检查接口
|
||||
package controller
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
)
|
||||
|
||||
var Health = new(health)
|
||||
|
||||
type health struct{}
|
||||
|
||||
// Check 健康检查
|
||||
func (c *health) Check(ctx context.Context, req *HealthCheckReq) (res *HealthCheckRes, err error) {
|
||||
res = &HealthCheckRes{
|
||||
Status: "ok",
|
||||
Service: "customerservice",
|
||||
Version: "v1.0.0",
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// HealthCheckReq 健康检查请求
|
||||
type HealthCheckReq struct {
|
||||
g.Meta `path:"/" method:"get" tags:"Health" summary:"健康检查" dc:"检查服务是否正常运行"`
|
||||
}
|
||||
|
||||
// HealthCheckRes 健康检查响应
|
||||
type HealthCheckRes struct {
|
||||
Status string `json:"status" dc:"状态"`
|
||||
Service string `json:"service" dc:"服务名称"`
|
||||
Version string `json:"version" dc:"版本"`
|
||||
}
|
||||
96
controller/product_controller.go
Normal file
96
controller/product_controller.go
Normal file
@@ -0,0 +1,96 @@
|
||||
// Package controller - 产品控制器
|
||||
// 功能:产品的增删改查、导入/导出ZIP、绑定/解绑客服账号
|
||||
package controller
|
||||
|
||||
import (
|
||||
"context"
|
||||
"customer-server/model/dto"
|
||||
"customer-server/service"
|
||||
|
||||
"gitea.com/red-future/common/beans"
|
||||
"github.com/gogf/gf/v2/errors/gerror"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/util/gconv"
|
||||
)
|
||||
|
||||
var Product = new(product)
|
||||
|
||||
type product struct{}
|
||||
|
||||
// Add 添加产品
|
||||
// 参数: req - 添加产品请求,包含产品名称、描述、价格等信息
|
||||
// 返回: res - 添加成功后的产品ID等信息
|
||||
// 功能: 创建新产品记录并同步到RAGFlow知识库
|
||||
func (c *product) Add(ctx context.Context, req *dto.AddProductReq) (res *dto.AddProductRes, err error) {
|
||||
res, err = service.Product.Add(ctx, req)
|
||||
return
|
||||
}
|
||||
|
||||
// Update 更新产品
|
||||
// 参数: req - 更新产品请求,包含产品ID和待更新字段
|
||||
// 返回: res - 空响应(成功则err为nil)
|
||||
// 功能: 更新产品信息并同步到RAGFlow
|
||||
func (c *product) Update(ctx context.Context, req *dto.UpdateProductReq) (res *beans.ResponseEmpty, err error) {
|
||||
err = service.Product.Update(ctx, req)
|
||||
return
|
||||
}
|
||||
|
||||
// Delete 删除产品
|
||||
// 参数: req - 删除产品请求,包含产品ID
|
||||
// 返回: res - 空响应(成功则err为nil)
|
||||
// 功能: 逻辑删除产品记录并从RAGFlow移除
|
||||
func (c *product) Delete(ctx context.Context, req *dto.DeleteProductReq) (res *beans.ResponseEmpty, err error) {
|
||||
err = service.Product.Delete(ctx, req)
|
||||
return
|
||||
}
|
||||
|
||||
// List 获取产品列表
|
||||
// 参数: req - 列表查询请求,支持分页、关键词搜索
|
||||
// 返回: res - 产品列表及分页信息
|
||||
// 功能: 分页查询产品记录,支持按名称、描述搜索
|
||||
func (c *product) List(ctx context.Context, req *dto.ListProductReq) (res *dto.ListProductRes, err error) {
|
||||
res, err = service.Product.List(ctx, req)
|
||||
return
|
||||
}
|
||||
|
||||
// Export 导出产品为ZIP文件
|
||||
// 参数: req - 导出请求,包含筛选条件
|
||||
// 返回: res - 空响应(直接写入Response流)
|
||||
// 功能: 将产品数据导出为ZIP文件,包含JSON数据
|
||||
func (c *product) Export(ctx context.Context, req *dto.ExportProductReq) (res *dto.ExportProductRes, err error) {
|
||||
// 调用Service层导出
|
||||
zipData, filename, err := service.Product.Export(ctx, req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 获取原始 Response 对象以设置响应头和写入文件
|
||||
r := g.RequestFromCtx(ctx)
|
||||
|
||||
// 设置响应头为文件下载
|
||||
r.Response.Header().Set("Content-Type", "application/zip")
|
||||
r.Response.Header().Set("Content-Disposition", "attachment; filename=\""+filename+"\"")
|
||||
r.Response.Header().Set("Content-Length", gconv.String(len(zipData)))
|
||||
|
||||
// 写入 ZIP 数据
|
||||
r.Response.Write(zipData)
|
||||
return
|
||||
}
|
||||
|
||||
// Import 导入产品(从ZIP文件)
|
||||
// 参数: req - 导入请求(实际从multipart/form-data获取文件)
|
||||
// 返回: res - 导入结果,包含成功和失败数量
|
||||
// 功能: 从ZIP文件批量导入产品数据并同步到RAGFlow
|
||||
func (c *product) Import(ctx context.Context, req *dto.ImportProductReq) (res *dto.ImportProductRes, err error) {
|
||||
r := g.RequestFromCtx(ctx)
|
||||
|
||||
// 获取上传的文件(虽然 req 中定义了 File,但实际需要从 Request 中获取)
|
||||
file := r.GetUploadFile("file")
|
||||
if file == nil {
|
||||
return nil, gerror.New("请上传ZIP文件")
|
||||
}
|
||||
|
||||
// 调用 Service 层处理导入(传递 FileHeader)
|
||||
res, err = service.Product.Import(ctx, file.FileHeader)
|
||||
return
|
||||
}
|
||||
31
controller/ragflow_config_controller.go
Normal file
31
controller/ragflow_config_controller.go
Normal file
@@ -0,0 +1,31 @@
|
||||
// Package controller - RAGFlow配置控制器
|
||||
// 功能:管理ragflow_config表,更新对话配置提示词
|
||||
package controller
|
||||
|
||||
import (
|
||||
"context"
|
||||
"customer-server/model/dto"
|
||||
"customer-server/service"
|
||||
)
|
||||
|
||||
var RAGFlowConfig = new(ragflowConfig)
|
||||
|
||||
type ragflowConfig struct{}
|
||||
|
||||
// Get 获取RAGFlow配置
|
||||
// 参数: req - 查询请求,包含客服账号名
|
||||
// 返回: res - RAGFlow配置信息,包含提示词、参数等
|
||||
// 功能: 查询指定客服账号的RAGFlow对话配置
|
||||
func (c *ragflowConfig) Get(ctx context.Context, req *dto.GetRAGFlowConfigReq) (res *dto.GetRAGFlowConfigRes, err error) {
|
||||
res, err = service.RAGFlowConfig.Get(ctx, req)
|
||||
return
|
||||
}
|
||||
|
||||
// UpdatePrompt 更新提示词
|
||||
// 参数: req - 更新提示词请求,包含客服账号名和新提示词内容
|
||||
// 返回: res - 更新结果信息
|
||||
// 功能: 更新RAGFlow对话的系统提示词,影响AI回复风格
|
||||
func (c *ragflowConfig) UpdatePrompt(ctx context.Context, req *dto.UpdatePromptReq) (res *dto.UpdatePromptRes, err error) {
|
||||
res, err = service.RAGFlowConfig.UpdatePrompt(ctx, req)
|
||||
return
|
||||
}
|
||||
64
controller/ragflow_controller.go
Normal file
64
controller/ragflow_controller.go
Normal file
@@ -0,0 +1,64 @@
|
||||
// Package controller - RAGFlow控制器
|
||||
// 功能:接收来自外部的RAGFlow请求(测试/调试用)
|
||||
package controller
|
||||
|
||||
import (
|
||||
"customer-server/consumer"
|
||||
|
||||
"gitea.com/red-future/common/redis"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/net/ghttp"
|
||||
)
|
||||
|
||||
type ragflow struct{}
|
||||
|
||||
var RAGFlow = new(ragflow)
|
||||
|
||||
// Process 处理RAGFlow请求
|
||||
// 参数: r - HTTP请求对象
|
||||
// 功能: 接收外部RAGFlow消息请求,直接调用consumer处理逻辑(用于测试)
|
||||
// 注意: 正常流程不经过此接口,而是直接消费Redis Stream
|
||||
func (c *ragflow) Process(r *ghttp.Request) {
|
||||
ctx := r.Context()
|
||||
|
||||
// 调试:打印原始请求体
|
||||
bodyBytes := r.GetBody()
|
||||
g.Log().Infof(ctx, "收到原始请求体: %s", string(bodyBytes))
|
||||
|
||||
var req redis.SendStreamMessage
|
||||
if err := r.Parse(&req); err != nil {
|
||||
r.Response.WriteJsonExit(g.Map{
|
||||
"code": 400,
|
||||
"msg": "参数错误: " + err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
g.Log().Infof(ctx, "收到RAGFlow请求 - 用户: %s, 内容: %s", req.UserId, req.Content)
|
||||
|
||||
// 直接调用consumer的处理逻辑
|
||||
message := map[string]interface{}{
|
||||
"UserId": req.UserId,
|
||||
"Content": req.Content,
|
||||
"MessageId": req.MessageId,
|
||||
"Platform": req.Platform,
|
||||
"TenantId": req.TenantId,
|
||||
"AccountName": req.AccountName,
|
||||
"ChatId": req.ChatId,
|
||||
"ReplyQueue": req.ReplyQueue,
|
||||
"History": req.History,
|
||||
}
|
||||
|
||||
if err := consumer.HandleMessageHTTP(ctx, message); err != nil {
|
||||
r.Response.WriteJsonExit(g.Map{
|
||||
"code": 500,
|
||||
"msg": "处理失败: " + err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
r.Response.WriteJsonExit(g.Map{
|
||||
"code": 0,
|
||||
"msg": "success",
|
||||
})
|
||||
}
|
||||
69
controller/speechcraft_controller.go
Normal file
69
controller/speechcraft_controller.go
Normal file
@@ -0,0 +1,69 @@
|
||||
// Package controller - 话术控制器
|
||||
// 功能:话术的增删改查、绑定/解绑客服账号
|
||||
package controller
|
||||
|
||||
import (
|
||||
"context"
|
||||
"customer-server/model/dto"
|
||||
"customer-server/service"
|
||||
|
||||
"gitea.com/red-future/common/beans"
|
||||
)
|
||||
|
||||
var Speechcraft = new(speechcraft)
|
||||
|
||||
type speechcraft struct{}
|
||||
|
||||
// Add 添加话术
|
||||
// 参数: req - 添加话术请求,包含话术标题、内容等信息
|
||||
// 返回: res - 添加成功后的话术ID等信息
|
||||
// 功能: 创建新的话术记录并同步到RAGFlow知识库
|
||||
func (c *speechcraft) Add(ctx context.Context, req *dto.AddSpeechcraftReq) (res *dto.AddSpeechcraftRes, err error) {
|
||||
res, err = service.Speechcraft.Add(ctx, req)
|
||||
return
|
||||
}
|
||||
|
||||
// Update 更新话术
|
||||
// 参数: req - 更新话术请求,包含话术ID和待更新字段
|
||||
// 返回: res - 空响应(成功则err为nil)
|
||||
// 功能: 更新话术内容并同步到RAGFlow
|
||||
func (c *speechcraft) Update(ctx context.Context, req *dto.UpdateSpeechcraftReq) (res *beans.ResponseEmpty, err error) {
|
||||
err = service.Speechcraft.Update(ctx, req)
|
||||
return
|
||||
}
|
||||
|
||||
// Delete 删除话术
|
||||
// 参数: req - 删除话术请求,包含话术ID
|
||||
// 返回: res - 空响应(成功则err为nil)
|
||||
// 功能: 逻辑删除话术记录并从RAGFlow移除
|
||||
func (c *speechcraft) Delete(ctx context.Context, req *dto.DeleteSpeechcraftReq) (res *beans.ResponseEmpty, err error) {
|
||||
err = service.Speechcraft.Delete(ctx, req)
|
||||
return
|
||||
}
|
||||
|
||||
// List 获取话术列表
|
||||
// 参数: req - 列表查询请求,支持分页、关键词搜索
|
||||
// 返回: res - 话术列表及分页信息
|
||||
// 功能: 分页查询话术记录,支持按标题、内容搜索
|
||||
func (c *speechcraft) List(ctx context.Context, req *dto.ListSpeechcraftReq) (res *dto.ListSpeechcraftRes, err error) {
|
||||
res, err = service.Speechcraft.List(ctx, req)
|
||||
return
|
||||
}
|
||||
|
||||
// Bind 绑定话术到客服账号
|
||||
// 参数: req - 绑定请求,包含话术ID和客服账号列表
|
||||
// 返回: res - 绑定结果,包含成功和失败的账号信息
|
||||
// 功能: 将话术绑定到指定客服账号,更新账号的RAGFlow配置
|
||||
func (c *speechcraft) Bind(ctx context.Context, req *dto.BindSpeechcraftReq) (res *dto.BindSpeechcraftRes, err error) {
|
||||
res, err = service.Speechcraft.BindToCustomerServices(ctx, req)
|
||||
return
|
||||
}
|
||||
|
||||
// Unbind 解绑话术
|
||||
// 参数: req - 解绑请求,包含话术ID和客服账号
|
||||
// 返回: res - 解绑结果信息
|
||||
// 功能: 从客服账号解绑指定话术,更新RAGFlow配置
|
||||
func (c *speechcraft) Unbind(ctx context.Context, req *dto.UnbindSpeechcraftReq) (res *dto.UnbindSpeechcraftRes, err error) {
|
||||
res, err = service.Speechcraft.UnbindFromCustomerService(ctx, req)
|
||||
return
|
||||
}
|
||||
41
controller/webhook_controller.go
Normal file
41
controller/webhook_controller.go
Normal file
@@ -0,0 +1,41 @@
|
||||
// Package controller - Webhook控制器
|
||||
// 功能:接收平台(小红书、抖音)的webhook消息
|
||||
package controller
|
||||
|
||||
import (
|
||||
"context"
|
||||
"customer-server/model/dto"
|
||||
"customer-server/service"
|
||||
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
)
|
||||
|
||||
var Webhook = new(webhook)
|
||||
|
||||
type webhook struct{}
|
||||
|
||||
// Receive 接收Webhook消息
|
||||
// 参数: req - Webhook消息请求,包含平台、用户ID、内容等
|
||||
// 返回: res - 处理结果
|
||||
// 功能: 接收来自各平台的Webhook消息推送,统一处理后推送到Redis Stream
|
||||
func (c *webhook) Receive(ctx context.Context, req *dto.WebhookReceiveReq) (res *dto.WebhookReceiveRes, err error) {
|
||||
res, err = service.Webhook.Receive(ctx, req)
|
||||
return
|
||||
}
|
||||
|
||||
// Verify 平台回调验证
|
||||
// 参数: req - 回调请求,包含echostr等
|
||||
// 返回: res - 处理结果
|
||||
// 功能: 验证平台回调请求,返回echostr
|
||||
func (c *webhook) Verify(ctx context.Context, req *dto.WebhookCallbackReq) (res *dto.WebhookCallbackRes, err error) {
|
||||
r := g.RequestFromCtx(ctx)
|
||||
// 直接返回 echostr(微信/抖音等平台验证方式)
|
||||
r.Response.Write(req.Echostr)
|
||||
return
|
||||
}
|
||||
|
||||
// History 查询对话记录
|
||||
func (c *webhook) History(ctx context.Context, req *dto.ConversationListReq) (res *dto.ConversationListRes, err error) {
|
||||
res, err = service.Webhook.GetHistory(ctx, req)
|
||||
return
|
||||
}
|
||||
52
controller/websocket_controller.go
Normal file
52
controller/websocket_controller.go
Normal file
@@ -0,0 +1,52 @@
|
||||
// Package controller - WebSocket控制器
|
||||
// 功能:WebSocket连接管理、实时消息推送
|
||||
package controller
|
||||
|
||||
import (
|
||||
"context"
|
||||
"customer-server/model/dto"
|
||||
"customer-server/service"
|
||||
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
)
|
||||
|
||||
var Websocket = new(websocket)
|
||||
|
||||
type websocket struct{}
|
||||
|
||||
// Connect WebSocket连接
|
||||
// 参数: req - WebSocket连接请求,包含用户ID和平台信息
|
||||
// 返回: res - 连接结果(实际通过WebSocket协议通信)
|
||||
// 功能: 升级HTTP连接为WebSocket,建立实时通信通道
|
||||
func (c *websocket) Connect(ctx context.Context, req *dto.WebSocketConnectReq) (res *dto.WebSocketConnectRes, err error) {
|
||||
r := g.RequestFromCtx(ctx)
|
||||
err = service.WebSocket.Connect(ctx, r, req.UserId, req.Platform)
|
||||
return
|
||||
}
|
||||
|
||||
// Send 发送消息到Redis Stream
|
||||
// 参数: req - 发送消息请求,包含用户ID、内容等
|
||||
// 返回: res - 发送结果,包含消息ID
|
||||
// 功能: 将用户消息推送到Redis Stream,由RAGFlow处理器消费
|
||||
func (c *websocket) Send(ctx context.Context, req *dto.WebSocketSendReq) (res *dto.WebSocketSendRes, err error) {
|
||||
res, err = service.WebSocket.Send(ctx, req)
|
||||
return
|
||||
}
|
||||
|
||||
// Broadcast 广播消息给所有连接
|
||||
// 参数: req - 广播请求,包含广播内容
|
||||
// 返回: res - 广播结果(空响应)
|
||||
// 功能: 向所有在线WebSocket连接广播消息
|
||||
func (c *websocket) Broadcast(ctx context.Context, req *dto.WebSocketBroadcastReq) (res *dto.WebSocketBroadcastRes, err error) {
|
||||
service.WebSocket.Broadcast(ctx, req.Content)
|
||||
return
|
||||
}
|
||||
|
||||
// Online 获取在线用户
|
||||
// 参数: req - 查询请求(无参数)
|
||||
// 返回: res - 在线用户列表
|
||||
// 功能: 查询当前所有WebSocket在线用户信息
|
||||
func (c *websocket) Online(ctx context.Context, req *dto.WebSocketOnlineReq) (res *dto.WebSocketOnlineRes, err error) {
|
||||
res = service.WebSocket.GetOnlineUsers()
|
||||
return
|
||||
}
|
||||
111
controller/xiaohongshu_controller.go
Normal file
111
controller/xiaohongshu_controller.go
Normal file
@@ -0,0 +1,111 @@
|
||||
package controller
|
||||
|
||||
import (
|
||||
"context"
|
||||
"customer-server/model/dto"
|
||||
"customer-server/service"
|
||||
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
)
|
||||
|
||||
var XiaohongshuController = new(xiaohongshuController)
|
||||
|
||||
type xiaohongshuController struct{}
|
||||
|
||||
// BindAccount 绑定小红书账户
|
||||
// 参数: req - 绑定账户请求,包含账户信息和授权码
|
||||
// 返回: res - 处理结果
|
||||
// 功能: 处理小红书账户绑定,保存授权码到客服账号
|
||||
func (c *xiaohongshuController) BindAccount(ctx context.Context, req *XhsBindAccountReq) (res *dto.XhsCommonRes, err error) {
|
||||
if err = service.Xiaohongshu.HandleBindAccount(ctx, &req.XhsBindAccountReq); err != nil {
|
||||
return
|
||||
}
|
||||
res = &dto.XhsCommonRes{Code: 0, Msg: "成功", Success: true}
|
||||
return
|
||||
}
|
||||
|
||||
// UnbindAccount 解绑小红书账户
|
||||
// 参数: req - 解绑账户请求,包含账户信息和授权码
|
||||
// 返回: res - 处理结果
|
||||
// 功能: 处理小红书账户解绑,删除授权码从客服账号
|
||||
func (c *xiaohongshuController) UnbindAccount(ctx context.Context, req *XhsUnbindAccountReq) (res *dto.XhsCommonRes, err error) {
|
||||
if err = service.Xiaohongshu.HandleUnbindAccount(ctx, &req.XhsUnbindAccountReq); err != nil {
|
||||
return
|
||||
}
|
||||
res = &dto.XhsCommonRes{Code: 0, Msg: "成功", Success: true}
|
||||
return
|
||||
}
|
||||
|
||||
// BindKosUser 绑定小红书KOS用户
|
||||
// 参数: req - KOS绑定请求,包含绑定状态和token
|
||||
// 返回: res - 处理结果
|
||||
// 功能: 处理小红书KOS授权回调,保存授权token到客服账号
|
||||
func (c *xiaohongshuController) BindKosUser(ctx context.Context, req *XhsBindKosUserReq) (res *dto.XhsCommonRes, err error) {
|
||||
g.Log().Infof(ctx, "[小红书] 收到KOS绑定通知: %s", req.Content)
|
||||
res = &dto.XhsCommonRes{Code: 0, Msg: "成功", Success: true}
|
||||
return
|
||||
}
|
||||
|
||||
// ReceiveMessage 接收小红书消息
|
||||
// 参数: req - 消息请求,包含消息内容和用户信息
|
||||
// 返回: res - 处理结果
|
||||
// 功能: 接收小红书消息,自动回复或转发到RAGFlow处理
|
||||
func (c *xiaohongshuController) ReceiveMessage(ctx context.Context, req *XhsReceiveMessageReq) (res *dto.XhsCommonRes, err error) {
|
||||
if err = service.Xiaohongshu.HandleReceiveMessage(ctx, &req.XhsReceiveMessageReq); err != nil {
|
||||
return
|
||||
}
|
||||
res = &dto.XhsCommonRes{Code: 0, Msg: "成功", Success: true}
|
||||
return
|
||||
}
|
||||
|
||||
// IntentCommentPush 接收意向评论推送
|
||||
// 参数: req - 评论推送请求,包含评论ID、内容、用户信息
|
||||
// 返回: res - 处理结果
|
||||
// 功能: 接收小红书意向评论,自动回复或转发到RAGFlow处理
|
||||
func (c *xiaohongshuController) IntentCommentPush(ctx context.Context, req *XhsIntentCommentPushReq) (res *dto.XhsCommonRes, err error) {
|
||||
g.Log().Infof(ctx, "[小红书] 收到意向评论推送: commentId=%s, content=%s", req.CommentId, req.CommentContent)
|
||||
res = &dto.XhsCommonRes{Code: 0, Msg: "成功", Success: true}
|
||||
return
|
||||
}
|
||||
|
||||
// PushLead 接收留资推送
|
||||
// 参数: req - 留资推送请求,包含用户留资信息
|
||||
// 返回: res - 处理结果
|
||||
// 功能: 接收小红书用户留资信息,记录到系统并触发后续流程
|
||||
func (c *xiaohongshuController) PushLead(ctx context.Context, req *XhsPushLeadReq) (res *dto.XhsCommonRes, err error) {
|
||||
g.Log().Infof(ctx, "[小红书] 收到留资推送: userId=%s, pushType=%d", req.UserId, req.PushType)
|
||||
res = &dto.XhsCommonRes{Code: 0, Msg: "成功", Success: true}
|
||||
return
|
||||
}
|
||||
|
||||
// ==================== 请求结构(路由元数据) ====================
|
||||
|
||||
type XhsBindAccountReq struct {
|
||||
g.Meta `path:"/api/open/im/third/bind_account" method:"post" tags:"Xiaohongshu" summary:"小红书绑定账户通知"`
|
||||
dto.XhsBindAccountReq
|
||||
}
|
||||
|
||||
type XhsUnbindAccountReq struct {
|
||||
g.Meta `path:"/api/open/im/third/unbind_account" method:"post" tags:"Xiaohongshu" summary:"小红书解绑账户通知"`
|
||||
dto.XhsUnbindAccountReq
|
||||
}
|
||||
|
||||
type XhsBindKosUserReq struct {
|
||||
g.Meta `path:"/api/open/im/auth/bind_user/event" method:"post" tags:"Xiaohongshu" summary:"小红书KOS绑定事件"`
|
||||
dto.XhsBindKosUserReq
|
||||
}
|
||||
|
||||
type XhsReceiveMessageReq struct {
|
||||
g.Meta `path:"/api/open/im/send" method:"post" tags:"Xiaohongshu" summary:"小红书接收消息"`
|
||||
dto.XhsReceiveMessageReq
|
||||
}
|
||||
|
||||
type XhsIntentCommentPushReq struct {
|
||||
g.Meta `path:"/api/open/intent/comment" method:"post" tags:"Xiaohongshu" summary:"小红书意向评论推送"`
|
||||
dto.XhsIntentCommentPushReq
|
||||
}
|
||||
|
||||
type XhsPushLeadReq struct {
|
||||
g.Meta `path:"/api/open/im/push_lead" method:"post" tags:"Xiaohongshu" summary:"小红书留资推送"`
|
||||
dto.XhsPushLeadReq
|
||||
}
|
||||
Reference in New Issue
Block a user