This commit is contained in:
2026-03-14 10:02:49 +08:00
parent 03b50ef904
commit 830f75a334
75 changed files with 10677 additions and 2 deletions

13
model/dto/archive_dto.go Normal file
View File

@@ -0,0 +1,13 @@
package dto
import "github.com/gogf/gf/v2/frame/g"
// ArchiveRunReq 手动触发归档请求
type ArchiveRunReq struct {
g.Meta `path:"/run" method:"post" tags:"归档管理" summary:"手动触发归档" dc:"立即执行月度归档任务"`
}
// ArchiveRunRes 手动触发归档响应
type ArchiveRunRes struct {
Message string `json:"message"` // 执行结果消息
}

View File

@@ -0,0 +1,107 @@
package dto
import (
"customer-server/model/entity"
"gitea.com/red-future/common/beans"
"github.com/gogf/gf/v2/frame/g"
)
// AddCustomerServiceAccountReq 添加客服账号
type AddCustomerServiceAccountReq struct {
g.Meta `path:"/add" method:"post" tags:"客服账号管理" summary:"添加客服账号" dc:"创建新的客服账号"` // 路由: POST /customerserviceaccount/add
AccountName string `json:"accountName" v:"required" dc:"客服账号名称" example:"cs_xhs_qixue"`
Platform string `json:"platform" v:"required" dc:"客服平台" example:"小红书"`
Prompt *string `json:"prompt" dc:"可选:自定义提示词"`
Greeting *string `json:"greeting" dc:"可选:开场白"`
SelfIdentity *string `json:"selfIdentity" dc:"可选AI身份描述"`
SpeechcraftIds []string `json:"speechcraftIds" dc:"绑定的话术ID列表为空则绑定该租户下所有话术"`
TenantId interface{} `json:"tenantId" dc:"租户ID可选不传则使用session中的租户ID"`
}
type AddCustomerServiceAccountRes struct {
Id string `json:"id" dc:"新创建的客服账号ID"`
}
// UpdateCustomerServiceAccountReq 更新客服账号
type UpdateCustomerServiceAccountReq struct {
g.Meta `path:"/update" method:"post" tags:"客服账号管理" summary:"更新客服账号" dc:"更新客服账号信息"` // 路由: POST /customerserviceaccount/update
Id string `json:"id" v:"required" dc:"客服账号ID"`
AccountName string `json:"accountName" dc:"客服账号名称"`
Platform string `json:"platform" dc:"客服平台"`
Prompt *string `json:"prompt" dc:"自定义提示词(可选)"`
Greeting *string `json:"greeting" dc:"开场白(可选)"`
SelfIdentity *string `json:"selfIdentity" dc:"AI身份描述可选"`
}
// ToggleCustomerServiceAccountStatusReq 切换客服账号状态(启用/禁用)
type ToggleCustomerServiceAccountStatusReq struct {
g.Meta `path:"/toggleStatus" method:"post" tags:"客服账号管理" summary:"切换客服账号状态" dc:"根据当前状态在启用/禁用之间切换客服账号"` // 路由: POST /customerserviceaccount/toggleStatus
Id string `json:"id" v:"required" dc:"客服账号ID"`
}
// GetCustomerServiceAccountReq 获取客服账号详情
type GetCustomerServiceAccountReq struct {
g.Meta `path:"/one" method:"get" tags:"客服账号管理" summary:"获取客服账号详情" dc:"根据ID获取单个客服账号信息"` // 路由: GET /customerserviceaccount/one
Id string `json:"id" v:"required" dc:"客服账号ID"`
}
// ListCustomerServiceAccountReq 获取客服账号列表
type ListCustomerServiceAccountReq struct {
g.Meta `path:"/list" method:"get" tags:"客服账号管理" summary:"获取客服账号列表" dc:"分页查询客服账号列表,支持多条件筛选"` // 路由: GET /customerserviceaccount/list
beans.Page
AccountName string `json:"accountName" dc:"客服账号名称"`
IsDisabled *bool `json:"isDisabled" dc:"筛选是否禁用true-禁用false-启用)"`
Platform string `json:"platform" dc:"筛选:平台"`
}
// RecreateRAGFlowConfigReq 重新创建RAGFlow配置
type RecreateRAGFlowConfigReq struct {
g.Meta `path:"/recreateRAGFlow" method:"post" tags:"客服账号管理" summary:"重新创建RAGFlow配置" dc:"为已存在的客服账号重新创建RAGFlow知识库和Chat配置"` // 路由: POST /customerserviceaccount/recreateRAGFlow
AccountName string `json:"accountName" v:"required" dc:"客服账号名称" example:"cs_xhs_qixue"`
Platform string `json:"platform" v:"required" dc:"客服平台" example:"xiaohongshu"`
}
// UpdateGreetingReq 更新开场白
type UpdateGreetingReq struct {
g.Meta `path:"/updateGreeting" method:"post" tags:"客服账号管理" summary:"更新开场白" dc:"更新客服账号的WebSocket连接开场白"` // 路由: POST /customerserviceaccount/updateGreeting
AccountName string `json:"accountName" v:"required" dc:"客服账号名称" example:"cs_xhs_qixue"`
Greeting string `json:"greeting" v:"required" dc:"开场白内容" example:"亲爱的,欢迎光临!🌸\n如果你有月经不调或气血不足的问题随时可以问我哦"`
}
type ListCustomerServiceAccountRes struct {
List []*entity.CustomerServiceAccount `json:"list" dc:"客服账号列表"`
Total int `json:"total" dc:"总记录数"`
}
// DeleteCustomerServiceAccountReq 删除客服账号
type DeleteCustomerServiceAccountReq struct {
g.Meta `path:"/delete" method:"post" tags:"客服账号管理" summary:"删除客服账号" dc:"软删除客服账号同时删除RAGFlow Chat实例"`
Id string `json:"id" v:"required" dc:"客服账号ID"`
}
type DeleteCustomerServiceAccountRes struct {
Success bool `json:"success" dc:"是否成功"`
Message string `json:"message" dc:"提示信息"`
}
// GetAccessibleSpeechcraftsReq 获取客服账号可访问的话术列表
type GetAccessibleSpeechcraftsReq struct {
g.Meta `path:"/speechcrafts/:accountName" method:"get" tags:"客服账号管理" summary:"获取可访问话术" dc:"获取客服账号可访问的话术列表(动态权限)"`
AccountName string `json:"accountName" v:"required" dc:"客服账号名称"`
}
type GetAccessibleSpeechcraftsRes struct {
Speechcrafts []SpeechcraftItem `json:"speechcrafts" dc:"话术列表"`
TotalCount int `json:"totalCount" dc:"总数"`
Permission string `json:"permission" dc:"权限类型dynamic=所有话术specified=指定话术"`
}
type SpeechcraftItem struct {
Id string `json:"id"`
Tag string `json:"tag"`
Content string `json:"content"`
Direction string `json:"direction"`
Platform string `json:"platform"`
Keywords []string `json:"keywords"`
}

74
model/dto/data_dto.go Normal file
View File

@@ -0,0 +1,74 @@
package dto
import (
"customer-server/model/entity"
"gitea.com/red-future/common/beans"
"github.com/gogf/gf/v2/frame/g"
)
// AddDataReq 添加数据
type AddDataReq struct {
g.Meta `path:"/add" method:"post" tags:"数据管理" summary:"添加数据" dc:"记录客服与客户的交互数据"` // 路由: POST /data/add
CustomerId string `json:"customerId" v:"required"` // 客户ID
AccountName string `json:"accountName" v:"required"` // 客服账号名称
CustomerServicePlatform string `json:"customerServicePlatform" v:"required"` // 客服平台
CustomerServiceName string `json:"customerServiceName" v:"required"` // 客服名称
IsInbound bool `json:"isInbound"` // 是否进线
IsActive bool `json:"isActive"` // 是否活跃
IsServed bool `json:"isServed"` // 是否接待
HasSentContactCard bool `json:"hasSentContactCard"` // 是否发联系卡
HasSentNameCard bool `json:"hasSentNameCard"` // 是否发名片
HasLeftContactInfo bool `json:"hasLeftContactInfo"` // 是否留资
SessionStartTime int64 `json:"sessionStartTime"` // 会话开始时间
MessageTime int64 `json:"messageTime"` // 消息时间
}
type AddDataRes struct {
Id string `json:"id"`
}
// UpdateDataReq 更新数据
type UpdateDataReq struct {
g.Meta `path:"/update" method:"post" tags:"数据管理" summary:"更新数据" dc:"更新客服交互数据"` // 路由: POST /data/update
Id string `json:"id" v:"required"` // ID
CustomerId string `json:"customerId"`
AccountName string `json:"accountName"`
CustomerServicePlatform string `json:"customerServicePlatform"`
CustomerServiceName string `json:"customerServiceName"`
IsInbound *bool `json:"isInbound"` // 使用指针以区分 false 和未传值
IsActive *bool `json:"isActive"`
IsServed *bool `json:"isServed"`
HasSentContactCard *bool `json:"hasSentContactCard"`
HasSentNameCard *bool `json:"hasSentNameCard"`
HasLeftContactInfo *bool `json:"hasLeftContactInfo"`
SessionStartTime int64 `json:"sessionStartTime"`
MessageTime int64 `json:"messageTime"`
}
// // DeleteDataReq 删除数据
// type DeleteDataReq struct {
// g.Meta `path:"/delete" method:"post" tags:"数据管理" summary:"删除数据" dc:"删除指定数据记录"` // 路由: POST /data/delete
// Id string `json:"id" v:"required"` // ID
// }
// GetDataReq 获取单个数据
type GetDataReq struct {
g.Meta `path:"/one" method:"get" tags:"数据管理" summary:"获取数据详情" dc:"根据ID获取单条数据记录"` // 路由: GET /data/one
Id string `json:"id" v:"required"` // ID
}
// ListDataReq 获取数据列表
type ListDataReq struct {
g.Meta `path:"/list" method:"get" tags:"数据管理" summary:"获取数据列表" dc:"分页查询交互数据,支持按客户、客服、时间筛选"` // 路由: GET /data/list
beans.Page
CustomerId string `json:"customerId" p:"customerId" dc:"筛选客户ID"` // 筛选客户ID
AccountName *string `json:"accountName" dc:"客服账号名称"` // 筛选客服ID
StartDate string `json:"startDate" p:"startDate" dc:"筛选开始日期YYYY-MM-DD"` // 筛选:开始日期
EndDate string `json:"endDate" p:"endDate" dc:"筛选结束日期YYYY-MM-DD"` // 筛选:结束日期
}
type ListDataRes struct {
List []*entity.Data `json:"list"`
Total int `json:"total"`
}

View File

@@ -0,0 +1,73 @@
package dto
import (
"customer-server/model/entity"
"gitea.com/red-future/common/beans"
"github.com/gogf/gf/v2/frame/g"
)
// AddDataStatisticsReq 添加数据统计
type AddDataStatisticsReq struct {
g.Meta `path:"/add" method:"post" tags:"数据统计" summary:"添加统计数据" dc:"记录每日客服的汇总统计数据"` // 路由: POST /data/statistics/add
Date string `json:"date" v:"required|date-format:2006-01-02"` // 日期格式YYYY-MM-DD
AccountName string `json:"accountName" v:"required"` // 客服账号名称
CustomerServiceName string `json:"customerServiceName" v:"required"` // 客服名称
CustomerServicePlatform string `json:"customerServicePlatform" v:"required"` // 客服平台
InboundCount int `json:"inboundCount"` // 进线数
ActiveCount int `json:"activeCount"` // 开口数
ServedCount int `json:"servedCount"` // 接待数
ContactCardSentCount int `json:"contactCardSentCount"` // 发名片数
NameCardSentCount int `json:"nameCardSentCount"` // 发留资卡数
LeftContactInfoCount int `json:"leftContactInfoCount"` // 留资数
ResponseRate30s float64 `json:"responseRate30s"` // 30s响应率
ResponseRate60s float64 `json:"responseRate60s"` // 60s响应率
ResponseRate360s float64 `json:"responseRate360s"` // 3分钟响应率
}
type AddDataStatisticsRes struct {
Id string `json:"id"`
}
// UpdateDataStatisticsReq 更新数据统计
type UpdateDataStatisticsReq struct {
g.Meta `path:"/update" method:"post" tags:"数据统计" summary:"更新统计数据" dc:"更新每日统计数据"` // 路由: POST /data/statistics/update
Id string `json:"id" v:"required"`
Date string `json:"date" v:"date-format:2006-01-02"`
AccountName string `json:"accountName"`
CustomerServiceName string `json:"customerServiceName"`
CustomerServicePlatform string `json:"customerServicePlatform"`
InboundCount *int `json:"inboundCount"`
ActiveCount *int `json:"activeCount"`
ServedCount *int `json:"servedCount"`
ContactCardSentCount *int `json:"contactCardSentCount"`
NameCardSentCount *int `json:"nameCardSentCount"`
LeftContactInfoCount *int `json:"leftContactInfoCount"`
ResponseRate30s *float64 `json:"responseRate30s"`
ResponseRate60s *float64 `json:"responseRate60s"`
ResponseRate360s *float64 `json:"responseRate360s"`
}
// ListDataStatisticsReq 获取数据统计列表
type ListDataStatisticsReq struct {
g.Meta `path:"/list" method:"get" tags:"数据统计" summary:"获取统计列表" dc:"分页查询统计数据,支持按平台、日期范围筛选"` // 路由: GET /data/statistics/list
beans.Page
// 同时写json和p ,同时支持get的 query解析和post的json解析
CustomerServicePlatform string `json:"customerServicePlatform" p:"customerServicePlatform" dc:"筛选:客服平台"` // 筛选:客服平台
StartDate string `json:"startDate" p:"startDate" dc:"筛选开始日期YYYY-MM-DD"` // 筛选:开始日期
EndDate string `json:"endDate" p:"endDate" dc:"筛选结束日期YYYY-MM-DD"` // 筛选:结束日期
}
type ListDataStatisticsRes struct {
List []*entity.DataStatistics `json:"list"`
Total int `json:"total"`
}
// ExportDataStatisticsReq 导出请求复用列表请求(忽略分页参数)
type ExportDataStatisticsReq struct {
g.Meta `path:"/export" method:"get" tags:"数据统计" summary:"导出统计数据" dc:"导出数据统计为ZIP文件包含TXT"` // 路由: GET /data/statistics/export
// 同时写json和p同时支持get的query解析和post的json解析
CustomerServicePlatform string `json:"customerServicePlatform" p:"customerServicePlatform" dc:"筛选:客服平台"` // 筛选:客服平台
StartDate string `json:"startDate" p:"startDate" dc:"筛选开始日期YYYY-MM-DD"` // 筛选:开始日期
EndDate string `json:"endDate" p:"endDate" dc:"筛选结束日期YYYY-MM-DD"` // 筛选:结束日期
}

102
model/dto/product_dto.go Normal file
View File

@@ -0,0 +1,102 @@
// Package dto - 产品DTO
// 功能:产品的增删改查、导入/导出、绑定/解绑客服账号的请求响应结构体
package dto
import (
"customer-server/model/entity"
"gitea.com/red-future/common/beans"
"github.com/gogf/gf/v2/frame/g"
)
// AddProductReq 添加产品
type AddProductReq struct {
g.Meta `path:"/add" method:"post" tags:"产品管理" summary:"添加产品" dc:"创建新的产品信息"` // 路由: POST /product/add
Name string `json:"name" v:"required"` // 产品名称
Description string `json:"description"` // 产品详情
}
type AddProductRes struct {
Id string `json:"id"`
}
// UpdateProductReq 更新产品
type UpdateProductReq struct {
g.Meta `path:"/update" method:"post" tags:"产品管理" summary:"更新产品" dc:"更新产品信息"` // 路由: POST /product/update
Id string `json:"id" v:"required"` // ID
Name string `json:"name"` // 产品名称
Description string `json:"description"` // 产品详情
}
// DeleteProductReq 删除产品
type DeleteProductReq struct {
g.Meta `path:"/delete" method:"post" tags:"产品管理" summary:"删除产品" dc:"删除指定产品"` // 路由: POST /product/delete
Id string `json:"id" v:"required"` // ID
}
// GetProductReq 获取单个产品
type GetProductReq struct {
g.Meta `path:"/one" method:"get" tags:"产品管理" summary:"获取产品详情" dc:"根据ID获取单个产品信息"` // 路由: GET /product/one
Id string `p:"id" v:"required"` // ID
}
// ListProductReq 获取产品列表
type ListProductReq struct {
g.Meta `path:"/list" method:"get" tags:"产品管理" summary:"获取产品列表" dc:"分页查询产品列表,支持按名称筛选"` // 路由: GET /product/list
beans.Page
Name string `p:"name"` // 筛选:产品名称
}
type ListProductRes struct {
List []*entity.Product `json:"list"`
Total int `json:"total"`
}
// ExportProductReq 导出产品
type ExportProductReq struct {
g.Meta `path:"/export" method:"get" tags:"产品管理" summary:"导出产品" dc:"导出产品为TXT格式的ZIP压缩包支持按名称筛选" produces:"application/zip"` // 路由: GET /product/export
Name string `p:"name" dc:"筛选:产品名称(支持模糊查询,为空则导出所有)"` // 筛选:产品名称
}
type ExportProductRes struct {
// 实际返回的是文件流,这个结构体只是为了 Swagger 文档
}
// ImportProductReq 导入产品
type ImportProductReq struct {
g.Meta `path:"/import" method:"post" tags:"产品管理" summary:"导入产品" dc:"上传ZIP文件批量导入产品TXT格式" consumes:"multipart/form-data"` // 路由: POST /product/import
File string `json:"file" type:"file" dc:"上传的ZIP文件" v:"required"` // ZIP文件
}
type ImportProductRes struct {
SuccessCount int `json:"successCount"` // 成功导入数量
FailCount int `json:"failCount"` // 失败数量
FailReasons []string `json:"failReasons"` // 失败原因列表
}
// BindProductReq 绑定产品到客服账号请求
type BindProductReq struct {
g.Meta `path:"/bind" method:"post" tags:"产品管理" summary:"绑定产品" dc:"将产品绑定到客服账号"`
ProductId string `json:"productId" v:"required#产品ID不能为空"`
AccountNames []string `json:"accountNames" v:"required" dc:"客服账号名称列表"`
}
// BindProductRes 绑定产品响应
type BindProductRes struct {
SuccessCount int `json:"successCount"` // 成功绑定数量
FailedIds []string `json:"failedIds"` // 失败的客服账号ID列表
Message string `json:"message"` // 提示信息
}
// UnbindProductReq 解绑产品请求
type UnbindProductReq struct {
g.Meta `path:"/unbind" method:"post" tags:"产品管理" summary:"解绑产品" dc:"将产品从客服账号解绑"`
ProductId string `json:"productId" v:"required#产品ID不能为空"`
AccountName string `json:"accountName" v:"required" dc:"客服账号名称"`
}
// UnbindProductRes 解绑产品响应
type UnbindProductRes struct {
Success bool `json:"success"`
Message string `json:"message"`
}

View File

@@ -0,0 +1,19 @@
// Package dto - RAGFlow对话配置DTO
// 功能:定义更新对话配置提示词的请求响应结构体
package dto
// UpdateChatPromptReq 更新对话配置提示词请求
type UpdateChatPromptReq struct {
ChatId string `json:"chatId" v:"required#对话配置ID不能为空"`
Prompt string `json:"prompt" v:"required#提示词不能为空"`
SimilarityThreshold float64 `json:"similarityThreshold"` // 相似度阈值0.0-1.0默认0.2
KeywordsSimilarityWeight float64 `json:"keywordsSimilarityWeight"` // 关键词权重0.0-1.0默认0.7
TopN int `json:"topN"` // 返回chunk数量默认8
EmptyResponse string `json:"emptyResponse"` // 无匹配时回复
}
// UpdateChatPromptRes 更新对话配置提示词响应
type UpdateChatPromptRes struct {
Success bool `json:"success"`
Message string `json:"message"`
}

View File

@@ -0,0 +1,41 @@
package dto
import "github.com/gogf/gf/v2/frame/g"
// GetRAGFlowConfigReq 获取RAGFlow配置请求
type GetRAGFlowConfigReq struct {
g.Meta `path:"/get" method:"get" tags:"RAGFlow配置" summary:"获取RAGFlow配置"`
AccountName string `json:"accountName" v:"required" dc:"客服账号名称"`
}
// GetRAGFlowConfigRes 获取RAGFlow配置响应
type GetRAGFlowConfigRes struct {
AccountName string `json:"accountName"`
Platform string `json:"platform"`
DatasetId string `json:"datasetId"`
DatasetName string `json:"datasetName"`
ChatId string `json:"chatId"`
Prompt string `json:"prompt"`
DocumentIds []string `json:"documentIds"`
SimilarityThreshold float64 `json:"similarityThreshold"`
KeywordsSimilarityWeight float64 `json:"keywordsSimilarityWeight"`
TopN int `json:"topN"`
EmptyResponse string `json:"emptyResponse"`
}
// UpdatePromptReq 更新提示词请求
type UpdatePromptReq struct {
g.Meta `path:"/updatePrompt" method:"post" tags:"RAGFlow配置" summary:"更新提示词"`
AccountName string `json:"accountName" v:"required" dc:"客服账号名称"`
Prompt string `json:"prompt" v:"required" dc:"提示词内容"`
SimilarityThreshold *float64 `json:"similarityThreshold" dc:"相似度阈值"`
KeywordsSimilarityWeight *float64 `json:"keywordsSimilarityWeight" dc:"关键词权重"`
TopN *int `json:"topN" dc:"返回chunk数量"`
EmptyResponse *string `json:"emptyResponse" dc:"无匹配时回复"`
}
// UpdatePromptRes 更新提示词响应
type UpdatePromptRes struct {
Success bool `json:"success"`
Message string `json:"message"`
}

View File

@@ -0,0 +1,29 @@
// Package dto - RAGFlow同步相关DTO
// 功能定义RAGFlow同步、重试消息的请求响应结构体
package dto
// SyncToRAGFlowReq 同步到RAGFlow请求
type SyncToRAGFlowReq struct {
SpeechcraftIds []string `json:"speechcraftIds" v:"required#话术ID列表不能为空"` // 话术ID列表
ProductIds []string `json:"productIds"` // 产品ID列表可选
ForceSync bool `json:"forceSync"` // 是否强制重新同步(已同步的也重新上传)
}
// SyncToRAGFlowRes 同步到RAGFlow响应
type SyncToRAGFlowRes struct {
TotalCount int `json:"totalCount"` // 总数
SuccessCount int `json:"successCount"` // 成功数量
FailedCount int `json:"failedCount"` // 失败数量
FailedIds []string `json:"failedIds"` // 失败的ID列表
Message string `json:"message"` // 提示信息
}
// RAGFlowSyncRetryMsg RAGFlow同步重试消息RabbitMQ
// 说明租户级知识库dataset_id从租户配置中获取
type RAGFlowSyncRetryMsg struct {
Type string `json:"type"` // speechcraft or product
Id string `json:"id"` // 话术/产品ID
AccountName string `json:"accountName"` // 客服账号名称
TenantId string `json:"tenantId"` // 租户ID用于查询知识库
RetryCount int `json:"retryCount"` // 当前重试次数
}

View File

@@ -0,0 +1,101 @@
// Package dto - 话术DTO
// 功能:话术的增删改查、绑定/解绑客服账号的请求响应结构体
package dto
import (
"customer-server/model/entity"
"gitea.com/red-future/common/beans"
"github.com/gogf/gf/v2/frame/g"
)
// AddSpeechcraftReq 添加话术
type AddSpeechcraftReq struct {
g.Meta `path:"/add" method:"post" tags:"话术管理" summary:"添加话术" dc:"创建新的客服话术模板"` // 路由: POST /speechcraft/add
Tag string `json:"tag" v:"required"` // 标签
Content string `json:"content" v:"required"` // 内容
Direction string `json:"direction"` // 咨询方向(气血、减肥、护肤等)
AccountName string `json:"accountName,omitempty"` // 客服账号名称可选用于绕过gateway时查询tenantId
TenantId interface{} `json:"tenantId,omitempty"` // 租户ID可选不传则使用默认值1
// 状态机字段
Stage int `json:"stage"` // 触发阶段0=初始)
Status string `json:"status"` // 触发行为click/keyword/空=任意)
Keywords []string `json:"keywords"` // 触发关键字(空=任意)
NextStage int `json:"nextStage"` // 下一阶段(-1=结束)
Platform string `json:"platform"` // 平台xiaohongshu
}
type AddSpeechcraftRes struct {
Id string `json:"id"`
}
// UpdateSpeechcraftReq 更新话术
type UpdateSpeechcraftReq struct {
g.Meta `path:"/update" method:"post" tags:"话术管理" summary:"更新话术" dc:"更新话术模板内容"` // 路由: POST /speechcraft/update
Id string `json:"id" v:"required"` // ID
Tag string `json:"tag"` // 标签
Content string `json:"content"` // 内容
// 状态机字段
Stage *int `json:"stage"` // 触发阶段
Status *string `json:"status"` // 触发行为
Keywords []string `json:"keywords"` // 触发关键字
NextStage *int `json:"nextStage"` // 下一阶段
Platform *string `json:"platform"` // 平台
}
// DeleteSpeechcraftReq 删除话术
type DeleteSpeechcraftReq struct {
g.Meta `path:"/delete" method:"post" tags:"话术管理" summary:"删除话术" dc:"删除指定话术模板"` // 路由: POST /speechcraft/delete
Id string `json:"id" v:"required"` // ID
}
// GetSpeechcraftReq 获取单个话术
type GetSpeechcraftReq struct {
g.Meta `path:"/one" method:"get" tags:"话术管理" summary:"获取话术详情" dc:"根据ID获取单个话术模板"` // 路由: GET /speechcraft/one
Id string `json:"id" v:"required"` // ID
}
// ListSpeechcraftReq 获取话术列表
type ListSpeechcraftReq struct {
g.Meta `path:"/list" method:"get" tags:"话术管理" summary:"获取话术列表" dc:"分页查询话术模板,支持按标签、内容筛选"` // 路由: GET /speechcraft/list
beans.Page
Tag string `json:"tag"` // 筛选:标签
Content string `json:"content"` // 筛选:内容
Stage *int `json:"stage"` // 筛选:阶段
Platform string `json:"platform"` // 筛选:平台
}
type ListSpeechcraftRes struct {
List []*entity.Speechcraft `json:"list"`
Total int `json:"total"`
}
// BindSpeechcraftReq 绑定话术到客服账号请求
type BindSpeechcraftReq struct {
g.Meta `path:"/bind" method:"post" tags:"话术管理" summary:"绑定话术" dc:"将话术绑定到客服账号"`
SpeechcraftId string `json:"speechcraftId" v:"required#话术ID不能为空"`
AccountNames []string `json:"accountNames" v:"required#客服账号名称列表不能为空"`
}
// BindSpeechcraftRes 绑定话术响应
type BindSpeechcraftRes struct {
SuccessCount int `json:"successCount"` // 成功绑定数量
AlreadyBound []string `json:"alreadyBound"` // 已绑定的客服账号ID
NotFound []string `json:"notFound"` // 不存在的客服账号ID
Message string `json:"message"` // 提示信息
}
// UnbindSpeechcraftReq 解绑话术请求
type UnbindSpeechcraftReq struct {
g.Meta `path:"/unbind" method:"post" tags:"话术管理" summary:"解绑话术" dc:"将话术从客服账号解绑"`
SpeechcraftId string `json:"speechcraftId" v:"required#话术ID不能为空"`
AccountName string `json:"accountName" v:"required#客服账号名称不能为空"`
}
// UnbindSpeechcraftRes 解绑话术响应
type UnbindSpeechcraftRes struct {
Success bool `json:"success"`
Message string `json:"message"`
}

51
model/dto/webhook_dto.go Normal file
View File

@@ -0,0 +1,51 @@
package dto
import "github.com/gogf/gf/v2/frame/g"
// WebhookReceiveReq 接收平台消息请求
type WebhookReceiveReq struct {
g.Meta `path:"/:platform" method:"post" tags:"Webhook" summary:"接收平台消息" dc:"接收小红书/抖音等平台推送的用户消息"`
Platform string `p:"platform" v:"required#平台标识不能为空" dc:"平台标识(xiaohongshu/douyin/kuaishou)"`
UserId string `json:"userId" v:"required#用户ID不能为空" dc:"平台用户ID"`
AccountId string `json:"accountId" dc:"客服账号ID"`
Content string `json:"content" v:"required#消息内容不能为空" dc:"消息内容"`
MsgId string `json:"msgId" dc:"平台消息ID用于去重"`
Timestamp int64 `json:"timestamp" dc:"消息时间戳"`
}
type WebhookReceiveRes struct {
Success bool `json:"success" dc:"是否成功"`
MsgId string `json:"msg_id,omitempty" dc:"消息ID"`
}
// WebhookCallbackReq 平台回调验证请求(部分平台需要)
type WebhookCallbackReq struct {
g.Meta `path:"/:platform/verify" method:"get" tags:"Webhook" summary:"回调验证" dc:"平台回调验证(部分平台接入时需要)"`
Platform string `p:"platform" dc:"平台标识"`
Signature string `p:"signature" dc:"签名"`
Timestamp string `p:"timestamp" dc:"时间戳"`
Nonce string `p:"nonce" dc:"随机数"`
Echostr string `p:"echostr" dc:"回显字符串"`
}
type WebhookCallbackRes struct {
g.Meta `mime:"text/plain"`
}
// ConversationListReq 对话记录查询请求
type ConversationListReq struct {
g.Meta `path:"/history" method:"get" tags:"Webhook" summary:"查询对话记录" dc:"查询用户历史对话记录"`
UserId string `p:"user_id" v:"required#用户ID不能为空" dc:"用户ID"`
Limit int64 `p:"limit" d:"20" dc:"返回数量默认20"`
}
type ConversationListRes struct {
List []*ConversationItem `json:"list" dc:"对话记录列表"`
}
type ConversationItem struct {
Question string `json:"question" dc:"用户问题"`
Answer string `json:"answer" dc:"AI回复"`
MsgTime string `json:"msgTime" dc:"消息时间"`
SessionId string `json:"sessionId" dc:"会话ID"`
}

View File

@@ -0,0 +1,58 @@
package dto
import (
"gitea.com/red-future/common/beans"
"github.com/gogf/gf/v2/frame/g"
)
// WebSocketConnectReq WebSocket 连接请求
type WebSocketConnectReq struct {
g.Meta `path:"/connect" method:"get" tags:"WebSocket" summary:"WebSocket连接" dc:"建立WebSocket连接用于实时消息推送"`
UserId string `p:"user_id" v:"required#用户ID不能为空" dc:"用户ID"`
Platform string `p:"platform" d:"xiaohongshu" dc:"平台(xiaohongshu/douyin/kuaishou)"`
}
type WebSocketConnectRes = beans.ResponseEmpty
// WebSocketSendReq 发送消息请求
type WebSocketSendReq struct {
g.Meta `path:"/send" method:"post" tags:"WebSocket" summary:"发送消息" dc:"发送消息到Redis Streammessage服务会消费并处理"`
UserId string `json:"userId" v:"required#用户ID不能为空" dc:"用户ID"`
Content string `json:"content" v:"required#消息内容不能为空" dc:"消息内容"`
}
type WebSocketSendRes struct {
MessageId string `json:"messageId" dc:"消息ID"`
}
// WebSocketBroadcastReq 广播消息请求
type WebSocketBroadcastReq struct {
g.Meta `path:"/broadcast" method:"post" tags:"WebSocket" summary:"广播消息" dc:"向所有WebSocket连接广播消息测试用"`
Content string `json:"content" v:"required#消息内容不能为空" dc:"消息内容"`
}
type WebSocketBroadcastRes = beans.ResponseEmpty
// WebSocketOnlineReq 获取在线用户请求
type WebSocketOnlineReq struct {
g.Meta `path:"/online" method:"get" tags:"WebSocket" summary:"获取在线用户" dc:"获取当前所有WebSocket在线用户"`
}
type WebSocketOnlineRes struct {
Count int `json:"count" dc:"在线用户数"`
Users []WebSocketOnlineUserRes `json:"users" dc:"在线用户列表"`
}
type WebSocketOnlineUserRes struct {
UserId string `json:"userId" dc:"用户ID"`
Platform string `json:"platform" dc:"平台"`
CreatedAt int64 `json:"createdAt" dc:"连接时间戳"`
}
// WebSocketPushMsg WebSocket 推送消息结构
type WebSocketPushMsg struct {
Type string `json:"type"` // 消息类型: ack, error, broadcast, answer
MessageId string `json:"message_id,omitempty"` // 消息IDack 时返回)
Message string `json:"message,omitempty"` // 提示消息
Content string `json:"content,omitempty"` // 内容broadcast/answer 时返回)
}

View File

@@ -0,0 +1,427 @@
package dto
// ==================== 通用响应结构 ====================
type XhsCommonRes struct {
Code int `json:"code"`
Msg string `json:"msg"`
Success bool `json:"success"`
}
// ==================== 绑定/解绑账户通知(接收) ====================
type XhsBindAccountReq struct {
Content string `json:"content" v:"required"` // 加密后内容
}
type XhsBindAccountDecrypted struct {
UserId string `json:"user_id"`
NickName string `json:"nick_name"`
AppId int64 `json:"app_id"`
Token string `json:"token"`
}
type XhsUnbindAccountReq struct {
Content string `json:"content" v:"required"` // 加密后内容
}
type XhsUnbindAccountDecrypted struct {
UserId string `json:"user_id"`
AppId int64 `json:"app_id"`
AccountCode string `json:"account_code"`
}
type XhsBindKosUserReq struct {
Content string `json:"content" v:"required"` // 加密后内容
}
// KOS账户绑定事件
type XhsBindKosUserDecrypted struct {
UserId string `json:"user_id"`
AuthStatus int `json:"auth_status"` // 2-已生效4-已取消
KosNickName string `json:"kos_nick_name"`
KosUserId string `json:"kos_user_id"`
KosAvatarImg string `json:"kos_avatar_img"`
}
// ==================== 查询KOS授权绑定列表发送 ====================
type XhsQueryBindUsersReq struct {
UserId string `json:"user_id" v:"required"`
PageNum int `json:"page_num" v:"required"`
PageSize int `json:"page_size" v:"required"`
}
type XhsQueryBindUsersRes struct {
Code int `json:"code"`
Msg string `json:"msg"`
Success bool `json:"success"`
Data struct {
Total int64 `json:"total"`
KosUserList []struct {
UserId string `json:"user_id"`
NickName string `json:"nick_name"`
AvatarImg string `json:"avatar_img"`
} `json:"kos_user_list"`
} `json:"data"`
}
// ==================== 发送消息接口(发送) ====================
type XhsSendMessageReq struct {
UserId string `json:"user_id" v:"required"`
RequestId string `json:"request_id" v:"required"`
MessageType string `json:"message_type" v:"required"` // TEXT/IMAGE/VIDEO/CARD/REVOKE
FromUserId string `json:"from_user_id" v:"required"`
ToUserId string `json:"to_user_id" v:"required"`
ThirdAccountId string `json:"third_account_id" v:"required"`
Timestamp int64 `json:"timestamp" v:"required"`
Content string `json:"content" v:"required"` // 加密后内容
}
type XhsSendMessageRes struct {
Code int `json:"code"`
Msg string `json:"msg"`
Success bool `json:"success"`
Data struct {
RequestId string `json:"request_id"`
MessageId string `json:"message_id"`
} `json:"data"`
}
// 消息内容解密后结构
type XhsTextContent struct {
Text string `json:"text"`
}
type XhsImageContent struct {
Link string `json:"link"`
Size struct {
Width int `json:"width"`
Height int `json:"height"`
} `json:"size"`
}
type XhsVideoContent struct {
Duration int64 `json:"duration"`
VideoSize int64 `json:"video_size"`
Cover string `json:"cover"`
Link string `json:"link"`
Size struct {
Width int `json:"width"`
Height int `json:"height"`
} `json:"size"`
}
// 通用卡片内容用于switch分支解析
type XhsCardContent struct {
Id string `json:"id"`
ContentType string `json:"content_type"`
}
type XhsCardNoteContent struct {
NoteId string `json:"note_id"`
ContentType string `json:"content_type"` // note
}
type XhsCardPageContent struct {
PageId string `json:"page_id"`
ContentType string `json:"content_type"` // common
}
type XhsCardCommentContent struct {
CommentId string `json:"comment_id"`
Content string `json:"content"`
ContentType string `json:"content_type"` // purchaseComments
}
type XhsCardSocialContent struct {
Id string `json:"id"`
ContentType string `json:"content_type"` // social_card
}
type XhsCardLeadContent struct {
Id string `json:"id"`
ContentType string `json:"content_type"` // lead_card
}
type XhsCardTradeContent struct {
Id string `json:"id"`
ContentType string `json:"content_type"` // tradeBusinessCard
}
type XhsRevokeContent struct {
MessageId string `json:"message_id"`
}
// ==================== 接收消息接口接收Webhook ====================
type XhsReceiveMessageReq struct {
MessageId string `json:"message_id" v:"required"`
MessageType string `json:"message_type" v:"required"` // TEXT/IMAGE/VIDEO/CARD/HINT/REVOKE/SMILES
MessageSource int `json:"message_source" v:"required"` // 1-C2B用户2-C2B系统3-B2C系统
FromUserId string `json:"from_user_id" v:"required"`
ToUserId string `json:"to_user_id" v:"required"`
Timestamp int64 `json:"timestamp" v:"required"`
Content string `json:"content" v:"required"` // 加密后内容
UserInfo []XhsReceiveMessageUser `json:"user_info"`
}
type XhsReceiveMessageUser struct {
UserId string `json:"user_id"`
Nickname string `json:"nickname"`
HeaderImage string `json:"header_image"`
}
// 接收消息-卡片内容(笔记)
type XhsReceiveCardNoteContent struct {
Title string `json:"title"`
Cover string `json:"cover"`
Link string `json:"link"`
ContentType string `json:"content_type"` // note
UserInfo struct {
Nickname string `json:"nickname"`
HeaderImage string `json:"header_image"`
} `json:"user_info"`
}
// 接收消息-卡片内容(落地页)
type XhsReceiveCardPageContent struct {
Title string `json:"title"`
Cover string `json:"cover"`
Link string `json:"link"`
Desc string `json:"desc"`
ContentType string `json:"content_type"` // common
}
// 接收消息-卡片内容(名片)
type XhsReceiveCardSocialContent struct {
Id string `json:"id"`
Title string `json:"title"`
Name string `json:"name"`
Image string `json:"image"`
ContentType string `json:"content_type"` // social_card
}
// 接收消息-卡片内容(留资卡)
type XhsReceiveCardLeadContent struct {
Id string `json:"id"`
Title string `json:"title"`
Name string `json:"name"`
Image string `json:"image"`
ContentType string `json:"content_type"` // lead_card
}
// 接收消息-卡片内容(交易卡)
type XhsReceiveCardTradeContent struct {
Id string `json:"id"`
Title string `json:"title"`
SubTitle string `json:"sub_title"`
Image string `json:"image"`
LinkPlatform string `json:"link_platform"` // wx_mini/ctrip/meituan
ContentType string `json:"content_type"` // tradeBusinessCard
}
// 接收消息-HINT内容
type XhsReceiveHintContent struct {
Text string `json:"text"`
}
// ==================== 查询物料接口(发送) ====================
// 查询落地页列表
type XhsQueryPageListReq struct {
UserId string `json:"user_id" v:"required"`
PageNum int `json:"page_num" v:"required"`
PageSize int `json:"page_size" v:"required"`
}
type XhsQueryPageListRes struct {
Code int `json:"code"`
Msg string `json:"msg"`
Success bool `json:"success"`
Data struct {
Total int64 `json:"total"`
List []struct {
Title string `json:"title"`
CreateTime int64 `json:"create_time"`
PageId string `json:"page_id"`
PageDesc string `json:"page_desc"`
PageUrl string `json:"page_url"`
Cover string `json:"cover"`
} `json:"list"`
} `json:"data"`
}
// 查询名片/留资卡/交易卡列表
type XhsQueryMaterialListReq struct {
UserId string `json:"user_id" v:"required"`
PageNum int `json:"page_num" v:"required"`
PageSize int `json:"page_size" v:"required"`
Type int `json:"type" v:"required"` // 4-名片 5-留资卡 7-交易卡
}
type XhsQueryMaterialListRes struct {
Code int `json:"code"`
Msg string `json:"msg"`
Success bool `json:"success"`
Data struct {
Total int64 `json:"total"`
List []struct {
Id string `json:"id"`
Name string `json:"name"`
Title string `json:"title"`
Image string `json:"image"`
Ext struct {
SocialCardExt *struct {
CardType int `json:"card_type"` // 1-微信、2-钉钉、3-电话、4-企微 5-留资卡
} `json:"social_card_ext,omitempty"`
TradeCardExt *struct {
SubTitle string `json:"sub_title"`
LinkPlatform string `json:"link_platform"` // ctrip/meituan/wx_mini
} `json:"trade_card_ext,omitempty"`
} `json:"ext"`
} `json:"list"`
} `json:"data"`
}
// 查询笔记列表
type XhsQueryNoteListReq struct {
UserId string `json:"user_id" v:"required"`
NoteId string `json:"note_id,omitempty"`
PageNum int `json:"page_num" v:"required"`
PageSize int `json:"page_size" v:"required"`
}
type XhsQueryNoteListRes struct {
Code int `json:"code"`
Msg string `json:"msg"`
Success bool `json:"success"`
Data struct {
Total int64 `json:"total"`
List []struct {
NoteId string `json:"note_id"`
PublishTime int64 `json:"publish_time"`
Link string `json:"link"`
Title string `json:"title"`
Cover string `json:"cover"`
UserInfo struct {
Nickname string `json:"nickname"`
HeaderImage string `json:"header_image"`
} `json:"user_info"`
} `json:"list"`
} `json:"data"`
}
// 查询意向评论列表
type XhsQueryCommentListReq struct {
UserId string `json:"user_id" v:"required"`
PageNum int `json:"page_num" v:"required"`
PageSize int `json:"page_size" v:"required"`
BeginTime string `json:"begin_time,omitempty"`
EndTime string `json:"end_time,omitempty"`
}
type XhsQueryCommentListRes struct {
Code int `json:"code"`
Msg string `json:"msg"`
Success bool `json:"success"`
Data struct {
Total int64 `json:"total"`
List []struct {
NoteId string `json:"note_id"`
Cover string `json:"cover"`
NoteTitle string `json:"note_title"`
NoteAuthorUserId string `json:"note_author_user_id"`
CommentContent string `json:"comment_content"`
CommentTime int64 `json:"comment_time"`
CommentUserName string `json:"comment_user_name"`
CommentUserId string `json:"comment_user_id"`
CommentId string `json:"comment_id"`
UniqId string `json:"uniq_id"`
ReplyState int `json:"reply_state"`
ReplyThirdAccountId string `json:"reply_third_account_id"`
} `json:"list"`
} `json:"data"`
}
// ==================== 意向评论推送接收Webhook ====================
type XhsIntentCommentPushReq struct {
NoteId string `json:"note_id"`
Cover string `json:"cover"`
NoteTitle string `json:"note_title"`
NoteAuthorUserId string `json:"note_author_user_id"`
CommentContent string `json:"comment_content"`
CommentTime int64 `json:"comment_time"`
CommentUserName string `json:"comment_user_name"`
CommentUserId string `json:"comment_user_id"`
CommentId string `json:"comment_id"`
UniqId string `json:"uniq_id"`
ReplyState int `json:"reply_state"`
ReplyThirdAccountId string `json:"reply_third_account_id"`
}
// ==================== 留资数据回传(发送) ====================
type XhsBackLeadResultReq struct {
UserId string `json:"user_id" v:"required"`
RequestId string `json:"request_id" v:"required"`
BrandUserId string `json:"brand_user_id" v:"required"`
CUserId string `json:"c_user_id" v:"required"`
ThirdBackSource string `json:"third_back_source" v:"required"`
Timestamp int64 `json:"timestamp" v:"required"`
Content string `json:"content" v:"required"` // 加密后内容
}
type XhsBackLeadResultDecrypted struct {
PhoneNum string `json:"phone_num"`
Wechat string `json:"wechat"`
Remark string `json:"remark"`
Area string `json:"area"`
City string `json:"city"`
CustomerServiceName string `json:"customer_service_name"`
Time int64 `json:"time"`
ExtList []struct {
Key string `json:"key"`
Name string `json:"name"`
Value string `json:"value"`
} `json:"extList"`
}
type XhsBackLeadResultRes struct {
Code int `json:"code"`
Msg string `json:"msg"`
Success bool `json:"success"`
Data struct {
RequestId string `json:"request_id"`
} `json:"data"`
}
// ==================== 留资和广告归因数据推送接收Webhook ====================
type XhsPushLeadReq struct {
UserId string `json:"user_id"`
BrandUserId string `json:"brand_user_id"`
KosUserId string `json:"kos_user_id"`
ConvTime string `json:"conv_time"`
AdvertiserName string `json:"advertiser_name"`
AdvertiserId string `json:"advertiser_id"`
CampaignName string `json:"campaign_name"`
CampaignId string `json:"campaign_id"`
CreativityName string `json:"creativity_name"`
CreativityId string `json:"creativity_id"`
LeadsTag string `json:"leads_tag"`
Area string `json:"area"`
PhoneNum string `json:"phone_num"`
Wechat string `json:"wechat"`
Remark string `json:"remark"`
PushType int `json:"push_type"` // 1-进线 2-开口 3-留资 4-留资归因
WechatCopy int `json:"wechat_copy"`
LinkId string `json:"link_id"`
LinkName string `json:"link_name"`
CustomerChannel string `json:"customer_channel"`
MsgAppOpen int `json:"msg_app_open"`
WechatType int `json:"wechat_type"` // 1-文本 2-图片链接
DecryptUserId string `json:"decrypt_user_id"`
}

View File

@@ -0,0 +1,27 @@
package entity
import (
"time"
"gitea.com/red-future/common/beans"
)
const ConversationCollection = "conversation"
// Conversation 对话记录实体
type Conversation struct {
beans.MongoBaseDO `bson:",inline"` // 嵌入基础字段
// 业务字段
UserId string `bson:"userId" json:"userId"` // 用户ID含平台前缀
Platform string `bson:"platform" json:"platform"` // 平台标识
SessionId string `bson:"sessionId" json:"sessionId"` // RAGFlow Session ID
CustomerServiceId string `bson:"customerServiceId" json:"customerServiceId"` // 客服账号ID
Role string `bson:"role" json:"role"` // 角色user/assistant
Content string `bson:"content" json:"content"` // 消息内容
Question string `bson:"question" json:"question"` // 用户问题(兼容旧字段)
Answer string `bson:"answer" json:"answer"` // AI 回复(兼容旧字段)
MessageId string `bson:"messageId" json:"messageId"` // 消息ID
MessageType string `bson:"messageType" json:"messageType"` // 消息类型TEXT/IMAGE/VIDEO等
MsgTime *time.Time `bson:"msgTime" json:"msgTime"` // 消息时间
}

View File

@@ -0,0 +1,71 @@
package entity
import (
"time"
"gitea.com/red-future/common/beans"
)
// ConversationArchiveTempCollection 归档临时表名
const ConversationArchiveTempCollection = "conversation_archive_temp"
// ConversationArchiveTemp 归档临时表实体(与 Conversation 结构相同)
type ConversationArchiveTemp struct {
beans.MongoBaseDO `bson:",inline"`
UserId string `bson:"userId" json:"userId"`
Platform string `bson:"platform" json:"platform"`
SessionId string `bson:"sessionId" json:"sessionId"`
Question string `bson:"question" json:"question"`
Answer string `bson:"answer" json:"answer"`
MessageId string `bson:"messageId" json:"messageId"`
MsgTime *time.Time `bson:"msgTime" json:"msgTime"` // 指针类型与MongoBaseDO一致
// 原始文档 ID用于删除原表数据
OriginalId string `bson:"originalId" json:"originalId"`
}
// ConversationES ES 索引文档结构
type ConversationES struct {
Id string `json:"id"` // MongoDB 原始 ID
UserId string `json:"userId"` // 用户ID
Platform string `json:"platform"` // 平台
SessionId string `json:"sessionId"` // Session ID
Question string `json:"question"` // 问题
Answer string `json:"answer"` // 回复
MessageId string `json:"messageId"` // 消息ID
MsgTime time.Time `json:"msgTime"` // 消息时间
TenantId string `json:"tenantId"` // 租户ID
CreatedAt time.Time `json:"createdAt"` // 创建时间
UpdatedAt time.Time `json:"updatedAt"` // 更新时间
ArchivedAt time.Time `json:"archivedAt"` // 归档时间
}
// ConversationESMapping ES 索引映射
const ConversationESMapping = `
{
"settings": {
"number_of_shards": 3,
"number_of_replicas": 1
},
"mappings": {
"properties": {
"id": { "type": "keyword" },
"userId": { "type": "keyword" },
"platform": { "type": "keyword" },
"sessionId": { "type": "keyword" },
"question": { "type": "text", "analyzer": "standard" },
"answer": { "type": "text", "analyzer": "standard" },
"messageId": { "type": "keyword" },
"msgTime": { "type": "date" },
"tenantId": { "type": "keyword" },
"createdAt": { "type": "date" },
"updatedAt": { "type": "date" },
"archivedAt": { "type": "date" }
}
}
}
`
// ConversationESIndex ES 索引名
const ConversationESIndex = "conversations"

View File

@@ -0,0 +1,33 @@
package entity
import (
"gitea.com/red-future/common/beans"
)
// CustomerServiceAccount 客服账号实体
const CustomerServiceAccountCollection = "customer_service_account"
type CustomerServiceAccount struct {
beans.MongoBaseDO `bson:",inline"` // 嵌入基础字段Id, Creator, CreatedAt, Updater, UpdatedAt, TenantId, IsDeleted
// 业务字段
AccountName string `bson:"accountName" json:"accountName"` // 客服账号名称如cs_xhs_qixue
IsDisabled bool `bson:"isDisabled" json:"isDisabled"` // 是否禁用true-禁用false-启用)
Greeting string `bson:"greeting" json:"greeting"` // 开场白WebSocket连接时自动发送
Prompt string `bson:"-" json:"prompt"` // 提示词不存储到MongoDB查询时从ragflow_config关联获取
SelfIdentity string `bson:"selfIdentity" json:"selfIdentity"` // AI身份描述前端显示为"AI身份"
// 绑定的资源(主体持有关系)
SpeechcraftIds []string `bson:"speechcraftIds" json:"speechcraftIds"` // 绑定的话术ID列表
ProductIds []string `bson:"productIds" json:"productIds"` // 绑定的产品ID列表
Platform string `bson:"platform" json:"platform"` // 客服平台xiaohongshu、douyin、kuaishou
// 小红书平台专属字段仅platform=xiaohongshu时有效
AccessToken string `bson:"accessToken,omitempty" json:"accessToken,omitempty"` // 小红书AccessToken14天有效期
AppId int64 `bson:"appId,omitempty" json:"appId,omitempty"` // 小红书应用ID
SecretKey string `bson:"secretKey,omitempty" json:"secretKey,omitempty"` // 小红书加解密密钥
XhsUserId string `bson:"xhsUserId,omitempty" json:"xhsUserId,omitempty"` // 小红书用户ID
ContactCardMessage string `bson:"contactCardMessage,omitempty" json:"contactCardMessage,omitempty"` // 留资卡文案(不同领域客服使用不同文案)
NameCardMessage string `bson:"nameCardMessage,omitempty" json:"nameCardMessage,omitempty"` // 名片文案(不同领域客服使用不同文案)
CardTriggerCount int `bson:"cardTriggerCount,omitempty" json:"cardTriggerCount,omitempty"` // 卡片触发次数默认5不同客服可定制
}

25
model/entity/data.go Normal file
View File

@@ -0,0 +1,25 @@
package entity
import (
"gitea.com/red-future/common/beans"
)
const DataCollection = "data"
type Data struct {
beans.MongoBaseDO `bson:",inline"` // 嵌入基础字段Id, Creator, CreatedAt, Updater, UpdatedAt, TenantId, IsDeleted
// 业务字段
CustomerId string `bson:"customerId" json:"customerId"` // 客户ID
AccountName string `bson:"accountName" json:"accountName"` // 客服账号名称
CustomerServicePlatform string `bson:"customerServicePlatform" json:"customerServicePlatform"` // 客服平台
CustomerServiceName string `bson:"customerServiceName" json:"customerServiceName"` // 客服名称
IsInbound bool `bson:"isInbound" json:"isInbound"` // 用户是否点开了客服页面
IsActive bool `bson:"isActive" json:"isActive"` // 用户是否开口询问
IsServed bool `bson:"isServed" json:"isServed"` // 客服是否回答了用户
HasSentContactCard bool `bson:"hasSentContactCard" json:"hasSentContactCard"` // 客服是否发送了联系卡
HasSentNameCard bool `bson:"hasSentNameCard" json:"hasSentNameCard"` // 客服是否发送了名称卡
HasLeftContactInfo bool `bson:"hasLeftContactInfo" json:"hasLeftContactInfo"` // 用户是否留下了联系信息
SessionStartTime int64 `bson:"sessionStartTime" json:"sessionStartTime"` // 业务数据的时间
MessageTime int64 `bson:"messageTime" json:"messageTime"` // 消息时间
}

View File

@@ -0,0 +1,30 @@
package entity
import (
"time"
"gitea.com/red-future/common/beans"
)
const DataStatisticsCollection = "data_statistics"
// DataStatistics 数据统计实体 (用于存储每天/每位客服的汇总数据)
type DataStatistics struct {
beans.MongoBaseDO `bson:",inline"` // 嵌入基础字段Id, Creator, CreatedAt, Updater, UpdatedAt, TenantId, IsDeleted
Date *time.Time `bson:"date" json:"date"` // 统计日期 (格式: YYYY-MM-DD)
AccountName string `bson:"accountName" json:"accountName"` // 客服账号名称
CustomerServiceName string `bson:"customerServiceName" json:"customerServiceName"` // 客服名称
CustomerServicePlatform string `bson:"customerServicePlatform" json:"customerServicePlatform"` // 客服平台
// 以下字段由 Data 表中的 bool 字段累加统计得出
InboundCount int `bson:"inboundCount" json:"inboundCount"` // 进线人数 (汇总 IsInbound)
ActiveCount int `bson:"activeCount" json:"activeCount"` // 开口人数 (汇总 IsActive)
ServedCount int `bson:"servedCount" json:"servedCount"` // 接待人数 (汇总 IsServed)
ContactCardSentCount int `bson:"contactCardSentCount" json:"contactCardSentCount"` // 留资卡发送数量 (汇总 HasSentContactCard)
NameCardSentCount int `bson:"nameCardSentCount" json:"nameCardSentCount"` // 名片发送数量 (汇总 HasSentNameCard)
LeftContactInfoCount int `bson:"leftContactInfoCount" json:"leftContactInfoCount"` // 留资人数 (汇总 HasLeftContactInfo)
ResponseRate30s float64 `bson:"responseRate30s" json:"responseRate30s"` // 30秒响应率
ResponseRate60s float64 `bson:"responseRate60s" json:"responseRate60s"` // 60秒响应率
ResponseRate360s float64 `bson:"responseRate360s" json:"responseRate360s"` // 360秒响应率
}

25
model/entity/product.go Normal file
View File

@@ -0,0 +1,25 @@
// Package entity - 产品实体
// 功能定义产品表结构支持多客服账号绑定、RAGFlow同步记录
package entity
import (
"gitea.com/red-future/common/beans"
)
// Product 产品实体
const ProductCollection = "product"
type Product struct {
beans.MongoBaseDO `bson:",inline"` // 嵌入基础字段Id, Creator, CreatedAt, Updater, UpdatedAt, TenantId, IsDeleted
// 业务字段
Name string `bson:"name" json:"name"` // 产品名称
Description string `bson:"description" json:"description"` // 产品详情
// 客服账号绑定(一个产品可以被多个账号使用)
AccountNames []string `bson:"accountNames" json:"accountNames"` // 绑定的客服账号名称列表
// RAGFlow同步字段租户级知识库每个客服账号独立同步记录
RagSyncRecords []RagSyncRecord `bson:"ragSyncRecords" json:"ragSyncRecords"` // RAGFlow同步记录按客服账号
RagLastSyncTime string `bson:"ragLastSyncTime" json:"ragLastSyncTime"` // 最后同步时间
}

View File

@@ -0,0 +1,13 @@
// Package entity - RAGFlow同步相关实体
// 功能RAGFlow同步记录话术和产品共用
package entity
// RagSyncRecord RAGFlow同步记录
// 说明租户级知识库每个客服账号独立的文档ID
type RagSyncRecord struct {
AccountName string `bson:"accountName" json:"accountName"` // 客服账号名称
RagDocumentId string `bson:"ragDocumentId" json:"ragDocumentId"` // RAGFlow文档ID租户级知识库中的文档
RagSyncStatus string `bson:"ragSyncStatus" json:"ragSyncStatus"` // 同步状态synced/pending/failed
SyncTime string `bson:"syncTime" json:"syncTime"` // 同步时间
RetryCount int `bson:"retryCount" json:"retryCount"` // 重试次数
}

View File

@@ -0,0 +1,46 @@
// Package entity - RAGFlow配置实体
// 功能客服账号级RAGFlow配置每个客服账号一个独立的对话实例
// 架构说明:
// - 租户级一个知识库dataset存储所有话术
// - 客服级每个客服有独立的Chat实例通过document_ids筛选使用哪些话术
package entity
import (
"time"
"gitea.com/red-future/common/beans"
)
const RAGFlowConfigCollection = "ragflow_config"
// RAGFlowConfig RAGFlow配置实体客服账号级别
type RAGFlowConfig struct {
beans.MongoBaseDO `bson:",inline"` // TenantId继承自基础DO
// 客服账号标识
AccountName string `bson:"accountName" json:"accountName"` // 客服账号名称
Platform string `bson:"platform" json:"platform"` // 平台xiaohongshu、douyin
// 租户级知识库(整个租户共享)
DatasetId string `bson:"datasetId" json:"datasetId"` // 话术知识库IDRAGFlow
DatasetIds []string `bson:"datasetIds" json:"datasetIds"` // Chat绑定的知识库ID列表与RAGFlow API保持一致
DatasetName string `bson:"datasetName" json:"datasetName"` // 话术知识库名称
// 客服账号级对话实例(每个客服独立)
ChatId string `bson:"chatId" json:"chatId"` // RAGFlow对话实例ID
Prompt string `bson:"prompt" json:"prompt"` // 提示词内容(完整)
// 文档筛选(该客服使用哪些话术文档)
DocumentIds []string `bson:"documentIds" json:"documentIds"` // 绑定的话术文档ID列表从租户知识库中筛选
// 检索参数
SimilarityThreshold float64 `bson:"similarityThreshold" json:"similarityThreshold"` // 相似度阈值默认0.2
KeywordsSimilarityWeight float64 `bson:"keywordsSimilarityWeight" json:"keywordsSimilarityWeight"` // 关键词权重默认0.7
TopN int `bson:"topN" json:"topN"` // 返回chunk数量默认8
EmptyResponse string `bson:"emptyResponse" json:"emptyResponse"` // 无匹配时回复
// 同步状态
SyncStatus string `bson:"syncStatus" json:"syncStatus"` // synced/pending/failed
LastSyncTime *time.Time `bson:"lastSyncTime" json:"lastSyncTime"` // 最后同步时间
SyncError string `bson:"syncError" json:"syncError"` // 同步错误信息
}

29
model/entity/session.go Normal file
View File

@@ -0,0 +1,29 @@
package entity
import (
"time"
"gitea.com/red-future/common/beans"
)
const SessionCollection = "session"
// SessionStatus 会话状态
const (
SessionStatusActive = "active" // 活跃中
SessionStatusArchived = "archived" // 已归档
)
// Session 会话实体
type Session struct {
beans.MongoBaseDO `bson:",inline"` // 嵌入基础字段
// 业务字段
UserId string `bson:"userId" json:"userId"` // 用户ID含平台前缀
Platform string `bson:"platform" json:"platform"` // 平台标识
SessionId string `bson:"sessionId" json:"sessionId"` // RAGFlow Session ID
Status string `bson:"status" json:"status"` // 状态active/archived
MessageCount int `bson:"messageCount" json:"messageCount"` // 消息数量
LastActiveAt *time.Time `bson:"lastActiveAt" json:"lastActiveAt"` // 最后活跃时间
ArchivedAt *time.Time `bson:"archivedAt" json:"archivedAt"` // 归档时间
}

View File

@@ -0,0 +1,32 @@
// Package entity - 话术实体
// 功能定义话术表结构支持多客服账号绑定、RAGFlow同步记录
package entity
import (
"gitea.com/red-future/common/beans"
)
// Speechcraft 话术实体
const SpeechcraftCollection = "speechcraft"
type Speechcraft struct {
beans.MongoBaseDO `bson:",inline"` // 嵌入基础字段Id, Creator, CreatedAt, Updater, UpdatedAt, TenantId, IsDeleted
// 原有字段
Tag string `bson:"tag" json:"tag"` // 标签(用于分类)
Content string `bson:"content" json:"content"` // 话术内容
// 状态机字段
Stage int `bson:"stage" json:"stage"` // 触发阶段0=初始)
Status string `bson:"status" json:"status"` // 触发行为click/keyword/空=任意)
Keywords []string `bson:"keywords" json:"keywords"` // 触发关键字(空=任意)
NextStage int `bson:"nextStage" json:"nextStage"` // 下一阶段(-1=结束)
Platform string `bson:"platform" json:"platform"` // 平台xiaohongshu
// 业务分类
Direction string `bson:"direction" json:"direction"` // 咨询方向(气血、减肥、护肤等)
// RAGFlow同步字段租户级知识库每个客服账号独立同步记录
RagSyncRecords []RagSyncRecord `bson:"ragSyncRecords" json:"ragSyncRecords"` // RAGFlow同步记录按客服账号
RagLastSyncTime string `bson:"ragLastSyncTime" json:"ragLastSyncTime"` // 最后同步时间
}

View File

@@ -0,0 +1,45 @@
package entity
import (
"time"
"gitea.com/red-future/common/beans"
)
// UserStage 用户阶段实体(记录用户在话术引导流程中的当前阶段)
const UserStageCollection = "user_stage"
type UserStage struct {
beans.MongoBaseDO `bson:",inline"` // 嵌入基础字段
// 业务字段
UserId string `bson:"userId" json:"userId"` // 用户ID含平台前缀
Platform string `bson:"platform" json:"platform"` // 平台标识
Stage int `bson:"stage" json:"stage"` // 当前阶段0=初始)
Status string `bson:"status" json:"status"` // 最近行为click/keyword 等)
LastMsgAt *time.Time `bson:"lastMsgAt" json:"lastMsgAt"` // 最后消息时间
AccountName string `bson:"accountName" json:"accountName"` // 用户选择的方向对应的客服账号名称
}
// 阶段常量
const (
StageInit = 0 // 初始
StageAutoComment = 1 // 自动跟评
StageClick = 2 // 点击
StageAutoReply = 3 // 点击自动回复
StageSendImage = 4 // 发图
StageOpenDoor = 5 // 开口询问
StageReply1 = 6 // 回复1
StageReply2 = 7 // 回复2
StageReply3 = 8 // 回复3
StageReply4 = 9 // 回复4
StageFollowUp = 10 // 追问
StageEnd = 99 // 结束
)
// 用户行为常量
const (
StatusIdle = "" // 空闲/任意
StatusClick = "click" // 点击
StatusKeyword = "keyword" // 发关键字
)