Init
This commit is contained in:
@@ -0,0 +1,156 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"cs-agent/internal/pkg/enums"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
Server ServerConfig `yaml:"server"`
|
||||
DB DBConfig `yaml:"db"`
|
||||
Logger LoggerConfig `yaml:"logger"`
|
||||
Auth AuthConfig `yaml:"auth"`
|
||||
Storage StorageConfig `yaml:"storage"`
|
||||
VectorDB VectorDBConfig `yaml:"vectorDB"`
|
||||
MCP MCPConfig `yaml:"mcp"`
|
||||
WxWork WxWorkConfig `yaml:"wxWork"`
|
||||
}
|
||||
|
||||
type ServerConfig struct {
|
||||
Port int `yaml:"port"`
|
||||
}
|
||||
|
||||
func (s ServerConfig) Address() string {
|
||||
if s.Port <= 0 {
|
||||
return ":8080"
|
||||
}
|
||||
return fmt.Sprintf(":%d", s.Port)
|
||||
}
|
||||
|
||||
type DBConfig struct {
|
||||
Type string `yaml:"type"`
|
||||
DSN string `yaml:"dsn"`
|
||||
MaxIdleConns int `yaml:"maxIdleConns"`
|
||||
MaxOpenConns int `yaml:"maxOpenConns"`
|
||||
ConnMaxIdleTimeSeconds int `yaml:"connMaxIdleTimeSeconds"`
|
||||
ConnMaxLifetimeSeconds int `yaml:"connMaxLifetimeSeconds"`
|
||||
}
|
||||
|
||||
type LoggerConfig struct {
|
||||
Level string `yaml:"level"`
|
||||
Format string `yaml:"format"`
|
||||
AddSource bool `yaml:"addSource"`
|
||||
}
|
||||
|
||||
type AuthConfig struct {
|
||||
AccessTokenTTLHours int `yaml:"accessTokenTTLHours"`
|
||||
RefreshTokenTTLDays int `yaml:"refreshTokenTTLDays"`
|
||||
MaxFailedAttempts int `yaml:"maxFailedAttempts"`
|
||||
CredentialLockMinute int `yaml:"credentialLockMinute"`
|
||||
}
|
||||
|
||||
type StorageConfig struct {
|
||||
Default enums.AssetProvider `yaml:"default"`
|
||||
MaxUploadSizeMB int64 `yaml:"maxUploadSizeMB"`
|
||||
Local LocalStorageConfig `yaml:"local"`
|
||||
OSS OSSStorageConfig `yaml:"oss"`
|
||||
}
|
||||
|
||||
func (s StorageConfig) MaxUploadSizeBytes() int64 {
|
||||
if s.MaxUploadSizeMB <= 0 {
|
||||
return 5 << 20
|
||||
}
|
||||
return s.MaxUploadSizeMB << 20
|
||||
}
|
||||
|
||||
func (s StorageConfig) MaxRequestBodySizeBytes() int64 {
|
||||
limit := s.MaxUploadSizeBytes()
|
||||
return limit + (1 << 20)
|
||||
}
|
||||
|
||||
type LocalStorageConfig struct {
|
||||
Root string `yaml:"root"`
|
||||
BaseURL string `yaml:"baseUrl"`
|
||||
}
|
||||
|
||||
type OSSStorageConfig struct {
|
||||
Endpoint string `yaml:"endpoint"`
|
||||
Bucket string `yaml:"bucket"`
|
||||
AccessKeyID string `yaml:"accessKeyId"`
|
||||
AccessKeySecret string `yaml:"accessKeySecret"`
|
||||
BaseURL string `yaml:"baseUrl"`
|
||||
Private bool `yaml:"private"`
|
||||
SignedURLExpire int `yaml:"signedUrlExpireSeconds"`
|
||||
}
|
||||
|
||||
type VectorDBConfig struct {
|
||||
Type string `yaml:"type"`
|
||||
Host string `yaml:"host"`
|
||||
Port int `yaml:"port"`
|
||||
APIKey string `yaml:"apiKey"`
|
||||
GrpcPort int `yaml:"grpcPort"`
|
||||
UseTLS bool `yaml:"useTls"`
|
||||
}
|
||||
|
||||
type MCPConfig struct {
|
||||
Enabled bool `yaml:"enabled"`
|
||||
Servers map[string]MCPServerConfig `yaml:"servers"`
|
||||
}
|
||||
|
||||
type MCPServerConfig struct {
|
||||
Enabled bool `yaml:"enabled"`
|
||||
Endpoint string `yaml:"endpoint"`
|
||||
TimeoutMS int `yaml:"timeoutMs"`
|
||||
Headers map[string]string `yaml:"headers"`
|
||||
}
|
||||
|
||||
// WxWorkConfig 定义企业微信接入配置。
|
||||
//
|
||||
// 当前主要用于后台管理台的企业微信登录流程:
|
||||
// 1. /api/auth/wxwork/login 生成企业微信授权地址
|
||||
// 2. 企业微信回调到 OAuthRedirect
|
||||
// 3. 后端通过 code 换取企业成员身份并完成系统登录
|
||||
//
|
||||
// 其中 OAuthRedirect、CorpID、CorpSecret、AgentID 为登录流程核心配置。
|
||||
type WxWorkConfig struct {
|
||||
// Enabled 表示是否启用企业微信登录能力。
|
||||
// false 时不会初始化企业微信 SDK,相关登录接口不可用。
|
||||
Enabled bool `yaml:"enabled"`
|
||||
// CorpID 为企业微信公司 ID,例如 wwxxxxxxxxxxxxxxxx。
|
||||
CorpID string `yaml:"corpId"`
|
||||
// CorpSecret 为企业微信应用 Secret,用于换取 access_token。
|
||||
CorpSecret string `yaml:"corpSecret"`
|
||||
// AgentID 为企业微信自建应用 AgentID。
|
||||
AgentID string `yaml:"agentId"`
|
||||
// OAuthRedirect 为企业微信网页授权回调地址。
|
||||
// 必须填写完整 URL,且通常指向后端接口 /api/auth/wxwork/callback。
|
||||
OAuthRedirect string `yaml:"oauthRedirect"`
|
||||
// StateSecret 为登录 state 的签名密钥,用于防止篡改和重放。
|
||||
// 建议填写独立随机字符串;留空时业务代码会退回使用 CorpSecret。
|
||||
StateSecret string `yaml:"stateSecret"`
|
||||
// RSAPrivateKey 为企业微信回调解密私钥。
|
||||
// 当前登录流程未使用,保留给消息回调等场景。
|
||||
RSAPrivateKey string `yaml:"rsaPrivateKey"`
|
||||
// Token 为企业微信回调 Token。
|
||||
// 当前登录流程未使用,保留给消息回调等场景。
|
||||
Token string `yaml:"token"`
|
||||
// EncodingAESKey 为企业微信消息加解密密钥。
|
||||
// 当前登录流程未使用,保留给消息回调等场景。
|
||||
EncodingAESKey string `yaml:"encodingAESKey"`
|
||||
}
|
||||
|
||||
func Load(path string) (*Config, error) {
|
||||
b, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cfg := &Config{}
|
||||
if err := yaml.Unmarshal(b, cfg); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return cfg, nil
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package config
|
||||
|
||||
var current *Config
|
||||
|
||||
func SetCurrent(cfg *Config) {
|
||||
current = cfg
|
||||
}
|
||||
|
||||
func Current() Config {
|
||||
if current == nil {
|
||||
panic("config not initialized")
|
||||
}
|
||||
return *current
|
||||
}
|
||||
@@ -0,0 +1,380 @@
|
||||
package constants
|
||||
|
||||
const (
|
||||
RoleCodeSuperAdmin = "super_admin" // 超管
|
||||
RoleCodeAdmin = "admin" // 管理员
|
||||
RoleCodeCsTeamLeader = "cs_team_leader" // 客服组长
|
||||
RoleCodeCsUser = "cs_user" // 客服
|
||||
)
|
||||
|
||||
const (
|
||||
AccessTokenPrefix = "atk_"
|
||||
RefreshTokenPrefix = "rtk_"
|
||||
)
|
||||
|
||||
const (
|
||||
TokenTypeAccess = "access"
|
||||
TokenTypeRefresh = "refresh"
|
||||
)
|
||||
|
||||
const (
|
||||
ClientTypeAdminWeb = "admin_web"
|
||||
)
|
||||
|
||||
const (
|
||||
BootstrapAdminUsername = "admin"
|
||||
BootstrapAdminPassword = "ChangeMe123!"
|
||||
BootstrapAdminNickname = "超级管理员"
|
||||
)
|
||||
|
||||
// Permission 权限结构体
|
||||
type Permission struct {
|
||||
Name string
|
||||
Code string
|
||||
Type string
|
||||
GroupName string
|
||||
Method string
|
||||
APIPath string
|
||||
SortNo int
|
||||
}
|
||||
|
||||
// 权限常量定义
|
||||
var (
|
||||
// 用户相关权限
|
||||
PermissionUserView = Permission{Name: "查看用户", Code: "user.view", Type: "api", GroupName: "user", Method: "ANY", APIPath: "/api/console/user/list", SortNo: 10}
|
||||
PermissionUserCreate = Permission{Name: "创建用户", Code: "user.create", Type: "api", GroupName: "user", Method: "POST", APIPath: "/api/console/user/create", SortNo: 20}
|
||||
PermissionUserUpdate = Permission{Name: "更新用户", Code: "user.update", Type: "api", GroupName: "user", Method: "POST", APIPath: "/api/console/user/update", SortNo: 30}
|
||||
PermissionUserDelete = Permission{Name: "删除用户", Code: "user.delete", Type: "api", GroupName: "user", Method: "POST", APIPath: "/api/console/user/delete", SortNo: 40}
|
||||
PermissionUserAssignRole = Permission{Name: "分配用户角色", Code: "user.assignRole", Type: "api", GroupName: "user", Method: "POST", APIPath: "/api/console/user/assign_role", SortNo: 50}
|
||||
|
||||
// 角色相关权限
|
||||
PermissionRoleView = Permission{Name: "查看角色", Code: "role.view", Type: "api", GroupName: "role", Method: "ANY", APIPath: "/api/console/role/list", SortNo: 110}
|
||||
PermissionRoleCreate = Permission{Name: "创建角色", Code: "role.create", Type: "api", GroupName: "role", Method: "POST", APIPath: "/api/console/role/create", SortNo: 120}
|
||||
PermissionRoleUpdate = Permission{Name: "更新角色", Code: "role.update", Type: "api", GroupName: "role", Method: "POST", APIPath: "/api/console/role/update", SortNo: 130}
|
||||
PermissionRoleDelete = Permission{Name: "删除角色", Code: "role.delete", Type: "api", GroupName: "role", Method: "POST", APIPath: "/api/console/role/delete", SortNo: 140}
|
||||
PermissionRoleAssignPermission = Permission{Name: "分配角色权限", Code: "role.assignPermission", Type: "api", GroupName: "role", Method: "POST", APIPath: "/api/console/role/assign_permission", SortNo: 150}
|
||||
|
||||
// 权限相关权限
|
||||
PermissionPermissionView = Permission{Name: "查看权限", Code: "permission.view", Type: "api", GroupName: "permission", Method: "ANY", APIPath: "/api/console/permission/list", SortNo: 210}
|
||||
PermissionPermissionSync = Permission{Name: "同步权限", Code: "permission.sync", Type: "api", GroupName: "permission", Method: "POST", APIPath: "/api/console/permission/sync", SortNo: 220}
|
||||
|
||||
// 会话相关权限
|
||||
PermissionSessionView = Permission{Name: "查看会话", Code: "session.view", Type: "api", GroupName: "session", Method: "ANY", APIPath: "/api/console/session/list", SortNo: 310}
|
||||
PermissionSessionRevoke = Permission{Name: "踢除会话", Code: "session.revoke", Type: "api", GroupName: "session", Method: "POST", APIPath: "/api/console/session/revoke", SortNo: 320}
|
||||
|
||||
// 客服会话相关权限
|
||||
PermissionConversationView = Permission{Name: "查看会话", Code: "conversation.view", Type: "api", GroupName: "conversation", Method: "ANY", APIPath: "/api/console/conversation/list", SortNo: 410}
|
||||
PermissionConversationAssign = Permission{Name: "分配会话", Code: "conversation.assign", Type: "api", GroupName: "conversation", Method: "POST", APIPath: "/api/console/conversation/assign", SortNo: 430}
|
||||
PermissionConversationTransfer = Permission{Name: "转接会话", Code: "conversation.transfer", Type: "api", GroupName: "conversation", Method: "POST", APIPath: "/api/console/conversation/transfer", SortNo: 440}
|
||||
PermissionConversationClose = Permission{Name: "关闭会话", Code: "conversation.close", Type: "api", GroupName: "conversation", Method: "POST", APIPath: "/api/console/conversation/close", SortNo: 450}
|
||||
PermissionConversationSend = Permission{Name: "发送会话消息", Code: "conversation.send", Type: "api", GroupName: "conversation", Method: "POST", APIPath: "/api/console/conversation/send_message", SortNo: 460}
|
||||
PermissionConversationTag = Permission{Name: "管理会话标签", Code: "conversation.tag", Type: "api", GroupName: "conversation", Method: "POST", APIPath: "/api/console/conversation/add_tag", SortNo: 470}
|
||||
PermissionConversationHandover = Permission{Name: "处理会话交接", Code: "conversation.handover", Type: "api", GroupName: "conversation", Method: "ANY", APIPath: "/api/console/conversation/handover_list", SortNo: 480}
|
||||
PermissionConversationRecycle = Permission{Name: "回收会话", Code: "conversation.recycle", Type: "api", GroupName: "conversation", Method: "POST", APIPath: "/api/console/conversation/recycle", SortNo: 490}
|
||||
PermissionConversationLinkCustomer = Permission{Name: "关联会话客户", Code: "conversation.linkCustomer", Type: "api", GroupName: "conversation", Method: "POST", APIPath: "/api/console/conversation/link_customer", SortNo: 495}
|
||||
|
||||
// 工单相关权限
|
||||
PermissionTicketView = Permission{Name: "查看工单", Code: "ticket.view", Type: "api", GroupName: "ticket", Method: "ANY", APIPath: "/api/console/ticket/list", SortNo: 500}
|
||||
PermissionTicketCreate = Permission{Name: "创建工单", Code: "ticket.create", Type: "api", GroupName: "ticket", Method: "POST", APIPath: "/api/console/ticket/create", SortNo: 510}
|
||||
PermissionTicketUpdate = Permission{Name: "更新工单", Code: "ticket.update", Type: "api", GroupName: "ticket", Method: "POST", APIPath: "/api/console/ticket/update", SortNo: 520}
|
||||
PermissionTicketAssign = Permission{Name: "指派工单", Code: "ticket.assign", Type: "api", GroupName: "ticket", Method: "POST", APIPath: "/api/console/ticket/assign", SortNo: 530}
|
||||
PermissionTicketChangeStatus = Permission{Name: "变更工单状态", Code: "ticket.changeStatus", Type: "api", GroupName: "ticket", Method: "POST", APIPath: "/api/console/ticket/change_status", SortNo: 540}
|
||||
PermissionTicketReply = Permission{Name: "回复工单", Code: "ticket.reply", Type: "api", GroupName: "ticket", Method: "POST", APIPath: "/api/console/ticket/reply", SortNo: 550}
|
||||
PermissionTicketClose = Permission{Name: "关闭工单", Code: "ticket.close", Type: "api", GroupName: "ticket", Method: "POST", APIPath: "/api/console/ticket/close", SortNo: 560}
|
||||
PermissionTicketReopen = Permission{Name: "重开工单", Code: "ticket.reopen", Type: "api", GroupName: "ticket", Method: "POST", APIPath: "/api/console/ticket/reopen", SortNo: 570}
|
||||
PermissionTicketResolutionCodeView = Permission{Name: "查看工单解决码", Code: "ticketResolutionCode.view", Type: "api", GroupName: "ticketResolutionCode", Method: "ANY", APIPath: "/api/console/ticket-resolution-code/list", SortNo: 580}
|
||||
PermissionTicketResolutionCodeCreate = Permission{Name: "创建工单解决码", Code: "ticketResolutionCode.create", Type: "api", GroupName: "ticketResolutionCode", Method: "POST", APIPath: "/api/console/ticket-resolution-code/create", SortNo: 590}
|
||||
PermissionTicketResolutionCodeUpdate = Permission{Name: "更新工单解决码", Code: "ticketResolutionCode.update", Type: "api", GroupName: "ticketResolutionCode", Method: "POST", APIPath: "/api/console/ticket-resolution-code/update", SortNo: 600}
|
||||
PermissionTicketResolutionCodeDelete = Permission{Name: "删除工单解决码", Code: "ticketResolutionCode.delete", Type: "api", GroupName: "ticketResolutionCode", Method: "POST", APIPath: "/api/console/ticket-resolution-code/delete", SortNo: 610}
|
||||
PermissionTicketPriorityConfigView = Permission{Name: "查看工单优先级", Code: "ticketPriorityConfig.view", Type: "api", GroupName: "ticketPriorityConfig", Method: "ANY", APIPath: "/api/console/ticket-priority-config/list", SortNo: 620}
|
||||
PermissionTicketPriorityConfigCreate = Permission{Name: "创建工单优先级", Code: "ticketPriorityConfig.create", Type: "api", GroupName: "ticketPriorityConfig", Method: "POST", APIPath: "/api/console/ticket-priority-config/create", SortNo: 630}
|
||||
PermissionTicketPriorityConfigUpdate = Permission{Name: "更新工单优先级", Code: "ticketPriorityConfig.update", Type: "api", GroupName: "ticketPriorityConfig", Method: "POST", APIPath: "/api/console/ticket-priority-config/update", SortNo: 640}
|
||||
PermissionTicketPriorityConfigDelete = Permission{Name: "删除工单优先级", Code: "ticketPriorityConfig.delete", Type: "api", GroupName: "ticketPriorityConfig", Method: "POST", APIPath: "/api/console/ticket-priority-config/delete", SortNo: 650}
|
||||
|
||||
// 快捷回复相关权限
|
||||
PermissionQuickReplyView = Permission{Name: "查看快捷回复", Code: "quickReply.view", Type: "api", GroupName: "quickReply", Method: "ANY", APIPath: "/api/console/quick-reply/list", SortNo: 610}
|
||||
PermissionQuickReplyCreate = Permission{Name: "创建快捷回复", Code: "quickReply.create", Type: "api", GroupName: "quickReply", Method: "POST", APIPath: "/api/console/quick-reply/create", SortNo: 620}
|
||||
PermissionQuickReplyUpdate = Permission{Name: "更新快捷回复", Code: "quickReply.update", Type: "api", GroupName: "quickReply", Method: "POST", APIPath: "/api/console/quick-reply/update", SortNo: 630}
|
||||
PermissionQuickReplyDelete = Permission{Name: "删除快捷回复", Code: "quickReply.delete", Type: "api", GroupName: "quickReply", Method: "POST", APIPath: "/api/console/quick-reply/delete", SortNo: 640}
|
||||
|
||||
// 标签相关权限
|
||||
PermissionTagView = Permission{Name: "查看标签", Code: "tag.view", Type: "api", GroupName: "tag", Method: "ANY", APIPath: "/api/console/tag/list", SortNo: 550}
|
||||
PermissionTagCreate = Permission{Name: "创建标签", Code: "tag.create", Type: "api", GroupName: "tag", Method: "POST", APIPath: "/api/console/tag/create", SortNo: 560}
|
||||
PermissionTagUpdate = Permission{Name: "更新标签", Code: "tag.update", Type: "api", GroupName: "tag", Method: "POST", APIPath: "/api/console/tag/update", SortNo: 570}
|
||||
PermissionTagDelete = Permission{Name: "删除标签", Code: "tag.delete", Type: "api", GroupName: "tag", Method: "POST", APIPath: "/api/console/tag/delete", SortNo: 580}
|
||||
|
||||
// 公司相关权限
|
||||
PermissionCompanyView = Permission{Name: "查看公司", Code: "company.view", Type: "api", GroupName: "company", Method: "ANY", APIPath: "/api/console/company/list", SortNo: 590}
|
||||
PermissionCompanyCreate = Permission{Name: "创建公司", Code: "company.create", Type: "api", GroupName: "company", Method: "POST", APIPath: "/api/console/company/create", SortNo: 600}
|
||||
PermissionCompanyUpdate = Permission{Name: "更新公司", Code: "company.update", Type: "api", GroupName: "company", Method: "POST", APIPath: "/api/console/company/update", SortNo: 610}
|
||||
PermissionCompanyDelete = Permission{Name: "删除公司", Code: "company.delete", Type: "api", GroupName: "company", Method: "POST", APIPath: "/api/console/company/delete", SortNo: 620}
|
||||
|
||||
// 接入渠道相关权限
|
||||
PermissionChannelView = Permission{Name: "查看接入渠道", Code: "channel.view", Type: "api", GroupName: "channel", Method: "ANY", APIPath: "/api/console/channel/list", SortNo: 625}
|
||||
PermissionChannelCreate = Permission{Name: "创建接入渠道", Code: "channel.create", Type: "api", GroupName: "channel", Method: "POST", APIPath: "/api/console/channel/create", SortNo: 626}
|
||||
PermissionChannelUpdate = Permission{Name: "更新接入渠道", Code: "channel.update", Type: "api", GroupName: "channel", Method: "POST", APIPath: "/api/console/channel/update", SortNo: 627}
|
||||
PermissionChannelDelete = Permission{Name: "删除接入渠道", Code: "channel.delete", Type: "api", GroupName: "channel", Method: "POST", APIPath: "/api/console/channel/delete", SortNo: 628}
|
||||
|
||||
// 客户相关权限
|
||||
PermissionCustomerView = Permission{Name: "查看客户", Code: "customer.view", Type: "api", GroupName: "customer", Method: "POST", APIPath: "/api/console/customer/list", SortNo: 630}
|
||||
PermissionCustomerCreate = Permission{Name: "创建客户", Code: "customer.create", Type: "api", GroupName: "customer", Method: "POST", APIPath: "/api/console/customer/create", SortNo: 640}
|
||||
PermissionCustomerUpdate = Permission{Name: "更新客户", Code: "customer.update", Type: "api", GroupName: "customer", Method: "POST", APIPath: "/api/console/customer/update", SortNo: 650}
|
||||
PermissionCustomerDelete = Permission{Name: "删除客户", Code: "customer.delete", Type: "api", GroupName: "customer", Method: "POST", APIPath: "/api/console/customer/delete", SortNo: 660}
|
||||
|
||||
// 客服相关权限
|
||||
PermissionAgentView = Permission{Name: "查看客服", Code: "agent.view", Type: "api", GroupName: "agent", Method: "ANY", APIPath: "/api/console/agent/list", SortNo: 610}
|
||||
PermissionAgentCreate = Permission{Name: "创建客服", Code: "agent.create", Type: "api", GroupName: "agent", Method: "POST", APIPath: "/api/console/agent/create", SortNo: 620}
|
||||
PermissionAgentUpdate = Permission{Name: "更新客服", Code: "agent.update", Type: "api", GroupName: "agent", Method: "POST", APIPath: "/api/console/agent/update", SortNo: 630}
|
||||
PermissionAgentDelete = Permission{Name: "删除客服", Code: "agent.delete", Type: "api", GroupName: "agent", Method: "POST", APIPath: "/api/console/agent/delete", SortNo: 640}
|
||||
PermissionAgentUpdateStatus = Permission{Name: "更新客服状态", Code: "agent.updateStatus", Type: "api", GroupName: "agent", Method: "POST", APIPath: "/api/console/agent/update_status", SortNo: 650}
|
||||
PermissionAgentConfig = Permission{Name: "配置客服服务规则", Code: "agent.config", Type: "api", GroupName: "agent", Method: "POST", APIPath: "/api/console/agent/update_service_config", SortNo: 660}
|
||||
|
||||
// 客服组相关权限
|
||||
PermissionAgentTeamView = Permission{Name: "查看客服组", Code: "agentTeam.view", Type: "api", GroupName: "agentTeam", Method: "ANY", APIPath: "/api/console/agent-team/list", SortNo: 710}
|
||||
PermissionAgentTeamCreate = Permission{Name: "创建客服组", Code: "agentTeam.create", Type: "api", GroupName: "agentTeam", Method: "POST", APIPath: "/api/console/agent-team/create", SortNo: 720}
|
||||
PermissionAgentTeamUpdate = Permission{Name: "更新客服组", Code: "agentTeam.update", Type: "api", GroupName: "agentTeam", Method: "POST", APIPath: "/api/console/agent-team/update", SortNo: 730}
|
||||
PermissionAgentTeamDelete = Permission{Name: "删除客服组", Code: "agentTeam.delete", Type: "api", GroupName: "agentTeam", Method: "POST", APIPath: "/api/console/agent-team/delete", SortNo: 740}
|
||||
|
||||
// 客服组排班相关权限
|
||||
PermissionAgentTeamScheduleView = Permission{Name: "查看客服组排班", Code: "agentTeamSchedule.view", Type: "api", GroupName: "agentTeamSchedule", Method: "ANY", APIPath: "/api/console/agent-team-schedule/list", SortNo: 810}
|
||||
PermissionAgentTeamScheduleCreate = Permission{Name: "创建客服组排班", Code: "agentTeamSchedule.create", Type: "api", GroupName: "agentTeamSchedule", Method: "POST", APIPath: "/api/console/agent-team-schedule/create", SortNo: 820}
|
||||
PermissionAgentTeamScheduleUpdate = Permission{Name: "更新客服组排班", Code: "agentTeamSchedule.update", Type: "api", GroupName: "agentTeamSchedule", Method: "POST", APIPath: "/api/console/agent-team-schedule/update", SortNo: 830}
|
||||
PermissionAgentTeamScheduleDelete = Permission{Name: "删除客服组排班", Code: "agentTeamSchedule.delete", Type: "api", GroupName: "agentTeamSchedule", Method: "POST", APIPath: "/api/console/agent-team-schedule/delete", SortNo: 840}
|
||||
PermissionAgentTeamScheduleBatchGenerate = Permission{Name: "批量生成客服组排班", Code: "agentTeamSchedule.batchGenerate", Type: "api", GroupName: "agentTeamSchedule", Method: "POST", APIPath: "/api/console/agent-team-schedule/batch_generate", SortNo: 850}
|
||||
|
||||
// 文件资源相关权限
|
||||
PermissionAssetView = Permission{Name: "查看文件资源", Code: "asset.view", Type: "api", GroupName: "asset", Method: "ANY", APIPath: "/api/console/asset/list", SortNo: 1210}
|
||||
PermissionAssetCreate = Permission{Name: "上传文件资源", Code: "asset.create", Type: "api", GroupName: "asset", Method: "POST", APIPath: "/api/console/asset/create", SortNo: 1220}
|
||||
PermissionAssetDelete = Permission{Name: "删除文件资源", Code: "asset.delete", Type: "api", GroupName: "asset", Method: "POST", APIPath: "/api/console/asset/delete", SortNo: 1230}
|
||||
|
||||
// AI 配置相关权限
|
||||
PermissionAIConfigView = Permission{Name: "查看 AI 配置", Code: "aiConfig.view", Type: "api", GroupName: "aiConfig", Method: "ANY", APIPath: "/api/console/ai-config/list", SortNo: 1390}
|
||||
PermissionAIConfigCreate = Permission{Name: "创建 AI 配置", Code: "aiConfig.create", Type: "api", GroupName: "aiConfig", Method: "POST", APIPath: "/api/console/ai-config/create", SortNo: 1400}
|
||||
PermissionAIConfigUpdate = Permission{Name: "更新 AI 配置", Code: "aiConfig.update", Type: "api", GroupName: "aiConfig", Method: "POST", APIPath: "/api/console/ai-config/update", SortNo: 1410}
|
||||
PermissionAIConfigDelete = Permission{Name: "删除 AI 配置", Code: "aiConfig.delete", Type: "api", GroupName: "aiConfig", Method: "POST", APIPath: "/api/console/ai-config/delete", SortNo: 1420}
|
||||
|
||||
// 知识库相关权限
|
||||
PermissionKnowledgeBaseView = Permission{Name: "查看知识库", Code: "knowledgeBase.view", Type: "api", GroupName: "knowledgeBase", Method: "ANY", APIPath: "/api/console/knowledge-base/list", SortNo: 1410}
|
||||
PermissionKnowledgeBaseCreate = Permission{Name: "创建知识库", Code: "knowledgeBase.create", Type: "api", GroupName: "knowledgeBase", Method: "POST", APIPath: "/api/console/knowledge-base/create", SortNo: 1420}
|
||||
PermissionKnowledgeBaseUpdate = Permission{Name: "更新知识库", Code: "knowledgeBase.update", Type: "api", GroupName: "knowledgeBase", Method: "POST", APIPath: "/api/console/knowledge-base/update", SortNo: 1430}
|
||||
PermissionKnowledgeBaseDelete = Permission{Name: "删除知识库", Code: "knowledgeBase.delete", Type: "api", GroupName: "knowledgeBase", Method: "POST", APIPath: "/api/console/knowledge-base/delete", SortNo: 1440}
|
||||
|
||||
// 知识文档相关权限
|
||||
PermissionKnowledgeDocumentView = Permission{Name: "查看知识文档", Code: "knowledgeDocument.view", Type: "api", GroupName: "knowledgeDocument", Method: "ANY", APIPath: "/api/console/knowledge-document/list", SortNo: 1510}
|
||||
PermissionKnowledgeDocumentCreate = Permission{Name: "创建知识文档", Code: "knowledgeDocument.create", Type: "api", GroupName: "knowledgeDocument", Method: "POST", APIPath: "/api/console/knowledge-document/create", SortNo: 1520}
|
||||
PermissionKnowledgeDocumentUpdate = Permission{Name: "更新知识文档", Code: "knowledgeDocument.update", Type: "api", GroupName: "knowledgeDocument", Method: "POST", APIPath: "/api/console/knowledge-document/update", SortNo: 1530}
|
||||
PermissionKnowledgeDocumentDelete = Permission{Name: "删除知识文档", Code: "knowledgeDocument.delete", Type: "api", GroupName: "knowledgeDocument", Method: "POST", APIPath: "/api/console/knowledge-document/delete", SortNo: 1540}
|
||||
PermissionKnowledgeFAQView = Permission{Name: "查看知识FAQ", Code: "knowledgeFAQ.view", Type: "api", GroupName: "knowledgeFAQ", Method: "ANY", APIPath: "/api/console/knowledge-faq/list", SortNo: 1550}
|
||||
PermissionKnowledgeFAQCreate = Permission{Name: "创建知识FAQ", Code: "knowledgeFAQ.create", Type: "api", GroupName: "knowledgeFAQ", Method: "POST", APIPath: "/api/console/knowledge-faq/create", SortNo: 1560}
|
||||
PermissionKnowledgeFAQUpdate = Permission{Name: "更新知识FAQ", Code: "knowledgeFAQ.update", Type: "api", GroupName: "knowledgeFAQ", Method: "POST", APIPath: "/api/console/knowledge-faq/update", SortNo: 1570}
|
||||
PermissionKnowledgeFAQDelete = Permission{Name: "删除知识FAQ", Code: "knowledgeFAQ.delete", Type: "api", GroupName: "knowledgeFAQ", Method: "POST", APIPath: "/api/console/knowledge-faq/delete", SortNo: 1580}
|
||||
|
||||
// Skill 定义相关权限
|
||||
PermissionSkillDefinitionView = Permission{Name: "查看技能定义", Code: "skillDefinition.view", Type: "api", GroupName: "skillDefinition", Method: "ANY", APIPath: "/api/console/skill-definition/list", SortNo: 1610}
|
||||
PermissionSkillDefinitionCreate = Permission{Name: "创建技能定义", Code: "skillDefinition.create", Type: "api", GroupName: "skillDefinition", Method: "POST", APIPath: "/api/console/skill-definition/create", SortNo: 1620}
|
||||
PermissionSkillDefinitionUpdate = Permission{Name: "更新技能定义", Code: "skillDefinition.update", Type: "api", GroupName: "skillDefinition", Method: "POST", APIPath: "/api/console/skill-definition/update", SortNo: 1630}
|
||||
PermissionSkillDefinitionDelete = Permission{Name: "删除技能定义", Code: "skillDefinition.delete", Type: "api", GroupName: "skillDefinition", Method: "POST", APIPath: "/api/console/skill-definition/delete", SortNo: 1640}
|
||||
|
||||
// MCP 调试相关权限
|
||||
PermissionMCPView = Permission{Name: "查看MCP调试信息", Code: "mcp.view", Type: "api", GroupName: "mcp", Method: "POST", APIPath: "/api/console/mcp/list_tools", SortNo: 1710}
|
||||
PermissionMCPCall = Permission{Name: "调用MCP工具", Code: "mcp.call", Type: "api", GroupName: "mcp", Method: "POST", APIPath: "/api/console/mcp/call_tool", SortNo: 1720}
|
||||
)
|
||||
|
||||
// Permissions 内置权限列表
|
||||
var Permissions = []Permission{
|
||||
PermissionUserView,
|
||||
PermissionUserCreate,
|
||||
PermissionUserUpdate,
|
||||
PermissionUserDelete,
|
||||
PermissionUserAssignRole,
|
||||
PermissionRoleView,
|
||||
PermissionRoleCreate,
|
||||
PermissionRoleUpdate,
|
||||
PermissionRoleDelete,
|
||||
PermissionRoleAssignPermission,
|
||||
PermissionPermissionView,
|
||||
PermissionPermissionSync,
|
||||
PermissionSessionView,
|
||||
PermissionSessionRevoke,
|
||||
PermissionConversationView,
|
||||
PermissionConversationAssign,
|
||||
PermissionConversationTransfer,
|
||||
PermissionConversationClose,
|
||||
PermissionConversationSend,
|
||||
PermissionConversationTag,
|
||||
PermissionConversationHandover,
|
||||
PermissionConversationRecycle,
|
||||
PermissionConversationLinkCustomer,
|
||||
PermissionTicketView,
|
||||
PermissionTicketCreate,
|
||||
PermissionTicketUpdate,
|
||||
PermissionTicketAssign,
|
||||
PermissionTicketChangeStatus,
|
||||
PermissionTicketReply,
|
||||
PermissionTicketClose,
|
||||
PermissionTicketReopen,
|
||||
PermissionTicketResolutionCodeView,
|
||||
PermissionTicketResolutionCodeCreate,
|
||||
PermissionTicketResolutionCodeUpdate,
|
||||
PermissionTicketResolutionCodeDelete,
|
||||
PermissionTicketPriorityConfigView,
|
||||
PermissionTicketPriorityConfigCreate,
|
||||
PermissionTicketPriorityConfigUpdate,
|
||||
PermissionTicketPriorityConfigDelete,
|
||||
PermissionQuickReplyView,
|
||||
PermissionQuickReplyCreate,
|
||||
PermissionQuickReplyUpdate,
|
||||
PermissionQuickReplyDelete,
|
||||
PermissionTagView,
|
||||
PermissionTagCreate,
|
||||
PermissionTagUpdate,
|
||||
PermissionTagDelete,
|
||||
PermissionCompanyView,
|
||||
PermissionCompanyCreate,
|
||||
PermissionCompanyUpdate,
|
||||
PermissionCompanyDelete,
|
||||
PermissionChannelView,
|
||||
PermissionChannelCreate,
|
||||
PermissionChannelUpdate,
|
||||
PermissionChannelDelete,
|
||||
PermissionCustomerView,
|
||||
PermissionCustomerCreate,
|
||||
PermissionCustomerUpdate,
|
||||
PermissionCustomerDelete,
|
||||
PermissionAgentView,
|
||||
PermissionAgentCreate,
|
||||
PermissionAgentUpdate,
|
||||
PermissionAgentDelete,
|
||||
PermissionAgentUpdateStatus,
|
||||
PermissionAgentConfig,
|
||||
PermissionAgentTeamView,
|
||||
PermissionAgentTeamCreate,
|
||||
PermissionAgentTeamUpdate,
|
||||
PermissionAgentTeamDelete,
|
||||
PermissionAgentTeamScheduleView,
|
||||
PermissionAgentTeamScheduleCreate,
|
||||
PermissionAgentTeamScheduleUpdate,
|
||||
PermissionAgentTeamScheduleDelete,
|
||||
PermissionAgentTeamScheduleBatchGenerate,
|
||||
PermissionAssetView,
|
||||
PermissionAssetCreate,
|
||||
PermissionAssetDelete,
|
||||
PermissionAIConfigView,
|
||||
PermissionAIConfigCreate,
|
||||
PermissionAIConfigUpdate,
|
||||
PermissionAIConfigDelete,
|
||||
PermissionKnowledgeBaseView,
|
||||
PermissionKnowledgeBaseCreate,
|
||||
PermissionKnowledgeBaseUpdate,
|
||||
PermissionKnowledgeBaseDelete,
|
||||
PermissionKnowledgeDocumentView,
|
||||
PermissionKnowledgeDocumentCreate,
|
||||
PermissionKnowledgeDocumentUpdate,
|
||||
PermissionKnowledgeDocumentDelete,
|
||||
PermissionKnowledgeFAQView,
|
||||
PermissionKnowledgeFAQCreate,
|
||||
PermissionKnowledgeFAQUpdate,
|
||||
PermissionKnowledgeFAQDelete,
|
||||
PermissionSkillDefinitionView,
|
||||
PermissionSkillDefinitionCreate,
|
||||
PermissionSkillDefinitionUpdate,
|
||||
PermissionSkillDefinitionDelete,
|
||||
PermissionMCPView,
|
||||
PermissionMCPCall,
|
||||
}
|
||||
|
||||
// PermissionMap 权限映射,用于通过 Code 查找 Permission
|
||||
var PermissionMap = make(map[string]Permission)
|
||||
|
||||
// init 初始化 PermissionMap
|
||||
func init() {
|
||||
for _, permission := range Permissions {
|
||||
PermissionMap[permission.Code] = permission
|
||||
}
|
||||
}
|
||||
|
||||
type RoleSpec struct {
|
||||
Name string
|
||||
Code string
|
||||
SortNo int
|
||||
}
|
||||
|
||||
var Roles = []RoleSpec{
|
||||
{Name: "超级管理员", Code: RoleCodeSuperAdmin, SortNo: 1},
|
||||
{Name: "管理员", Code: RoleCodeAdmin, SortNo: 2},
|
||||
{Name: "客服组长", Code: RoleCodeCsTeamLeader, SortNo: 3},
|
||||
{Name: "客服", Code: RoleCodeCsUser, SortNo: 4},
|
||||
}
|
||||
|
||||
var RolePermissions = map[string][]Permission{
|
||||
RoleCodeSuperAdmin: Permissions,
|
||||
RoleCodeAdmin: {
|
||||
PermissionUserView, PermissionUserCreate, PermissionUserUpdate, PermissionUserAssignRole,
|
||||
PermissionRoleView, PermissionRoleCreate, PermissionRoleUpdate, PermissionRoleAssignPermission,
|
||||
PermissionPermissionView, PermissionPermissionSync,
|
||||
PermissionSessionView, PermissionSessionRevoke,
|
||||
PermissionConversationView, PermissionConversationAssign, PermissionConversationTransfer, PermissionConversationClose, PermissionConversationSend, PermissionConversationTag, PermissionConversationHandover, PermissionConversationRecycle, PermissionConversationLinkCustomer,
|
||||
PermissionTicketView, PermissionTicketCreate, PermissionTicketUpdate, PermissionTicketAssign, PermissionTicketChangeStatus, PermissionTicketReply, PermissionTicketClose, PermissionTicketReopen,
|
||||
PermissionTicketResolutionCodeView, PermissionTicketResolutionCodeCreate, PermissionTicketResolutionCodeUpdate, PermissionTicketResolutionCodeDelete,
|
||||
PermissionTicketPriorityConfigView, PermissionTicketPriorityConfigCreate, PermissionTicketPriorityConfigUpdate, PermissionTicketPriorityConfigDelete,
|
||||
PermissionQuickReplyView, PermissionQuickReplyCreate, PermissionQuickReplyUpdate, PermissionQuickReplyDelete,
|
||||
PermissionTagView, PermissionTagCreate, PermissionTagUpdate, PermissionTagDelete,
|
||||
PermissionCompanyView, PermissionCompanyCreate, PermissionCompanyUpdate, PermissionCompanyDelete,
|
||||
PermissionChannelView, PermissionChannelCreate, PermissionChannelUpdate, PermissionChannelDelete,
|
||||
PermissionCustomerView, PermissionCustomerCreate, PermissionCustomerUpdate, PermissionCustomerDelete,
|
||||
PermissionAgentView, PermissionAgentCreate, PermissionAgentUpdate, PermissionAgentDelete, PermissionAgentUpdateStatus, PermissionAgentConfig,
|
||||
PermissionAgentTeamView, PermissionAgentTeamCreate, PermissionAgentTeamUpdate, PermissionAgentTeamDelete,
|
||||
PermissionAgentTeamScheduleView, PermissionAgentTeamScheduleCreate, PermissionAgentTeamScheduleUpdate, PermissionAgentTeamScheduleDelete, PermissionAgentTeamScheduleBatchGenerate,
|
||||
PermissionAssetView, PermissionAssetCreate, PermissionAssetDelete,
|
||||
PermissionAIConfigView, PermissionAIConfigCreate, PermissionAIConfigUpdate, PermissionAIConfigDelete,
|
||||
PermissionSkillDefinitionView, PermissionSkillDefinitionCreate, PermissionSkillDefinitionUpdate, PermissionSkillDefinitionDelete,
|
||||
},
|
||||
RoleCodeCsTeamLeader: {
|
||||
PermissionUserView,
|
||||
PermissionRoleView,
|
||||
PermissionPermissionView,
|
||||
PermissionSessionView,
|
||||
PermissionConversationView, PermissionConversationClose, PermissionConversationSend, PermissionConversationTag, PermissionConversationHandover, PermissionConversationRecycle, PermissionConversationLinkCustomer,
|
||||
PermissionTicketView, PermissionTicketCreate, PermissionTicketUpdate, PermissionTicketAssign, PermissionTicketChangeStatus, PermissionTicketReply, PermissionTicketClose, PermissionTicketReopen,
|
||||
PermissionTicketResolutionCodeView, PermissionTicketResolutionCodeCreate, PermissionTicketResolutionCodeUpdate, PermissionTicketResolutionCodeDelete,
|
||||
PermissionTicketPriorityConfigView, PermissionTicketPriorityConfigCreate, PermissionTicketPriorityConfigUpdate, PermissionTicketPriorityConfigDelete,
|
||||
PermissionQuickReplyView, PermissionQuickReplyCreate, PermissionQuickReplyUpdate, PermissionQuickReplyDelete,
|
||||
PermissionTagView, PermissionTagCreate, PermissionTagUpdate, PermissionTagDelete,
|
||||
PermissionCompanyView,
|
||||
PermissionChannelView, PermissionChannelCreate, PermissionChannelUpdate,
|
||||
PermissionCustomerView, PermissionCustomerCreate, PermissionCustomerUpdate,
|
||||
PermissionAgentView, PermissionAgentUpdate,
|
||||
PermissionAgentTeamView,
|
||||
PermissionAgentTeamScheduleView, PermissionAgentTeamScheduleCreate, PermissionAgentTeamScheduleUpdate, PermissionAgentTeamScheduleDelete, PermissionAgentTeamScheduleBatchGenerate,
|
||||
PermissionAssetView, PermissionAssetCreate, PermissionAssetDelete,
|
||||
PermissionAIConfigView,
|
||||
PermissionSkillDefinitionView, PermissionSkillDefinitionCreate, PermissionSkillDefinitionUpdate,
|
||||
},
|
||||
RoleCodeCsUser: {
|
||||
PermissionUserView,
|
||||
PermissionRoleView,
|
||||
PermissionPermissionView,
|
||||
PermissionConversationView,
|
||||
PermissionTicketView, PermissionTicketCreate, PermissionTicketReply,
|
||||
PermissionTicketResolutionCodeView, PermissionTicketPriorityConfigView,
|
||||
PermissionQuickReplyView,
|
||||
PermissionTagView,
|
||||
PermissionCompanyView,
|
||||
PermissionChannelView,
|
||||
PermissionCustomerView,
|
||||
PermissionAssetView,
|
||||
PermissionAgentView,
|
||||
PermissionAgentTeamView,
|
||||
PermissionAgentTeamScheduleView,
|
||||
PermissionAIConfigView,
|
||||
PermissionSkillDefinitionView,
|
||||
},
|
||||
}
|
||||
|
||||
func PermissionCodes() []string {
|
||||
ret := make([]string, 0, len(Permissions))
|
||||
for _, permission := range Permissions {
|
||||
ret = append(ret, permission.Code)
|
||||
}
|
||||
return ret
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package constants
|
||||
|
||||
const (
|
||||
SystemAuditUserID int64 = 0
|
||||
SystemAuditUserName string = "system"
|
||||
)
|
||||
@@ -0,0 +1,13 @@
|
||||
package dto
|
||||
|
||||
import "cs-agent/internal/pkg/enums"
|
||||
|
||||
type AuthPrincipal struct {
|
||||
UserID int64
|
||||
Username string
|
||||
Nickname string
|
||||
Avatar string
|
||||
Status enums.Status
|
||||
Roles []string
|
||||
Permissions []string
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
package request
|
||||
|
||||
import "cs-agent/internal/pkg/enums"
|
||||
|
||||
type RevokeSessionRequest struct {
|
||||
ID int64 `json:"id"`
|
||||
}
|
||||
|
||||
type RevokeUserSessionsRequest struct {
|
||||
UserID int64 `json:"userId"`
|
||||
}
|
||||
|
||||
type CreateUserRequest struct {
|
||||
Username string `json:"username"`
|
||||
Nickname string `json:"nickname"`
|
||||
Avatar string `json:"avatar"`
|
||||
Mobile *string `json:"mobile"`
|
||||
Email *string `json:"email"`
|
||||
Remark string `json:"remark"`
|
||||
RoleIDs []int64 `json:"roleIds"`
|
||||
}
|
||||
|
||||
type UpdateUserRequest struct {
|
||||
ID int64 `json:"id"`
|
||||
Nickname string `json:"nickname"`
|
||||
Avatar string `json:"avatar"`
|
||||
Mobile *string `json:"mobile"`
|
||||
Email *string `json:"email"`
|
||||
Remark string `json:"remark"`
|
||||
}
|
||||
|
||||
type DeleteUserRequest struct {
|
||||
ID int64 `json:"id"`
|
||||
}
|
||||
|
||||
type UpdateUserStatusRequest struct {
|
||||
ID int64 `json:"id"`
|
||||
Status int `json:"status"`
|
||||
}
|
||||
|
||||
type ChangePasswordRequest struct {
|
||||
Password string `json:"password"`
|
||||
}
|
||||
|
||||
type AssignRoleRequest struct {
|
||||
UserID int64 `json:"userId"`
|
||||
RoleIDs []int64 `json:"roleIds"`
|
||||
}
|
||||
|
||||
type CreateRoleRequest struct {
|
||||
Name string `json:"name"`
|
||||
Code string `json:"code"`
|
||||
SortNo int `json:"sortNo"`
|
||||
Remark string `json:"remark"`
|
||||
}
|
||||
|
||||
type UpdateRoleRequest struct {
|
||||
ID int64 `json:"id"`
|
||||
Name string `json:"name"`
|
||||
SortNo int `json:"sortNo"`
|
||||
Remark string `json:"remark"`
|
||||
}
|
||||
|
||||
type DeleteRoleRequest struct {
|
||||
ID int64 `json:"id"`
|
||||
}
|
||||
|
||||
type UpdateRoleStatusRequest struct {
|
||||
ID int64 `json:"id"`
|
||||
Status enums.Status `json:"status"`
|
||||
}
|
||||
|
||||
type AssignPermissionRequest struct {
|
||||
RoleID int64 `json:"roleId"`
|
||||
PermissionIDs []int64 `json:"permissionIds"`
|
||||
}
|
||||
|
||||
type CreateConversationTagRequest struct {
|
||||
Name string `json:"name"`
|
||||
Color string `json:"color"`
|
||||
Status int `json:"status"`
|
||||
SortNo int `json:"sortNo"`
|
||||
Remark string `json:"remark"`
|
||||
}
|
||||
|
||||
type UpdateConversationTagRequest struct {
|
||||
ID int64 `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Color string `json:"color"`
|
||||
Status int `json:"status"`
|
||||
SortNo int `json:"sortNo"`
|
||||
Remark string `json:"remark"`
|
||||
}
|
||||
|
||||
type DeleteConversationTagRequest struct {
|
||||
ID int64 `json:"id"`
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
package request
|
||||
|
||||
import "cs-agent/internal/pkg/enums"
|
||||
|
||||
type CreateAgentProfileRequest struct {
|
||||
UserID int64 `json:"userId"`
|
||||
TeamID int64 `json:"teamId"`
|
||||
AgentCode string `json:"agentCode"`
|
||||
DisplayName string `json:"displayName"`
|
||||
Avatar string `json:"avatar"`
|
||||
ServiceStatus enums.ServiceStatus `json:"serviceStatus"`
|
||||
MaxConcurrentCount int `json:"maxConcurrentCount"`
|
||||
PriorityLevel int `json:"priorityLevel"`
|
||||
AutoAssignEnabled bool `json:"autoAssignEnabled"`
|
||||
ReceiveOfflineMessage bool `json:"receiveOfflineMessage"`
|
||||
Remark string `json:"remark"`
|
||||
}
|
||||
|
||||
type UpdateAgentProfileRequest struct {
|
||||
ID int64 `json:"id"`
|
||||
CreateAgentProfileRequest
|
||||
}
|
||||
|
||||
type DeleteAgentProfileRequest struct {
|
||||
ID int64 `json:"id"`
|
||||
}
|
||||
|
||||
type CreateAgentTeamRequest struct {
|
||||
Name string `json:"name"`
|
||||
LeaderUserID int64 `json:"leaderUserId"`
|
||||
Status int `json:"status"`
|
||||
Description string `json:"description"`
|
||||
Remark string `json:"remark"`
|
||||
}
|
||||
|
||||
type UpdateAgentTeamRequest struct {
|
||||
ID int64 `json:"id"`
|
||||
Name string `json:"name"`
|
||||
LeaderUserID int64 `json:"leaderUserId"`
|
||||
Status int `json:"status"`
|
||||
Description string `json:"description"`
|
||||
Remark string `json:"remark"`
|
||||
}
|
||||
|
||||
type DeleteAgentTeamRequest struct {
|
||||
ID int64 `json:"id"`
|
||||
}
|
||||
|
||||
type CreateAgentTeamScheduleRequest struct {
|
||||
TeamID int64 `json:"teamId"`
|
||||
StartAt string `json:"startAt"`
|
||||
EndAt string `json:"endAt"`
|
||||
SourceType string `json:"sourceType"`
|
||||
Remark string `json:"remark"`
|
||||
}
|
||||
|
||||
type UpdateAgentTeamScheduleRequest struct {
|
||||
ID int64 `json:"id"`
|
||||
CreateAgentTeamScheduleRequest
|
||||
}
|
||||
|
||||
type DeleteAgentTeamScheduleRequest struct {
|
||||
ID int64 `json:"id"`
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
package request
|
||||
|
||||
import "cs-agent/internal/pkg/enums"
|
||||
|
||||
type AIAgentMCPToolRequest struct {
|
||||
ServerCode string `json:"serverCode"`
|
||||
ToolName string `json:"toolName"`
|
||||
Title string `json:"title"`
|
||||
Description string `json:"description"`
|
||||
Arguments map[string]string `json:"arguments"`
|
||||
}
|
||||
|
||||
type CreateAIConfigRequest struct {
|
||||
Name string `json:"name"`
|
||||
Provider enums.AIProvider `json:"provider"`
|
||||
BaseURL string `json:"baseUrl"`
|
||||
APIKey string `json:"apiKey"`
|
||||
ModelType enums.AIModelType `json:"modelType"`
|
||||
ModelName string `json:"modelName"`
|
||||
Dimension int `json:"dimension"`
|
||||
MaxContextTokens int `json:"maxContextTokens"`
|
||||
MaxOutputTokens int `json:"maxOutputTokens"`
|
||||
TimeoutMS int `json:"timeoutMs"`
|
||||
MaxRetryCount int `json:"maxRetryCount"`
|
||||
RPMLimit int `json:"rpmLimit"`
|
||||
TPMLimit int `json:"tpmLimit"`
|
||||
Remark string `json:"remark"`
|
||||
}
|
||||
|
||||
type UpdateAIConfigRequest struct {
|
||||
ID int64 `json:"id"`
|
||||
CreateAIConfigRequest
|
||||
}
|
||||
|
||||
type DeleteAIConfigRequest struct {
|
||||
ID int64 `json:"id"`
|
||||
}
|
||||
|
||||
type UpdateAIConfigStatusRequest struct {
|
||||
ID int64 `json:"id"`
|
||||
Status enums.Status `json:"status"`
|
||||
}
|
||||
|
||||
type CreateAIAgentRequest struct {
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
AIConfigID int64 `json:"aiConfigId"`
|
||||
ServiceMode enums.IMConversationServiceMode `json:"serviceMode"`
|
||||
SystemPrompt string `json:"systemPrompt"`
|
||||
WelcomeMessage string `json:"welcomeMessage"`
|
||||
ReplyTimeoutSeconds int `json:"replyTimeoutSeconds"`
|
||||
TeamIDs []int64 `json:"teamIds"`
|
||||
HandoffMode enums.AIAgentHandoffMode `json:"handoffMode"`
|
||||
MaxAIReplyRounds int `json:"maxAiReplyRounds"`
|
||||
FallbackMode enums.AIAgentFallbackMode `json:"fallbackMode"`
|
||||
FallbackMessage string `json:"fallbackMessage"`
|
||||
KnowledgeIDs []int64 `json:"knowledgeIds"`
|
||||
SkillIDs []int64 `json:"skillIds"`
|
||||
DirectTools []AIAgentMCPToolRequest `json:"directTools"`
|
||||
Remark string `json:"remark"`
|
||||
}
|
||||
|
||||
type UpdateAIAgentRequest struct {
|
||||
ID int64 `json:"id"`
|
||||
CreateAIAgentRequest
|
||||
}
|
||||
|
||||
type DeleteAIAgentRequest struct {
|
||||
ID int64 `json:"id"`
|
||||
}
|
||||
|
||||
type UpdateAIAgentStatusRequest struct {
|
||||
ID int64 `json:"id"`
|
||||
Status int `json:"status"`
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package request
|
||||
|
||||
type CreateAssetRequest struct {
|
||||
Prefix string `form:"prefix"`
|
||||
}
|
||||
|
||||
type DeleteAssetRequest struct {
|
||||
ID int64 `json:"id"`
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package request
|
||||
|
||||
type LoginRequest struct {
|
||||
Username string `json:"username"`
|
||||
Password string `json:"password"`
|
||||
}
|
||||
|
||||
type RefreshTokenRequest struct {
|
||||
RefreshToken string `json:"refreshToken"`
|
||||
}
|
||||
|
||||
type LogoutRequest struct {
|
||||
RefreshToken string `json:"refreshToken"`
|
||||
}
|
||||
|
||||
type WxWorkExchangeRequest struct {
|
||||
Ticket string `json:"ticket"`
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package request
|
||||
|
||||
type CreateChannelRequest struct {
|
||||
ChannelType string `json:"channelType"`
|
||||
AIAgentID int64 `json:"aiAgentId"`
|
||||
Name string `json:"name"`
|
||||
ConfigJSON string `json:"configJson"`
|
||||
Status int `json:"status"`
|
||||
Remark string `json:"remark"`
|
||||
}
|
||||
|
||||
type UpdateChannelRequest struct {
|
||||
ID int64 `json:"id"`
|
||||
CreateChannelRequest
|
||||
}
|
||||
|
||||
type UpdateChannelStatusRequest struct {
|
||||
ID int64 `json:"id"`
|
||||
Status int `json:"status"`
|
||||
}
|
||||
|
||||
type DeleteChannelRequest struct {
|
||||
ID int64 `json:"id"`
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package request
|
||||
|
||||
type CreateCompanyRequest struct {
|
||||
Name string `json:"name"`
|
||||
Code string `json:"code"`
|
||||
Remark string `json:"remark"`
|
||||
}
|
||||
|
||||
type UpdateCompanyRequest struct {
|
||||
ID int64 `json:"id"`
|
||||
CreateCompanyRequest
|
||||
}
|
||||
|
||||
type DeleteCompanyRequest struct {
|
||||
ID int64 `json:"id"`
|
||||
}
|
||||
|
||||
type UpdateCompanyStatusRequest struct {
|
||||
ID int64 `json:"id"`
|
||||
Status int `json:"status"`
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
package request
|
||||
|
||||
type AgentConversationFilter string
|
||||
|
||||
const (
|
||||
AgentConversationFilterMine AgentConversationFilter = "mine"
|
||||
AgentConversationFilterActive AgentConversationFilter = "active"
|
||||
AgentConversationFilterPending AgentConversationFilter = "pending"
|
||||
AgentConversationFilterClosed AgentConversationFilter = "closed"
|
||||
)
|
||||
|
||||
type ConversationListRequest struct {
|
||||
Status int `json:"status"`
|
||||
ExternalSource string `json:"externalSource"`
|
||||
ServiceMode int `json:"serviceMode"`
|
||||
CurrentAssigneeID int64 `json:"currentAssigneeId"`
|
||||
Keyword string `json:"keyword"`
|
||||
TagID int64 `json:"tagId"`
|
||||
}
|
||||
|
||||
type AssignConversationRequest struct {
|
||||
ConversationID int64 `json:"conversationId"`
|
||||
AssigneeID int64 `json:"assigneeId"`
|
||||
Reason string `json:"reason"`
|
||||
}
|
||||
|
||||
type DispatchConversationRequest struct {
|
||||
ConversationID int64 `json:"conversationId"`
|
||||
}
|
||||
|
||||
type TransferConversationRequest struct {
|
||||
ConversationID int64 `json:"conversationId"`
|
||||
ToUserID int64 `json:"toUserId"`
|
||||
Reason string `json:"reason"`
|
||||
}
|
||||
|
||||
type CloseConversationRequest struct {
|
||||
ConversationID int64 `json:"conversationId"`
|
||||
CloseReason string `json:"closeReason"`
|
||||
}
|
||||
|
||||
type ReadConversationRequest struct {
|
||||
ConversationID int64 `json:"conversationId"`
|
||||
MessageID int64 `json:"messageId"`
|
||||
}
|
||||
|
||||
type AddConversationTagRequest struct {
|
||||
ConversationID int64 `json:"conversationId"`
|
||||
TagID int64 `json:"tagId"`
|
||||
}
|
||||
|
||||
type RemoveConversationTagRequest struct {
|
||||
ConversationID int64 `json:"conversationId"`
|
||||
TagID int64 `json:"tagId"`
|
||||
}
|
||||
|
||||
// LinkConversationCustomerRequest 将客服会话关联到 CRM 客户(并同步访客身份映射)。
|
||||
type LinkConversationCustomerRequest struct {
|
||||
ConversationID int64 `json:"conversationId"`
|
||||
CustomerID int64 `json:"customerId"`
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package request
|
||||
|
||||
type CreateCustomerContactRequest struct {
|
||||
CustomerID int64 `json:"customerId"`
|
||||
ContactType string `json:"contactType"`
|
||||
ContactValue string `json:"contactValue"`
|
||||
IsPrimary bool `json:"isPrimary"`
|
||||
IsVerified bool `json:"isVerified"`
|
||||
Source string `json:"source"`
|
||||
Status int `json:"status"`
|
||||
Remark string `json:"remark"`
|
||||
}
|
||||
|
||||
type UpdateCustomerContactRequest struct {
|
||||
ID int64 `json:"id"`
|
||||
ContactType string `json:"contactType"`
|
||||
ContactValue string `json:"contactValue"`
|
||||
IsPrimary bool `json:"isPrimary"`
|
||||
IsVerified bool `json:"isVerified"`
|
||||
Source string `json:"source"`
|
||||
Status int `json:"status"`
|
||||
Remark string `json:"remark"`
|
||||
}
|
||||
|
||||
type DeleteCustomerContactRequest struct {
|
||||
ID int64 `json:"id"`
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
package request
|
||||
|
||||
// CustomerListRequest 客户分页列表查询(POST /customer/list JSON Body)。
|
||||
type CustomerListRequest struct {
|
||||
Page int `json:"page"`
|
||||
Limit int `json:"limit"`
|
||||
Status *int `json:"status,omitempty"`
|
||||
Gender *int `json:"gender,omitempty"`
|
||||
CompanyID *int64 `json:"companyId,omitempty"`
|
||||
// Keyword 模糊匹配:客户姓名、主手机号、主邮箱、任意联系方式(t_customer_contact)、公司名称(t_company)。
|
||||
Keyword string `json:"keyword"`
|
||||
}
|
||||
|
||||
func (r CustomerListRequest) GetPage() int {
|
||||
if r.Page <= 0 {
|
||||
return 1
|
||||
}
|
||||
return r.Page
|
||||
}
|
||||
|
||||
func (r CustomerListRequest) GetLimit() int {
|
||||
if r.Limit <= 0 {
|
||||
return 20
|
||||
}
|
||||
return r.Limit
|
||||
}
|
||||
|
||||
func (r CustomerListRequest) Offset() int {
|
||||
return (r.GetPage() - 1) * r.GetLimit()
|
||||
}
|
||||
|
||||
type CreateCustomerRequest struct {
|
||||
Name string `json:"name"`
|
||||
Gender int `json:"gender"`
|
||||
CompanyID int64 `json:"companyId"`
|
||||
PrimaryMobile string `json:"primaryMobile"`
|
||||
PrimaryEmail string `json:"primaryEmail"`
|
||||
Remark string `json:"remark"`
|
||||
}
|
||||
|
||||
type UpdateCustomerRequest struct {
|
||||
ID int64 `json:"id"`
|
||||
CreateCustomerRequest
|
||||
}
|
||||
|
||||
type DeleteCustomerRequest struct {
|
||||
ID int64 `json:"id"`
|
||||
}
|
||||
|
||||
type UpdateCustomerStatusRequest struct {
|
||||
ID int64 `json:"id"`
|
||||
Status int `json:"status"`
|
||||
}
|
||||
|
||||
// CustomerProfileContactItem 保存客户档案时的联系方式行(无 id 表示新建)。
|
||||
type CustomerProfileContactItem struct {
|
||||
ID *int64 `json:"id,omitempty"`
|
||||
ContactType string `json:"contactType"`
|
||||
ContactValue string `json:"contactValue"`
|
||||
IsPrimary bool `json:"isPrimary"`
|
||||
Remark string `json:"remark"`
|
||||
}
|
||||
|
||||
// SaveCustomerProfileRequest 客户主信息与联系方式一并保存(单事务);id 为空或 0 表示新建客户。
|
||||
type SaveCustomerProfileRequest struct {
|
||||
ID *int64 `json:"id,omitempty"`
|
||||
Name string `json:"name"`
|
||||
Gender int `json:"gender"`
|
||||
CompanyID int64 `json:"companyId"`
|
||||
Remark string `json:"remark"`
|
||||
Contacts []CustomerProfileContactItem `json:"contacts"`
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
package request
|
||||
|
||||
import "cs-agent/internal/pkg/enums"
|
||||
|
||||
type CreateKnowledgeBaseRequest struct {
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
KnowledgeType string `json:"knowledgeType"`
|
||||
DefaultTopK int `json:"defaultTopK"`
|
||||
DefaultScoreThreshold float64 `json:"defaultScoreThreshold"`
|
||||
DefaultRerankLimit int `json:"defaultRerankLimit"`
|
||||
ChunkProvider string `json:"chunkProvider"`
|
||||
ChunkTargetTokens int `json:"chunkTargetTokens"`
|
||||
ChunkMaxTokens int `json:"chunkMaxTokens"`
|
||||
ChunkOverlapTokens int `json:"chunkOverlapTokens"`
|
||||
AnswerMode int `json:"answerMode"`
|
||||
FallbackMode int `json:"fallbackMode"`
|
||||
Remark string `json:"remark"`
|
||||
}
|
||||
|
||||
type UpdateKnowledgeBaseRequest struct {
|
||||
ID int64 `json:"id"`
|
||||
CreateKnowledgeBaseRequest
|
||||
}
|
||||
|
||||
type CreateKnowledgeDocumentRequest struct {
|
||||
KnowledgeBaseID int64 `json:"knowledgeBaseId"`
|
||||
Title string `json:"title"`
|
||||
ContentType enums.KnowledgeDocumentContentType `json:"contentType"`
|
||||
Content string `json:"content"`
|
||||
}
|
||||
|
||||
type UpdateKnowledgeDocumentRequest struct {
|
||||
ID int64 `json:"id"`
|
||||
CreateKnowledgeDocumentRequest
|
||||
}
|
||||
|
||||
type CreateKnowledgeFAQRequest struct {
|
||||
KnowledgeBaseID int64 `json:"knowledgeBaseId"`
|
||||
Question string `json:"question"`
|
||||
Answer string `json:"answer"`
|
||||
SimilarQuestions []string `json:"similarQuestions"`
|
||||
Remark string `json:"remark"`
|
||||
}
|
||||
|
||||
type UpdateKnowledgeFAQRequest struct {
|
||||
ID int64 `json:"id"`
|
||||
CreateKnowledgeFAQRequest
|
||||
}
|
||||
|
||||
type KnowledgeSearchRequest struct {
|
||||
KnowledgeBaseIDs []int64 `json:"knowledgeBaseIds"`
|
||||
Question string `json:"question"`
|
||||
TopK int `json:"topK"`
|
||||
ScoreThreshold float64 `json:"scoreThreshold"`
|
||||
RerankLimit int `json:"rerankLimit"`
|
||||
Channel string `json:"channel"`
|
||||
Scene string `json:"scene"`
|
||||
SessionID string `json:"sessionId"`
|
||||
ConversationID int64 `json:"conversationId"`
|
||||
}
|
||||
|
||||
type KnowledgeAnswerRequest struct {
|
||||
KnowledgeBaseIDs []int64 `json:"knowledgeBaseIds"`
|
||||
Question string `json:"question"`
|
||||
TopK int `json:"topK"`
|
||||
ScoreThreshold float64 `json:"scoreThreshold"`
|
||||
RerankLimit int `json:"rerankLimit"`
|
||||
Channel string `json:"channel"`
|
||||
Scene string `json:"scene"`
|
||||
SessionID string `json:"sessionId"`
|
||||
ConversationID int64 `json:"conversationId"`
|
||||
AnswerMode int `json:"answerMode"`
|
||||
FallbackMode int `json:"fallbackMode"`
|
||||
}
|
||||
|
||||
type CreateKnowledgeFeedbackRequest struct {
|
||||
RetrieveLogID int64 `json:"retrieveLogId"`
|
||||
FeedbackType int `json:"feedbackType"`
|
||||
FeedbackReason string `json:"feedbackReason"`
|
||||
Remark string `json:"remark"`
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package request
|
||||
|
||||
type MCPServerDebugRequest struct {
|
||||
ServerCode string `json:"serverCode"`
|
||||
}
|
||||
|
||||
type MCPCallToolRequest struct {
|
||||
ServerCode string `json:"serverCode"`
|
||||
ToolName string `json:"toolName"`
|
||||
Arguments map[string]any `json:"arguments"`
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package request
|
||||
|
||||
import "cs-agent/internal/pkg/enums"
|
||||
|
||||
type MessageListRequest struct {
|
||||
ConversationID int64 `json:"conversationId"`
|
||||
SenderType string `json:"senderType"`
|
||||
MessageType string `json:"messageType"`
|
||||
}
|
||||
|
||||
type SendConversationMessageRequest struct {
|
||||
ConversationID int64 `json:"conversationId"`
|
||||
MessageType enums.IMMessageType `json:"messageType"`
|
||||
Content string `json:"content"`
|
||||
Payload string `json:"payload"`
|
||||
ClientMsgID string `json:"clientMsgId"`
|
||||
}
|
||||
|
||||
type RecallConversationMessageRequest struct {
|
||||
MessageID int64 `json:"messageId"`
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package request
|
||||
|
||||
import "cs-agent/internal/pkg/enums"
|
||||
|
||||
type QuickReplyListRequest struct {
|
||||
GroupName string `json:"groupName"`
|
||||
Keyword string `json:"keyword"`
|
||||
Status int `json:"status"`
|
||||
}
|
||||
|
||||
type CreateQuickReplyRequest struct {
|
||||
GroupName string `json:"groupName"`
|
||||
Title string `json:"title"`
|
||||
Content string `json:"content"`
|
||||
Status enums.Status `json:"status"`
|
||||
SortNo int `json:"sortNo"`
|
||||
}
|
||||
|
||||
type UpdateQuickReplyRequest struct {
|
||||
ID int64 `json:"id"`
|
||||
CreateQuickReplyRequest
|
||||
}
|
||||
|
||||
type DeleteQuickReplyRequest struct {
|
||||
ID int64 `json:"id"`
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package request
|
||||
|
||||
import "cs-agent/internal/pkg/enums"
|
||||
|
||||
type SkillDefinitionListRequest struct {
|
||||
Name string `json:"name"`
|
||||
Code string `json:"code"`
|
||||
Status int `json:"status"`
|
||||
}
|
||||
|
||||
type CreateSkillDefinitionRequest struct {
|
||||
Code string `json:"code"`
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
Prompt string `json:"prompt"`
|
||||
ExecutionMode enums.SkillExecutionMode `json:"executionMode"`
|
||||
ExecutionConfig string `json:"executionConfig"`
|
||||
Remark string `json:"remark"`
|
||||
}
|
||||
|
||||
type UpdateSkillDefinitionRequest struct {
|
||||
ID int64 `json:"id"`
|
||||
CreateSkillDefinitionRequest
|
||||
}
|
||||
|
||||
type DeleteSkillDefinitionRequest struct {
|
||||
ID int64 `json:"id"`
|
||||
}
|
||||
|
||||
type UpdateSkillDefinitionStatusRequest struct {
|
||||
ID int64 `json:"id"`
|
||||
Status int `json:"status"`
|
||||
}
|
||||
|
||||
type SkillDebugRunRequest struct {
|
||||
AIAgentID int64 `json:"aiAgentId"`
|
||||
ConversationID int64 `json:"conversationId"`
|
||||
SkillCode string `json:"skillCode"`
|
||||
UserMessage string `json:"userMessage"`
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package request
|
||||
|
||||
type TagListRequest struct {
|
||||
ParentID int64 `json:"parentId"`
|
||||
Name string `json:"name"`
|
||||
Status int `json:"status"`
|
||||
}
|
||||
|
||||
type CreateTagRequest struct {
|
||||
ParentID int64 `json:"parentId"`
|
||||
Name string `json:"name"`
|
||||
Remark string `json:"remark"`
|
||||
}
|
||||
|
||||
type UpdateTagRequest struct {
|
||||
ID int64 `json:"id"`
|
||||
CreateTagRequest
|
||||
}
|
||||
|
||||
type DeleteTagRequest struct {
|
||||
ID int64 `json:"id"`
|
||||
}
|
||||
|
||||
type UpdateTagStatusRequest struct {
|
||||
ID int64 `json:"id"`
|
||||
Status int `json:"status"`
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package request
|
||||
|
||||
import "cs-agent/internal/pkg/enums"
|
||||
|
||||
type CreateTicketResolutionCodeRequest struct {
|
||||
Name string `json:"name"`
|
||||
Code string `json:"code"`
|
||||
SortNo int `json:"sortNo"`
|
||||
Status enums.Status `json:"status"`
|
||||
Remark string `json:"remark"`
|
||||
}
|
||||
|
||||
type UpdateTicketResolutionCodeRequest struct {
|
||||
ID int64 `json:"id"`
|
||||
CreateTicketResolutionCodeRequest
|
||||
}
|
||||
|
||||
type DeleteTicketResolutionCodeRequest struct {
|
||||
ID int64 `json:"id"`
|
||||
}
|
||||
|
||||
type CreateTicketPriorityConfigRequest struct {
|
||||
Name string `json:"name"`
|
||||
FirstResponseMinutes int `json:"firstResponseMinutes"`
|
||||
ResolutionMinutes int `json:"resolutionMinutes"`
|
||||
Status enums.Status `json:"status"`
|
||||
Remark string `json:"remark"`
|
||||
}
|
||||
|
||||
type UpdateTicketPriorityConfigRequest struct {
|
||||
ID int64 `json:"id"`
|
||||
CreateTicketPriorityConfigRequest
|
||||
}
|
||||
|
||||
type DeleteTicketPriorityConfigRequest struct {
|
||||
ID int64 `json:"id"`
|
||||
}
|
||||
@@ -0,0 +1,149 @@
|
||||
package request
|
||||
|
||||
type CreateTicketRequest struct {
|
||||
Title string `json:"title"`
|
||||
Description string `json:"description"`
|
||||
Source string `json:"source"`
|
||||
Channel string `json:"channel"`
|
||||
CustomerID int64 `json:"customerId"`
|
||||
ConversationID int64 `json:"conversationId"`
|
||||
TagIDs []int64 `json:"tagIds"`
|
||||
Type string `json:"type"`
|
||||
Priority int64 `json:"priority"`
|
||||
Severity int `json:"severity"`
|
||||
CurrentTeamID int64 `json:"currentTeamId"`
|
||||
CurrentAssigneeID int64 `json:"currentAssigneeId"`
|
||||
DueAt string `json:"dueAt"`
|
||||
CustomFields map[string]any `json:"customFields"`
|
||||
}
|
||||
|
||||
type CreateTicketFromConversationRequest struct {
|
||||
ConversationID int64 `json:"conversationId"`
|
||||
Title string `json:"title"`
|
||||
Description string `json:"description"`
|
||||
TagIDs []int64 `json:"tagIds"`
|
||||
Priority int64 `json:"priority"`
|
||||
Severity int `json:"severity"`
|
||||
CurrentTeamID int64 `json:"currentTeamId"`
|
||||
CurrentAssigneeID int64 `json:"currentAssigneeId"`
|
||||
SyncToConversation bool `json:"syncToConversation"`
|
||||
CustomFields map[string]any `json:"customFields"`
|
||||
}
|
||||
|
||||
type UpdateTicketRequest struct {
|
||||
TicketID int64 `json:"ticketId"`
|
||||
Title string `json:"title"`
|
||||
Description string `json:"description"`
|
||||
TagIDs []int64 `json:"tagIds"`
|
||||
Type string `json:"type"`
|
||||
Priority int64 `json:"priority"`
|
||||
Severity int `json:"severity"`
|
||||
CurrentTeamID int64 `json:"currentTeamId"`
|
||||
CurrentAssigneeID int64 `json:"currentAssigneeId"`
|
||||
DueAt string `json:"dueAt"`
|
||||
CustomFields map[string]any `json:"customFields"`
|
||||
}
|
||||
|
||||
type AssignTicketRequest struct {
|
||||
TicketID int64 `json:"ticketId"`
|
||||
ToUserID int64 `json:"toUserId"`
|
||||
ToTeamID int64 `json:"toTeamId"`
|
||||
Reason string `json:"reason"`
|
||||
}
|
||||
|
||||
type ChangeTicketStatusRequest struct {
|
||||
TicketID int64 `json:"ticketId"`
|
||||
Status string `json:"status"`
|
||||
PendingReason string `json:"pendingReason"`
|
||||
CloseReason string `json:"closeReason"`
|
||||
ResolutionCode string `json:"resolutionCode"`
|
||||
ResolutionSummary string `json:"resolutionSummary"`
|
||||
Reason string `json:"reason"`
|
||||
}
|
||||
|
||||
type ReplyTicketRequest struct {
|
||||
TicketID int64 `json:"ticketId"`
|
||||
ContentType string `json:"contentType"`
|
||||
Content string `json:"content"`
|
||||
Payload string `json:"payload"`
|
||||
}
|
||||
|
||||
type InternalNoteRequest struct {
|
||||
TicketID int64 `json:"ticketId"`
|
||||
ContentType string `json:"contentType"`
|
||||
Content string `json:"content"`
|
||||
Payload string `json:"payload"`
|
||||
}
|
||||
|
||||
type CloseTicketRequest struct {
|
||||
TicketID int64 `json:"ticketId"`
|
||||
CloseReason string `json:"closeReason"`
|
||||
}
|
||||
|
||||
type ReopenTicketRequest struct {
|
||||
TicketID int64 `json:"ticketId"`
|
||||
Reason string `json:"reason"`
|
||||
}
|
||||
|
||||
type WatchTicketRequest struct {
|
||||
TicketID int64 `json:"ticketId"`
|
||||
}
|
||||
|
||||
type BatchAssignTicketRequest struct {
|
||||
TicketIDs []int64 `json:"ticketIds"`
|
||||
ToUserID int64 `json:"toUserId"`
|
||||
ToTeamID int64 `json:"toTeamId"`
|
||||
Reason string `json:"reason"`
|
||||
}
|
||||
|
||||
type BatchChangeTicketStatusRequest struct {
|
||||
TicketIDs []int64 `json:"ticketIds"`
|
||||
Status string `json:"status"`
|
||||
PendingReason string `json:"pendingReason"`
|
||||
CloseReason string `json:"closeReason"`
|
||||
ResolutionCode string `json:"resolutionCode"`
|
||||
ResolutionSummary string `json:"resolutionSummary"`
|
||||
Reason string `json:"reason"`
|
||||
}
|
||||
|
||||
type BatchWatchTicketRequest struct {
|
||||
TicketIDs []int64 `json:"ticketIds"`
|
||||
Watched bool `json:"watched"`
|
||||
}
|
||||
|
||||
type AddTicketRelationRequest struct {
|
||||
TicketID int64 `json:"ticketId"`
|
||||
RelatedTicketID int64 `json:"relatedTicketId"`
|
||||
RelatedTicketNo string `json:"relatedTicketNo"`
|
||||
RelationType string `json:"relationType"`
|
||||
}
|
||||
|
||||
type DeleteTicketRelationRequest struct {
|
||||
TicketID int64 `json:"ticketId"`
|
||||
RelationID int64 `json:"relationId"`
|
||||
}
|
||||
|
||||
type AddTicketCollaboratorRequest struct {
|
||||
TicketID int64 `json:"ticketId"`
|
||||
UserID int64 `json:"userId"`
|
||||
}
|
||||
|
||||
type DeleteTicketCollaboratorRequest struct {
|
||||
TicketID int64 `json:"ticketId"`
|
||||
CollaboratorID int64 `json:"collaboratorId"`
|
||||
}
|
||||
|
||||
type LinkTicketCustomerRequest struct {
|
||||
TicketID int64 `json:"ticketId"`
|
||||
CustomerID int64 `json:"customerId"`
|
||||
}
|
||||
|
||||
type SaveTicketViewRequest struct {
|
||||
ID int64 `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Filters map[string]any `json:"filters"`
|
||||
}
|
||||
|
||||
type DeleteTicketViewRequest struct {
|
||||
ID int64 `json:"id"`
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
package response
|
||||
|
||||
import "cs-agent/internal/pkg/enums"
|
||||
|
||||
type PermissionResponse struct {
|
||||
ID int64 `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Code string `json:"code"`
|
||||
Type string `json:"type"`
|
||||
GroupName string `json:"groupName"`
|
||||
Method string `json:"method"`
|
||||
ApiPath string `json:"apiPath"`
|
||||
Status enums.Status `json:"status"`
|
||||
SortNo int `json:"sortNo"`
|
||||
}
|
||||
|
||||
type RoleResponse struct {
|
||||
ID int64 `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Code string `json:"code"`
|
||||
Status enums.Status `json:"status"`
|
||||
IsSystem bool `json:"isSystem"`
|
||||
SortNo int `json:"sortNo"`
|
||||
Permissions []string `json:"permissions,omitempty"`
|
||||
}
|
||||
|
||||
type UserResponse struct {
|
||||
ID int64 `json:"id"`
|
||||
Username string `json:"username"`
|
||||
Nickname string `json:"nickname"`
|
||||
Avatar string `json:"avatar"`
|
||||
Mobile string `json:"mobile,omitempty"`
|
||||
Email string `json:"email,omitempty"`
|
||||
Status enums.Status `json:"status"`
|
||||
LastLoginAt string `json:"lastLoginAt,omitempty"`
|
||||
LastLoginIP string `json:"lastLoginIp,omitempty"`
|
||||
Roles []RoleResponse `json:"roles,omitempty"`
|
||||
Permissions []string `json:"permissions,omitempty"`
|
||||
}
|
||||
|
||||
// CreateUserResultResponse 创建用户成功响应;password 仅在本次响应中返回一次。
|
||||
type CreateUserResultResponse struct {
|
||||
User *UserResponse `json:"user"`
|
||||
Password string `json:"password"`
|
||||
}
|
||||
|
||||
type SessionResponse struct {
|
||||
ID int64 `json:"id"`
|
||||
UserID int64 `json:"userId"`
|
||||
Username string `json:"username,omitempty"`
|
||||
TokenType string `json:"tokenType"`
|
||||
ClientType string `json:"clientType"`
|
||||
ClientIP string `json:"clientIp"`
|
||||
UserAgent string `json:"userAgent"`
|
||||
ExpiredAt string `json:"expiredAt"`
|
||||
RevokedAt string `json:"revokedAt,omitempty"`
|
||||
LastSeenAt string `json:"lastSeenAt,omitempty"`
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package response
|
||||
|
||||
import "cs-agent/internal/pkg/enums"
|
||||
|
||||
type AgentProfileResponse struct {
|
||||
ID int64 `json:"id"`
|
||||
UserID int64 `json:"userId"`
|
||||
TeamID int64 `json:"teamId"`
|
||||
TeamName string `json:"teamName,omitempty"`
|
||||
Username string `json:"username,omitempty"`
|
||||
Nickname string `json:"nickname,omitempty"`
|
||||
AgentCode string `json:"agentCode"`
|
||||
DisplayName string `json:"displayName"`
|
||||
Avatar string `json:"avatar"`
|
||||
ServiceStatus enums.ServiceStatus `json:"serviceStatus"`
|
||||
MaxConcurrentCount int `json:"maxConcurrentCount"`
|
||||
PriorityLevel int `json:"priorityLevel"`
|
||||
AutoAssignEnabled bool `json:"autoAssignEnabled"`
|
||||
ReceiveOfflineMessage bool `json:"receiveOfflineMessage"`
|
||||
LastOnlineAt string `json:"lastOnlineAt,omitempty"`
|
||||
LastStatusAt string `json:"lastStatusAt,omitempty"`
|
||||
Remark string `json:"remark"`
|
||||
}
|
||||
|
||||
type AgentTeamResponse struct {
|
||||
ID int64 `json:"id"`
|
||||
Name string `json:"name"`
|
||||
LeaderUserID int64 `json:"leaderUserId"`
|
||||
LeaderUsername string `json:"leaderUsername,omitempty"`
|
||||
LeaderNickname string `json:"leaderNickname,omitempty"`
|
||||
Status enums.Status `json:"status"`
|
||||
Description string `json:"description"`
|
||||
Remark string `json:"remark"`
|
||||
}
|
||||
|
||||
type AgentTeamScheduleResponse struct {
|
||||
ID int64 `json:"id"`
|
||||
TeamID int64 `json:"teamId"`
|
||||
TeamName string `json:"teamName,omitempty"`
|
||||
StartAt string `json:"startAt"`
|
||||
EndAt string `json:"endAt"`
|
||||
SourceType string `json:"sourceType"`
|
||||
Remark string `json:"remark"`
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
package response
|
||||
|
||||
import (
|
||||
"cs-agent/internal/models"
|
||||
"cs-agent/internal/pkg/enums"
|
||||
)
|
||||
|
||||
type AIAgentTeamResponse struct {
|
||||
ID int64 `json:"id"`
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
type AIAgentSkillResponse struct {
|
||||
ID int64 `json:"id"`
|
||||
Code string `json:"code"`
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
type AIAgentMCPToolResponse struct {
|
||||
ServerCode string `json:"serverCode"`
|
||||
ToolName string `json:"toolName"`
|
||||
Title string `json:"title"`
|
||||
Description string `json:"description"`
|
||||
Arguments map[string]string `json:"arguments"`
|
||||
}
|
||||
|
||||
type AIConfigResponse struct {
|
||||
ID int64 `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Provider enums.AIProvider `json:"provider"`
|
||||
BaseURL string `json:"baseUrl"`
|
||||
APIKey string `json:"apiKey"`
|
||||
ModelType enums.AIModelType `json:"modelType"`
|
||||
ModelName string `json:"modelName"`
|
||||
Dimension int `json:"dimension"`
|
||||
MaxContextTokens int `json:"maxContextTokens"`
|
||||
MaxOutputTokens int `json:"maxOutputTokens"`
|
||||
TimeoutMS int `json:"timeoutMs"`
|
||||
MaxRetryCount int `json:"maxRetryCount"`
|
||||
RPMLimit int `json:"rpmLimit"`
|
||||
TPMLimit int `json:"tpmLimit"`
|
||||
Status enums.Status `json:"status"`
|
||||
SortNo int `json:"sortNo"`
|
||||
Remark string `json:"remark"`
|
||||
}
|
||||
|
||||
func BuildAIConfigResponse(item *models.AIConfig) AIConfigResponse {
|
||||
return AIConfigResponse{
|
||||
ID: item.ID,
|
||||
Name: item.Name,
|
||||
Provider: item.Provider,
|
||||
BaseURL: item.BaseURL,
|
||||
APIKey: item.APIKey,
|
||||
ModelType: item.ModelType,
|
||||
ModelName: item.ModelName,
|
||||
Dimension: item.Dimension,
|
||||
MaxContextTokens: item.MaxContextTokens,
|
||||
MaxOutputTokens: item.MaxOutputTokens,
|
||||
TimeoutMS: item.TimeoutMS,
|
||||
MaxRetryCount: item.MaxRetryCount,
|
||||
RPMLimit: item.RPMLimit,
|
||||
TPMLimit: item.TPMLimit,
|
||||
Status: item.Status,
|
||||
SortNo: item.SortNo,
|
||||
Remark: item.Remark,
|
||||
}
|
||||
}
|
||||
|
||||
type AIAgentResponse struct {
|
||||
ID int64 `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
Status enums.Status `json:"status"`
|
||||
StatusName string `json:"statusName"`
|
||||
AIConfigID int64 `json:"aiConfigId"`
|
||||
AIConfigName string `json:"aiConfigName"`
|
||||
ServiceMode enums.IMConversationServiceMode `json:"serviceMode"`
|
||||
ServiceModeName string `json:"serviceModeName"`
|
||||
SystemPrompt string `json:"systemPrompt"`
|
||||
WelcomeMessage string `json:"welcomeMessage"`
|
||||
ReplyTimeoutSeconds int `json:"replyTimeoutSeconds"`
|
||||
Teams []AIAgentTeamResponse `json:"teams"`
|
||||
HandoffMode enums.AIAgentHandoffMode `json:"handoffMode"`
|
||||
HandoffModeName string `json:"handoffModeName"`
|
||||
MaxAIReplyRounds int `json:"maxAiReplyRounds"`
|
||||
FallbackMode enums.AIAgentFallbackMode `json:"fallbackMode"`
|
||||
FallbackModeName string `json:"fallbackModeName"`
|
||||
FallbackMessage string `json:"fallbackMessage"`
|
||||
KnowledgeIDs []int64 `json:"knowledgeIds"`
|
||||
KnowledgeBaseNames []string `json:"knowledgeBaseNames"`
|
||||
SkillIDs []int64 `json:"skillIds"`
|
||||
Skills []AIAgentSkillResponse `json:"skills"`
|
||||
DirectTools []AIAgentMCPToolResponse `json:"directTools"`
|
||||
SortNo int `json:"sortNo"`
|
||||
Remark string `json:"remark"`
|
||||
CreatedAt string `json:"createdAt"`
|
||||
UpdatedAt string `json:"updatedAt"`
|
||||
CreateUserName string `json:"createUserName"`
|
||||
UpdateUserName string `json:"updateUserName"`
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package response
|
||||
|
||||
import "cs-agent/internal/pkg/enums"
|
||||
|
||||
type AssetResponse struct {
|
||||
ID int64 `json:"id"`
|
||||
AssetID string `json:"assetId"`
|
||||
Provider enums.AssetProvider `json:"provider"`
|
||||
Filename string `json:"filename"`
|
||||
FileSize int64 `json:"fileSize"`
|
||||
MimeType string `json:"mimeType"`
|
||||
Status enums.AssetStatus `json:"status"`
|
||||
StorageKey string `json:"storageKey"`
|
||||
URL string `json:"url"`
|
||||
CreatedAt string `json:"createdAt"`
|
||||
UpdatedAt string `json:"updatedAt"`
|
||||
CreateUserID int64 `json:"createUserId"`
|
||||
CreateUserName string `json:"createUserName"`
|
||||
UpdateUserID int64 `json:"updateUserId"`
|
||||
UpdateUserName string `json:"updateUserName"`
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package response
|
||||
|
||||
import "cs-agent/internal/pkg/enums"
|
||||
|
||||
type AuthUserResponse struct {
|
||||
ID int64 `json:"id"`
|
||||
Username string `json:"username"`
|
||||
Nickname string `json:"nickname"`
|
||||
Avatar string `json:"avatar"`
|
||||
Status enums.Status `json:"status"`
|
||||
Roles []string `json:"roles"`
|
||||
}
|
||||
|
||||
type LoginResponse struct {
|
||||
AccessToken string `json:"accessToken"`
|
||||
RefreshToken string `json:"refreshToken"`
|
||||
ExpiresAt string `json:"expiresAt"`
|
||||
User *AuthUserResponse `json:"user"`
|
||||
Permissions []string `json:"permissions"`
|
||||
Roles []string `json:"roles"`
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package response
|
||||
|
||||
import (
|
||||
"cs-agent/internal/models"
|
||||
"cs-agent/internal/pkg/enums"
|
||||
)
|
||||
|
||||
type ChannelResponse struct {
|
||||
ID int64 `json:"id"`
|
||||
ChannelType string `json:"channelType"`
|
||||
ChannelID string `json:"channelId"`
|
||||
AIAgentID int64 `json:"aiAgentId"`
|
||||
AIAgentName string `json:"aiAgentName,omitempty"`
|
||||
Name string `json:"name"`
|
||||
ConfigJSON string `json:"configJson"`
|
||||
Status enums.Status `json:"status"`
|
||||
Remark string `json:"remark"`
|
||||
}
|
||||
|
||||
func BuildChannelResponse(item *models.Channel) ChannelResponse {
|
||||
if item == nil {
|
||||
return ChannelResponse{}
|
||||
}
|
||||
return ChannelResponse{
|
||||
ID: item.ID,
|
||||
ChannelType: item.ChannelType,
|
||||
ChannelID: item.ChannelID,
|
||||
AIAgentID: item.AIAgentID,
|
||||
Name: item.Name,
|
||||
ConfigJSON: item.ConfigJSON,
|
||||
Status: item.Status,
|
||||
Remark: item.Remark,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package response
|
||||
|
||||
import "cs-agent/internal/pkg/enums"
|
||||
|
||||
type CompanyResponse struct {
|
||||
ID int64 `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Code string `json:"code"`
|
||||
CustomerCount int64 `json:"customerCount"`
|
||||
Status enums.Status `json:"status"`
|
||||
Remark string `json:"remark"`
|
||||
CreatedAt string `json:"createdAt"`
|
||||
UpdatedAt string `json:"updatedAt"`
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package response
|
||||
|
||||
import "cs-agent/internal/pkg/enums"
|
||||
|
||||
type ConversationTagResponse struct {
|
||||
ID int64 `json:"id"`
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
type ConversationParticipantResponse struct {
|
||||
ID int64 `json:"id"`
|
||||
ParticipantType string `json:"participantType"`
|
||||
ParticipantID int64 `json:"participantId"`
|
||||
ExternalParticipantID string `json:"externalParticipantId,omitempty"`
|
||||
JoinedAt string `json:"joinedAt,omitempty"`
|
||||
LeftAt string `json:"leftAt,omitempty"`
|
||||
Status enums.Status `json:"status"`
|
||||
}
|
||||
|
||||
type ConversationResponse struct {
|
||||
ID int64 `json:"id"`
|
||||
AIAgentID int64 `json:"aiAgentId"`
|
||||
CustomerID int64 `json:"customerId"`
|
||||
ExternalSource enums.ExternalSource `json:"externalSource"`
|
||||
ExternalID string `json:"externalId"`
|
||||
Subject string `json:"subject"`
|
||||
Status enums.IMConversationStatus `json:"status"`
|
||||
ServiceMode enums.IMConversationServiceMode `json:"serviceMode"`
|
||||
Priority int `json:"priority"`
|
||||
CurrentAssigneeID int64 `json:"currentAssigneeId"`
|
||||
CurrentAssigneeName string `json:"currentAssigneeName,omitempty"`
|
||||
LastMessageID int64 `json:"lastMessageId"`
|
||||
LastMessageAt string `json:"lastMessageAt,omitempty"`
|
||||
LastActiveAt string `json:"lastActiveAt,omitempty"`
|
||||
LastMessageSummary string `json:"lastMessageSummary,omitempty"`
|
||||
CustomerUnreadCount int `json:"customerUnreadCount"`
|
||||
AgentUnreadCount int `json:"agentUnreadCount"`
|
||||
CustomerLastReadMessageID int64 `json:"customerLastReadMessageId"`
|
||||
CustomerLastReadSeqNo int64 `json:"customerLastReadSeqNo"`
|
||||
CustomerLastReadAt string `json:"customerLastReadAt,omitempty"`
|
||||
AgentLastReadMessageID int64 `json:"agentLastReadMessageId"`
|
||||
AgentLastReadSeqNo int64 `json:"agentLastReadSeqNo"`
|
||||
AgentLastReadAt string `json:"agentLastReadAt,omitempty"`
|
||||
ClosedAt string `json:"closedAt,omitempty"`
|
||||
ClosedBy int64 `json:"closedBy"`
|
||||
ClosedByName string `json:"closedByName,omitempty"`
|
||||
CloseReason string `json:"closeReason,omitempty"`
|
||||
}
|
||||
|
||||
type ConversationDetailResponse struct {
|
||||
ConversationResponse
|
||||
Participants []ConversationParticipantResponse `json:"participants,omitempty"`
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package response
|
||||
|
||||
import "cs-agent/internal/pkg/enums"
|
||||
|
||||
type CustomerContactResponse struct {
|
||||
ID int64 `json:"id"`
|
||||
CustomerID int64 `json:"customerId"`
|
||||
ContactType enums.ContactType `json:"contactType"`
|
||||
ContactValue string `json:"contactValue"`
|
||||
IsPrimary bool `json:"isPrimary"`
|
||||
IsVerified bool `json:"isVerified"`
|
||||
VerifiedAt string `json:"verifiedAt,omitempty"`
|
||||
Source string `json:"source"`
|
||||
Status enums.Status `json:"status"`
|
||||
Remark string `json:"remark"`
|
||||
CreatedAt string `json:"createdAt"`
|
||||
UpdatedAt string `json:"updatedAt"`
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package response
|
||||
|
||||
import "cs-agent/internal/pkg/enums"
|
||||
|
||||
type CustomerResponse struct {
|
||||
ID int64 `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Gender enums.Gender `json:"gender"`
|
||||
CompanyID int64 `json:"companyId"`
|
||||
Company *CompanyResponse `json:"company"`
|
||||
LastActiveAt string `json:"lastActiveAt"`
|
||||
PrimaryMobile string `json:"primaryMobile"`
|
||||
PrimaryEmail string `json:"primaryEmail"`
|
||||
Status enums.Status `json:"status"`
|
||||
Remark string `json:"remark"`
|
||||
CreatedAt string `json:"createdAt"`
|
||||
UpdatedAt string `json:"updatedAt"`
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
package response
|
||||
|
||||
type DashboardOverviewResponse struct {
|
||||
Range string `json:"range"`
|
||||
GeneratedAt string `json:"generatedAt"`
|
||||
Summary DashboardSummaryResponse `json:"summary"`
|
||||
ConversationStats DashboardSectionStatsResponse `json:"conversationStats"`
|
||||
AgentStats DashboardAgentStatsResponse `json:"agentStats"`
|
||||
AIStats DashboardAIStatsResponse `json:"aiStats"`
|
||||
Alerts []DashboardAlertResponse `json:"alerts"`
|
||||
QuickLinks []DashboardQuickLinkResponse `json:"quickLinks"`
|
||||
}
|
||||
|
||||
type DashboardSummaryResponse struct {
|
||||
TodayNewConversations int64 `json:"todayNewConversations"`
|
||||
ProcessingConversations int64 `json:"processingConversations"`
|
||||
PendingDispatchConversations int64 `json:"pendingDispatchConversations"`
|
||||
OnlineAgents int64 `json:"onlineAgents"`
|
||||
AIServiceRate float64 `json:"aiServiceRate"`
|
||||
}
|
||||
|
||||
type DashboardSectionStatsResponse struct {
|
||||
StatusDistribution []DashboardStatusDistributionItem `json:"statusDistribution"`
|
||||
Trend []DashboardTrendItem `json:"trend"`
|
||||
}
|
||||
|
||||
type DashboardStatusDistributionItem struct {
|
||||
Status int `json:"status"`
|
||||
Label string `json:"label"`
|
||||
Count int64 `json:"count"`
|
||||
}
|
||||
|
||||
type DashboardTrendItem struct {
|
||||
Date string `json:"date"`
|
||||
NewCount int64 `json:"newCount"`
|
||||
ClosedCount int64 `json:"closedCount"`
|
||||
}
|
||||
|
||||
type DashboardAgentStatsResponse struct {
|
||||
OnlineAgents int64 `json:"onlineAgents"`
|
||||
BusyAgents int64 `json:"busyAgents"`
|
||||
OfflineAgents int64 `json:"offlineAgents"`
|
||||
TeamLoads []DashboardTeamLoadResponse `json:"teamLoads"`
|
||||
}
|
||||
|
||||
type DashboardTeamLoadResponse struct {
|
||||
TeamID int64 `json:"teamId"`
|
||||
TeamName string `json:"teamName"`
|
||||
TotalAgents int64 `json:"totalAgents"`
|
||||
OnlineAgents int64 `json:"onlineAgents"`
|
||||
BusyAgents int64 `json:"busyAgents"`
|
||||
OfflineAgents int64 `json:"offlineAgents"`
|
||||
WaitingConversations int64 `json:"waitingConversations"`
|
||||
ProcessingConversations int64 `json:"processingConversations"`
|
||||
MaxConcurrentCapacity int64 `json:"maxConcurrentCapacity"`
|
||||
LoadRate float64 `json:"loadRate"`
|
||||
HasScheduleNow bool `json:"hasScheduleNow"`
|
||||
}
|
||||
|
||||
type DashboardAIStatsResponse struct {
|
||||
EnabledAIAgents int64 `json:"enabledAiAgents"`
|
||||
EnabledChannels int64 `json:"enabledChannels"`
|
||||
TodayKnowledgeRetrieves int64 `json:"todayKnowledgeRetrieves"`
|
||||
TodayKnowledgeRetrieveFailCount int64 `json:"todayKnowledgeRetrieveFailCount"`
|
||||
TodayKnowledgeRetrieveFailRate float64 `json:"todayKnowledgeRetrieveFailRate"`
|
||||
TodaySkillRunFailCount int64 `json:"todaySkillRunFailCount"`
|
||||
TodayAIHandoffCount int64 `json:"todayAiHandoffCount"`
|
||||
}
|
||||
|
||||
type DashboardAlertResponse struct {
|
||||
ID string `json:"id"`
|
||||
Level string `json:"level"`
|
||||
Title string `json:"title"`
|
||||
Description string `json:"description"`
|
||||
Count int64 `json:"count"`
|
||||
Link string `json:"link"`
|
||||
}
|
||||
|
||||
type DashboardQuickLinkResponse struct {
|
||||
Title string `json:"title"`
|
||||
Description string `json:"description"`
|
||||
Link string `json:"link"`
|
||||
}
|
||||
@@ -0,0 +1,204 @@
|
||||
package response
|
||||
|
||||
import (
|
||||
"cs-agent/internal/pkg/enums"
|
||||
"time"
|
||||
)
|
||||
|
||||
type KnowledgeBaseResponse struct {
|
||||
ID int64 `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
KnowledgeType string `json:"knowledgeType"`
|
||||
KnowledgeTypeName string `json:"knowledgeTypeName"`
|
||||
Status enums.Status `json:"status"`
|
||||
StatusName string `json:"statusName"`
|
||||
DefaultTopK int `json:"defaultTopK"`
|
||||
DefaultScoreThreshold float64 `json:"defaultScoreThreshold"`
|
||||
DefaultRerankLimit int `json:"defaultRerankLimit"`
|
||||
ChunkProvider string `json:"chunkProvider"`
|
||||
ChunkTargetTokens int `json:"chunkTargetTokens"`
|
||||
ChunkMaxTokens int `json:"chunkMaxTokens"`
|
||||
ChunkOverlapTokens int `json:"chunkOverlapTokens"`
|
||||
AnswerMode int `json:"answerMode"`
|
||||
AnswerModeName string `json:"answerModeName"`
|
||||
FallbackMode int `json:"fallbackMode"`
|
||||
FallbackModeName string `json:"fallbackModeName"`
|
||||
DocumentCount int64 `json:"documentCount"`
|
||||
FAQCount int64 `json:"faqCount"`
|
||||
Remark string `json:"remark"`
|
||||
CreatedAt time.Time `json:"createdAt"`
|
||||
UpdatedAt time.Time `json:"updatedAt"`
|
||||
CreateUserName string `json:"createUserName"`
|
||||
UpdateUserName string `json:"updateUserName"`
|
||||
}
|
||||
|
||||
type KnowledgeDocumentResponse struct {
|
||||
ID int64 `json:"id"`
|
||||
KnowledgeBaseID int64 `json:"knowledgeBaseId"`
|
||||
KnowledgeBaseName string `json:"knowledgeBaseName,omitempty"`
|
||||
Title string `json:"title"`
|
||||
ContentType enums.KnowledgeDocumentContentType `json:"contentType"`
|
||||
Content string `json:"content"`
|
||||
Status enums.Status `json:"status"`
|
||||
StatusName string `json:"statusName"`
|
||||
IndexStatus enums.KnowledgeDocumentIndexStatus `json:"indexStatus"`
|
||||
IndexStatusName string `json:"indexStatusName"`
|
||||
IndexedAt *time.Time `json:"indexedAt"`
|
||||
IndexError string `json:"indexError"`
|
||||
ContentHash string `json:"contentHash"`
|
||||
CreatedAt time.Time `json:"createdAt"`
|
||||
UpdatedAt time.Time `json:"updatedAt"`
|
||||
CreateUserName string `json:"createUserName"`
|
||||
UpdateUserName string `json:"updateUserName"`
|
||||
}
|
||||
|
||||
type KnowledgeFAQResponse struct {
|
||||
ID int64 `json:"id"`
|
||||
KnowledgeBaseID int64 `json:"knowledgeBaseId"`
|
||||
KnowledgeBaseName string `json:"knowledgeBaseName,omitempty"`
|
||||
Question string `json:"question"`
|
||||
Answer string `json:"answer"`
|
||||
SimilarQuestions []string `json:"similarQuestions"`
|
||||
Status enums.Status `json:"status"`
|
||||
StatusName string `json:"statusName"`
|
||||
IndexStatus enums.KnowledgeDocumentIndexStatus `json:"indexStatus"`
|
||||
IndexStatusName string `json:"indexStatusName"`
|
||||
IndexedAt *time.Time `json:"indexedAt"`
|
||||
IndexError string `json:"indexError"`
|
||||
Remark string `json:"remark"`
|
||||
CreatedAt time.Time `json:"createdAt"`
|
||||
UpdatedAt time.Time `json:"updatedAt"`
|
||||
CreateUserName string `json:"createUserName"`
|
||||
UpdateUserName string `json:"updateUserName"`
|
||||
}
|
||||
|
||||
type KnowledgeSearchResult struct {
|
||||
KnowledgeBaseID int64 `json:"knowledgeBaseId"`
|
||||
ChunkID int64 `json:"chunkId"`
|
||||
DocumentID int64 `json:"documentId"`
|
||||
DocumentTitle string `json:"documentTitle"`
|
||||
FaqID int64 `json:"faqId"`
|
||||
FaqQuestion string `json:"faqQuestion"`
|
||||
ChunkNo int `json:"chunkNo"`
|
||||
Title string `json:"title"`
|
||||
SectionPath string `json:"sectionPath"`
|
||||
Content string `json:"content"`
|
||||
Score float64 `json:"score"`
|
||||
RerankScore float64 `json:"rerankScore"`
|
||||
}
|
||||
|
||||
type KnowledgeSearchResponse struct {
|
||||
Question string `json:"question"`
|
||||
Results []KnowledgeSearchResult `json:"results"`
|
||||
HitCount int `json:"hitCount"`
|
||||
LatencyMs int64 `json:"latencyMs"`
|
||||
}
|
||||
|
||||
type KnowledgeAnswerResponse struct {
|
||||
Question string `json:"question"`
|
||||
RewriteQuestion string `json:"rewriteQuestion,omitempty"`
|
||||
Answer string `json:"answer"`
|
||||
AnswerStatus int `json:"answerStatus"`
|
||||
AnswerStatusName string `json:"answerStatusName"`
|
||||
Citations []KnowledgeCitation `json:"citations"`
|
||||
Hits []KnowledgeSearchResult `json:"hits"`
|
||||
HitCount int `json:"hitCount"`
|
||||
TopScore float64 `json:"topScore"`
|
||||
LatencyMs int64 `json:"latencyMs"`
|
||||
RetrieveMs int64 `json:"retrieveMs"`
|
||||
GenerateMs int64 `json:"generateMs"`
|
||||
PromptTokens int `json:"promptTokens"`
|
||||
CompletionTokens int `json:"completionTokens"`
|
||||
ModelName string `json:"modelName"`
|
||||
RetrieveLogID int64 `json:"retrieveLogId"`
|
||||
}
|
||||
|
||||
type KnowledgeCitation struct {
|
||||
DocumentID int64 `json:"documentId"`
|
||||
DocumentTitle string `json:"documentTitle"`
|
||||
FaqID int64 `json:"faqId"`
|
||||
FaqQuestion string `json:"faqQuestion"`
|
||||
ChunkNo int `json:"chunkNo"`
|
||||
Title string `json:"title"`
|
||||
SectionPath string `json:"sectionPath"`
|
||||
Snippet string `json:"snippet"`
|
||||
Score float64 `json:"score"`
|
||||
}
|
||||
|
||||
type KnowledgeRetrieveLogResponse struct {
|
||||
ID int64 `json:"id"`
|
||||
KnowledgeBaseID int64 `json:"knowledgeBaseId"`
|
||||
KnowledgeBaseName string `json:"knowledgeBaseName,omitempty"`
|
||||
Channel string `json:"channel"`
|
||||
ChannelName string `json:"channelName"`
|
||||
Scene string `json:"scene"`
|
||||
SceneName string `json:"sceneName"`
|
||||
SessionID string `json:"sessionId"`
|
||||
ConversationID int64 `json:"conversationId"`
|
||||
RequestID string `json:"requestId"`
|
||||
Question string `json:"question"`
|
||||
RewriteQuestion string `json:"rewriteQuestion"`
|
||||
Answer string `json:"answer"`
|
||||
AnswerStatus int `json:"answerStatus"`
|
||||
AnswerStatusName string `json:"answerStatusName"`
|
||||
HitCount int `json:"hitCount"`
|
||||
TopScore float64 `json:"topScore"`
|
||||
ChunkProvider string `json:"chunkProvider"`
|
||||
ChunkTargetTokens int `json:"chunkTargetTokens"`
|
||||
ChunkMaxTokens int `json:"chunkMaxTokens"`
|
||||
ChunkOverlapTokens int `json:"chunkOverlapTokens"`
|
||||
RerankEnabled bool `json:"rerankEnabled"`
|
||||
RerankLimit int `json:"rerankLimit"`
|
||||
CitationCount int `json:"citationCount"`
|
||||
UsedChunkCount int `json:"usedChunkCount"`
|
||||
LatencyMs int64 `json:"latencyMs"`
|
||||
RetrieveMs int64 `json:"retrieveMs"`
|
||||
GenerateMs int64 `json:"generateMs"`
|
||||
PromptTokens int `json:"promptTokens"`
|
||||
CompletionTokens int `json:"completionTokens"`
|
||||
ModelName string `json:"modelName"`
|
||||
TraceData string `json:"traceData"`
|
||||
CreatedAt time.Time `json:"createdAt"`
|
||||
}
|
||||
|
||||
type KnowledgeRetrieveHitResponse struct {
|
||||
ID int64 `json:"id"`
|
||||
RetrieveLogID int64 `json:"retrieveLogId"`
|
||||
KnowledgeBaseID int64 `json:"knowledgeBaseId"`
|
||||
ChunkID int64 `json:"chunkId"`
|
||||
DocumentID int64 `json:"documentId"`
|
||||
DocumentTitle string `json:"documentTitle"`
|
||||
FaqID int64 `json:"faqId"`
|
||||
FaqQuestion string `json:"faqQuestion"`
|
||||
ChunkNo int `json:"chunkNo"`
|
||||
Title string `json:"title"`
|
||||
SectionPath string `json:"sectionPath"`
|
||||
ChunkType string `json:"chunkType"`
|
||||
ChunkTypeName string `json:"chunkTypeName"`
|
||||
Provider string `json:"provider"`
|
||||
RankNo int `json:"rankNo"`
|
||||
Score float64 `json:"score"`
|
||||
RerankScore float64 `json:"rerankScore"`
|
||||
UsedInAnswer bool `json:"usedInAnswer"`
|
||||
IsCitation bool `json:"isCitation"`
|
||||
Snippet string `json:"snippet"`
|
||||
CreatedAt time.Time `json:"createdAt"`
|
||||
}
|
||||
|
||||
type KnowledgeRetrieveLogDetailResponse struct {
|
||||
Log KnowledgeRetrieveLogResponse `json:"log"`
|
||||
Hits []KnowledgeRetrieveHitResponse `json:"hits"`
|
||||
}
|
||||
|
||||
type KnowledgeFeedbackResponse struct {
|
||||
ID int64 `json:"id"`
|
||||
RetrieveLogID int64 `json:"retrieveLogId"`
|
||||
FeedbackType int `json:"feedbackType"`
|
||||
FeedbackTypeName string `json:"feedbackTypeName"`
|
||||
FeedbackReason string `json:"feedbackReason"`
|
||||
UserID int64 `json:"userId"`
|
||||
AgentID int64 `json:"agentId"`
|
||||
Remark string `json:"remark"`
|
||||
CreatedAt time.Time `json:"createdAt"`
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
package response
|
||||
|
||||
import "cs-agent/internal/ai/mcps"
|
||||
|
||||
type MCPConnectionResponse struct {
|
||||
ServerCode string `json:"serverCode"`
|
||||
Endpoint string `json:"endpoint"`
|
||||
Protocol string `json:"protocol"`
|
||||
ServerName string `json:"serverName"`
|
||||
Version string `json:"version"`
|
||||
}
|
||||
|
||||
func BuildMCPConnectionResponse(item *mcps.ConnectionResult) *MCPConnectionResponse {
|
||||
if item == nil {
|
||||
return nil
|
||||
}
|
||||
return &MCPConnectionResponse{
|
||||
ServerCode: item.ServerCode,
|
||||
Endpoint: item.Endpoint,
|
||||
Protocol: item.Protocol,
|
||||
ServerName: item.ServerName,
|
||||
Version: item.Version,
|
||||
}
|
||||
}
|
||||
|
||||
type MCPServerInfoResponse struct {
|
||||
Code string `json:"code"`
|
||||
Enabled bool `json:"enabled"`
|
||||
Endpoint string `json:"endpoint"`
|
||||
TimeoutMS int `json:"timeoutMs"`
|
||||
}
|
||||
|
||||
func BuildMCPServerInfoResponses(items []mcps.ServerInfo) []MCPServerInfoResponse {
|
||||
ret := make([]MCPServerInfoResponse, 0, len(items))
|
||||
for _, item := range items {
|
||||
ret = append(ret, MCPServerInfoResponse{
|
||||
Code: item.Code,
|
||||
Enabled: item.Enabled,
|
||||
Endpoint: item.Endpoint,
|
||||
TimeoutMS: item.TimeoutMS,
|
||||
})
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
type MCPToolInfoResponse struct {
|
||||
Name string `json:"name"`
|
||||
Title string `json:"title"`
|
||||
Description string `json:"description"`
|
||||
InputSchema any `json:"inputSchema"`
|
||||
OutputSchema any `json:"outputSchema,omitempty"`
|
||||
}
|
||||
|
||||
func BuildMCPToolInfoResponses(items []mcps.ToolInfo) []MCPToolInfoResponse {
|
||||
ret := make([]MCPToolInfoResponse, 0, len(items))
|
||||
for _, item := range items {
|
||||
ret = append(ret, MCPToolInfoResponse{
|
||||
Name: item.Name,
|
||||
Title: item.Title,
|
||||
Description: item.Description,
|
||||
InputSchema: item.InputSchema,
|
||||
OutputSchema: item.OutputSchema,
|
||||
})
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
type MCPToolResultContentResponse struct {
|
||||
Type string `json:"type"`
|
||||
Text string `json:"text,omitempty"`
|
||||
Data any `json:"data,omitempty"`
|
||||
}
|
||||
|
||||
type MCPCallToolResponse struct {
|
||||
ServerCode string `json:"serverCode"`
|
||||
ToolName string `json:"toolName"`
|
||||
IsError bool `json:"isError"`
|
||||
Content []MCPToolResultContentResponse `json:"content"`
|
||||
StructuredContent any `json:"structuredContent,omitempty"`
|
||||
}
|
||||
|
||||
func BuildMCPCallToolResponse(item *mcps.ToolCallResult) *MCPCallToolResponse {
|
||||
if item == nil {
|
||||
return nil
|
||||
}
|
||||
content := make([]MCPToolResultContentResponse, 0, len(item.Content))
|
||||
for _, c := range item.Content {
|
||||
content = append(content, MCPToolResultContentResponse{
|
||||
Type: c.Type,
|
||||
Text: c.Text,
|
||||
Data: c.Data,
|
||||
})
|
||||
}
|
||||
return &MCPCallToolResponse{
|
||||
ServerCode: item.ServerCode,
|
||||
ToolName: item.ToolName,
|
||||
IsError: item.IsError,
|
||||
Content: content,
|
||||
StructuredContent: item.StructuredContent,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package response
|
||||
|
||||
import "cs-agent/internal/pkg/enums"
|
||||
|
||||
type MessageResponse struct {
|
||||
ID int64 `json:"id"`
|
||||
ConversationID int64 `json:"conversationId"`
|
||||
ClientMsgID string `json:"clientMsgId,omitempty"`
|
||||
SenderType enums.IMSenderType `json:"senderType"`
|
||||
SenderID int64 `json:"senderId"`
|
||||
SenderName string `json:"senderName,omitempty"`
|
||||
SenderAvatar string `json:"senderAvatar,omitempty"`
|
||||
MessageType enums.IMMessageType `json:"messageType"`
|
||||
Content string `json:"content"`
|
||||
Payload string `json:"payload,omitempty"`
|
||||
SeqNo int64 `json:"seqNo"`
|
||||
SendStatus int `json:"sendStatus"`
|
||||
SentAt string `json:"sentAt,omitempty"`
|
||||
DeliveredAt string `json:"deliveredAt,omitempty"`
|
||||
ReadAt string `json:"readAt,omitempty"`
|
||||
CustomerRead bool `json:"customerRead"`
|
||||
CustomerReadAt string `json:"customerReadAt,omitempty"`
|
||||
AgentRead bool `json:"agentRead"`
|
||||
AgentReadAt string `json:"agentReadAt,omitempty"`
|
||||
RecalledAt string `json:"recalledAt,omitempty"`
|
||||
QuotedMessageID int64 `json:"quotedMessageId,omitempty"`
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package response
|
||||
|
||||
import "cs-agent/internal/pkg/enums"
|
||||
|
||||
type QuickReplyResponse struct {
|
||||
ID int64 `json:"id"`
|
||||
GroupName string `json:"groupName"`
|
||||
Title string `json:"title"`
|
||||
Content string `json:"content"`
|
||||
Status enums.Status `json:"status"`
|
||||
SortNo int `json:"sortNo"`
|
||||
CreatedBy int64 `json:"createdBy"`
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package response
|
||||
|
||||
import "time"
|
||||
|
||||
type SkillDefinitionResponse struct {
|
||||
ID int64 `json:"id"`
|
||||
Code string `json:"code"`
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
Prompt string `json:"prompt"`
|
||||
ExecutionMode string `json:"executionMode"`
|
||||
ExecutionModeName string `json:"executionModeName"`
|
||||
ExecutionConfig string `json:"executionConfig"`
|
||||
Priority int `json:"priority"`
|
||||
Status int `json:"status"`
|
||||
StatusName string `json:"statusName"`
|
||||
Remark string `json:"remark"`
|
||||
CreatedAt time.Time `json:"createdAt"`
|
||||
UpdatedAt time.Time `json:"updatedAt"`
|
||||
CreateUserName string `json:"createUserName"`
|
||||
UpdateUserName string `json:"updateUserName"`
|
||||
}
|
||||
|
||||
type SkillDebugRunResponse struct {
|
||||
SkillCode string `json:"skillCode"`
|
||||
SkillName string `json:"skillName"`
|
||||
ReplyText string `json:"replyText"`
|
||||
RunLogID int64 `json:"runLogId"`
|
||||
TraceData string `json:"traceData"`
|
||||
ConversationID int64 `json:"conversationId"`
|
||||
AIAgentID int64 `json:"aiAgentId"`
|
||||
}
|
||||
|
||||
type AgentRunLogResponse struct {
|
||||
ID int64 `json:"id"`
|
||||
ConversationID int64 `json:"conversationId"`
|
||||
MessageID int64 `json:"messageId"`
|
||||
AIAgentID int64 `json:"aiAgentId"`
|
||||
AIConfigID int64 `json:"aiConfigId"`
|
||||
UserMessage string `json:"userMessage"`
|
||||
PlannedAction string `json:"plannedAction"`
|
||||
PlannedSkillCode string `json:"plannedSkillCode"`
|
||||
PlannedToolCode string `json:"plannedToolCode"`
|
||||
PlanReason string `json:"planReason"`
|
||||
FinalAction string `json:"finalAction"`
|
||||
ReplyText string `json:"replyText"`
|
||||
ErrorMessage string `json:"errorMessage"`
|
||||
LatencyMs int64 `json:"latencyMs"`
|
||||
TraceData string `json:"traceData"`
|
||||
CreatedAt string `json:"createdAt"`
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package response
|
||||
|
||||
import "cs-agent/internal/pkg/enums"
|
||||
|
||||
type TagResponse struct {
|
||||
ID int64 `json:"id"`
|
||||
ParentID int64 `json:"parentId"`
|
||||
Name string `json:"name"`
|
||||
Remark string `json:"remark"`
|
||||
SortNo int `json:"sortNo"`
|
||||
Status enums.Status `json:"status"`
|
||||
CreatedAt string `json:"createdAt"`
|
||||
UpdatedAt string `json:"updatedAt"`
|
||||
}
|
||||
|
||||
type TagTreeResponse struct {
|
||||
ID int64 `json:"id"`
|
||||
ParentID int64 `json:"parentId"`
|
||||
Name string `json:"name"`
|
||||
Remark string `json:"remark"`
|
||||
SortNo int `json:"sortNo"`
|
||||
Status enums.Status `json:"status"`
|
||||
CreatedAt string `json:"createdAt"`
|
||||
UpdatedAt string `json:"updatedAt"`
|
||||
Children []*TagTreeResponse `json:"children"`
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package response
|
||||
|
||||
import "cs-agent/internal/pkg/enums"
|
||||
|
||||
type TicketResolutionCodeResponse struct {
|
||||
ID int64 `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Code string `json:"code"`
|
||||
SortNo int `json:"sortNo"`
|
||||
Status enums.Status `json:"status"`
|
||||
Remark string `json:"remark"`
|
||||
}
|
||||
|
||||
type TicketPriorityConfigResponse struct {
|
||||
ID int64 `json:"id"`
|
||||
Name string `json:"name"`
|
||||
SortNo int `json:"sortNo"`
|
||||
FirstResponseMinutes int `json:"firstResponseMinutes"`
|
||||
ResolutionMinutes int `json:"resolutionMinutes"`
|
||||
Status enums.Status `json:"status"`
|
||||
Remark string `json:"remark"`
|
||||
}
|
||||
@@ -0,0 +1,151 @@
|
||||
package response
|
||||
|
||||
import "cs-agent/internal/pkg/enums"
|
||||
|
||||
type TicketSLAResponse struct {
|
||||
SLAType enums.TicketSLAType `json:"slaType"`
|
||||
TargetMinutes int `json:"targetMinutes"`
|
||||
Status enums.TicketSLAStatus `json:"status"`
|
||||
StartedAt string `json:"startedAt,omitempty"`
|
||||
PausedAt string `json:"pausedAt,omitempty"`
|
||||
StoppedAt string `json:"stoppedAt,omitempty"`
|
||||
BreachedAt string `json:"breachedAt,omitempty"`
|
||||
ElapsedMin int `json:"elapsedMin"`
|
||||
}
|
||||
|
||||
type TicketWatcherResponse struct {
|
||||
ID int64 `json:"id"`
|
||||
UserID int64 `json:"userId"`
|
||||
UserName string `json:"userName,omitempty"`
|
||||
}
|
||||
|
||||
type TicketCommentResponse struct {
|
||||
ID int64 `json:"id"`
|
||||
TicketID int64 `json:"ticketId"`
|
||||
CommentType enums.TicketCommentType `json:"commentType"`
|
||||
AuthorType enums.IMSenderType `json:"authorType"`
|
||||
AuthorID int64 `json:"authorId"`
|
||||
AuthorName string `json:"authorName,omitempty"`
|
||||
ContentType string `json:"contentType"`
|
||||
Content string `json:"content"`
|
||||
Payload string `json:"payload,omitempty"`
|
||||
CreatedAt string `json:"createdAt,omitempty"`
|
||||
}
|
||||
|
||||
type TicketEventLogResponse struct {
|
||||
ID int64 `json:"id"`
|
||||
TicketID int64 `json:"ticketId"`
|
||||
EventType enums.TicketEventType `json:"eventType"`
|
||||
OperatorType enums.IMSenderType `json:"operatorType"`
|
||||
OperatorID int64 `json:"operatorId"`
|
||||
OperatorName string `json:"operatorName,omitempty"`
|
||||
OldValue string `json:"oldValue,omitempty"`
|
||||
NewValue string `json:"newValue,omitempty"`
|
||||
Content string `json:"content,omitempty"`
|
||||
Payload string `json:"payload,omitempty"`
|
||||
CreatedAt string `json:"createdAt,omitempty"`
|
||||
}
|
||||
|
||||
type TicketResponse struct {
|
||||
ID int64 `json:"id"`
|
||||
TicketNo string `json:"ticketNo"`
|
||||
Title string `json:"title"`
|
||||
Description string `json:"description"`
|
||||
Source enums.TicketSource `json:"source"`
|
||||
Channel string `json:"channel"`
|
||||
CustomerID int64 `json:"customerId"`
|
||||
ConversationID int64 `json:"conversationId"`
|
||||
Tags []TagResponse `json:"tags,omitempty"`
|
||||
Type string `json:"type"`
|
||||
Priority int64 `json:"priority"`
|
||||
PriorityName string `json:"priorityName,omitempty"`
|
||||
Severity enums.TicketSeverity `json:"severity"`
|
||||
Status enums.TicketStatus `json:"status"`
|
||||
CurrentTeamID int64 `json:"currentTeamId"`
|
||||
CurrentTeamName string `json:"currentTeamName,omitempty"`
|
||||
CurrentAssigneeID int64 `json:"currentAssigneeId"`
|
||||
CurrentAssigneeName string `json:"currentAssigneeName,omitempty"`
|
||||
WatchedByMe bool `json:"watchedByMe"`
|
||||
PendingReason string `json:"pendingReason,omitempty"`
|
||||
CloseReason string `json:"closeReason,omitempty"`
|
||||
ResolutionCode string `json:"resolutionCode,omitempty"`
|
||||
ResolutionCodeName string `json:"resolutionCodeName,omitempty"`
|
||||
ResolutionSummary string `json:"resolutionSummary,omitempty"`
|
||||
FirstResponseAt string `json:"firstResponseAt,omitempty"`
|
||||
ResolvedAt string `json:"resolvedAt,omitempty"`
|
||||
ClosedAt string `json:"closedAt,omitempty"`
|
||||
DueAt string `json:"dueAt,omitempty"`
|
||||
NextReplyDeadlineAt string `json:"nextReplyDeadlineAt,omitempty"`
|
||||
ResolveDeadlineAt string `json:"resolveDeadlineAt,omitempty"`
|
||||
ReopenedCount int `json:"reopenedCount"`
|
||||
CreatedAt string `json:"createdAt,omitempty"`
|
||||
UpdatedAt string `json:"updatedAt,omitempty"`
|
||||
Customer *CustomerResponse `json:"customer,omitempty"`
|
||||
SLA []TicketSLAResponse `json:"sla,omitempty"`
|
||||
}
|
||||
|
||||
type TicketDetailResponse struct {
|
||||
Ticket TicketResponse `json:"ticket"`
|
||||
Watchers []TicketWatcherResponse `json:"watchers,omitempty"`
|
||||
Collaborators []TicketCollaboratorResponse `json:"collaborators,omitempty"`
|
||||
Comments []TicketCommentResponse `json:"comments,omitempty"`
|
||||
Events []TicketEventLogResponse `json:"events,omitempty"`
|
||||
RelatedTickets []TicketRelationResponse `json:"relatedTickets,omitempty"`
|
||||
}
|
||||
|
||||
type TicketSummaryResponse struct {
|
||||
All int64 `json:"all"`
|
||||
Mine int64 `json:"mine"`
|
||||
Watching int64 `json:"watching"`
|
||||
Collaboration int64 `json:"collaboration"`
|
||||
Participating int64 `json:"participating"`
|
||||
Mentioned int64 `json:"mentioned"`
|
||||
Unassigned int64 `json:"unassigned"`
|
||||
PendingCustomer int64 `json:"pendingCustomer"`
|
||||
PendingInternal int64 `json:"pendingInternal"`
|
||||
Overdue int64 `json:"overdue"`
|
||||
}
|
||||
|
||||
type TicketRiskReasonResponse struct {
|
||||
Code string `json:"code"`
|
||||
Title string `json:"title"`
|
||||
Description string `json:"description"`
|
||||
Count int64 `json:"count"`
|
||||
}
|
||||
|
||||
type TicketRiskOverviewResponse struct {
|
||||
Overdue int64 `json:"overdue"`
|
||||
HighRisk int64 `json:"highRisk"`
|
||||
Unassigned int64 `json:"unassigned"`
|
||||
PendingInternal int64 `json:"pendingInternal"`
|
||||
PendingCustomer int64 `json:"pendingCustomer"`
|
||||
RiskWindowMins int `json:"riskWindowMins"`
|
||||
Reasons []TicketRiskReasonResponse `json:"reasons,omitempty"`
|
||||
}
|
||||
|
||||
type TicketRelationResponse struct {
|
||||
ID int64 `json:"id"`
|
||||
TicketID int64 `json:"ticketId"`
|
||||
RelatedTicketID int64 `json:"relatedTicketId"`
|
||||
RelationType enums.TicketRelationType `json:"relationType"`
|
||||
RelatedTicketNo string `json:"relatedTicketNo,omitempty"`
|
||||
RelatedTicketTitle string `json:"relatedTicketTitle,omitempty"`
|
||||
RelatedTicketStatus enums.TicketStatus `json:"relatedTicketStatus,omitempty"`
|
||||
CurrentTeamName string `json:"currentTeamName,omitempty"`
|
||||
CurrentAssigneeName string `json:"currentAssigneeName,omitempty"`
|
||||
UpdatedAt string `json:"updatedAt,omitempty"`
|
||||
}
|
||||
|
||||
type TicketCollaboratorResponse struct {
|
||||
ID int64 `json:"id"`
|
||||
UserID int64 `json:"userId"`
|
||||
UserName string `json:"userName,omitempty"`
|
||||
TeamName string `json:"teamName,omitempty"`
|
||||
}
|
||||
|
||||
type TicketViewResponse struct {
|
||||
ID int64 `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Filters map[string]any `json:"filters,omitempty"`
|
||||
SortNo int `json:"sortNo"`
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package response
|
||||
|
||||
type WidgetConfigResponse struct {
|
||||
ChannelID string `json:"channelId"`
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package enums
|
||||
|
||||
type ServiceStatus int
|
||||
|
||||
const (
|
||||
ServiceStatusIdle ServiceStatus = 0
|
||||
ServiceStatusBusy ServiceStatus = 1
|
||||
)
|
||||
|
||||
var ServiceStatusValues = []ServiceStatus{
|
||||
ServiceStatusIdle,
|
||||
ServiceStatusBusy,
|
||||
}
|
||||
|
||||
var serviceStatusLabelMap = map[ServiceStatus]string{
|
||||
ServiceStatusIdle: "空闲",
|
||||
ServiceStatusBusy: "忙碌",
|
||||
}
|
||||
|
||||
func IsValidServiceStatus(status ServiceStatus) bool {
|
||||
for _, item := range ServiceStatusValues {
|
||||
if item == status {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func GetServiceStatusLabel(status ServiceStatus) string {
|
||||
return serviceStatusLabelMap[status]
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package enums
|
||||
|
||||
type AIProvider string
|
||||
|
||||
const (
|
||||
AIProviderOpenAI AIProvider = "openai"
|
||||
)
|
||||
|
||||
var aiProviderLabelMap = map[AIProvider]string{
|
||||
AIProviderOpenAI: "OpenAI",
|
||||
}
|
||||
|
||||
func GetAIProviderLabel(provider AIProvider) string {
|
||||
return aiProviderLabelMap[provider]
|
||||
}
|
||||
|
||||
type AIModelType string
|
||||
|
||||
const (
|
||||
AIModelTypeLLM AIModelType = "llm"
|
||||
AIModelTypeEmbedding AIModelType = "embedding"
|
||||
AIModelTypeRerank AIModelType = "rerank"
|
||||
)
|
||||
|
||||
var aiModelTypeLabelMap = map[AIModelType]string{
|
||||
AIModelTypeLLM: "大语言模型",
|
||||
AIModelTypeEmbedding: "向量模型",
|
||||
AIModelTypeRerank: "重排序模型",
|
||||
}
|
||||
|
||||
func GetAIModelTypeLabel(modelType AIModelType) string {
|
||||
return aiModelTypeLabelMap[modelType]
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package enums
|
||||
|
||||
type AssetStatus int
|
||||
|
||||
const (
|
||||
AssetStatusPending AssetStatus = 1
|
||||
AssetStatusSuccess AssetStatus = 2
|
||||
AssetStatusFailed AssetStatus = 3
|
||||
AssetStatusDeleted AssetStatus = 4
|
||||
)
|
||||
|
||||
var assetStatusLabelMap = map[AssetStatus]string{
|
||||
AssetStatusPending: "处理中",
|
||||
AssetStatusSuccess: "成功",
|
||||
AssetStatusFailed: "失败",
|
||||
AssetStatusDeleted: "已删除",
|
||||
}
|
||||
|
||||
func GetAssetStatusLabel(status AssetStatus) string {
|
||||
return assetStatusLabelMap[status]
|
||||
}
|
||||
|
||||
type AssetProvider string
|
||||
|
||||
const (
|
||||
AssetProviderLocal AssetProvider = "local"
|
||||
AssetProviderOSS AssetProvider = "oss"
|
||||
)
|
||||
|
||||
var assetProviderLabelMap = map[AssetProvider]string{
|
||||
AssetProviderLocal: "本地存储",
|
||||
AssetProviderOSS: "对象存储",
|
||||
}
|
||||
|
||||
func GetAssetProviderLabel(provider AssetProvider) string {
|
||||
return assetProviderLabelMap[provider]
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package enums
|
||||
|
||||
// CustomerSourceType 已合并为 ExternalIdentitySource,保留类型别名以兼容旧代码。
|
||||
type CustomerSourceType = ExternalSource
|
||||
|
||||
const CustomerSourceTypeWebChat = ExternalSourceWebChat
|
||||
|
||||
func GetCustomerSourceTypeLabel(sourceType CustomerSourceType) string {
|
||||
return GetExternalSourceLabel(ExternalSource(sourceType))
|
||||
}
|
||||
|
||||
// 联系方式类型
|
||||
type ContactType string
|
||||
|
||||
const (
|
||||
ContactTypeMobile ContactType = "mobile"
|
||||
ContactTypeEmail ContactType = "email"
|
||||
ContactTypeWeChat ContactType = "wechat"
|
||||
ContactTypeOther ContactType = "other"
|
||||
)
|
||||
|
||||
var contactTypeLabelMap = map[ContactType]string{
|
||||
ContactTypeMobile: "手机号",
|
||||
ContactTypeEmail: "邮箱",
|
||||
ContactTypeOther: "其他",
|
||||
}
|
||||
|
||||
func GetContactTypeLabel(contactType ContactType) string {
|
||||
return contactTypeLabelMap[contactType]
|
||||
}
|
||||
|
||||
// IsValidContactType 判断字符串是否为合法联系方式类型。
|
||||
func IsValidContactType(v string) bool {
|
||||
switch ContactType(v) {
|
||||
case ContactTypeMobile, ContactTypeEmail, ContactTypeWeChat, ContactTypeOther:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
package enums
|
||||
|
||||
type Status int
|
||||
|
||||
const (
|
||||
StatusOk Status = 0
|
||||
StatusDisabled Status = 1
|
||||
StatusDeleted Status = 2
|
||||
)
|
||||
|
||||
var StatusValues = []Status{StatusOk, StatusDisabled, StatusDeleted}
|
||||
|
||||
var statusLabelMap = map[Status]string{
|
||||
StatusOk: "启用",
|
||||
StatusDisabled: "禁用",
|
||||
StatusDeleted: "已删除",
|
||||
}
|
||||
|
||||
func GetStatusLabel(status Status) string {
|
||||
return statusLabelMap[status]
|
||||
}
|
||||
|
||||
func IsValidStatus(status int) bool {
|
||||
for _, s := range StatusValues {
|
||||
if int(s) == status {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type Gender int
|
||||
|
||||
const (
|
||||
GenderUnknown Gender = 0
|
||||
GenderMale Gender = 1
|
||||
GenderFemale Gender = 2
|
||||
)
|
||||
|
||||
var GenderValues = []Gender{GenderUnknown, GenderMale, GenderFemale}
|
||||
|
||||
var genderLabelMap = map[Gender]string{
|
||||
GenderUnknown: "未知",
|
||||
GenderMale: "男",
|
||||
GenderFemale: "女",
|
||||
}
|
||||
|
||||
func GetGenderLabel(gender Gender) string {
|
||||
return genderLabelMap[gender]
|
||||
}
|
||||
|
||||
func IsValidGender(gender int) bool {
|
||||
for _, g := range GenderValues {
|
||||
if int(g) == gender {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type ThirdProvider string
|
||||
|
||||
const (
|
||||
ThirdProviderWxWork ThirdProvider = "wxwork"
|
||||
ThirdProviderDingtalk ThirdProvider = "dingtalk"
|
||||
)
|
||||
|
||||
var ThirdProviderValues = []ThirdProvider{ThirdProviderWxWork, ThirdProviderDingtalk}
|
||||
|
||||
var thirdProviderLabelMap = map[ThirdProvider]string{
|
||||
ThirdProviderWxWork: "企业微信",
|
||||
ThirdProviderDingtalk: "钉钉",
|
||||
}
|
||||
|
||||
func GetThirdProviderLabel(provider ThirdProvider) string {
|
||||
return thirdProviderLabelMap[provider]
|
||||
}
|
||||
|
||||
func IsValidThirdProvider(provider string) bool {
|
||||
for _, p := range ThirdProviderValues {
|
||||
if string(p) == provider {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package enums
|
||||
|
||||
// ExternalSource 外部身份来源。
|
||||
//
|
||||
// 与 ExternalID 组合即可唯一标识某渠道下的访客身份。
|
||||
type ExternalSource string
|
||||
|
||||
const (
|
||||
ExternalSourceWebChat ExternalSource = "web_chat"
|
||||
ExternalSourceWxWorkKF ExternalSource = "wxwork_kf"
|
||||
)
|
||||
|
||||
var externalSourceLabelMap = map[ExternalSource]string{
|
||||
ExternalSourceWebChat: "网页客服",
|
||||
ExternalSourceWxWorkKF: "企业微信客服",
|
||||
}
|
||||
|
||||
func GetExternalSourceLabel(v ExternalSource) string {
|
||||
if s, ok := externalSourceLabelMap[v]; ok {
|
||||
return s
|
||||
}
|
||||
return string(v)
|
||||
}
|
||||
|
||||
// IsAllowedOpenImExternalSource 开放 IM 入口允许的外部来源(闭集校验)。
|
||||
func IsAllowedOpenImExternalSource(s ExternalSource) bool {
|
||||
switch s {
|
||||
case ExternalSourceWebChat:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,266 @@
|
||||
package enums
|
||||
|
||||
type IMConversationStatus int
|
||||
|
||||
const (
|
||||
IMConversationStatusPending IMConversationStatus = 1
|
||||
IMConversationStatusActive IMConversationStatus = 2
|
||||
IMConversationStatusClosed IMConversationStatus = 3
|
||||
)
|
||||
|
||||
var imConversationStatusLabelMap = map[IMConversationStatus]string{
|
||||
IMConversationStatusPending: "待接入",
|
||||
IMConversationStatusActive: "处理中",
|
||||
IMConversationStatusClosed: "已关闭",
|
||||
}
|
||||
|
||||
var IMConversationStatusValues = []IMConversationStatus{
|
||||
IMConversationStatusPending,
|
||||
IMConversationStatusActive,
|
||||
IMConversationStatusClosed,
|
||||
}
|
||||
|
||||
func GetIMConversationStatusLabel(status IMConversationStatus) string {
|
||||
return imConversationStatusLabelMap[status]
|
||||
}
|
||||
|
||||
type IMConversationServiceMode int
|
||||
|
||||
const (
|
||||
IMConversationServiceModeAIOnly IMConversationServiceMode = 1
|
||||
IMConversationServiceModeHumanOnly IMConversationServiceMode = 2
|
||||
IMConversationServiceModeAIFirst IMConversationServiceMode = 3
|
||||
)
|
||||
|
||||
var IMConversationServiceModeValues = []IMConversationServiceMode{
|
||||
IMConversationServiceModeAIOnly,
|
||||
IMConversationServiceModeHumanOnly,
|
||||
IMConversationServiceModeAIFirst,
|
||||
}
|
||||
|
||||
var imConversationServiceModeLabelMap = map[IMConversationServiceMode]string{
|
||||
IMConversationServiceModeAIOnly: "仅AI",
|
||||
IMConversationServiceModeHumanOnly: "仅人工",
|
||||
IMConversationServiceModeAIFirst: "AI优先",
|
||||
}
|
||||
|
||||
func GetIMConversationServiceModeLabel(mode IMConversationServiceMode) string {
|
||||
return imConversationServiceModeLabelMap[mode]
|
||||
}
|
||||
|
||||
type IMSenderType string
|
||||
|
||||
const (
|
||||
IMSenderTypeAgent IMSenderType = "agent"
|
||||
IMSenderTypeCustomer IMSenderType = "customer"
|
||||
IMSenderTypeAI IMSenderType = "ai"
|
||||
IMSenderTypeSystem IMSenderType = "system"
|
||||
)
|
||||
|
||||
var imSenderTypeLabelMap = map[IMSenderType]string{
|
||||
IMSenderTypeAgent: "客服",
|
||||
IMSenderTypeCustomer: "客户",
|
||||
IMSenderTypeAI: "AI",
|
||||
IMSenderTypeSystem: "系统",
|
||||
}
|
||||
|
||||
func GetIMSenderTypeLabel(senderType IMSenderType) string {
|
||||
return imSenderTypeLabelMap[senderType]
|
||||
}
|
||||
|
||||
type IMParticipantType string
|
||||
|
||||
const (
|
||||
IMParticipantTypeCustomer IMParticipantType = "customer"
|
||||
IMParticipantTypeAgent IMParticipantType = "agent"
|
||||
IMParticipantTypeAI IMParticipantType = "ai"
|
||||
IMParticipantTypeSystem IMParticipantType = "system"
|
||||
)
|
||||
|
||||
var imParticipantTypeLabelMap = map[IMParticipantType]string{
|
||||
IMParticipantTypeCustomer: "客户",
|
||||
IMParticipantTypeAgent: "客服",
|
||||
IMParticipantTypeAI: "AI",
|
||||
IMParticipantTypeSystem: "系统",
|
||||
}
|
||||
|
||||
func GetIMParticipantTypeLabel(participantType IMParticipantType) string {
|
||||
return imParticipantTypeLabelMap[participantType]
|
||||
}
|
||||
|
||||
type IMAssignmentType string
|
||||
|
||||
const (
|
||||
IMAssignmentTypeAssign IMAssignmentType = "assign"
|
||||
IMAssignmentTypeTransfer IMAssignmentType = "transfer"
|
||||
)
|
||||
|
||||
var imAssignmentTypeLabelMap = map[IMAssignmentType]string{
|
||||
IMAssignmentTypeAssign: "分配",
|
||||
IMAssignmentTypeTransfer: "转接",
|
||||
}
|
||||
|
||||
func GetIMAssignmentTypeLabel(assignType IMAssignmentType) string {
|
||||
return imAssignmentTypeLabelMap[assignType]
|
||||
}
|
||||
|
||||
type IMAssignmentStatus int
|
||||
|
||||
const (
|
||||
IMAssignmentStatusActive IMAssignmentStatus = 0
|
||||
IMAssignmentStatusInactive IMAssignmentStatus = 1
|
||||
)
|
||||
|
||||
var imAssignmentStatusLabelMap = map[IMAssignmentStatus]string{
|
||||
IMAssignmentStatusActive: "进行中",
|
||||
IMAssignmentStatusInactive: "已结束",
|
||||
}
|
||||
|
||||
func GetIMAssignmentStatusLabel(status IMAssignmentStatus) string {
|
||||
return imAssignmentStatusLabelMap[status]
|
||||
}
|
||||
|
||||
type IMMessageType string
|
||||
|
||||
const (
|
||||
IMMessageTypeText IMMessageType = "text"
|
||||
IMMessageTypeImage IMMessageType = "image"
|
||||
IMMessageTypeAttachment IMMessageType = "attachment"
|
||||
IMMessageTypeHTML IMMessageType = "html"
|
||||
)
|
||||
|
||||
var imMessageTypeLabelMap = map[IMMessageType]string{
|
||||
IMMessageTypeText: "文本",
|
||||
IMMessageTypeImage: "图片",
|
||||
IMMessageTypeAttachment: "附件",
|
||||
IMMessageTypeHTML: "富文本",
|
||||
}
|
||||
|
||||
func GetIMMessageTypeLabel(messageType IMMessageType) string {
|
||||
return imMessageTypeLabelMap[messageType]
|
||||
}
|
||||
|
||||
type IMMessageStatus int
|
||||
|
||||
const (
|
||||
IMMessageStatusSending IMMessageStatus = 1
|
||||
IMMessageStatusSent IMMessageStatus = 2
|
||||
IMMessageStatusDelivered IMMessageStatus = 3
|
||||
IMMessageStatusRead IMMessageStatus = 4
|
||||
IMMessageStatusFailed IMMessageStatus = 5
|
||||
IMMessageStatusRecalled IMMessageStatus = 6
|
||||
)
|
||||
|
||||
var imMessageStatusLabelMap = map[IMMessageStatus]string{
|
||||
IMMessageStatusSending: "发送中",
|
||||
IMMessageStatusSent: "已发送",
|
||||
IMMessageStatusDelivered: "已送达",
|
||||
IMMessageStatusRead: "已读",
|
||||
IMMessageStatusFailed: "发送失败",
|
||||
IMMessageStatusRecalled: "已撤回",
|
||||
}
|
||||
|
||||
func GetIMMessageStatusLabel(status IMMessageStatus) string {
|
||||
return imMessageStatusLabelMap[status]
|
||||
}
|
||||
|
||||
type IMEventType string
|
||||
|
||||
const (
|
||||
IMEventTypeCreate IMEventType = "create"
|
||||
IMEventTypeAssign IMEventType = "assign"
|
||||
IMEventTypeTransfer IMEventType = "transfer"
|
||||
IMEventTypeClose IMEventType = "close"
|
||||
IMEventTypeMessageSend IMEventType = "message_send"
|
||||
IMEventTypeMessageRecall IMEventType = "message_recall"
|
||||
)
|
||||
|
||||
var imEventTypeLabelMap = map[IMEventType]string{
|
||||
IMEventTypeCreate: "创建会话",
|
||||
IMEventTypeAssign: "分配会话",
|
||||
IMEventTypeTransfer: "转接会话",
|
||||
IMEventTypeClose: "关闭会话",
|
||||
IMEventTypeMessageSend: "发送消息",
|
||||
IMEventTypeMessageRecall: "撤回消息",
|
||||
}
|
||||
|
||||
func GetIMEventTypeLabel(eventType IMEventType) string {
|
||||
return imEventTypeLabelMap[eventType]
|
||||
}
|
||||
|
||||
type AIAgentHandoffMode int
|
||||
|
||||
const (
|
||||
AIAgentHandoffModeWaitPool AIAgentHandoffMode = 1
|
||||
AIAgentHandoffModeDefaultTeamPool AIAgentHandoffMode = 2
|
||||
AIAgentHandoffModeAIHoldAndNotify AIAgentHandoffMode = 3
|
||||
)
|
||||
|
||||
var AIAgentHandoffModeValues = []AIAgentHandoffMode{
|
||||
AIAgentHandoffModeWaitPool,
|
||||
AIAgentHandoffModeDefaultTeamPool,
|
||||
AIAgentHandoffModeAIHoldAndNotify,
|
||||
}
|
||||
|
||||
var aiAgentHandoffModeLabelMap = map[AIAgentHandoffMode]string{
|
||||
AIAgentHandoffModeWaitPool: "进入待接入池",
|
||||
AIAgentHandoffModeDefaultTeamPool: "进入默认客服组待接入池",
|
||||
AIAgentHandoffModeAIHoldAndNotify: "AI托底并提醒人工",
|
||||
}
|
||||
|
||||
func GetAIAgentHandoffModeLabel(mode AIAgentHandoffMode) string {
|
||||
return aiAgentHandoffModeLabelMap[mode]
|
||||
}
|
||||
|
||||
type AIAgentFallbackMode int
|
||||
|
||||
const (
|
||||
AIAgentFallbackModeNoAnswer AIAgentFallbackMode = 1
|
||||
AIAgentFallbackModeGuideRephrase AIAgentFallbackMode = 2
|
||||
AIAgentFallbackModeHandoff AIAgentFallbackMode = 3
|
||||
)
|
||||
|
||||
var AIAgentFallbackModeValues = []AIAgentFallbackMode{
|
||||
AIAgentFallbackModeNoAnswer,
|
||||
AIAgentFallbackModeGuideRephrase,
|
||||
AIAgentFallbackModeHandoff,
|
||||
}
|
||||
|
||||
var aiAgentFallbackModeLabelMap = map[AIAgentFallbackMode]string{
|
||||
AIAgentFallbackModeNoAnswer: "直接声明无答案",
|
||||
AIAgentFallbackModeGuideRephrase: "引导补充信息或换个问法",
|
||||
AIAgentFallbackModeHandoff: "直接转人工",
|
||||
}
|
||||
|
||||
func GetAIAgentFallbackModeLabel(mode AIAgentFallbackMode) string {
|
||||
return aiAgentFallbackModeLabelMap[mode]
|
||||
}
|
||||
|
||||
const (
|
||||
IMRealtimeEventConnected = "connected"
|
||||
IMRealtimeEventPong = "pong"
|
||||
IMRealtimeEventSubscribed = "subscribed"
|
||||
IMRealtimeEventUnsubscribed = "unsubscribed"
|
||||
IMRealtimeEventResyncRequired = "resyncRequired"
|
||||
IMRealtimeEventMessageCreated = "message.created"
|
||||
IMRealtimeEventMessageRecalled = "message.recalled"
|
||||
IMRealtimeEventConversationCreated = "conversation.created"
|
||||
IMRealtimeEventConversationUpdated = "conversation.updated"
|
||||
IMRealtimeEventConversationAssigned = "conversation.assigned"
|
||||
IMRealtimeEventConversationTransferred = "conversation.transferred"
|
||||
IMRealtimeEventConversationClosed = "conversation.closed"
|
||||
IMRealtimeEventConversationRead = "conversation.read"
|
||||
)
|
||||
|
||||
const (
|
||||
IMRealtimeClientTypePing = "ping"
|
||||
IMRealtimeClientTypeSubscribe = "subscribe"
|
||||
IMRealtimeClientTypeUnsubscribe = "unsubscribe"
|
||||
IMRealtimeClientTypeAck = "ack"
|
||||
)
|
||||
|
||||
const (
|
||||
IMRealtimeResyncReasonInvalidPayload = "invalid_payload"
|
||||
IMRealtimeResyncReasonUnsupportedMessageType = "unsupported_message_type"
|
||||
IMRealtimeResyncReasonManual = "manual"
|
||||
)
|
||||
@@ -0,0 +1,234 @@
|
||||
package enums
|
||||
|
||||
type VectorDBType string
|
||||
|
||||
const (
|
||||
VectorDBTypeQdrant VectorDBType = "qdrant"
|
||||
)
|
||||
|
||||
var vectorDBTypeLabelMap = map[VectorDBType]string{
|
||||
VectorDBTypeQdrant: "Qdrant",
|
||||
}
|
||||
|
||||
func GetVectorDBTypeLabel(dbType VectorDBType) string {
|
||||
return vectorDBTypeLabelMap[dbType]
|
||||
}
|
||||
|
||||
type KnowledgeDocumentContentType string
|
||||
|
||||
const (
|
||||
KnowledgeDocumentContentTypeHTML KnowledgeDocumentContentType = "html"
|
||||
KnowledgeDocumentContentTypeMarkdown KnowledgeDocumentContentType = "markdown"
|
||||
)
|
||||
|
||||
type KnowledgeBaseType string
|
||||
|
||||
const (
|
||||
KnowledgeBaseTypeDocument KnowledgeBaseType = "document"
|
||||
KnowledgeBaseTypeFAQ KnowledgeBaseType = "faq"
|
||||
)
|
||||
|
||||
var knowledgeBaseTypeLabelMap = map[KnowledgeBaseType]string{
|
||||
KnowledgeBaseTypeDocument: "文档知识库",
|
||||
KnowledgeBaseTypeFAQ: "FAQ知识库",
|
||||
}
|
||||
|
||||
func GetKnowledgeBaseTypeLabel(knowledgeType KnowledgeBaseType) string {
|
||||
return knowledgeBaseTypeLabelMap[knowledgeType]
|
||||
}
|
||||
|
||||
var knowledgeDocumentContentTypeLabelMap = map[KnowledgeDocumentContentType]string{
|
||||
KnowledgeDocumentContentTypeHTML: "HTML",
|
||||
KnowledgeDocumentContentTypeMarkdown: "Markdown",
|
||||
}
|
||||
|
||||
func GetKnowledgeDocumentContentTypeLabel(contentType KnowledgeDocumentContentType) string {
|
||||
return knowledgeDocumentContentTypeLabelMap[contentType]
|
||||
}
|
||||
|
||||
type KnowledgeDocumentIndexStatus string
|
||||
|
||||
const (
|
||||
KnowledgeDocumentIndexStatusPending KnowledgeDocumentIndexStatus = "pending"
|
||||
KnowledgeDocumentIndexStatusIndexed KnowledgeDocumentIndexStatus = "indexed"
|
||||
KnowledgeDocumentIndexStatusFailed KnowledgeDocumentIndexStatus = "failed"
|
||||
)
|
||||
|
||||
var KnowledgeDocumentIndexStatusValues = []KnowledgeDocumentIndexStatus{
|
||||
KnowledgeDocumentIndexStatusPending,
|
||||
KnowledgeDocumentIndexStatusIndexed,
|
||||
KnowledgeDocumentIndexStatusFailed,
|
||||
}
|
||||
|
||||
var knowledgeDocumentIndexStatusLabelMap = map[KnowledgeDocumentIndexStatus]string{
|
||||
KnowledgeDocumentIndexStatusPending: "待索引",
|
||||
KnowledgeDocumentIndexStatusIndexed: "已索引",
|
||||
KnowledgeDocumentIndexStatusFailed: "索引失败",
|
||||
}
|
||||
|
||||
func GetKnowledgeDocumentIndexStatusLabel(status KnowledgeDocumentIndexStatus) string {
|
||||
return knowledgeDocumentIndexStatusLabelMap[status]
|
||||
}
|
||||
|
||||
func IsValidKnowledgeDocumentIndexStatus(status string) bool {
|
||||
for _, item := range KnowledgeDocumentIndexStatusValues {
|
||||
if string(item) == status {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type KnowledgeChunkType string
|
||||
|
||||
const (
|
||||
KnowledgeChunkTypeText KnowledgeChunkType = "text"
|
||||
KnowledgeChunkTypeFAQ KnowledgeChunkType = "faq"
|
||||
KnowledgeChunkTypeTable KnowledgeChunkType = "table"
|
||||
KnowledgeChunkTypeCode KnowledgeChunkType = "code"
|
||||
)
|
||||
|
||||
var knowledgeChunkTypeLabelMap = map[KnowledgeChunkType]string{
|
||||
KnowledgeChunkTypeText: "文本",
|
||||
KnowledgeChunkTypeFAQ: "问答",
|
||||
KnowledgeChunkTypeTable: "表格",
|
||||
KnowledgeChunkTypeCode: "代码",
|
||||
}
|
||||
|
||||
func GetKnowledgeChunkTypeLabel(chunkType KnowledgeChunkType) string {
|
||||
return knowledgeChunkTypeLabelMap[chunkType]
|
||||
}
|
||||
|
||||
type KnowledgeChunkProvider string
|
||||
|
||||
const (
|
||||
KnowledgeChunkProviderFixed KnowledgeChunkProvider = "fixed"
|
||||
KnowledgeChunkProviderStructured KnowledgeChunkProvider = "structured"
|
||||
KnowledgeChunkProviderFAQ KnowledgeChunkProvider = "faq"
|
||||
KnowledgeChunkProviderSemantic KnowledgeChunkProvider = "semantic"
|
||||
)
|
||||
|
||||
var knowledgeChunkProviderLabelMap = map[KnowledgeChunkProvider]string{
|
||||
KnowledgeChunkProviderFixed: "固定长度",
|
||||
KnowledgeChunkProviderStructured: "结构化分块",
|
||||
KnowledgeChunkProviderFAQ: "问答式分块",
|
||||
KnowledgeChunkProviderSemantic: "语义分块",
|
||||
}
|
||||
|
||||
func GetKnowledgeChunkProviderLabel(provider KnowledgeChunkProvider) string {
|
||||
return knowledgeChunkProviderLabelMap[provider]
|
||||
}
|
||||
|
||||
type KnowledgeRetrieveChannel string
|
||||
|
||||
const (
|
||||
KnowledgeRetrieveChannelIM KnowledgeRetrieveChannel = "im"
|
||||
KnowledgeRetrieveChannelAgentAssist KnowledgeRetrieveChannel = "agent_assist"
|
||||
KnowledgeRetrieveChannelAPI KnowledgeRetrieveChannel = "api"
|
||||
KnowledgeRetrieveChannelDebug KnowledgeRetrieveChannel = "debug"
|
||||
)
|
||||
|
||||
var knowledgeRetrieveChannelLabelMap = map[KnowledgeRetrieveChannel]string{
|
||||
KnowledgeRetrieveChannelIM: "客服会话",
|
||||
KnowledgeRetrieveChannelAgentAssist: "客服助手",
|
||||
KnowledgeRetrieveChannelAPI: "API接口",
|
||||
KnowledgeRetrieveChannelDebug: "调试",
|
||||
}
|
||||
|
||||
func GetKnowledgeRetrieveChannelLabel(channel KnowledgeRetrieveChannel) string {
|
||||
return knowledgeRetrieveChannelLabelMap[channel]
|
||||
}
|
||||
|
||||
type KnowledgeRetrieveScene string
|
||||
|
||||
const (
|
||||
KnowledgeRetrieveSceneFirstResponse KnowledgeRetrieveScene = "first_response"
|
||||
KnowledgeRetrieveSceneAssist KnowledgeRetrieveScene = "assist"
|
||||
KnowledgeRetrieveSceneQA KnowledgeRetrieveScene = "qa"
|
||||
)
|
||||
|
||||
var knowledgeRetrieveSceneLabelMap = map[KnowledgeRetrieveScene]string{
|
||||
KnowledgeRetrieveSceneFirstResponse: "首次回复",
|
||||
KnowledgeRetrieveSceneAssist: "辅助回复",
|
||||
KnowledgeRetrieveSceneQA: "问答",
|
||||
}
|
||||
|
||||
func GetKnowledgeRetrieveSceneLabel(scene KnowledgeRetrieveScene) string {
|
||||
return knowledgeRetrieveSceneLabelMap[scene]
|
||||
}
|
||||
|
||||
type KnowledgeAnswerStatus int
|
||||
|
||||
const (
|
||||
KnowledgeAnswerStatusNormal KnowledgeAnswerStatus = 1
|
||||
KnowledgeAnswerStatusNoAnswer KnowledgeAnswerStatus = 2
|
||||
KnowledgeAnswerStatusFallback KnowledgeAnswerStatus = 3
|
||||
KnowledgeAnswerStatusBlocked KnowledgeAnswerStatus = 4
|
||||
)
|
||||
|
||||
var knowledgeAnswerStatusLabelMap = map[KnowledgeAnswerStatus]string{
|
||||
KnowledgeAnswerStatusNormal: "正常",
|
||||
KnowledgeAnswerStatusNoAnswer: "无答案",
|
||||
KnowledgeAnswerStatusFallback: "兜底回复",
|
||||
KnowledgeAnswerStatusBlocked: "已屏蔽",
|
||||
}
|
||||
|
||||
func GetKnowledgeAnswerStatusLabel(status KnowledgeAnswerStatus) string {
|
||||
return knowledgeAnswerStatusLabelMap[status]
|
||||
}
|
||||
|
||||
type KnowledgeFeedbackType int
|
||||
|
||||
const (
|
||||
KnowledgeFeedbackTypeLike KnowledgeFeedbackType = 1
|
||||
KnowledgeFeedbackTypeDislike KnowledgeFeedbackType = 2
|
||||
KnowledgeFeedbackTypeNotHelpful KnowledgeFeedbackType = 3
|
||||
KnowledgeFeedbackTypeWrongCitation KnowledgeFeedbackType = 4
|
||||
KnowledgeFeedbackTypeOther KnowledgeFeedbackType = 5
|
||||
)
|
||||
|
||||
var knowledgeFeedbackTypeLabelMap = map[KnowledgeFeedbackType]string{
|
||||
KnowledgeFeedbackTypeLike: "点赞",
|
||||
KnowledgeFeedbackTypeDislike: "点踩",
|
||||
KnowledgeFeedbackTypeNotHelpful: "无帮助",
|
||||
KnowledgeFeedbackTypeWrongCitation: "引用错误",
|
||||
KnowledgeFeedbackTypeOther: "其他",
|
||||
}
|
||||
|
||||
func GetKnowledgeFeedbackTypeLabel(feedbackType KnowledgeFeedbackType) string {
|
||||
return knowledgeFeedbackTypeLabelMap[feedbackType]
|
||||
}
|
||||
|
||||
type KnowledgeAnswerMode int
|
||||
|
||||
const (
|
||||
KnowledgeAnswerModeStrict KnowledgeAnswerMode = 1
|
||||
KnowledgeAnswerModeAssist KnowledgeAnswerMode = 2
|
||||
)
|
||||
|
||||
var knowledgeAnswerModeLabelMap = map[KnowledgeAnswerMode]string{
|
||||
KnowledgeAnswerModeStrict: "严格模式",
|
||||
KnowledgeAnswerModeAssist: "辅助模式",
|
||||
}
|
||||
|
||||
func GetKnowledgeAnswerModeLabel(mode KnowledgeAnswerMode) string {
|
||||
return knowledgeAnswerModeLabelMap[mode]
|
||||
}
|
||||
|
||||
type KnowledgeFallbackMode int
|
||||
|
||||
const (
|
||||
KnowledgeFallbackModeNoAnswer KnowledgeFallbackMode = 1
|
||||
KnowledgeFallbackModeSuggestRetry KnowledgeFallbackMode = 2
|
||||
KnowledgeFallbackModeTransferHuman KnowledgeFallbackMode = 3
|
||||
)
|
||||
|
||||
var knowledgeFallbackModeLabelMap = map[KnowledgeFallbackMode]string{
|
||||
KnowledgeFallbackModeNoAnswer: "直接声明无答案",
|
||||
KnowledgeFallbackModeSuggestRetry: "建议重试",
|
||||
KnowledgeFallbackModeTransferHuman: "转人工",
|
||||
}
|
||||
|
||||
func GetKnowledgeFallbackModeLabel(mode KnowledgeFallbackMode) string {
|
||||
return knowledgeFallbackModeLabelMap[mode]
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package enums
|
||||
|
||||
type SkillExecutionMode string
|
||||
|
||||
const (
|
||||
SkillExecutionModePromptOnly SkillExecutionMode = "prompt_only"
|
||||
SkillExecutionModeMCPTool SkillExecutionMode = "mcp_tool"
|
||||
)
|
||||
|
||||
var skillExecutionModeLabelMap = map[SkillExecutionMode]string{
|
||||
SkillExecutionModePromptOnly: "Prompt直出",
|
||||
SkillExecutionModeMCPTool: "MCP工具",
|
||||
}
|
||||
|
||||
func GetSkillExecutionModeLabel(mode SkillExecutionMode) string {
|
||||
return skillExecutionModeLabelMap[mode]
|
||||
}
|
||||
@@ -0,0 +1,156 @@
|
||||
package enums
|
||||
|
||||
type TicketStatus string
|
||||
|
||||
const (
|
||||
TicketStatusNew TicketStatus = "new"
|
||||
TicketStatusOpen TicketStatus = "open"
|
||||
TicketStatusPendingCustomer TicketStatus = "pending_customer"
|
||||
TicketStatusPendingInternal TicketStatus = "pending_internal"
|
||||
TicketStatusResolved TicketStatus = "resolved"
|
||||
TicketStatusClosed TicketStatus = "closed"
|
||||
TicketStatusCancelled TicketStatus = "cancelled"
|
||||
)
|
||||
|
||||
var TicketStatusValues = []TicketStatus{
|
||||
TicketStatusNew,
|
||||
TicketStatusOpen,
|
||||
TicketStatusPendingCustomer,
|
||||
TicketStatusPendingInternal,
|
||||
TicketStatusResolved,
|
||||
TicketStatusClosed,
|
||||
TicketStatusCancelled,
|
||||
}
|
||||
|
||||
var ticketStatusLabelMap = map[TicketStatus]string{
|
||||
TicketStatusNew: "新建",
|
||||
TicketStatusOpen: "处理中",
|
||||
TicketStatusPendingCustomer: "待客户反馈",
|
||||
TicketStatusPendingInternal: "待内部处理",
|
||||
TicketStatusResolved: "已解决",
|
||||
TicketStatusClosed: "已关闭",
|
||||
TicketStatusCancelled: "已取消",
|
||||
}
|
||||
|
||||
func GetTicketStatusLabel(status TicketStatus) string {
|
||||
return ticketStatusLabelMap[status]
|
||||
}
|
||||
|
||||
func IsValidTicketStatus(status string) bool {
|
||||
for _, item := range TicketStatusValues {
|
||||
if string(item) == status {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type TicketSeverity int
|
||||
|
||||
const (
|
||||
TicketSeverityMinor TicketSeverity = 1
|
||||
TicketSeverityMajor TicketSeverity = 2
|
||||
TicketSeverityCritical TicketSeverity = 3
|
||||
)
|
||||
|
||||
var TicketSeverityValues = []TicketSeverity{
|
||||
TicketSeverityMinor,
|
||||
TicketSeverityMajor,
|
||||
TicketSeverityCritical,
|
||||
}
|
||||
|
||||
var ticketSeverityLabelMap = map[TicketSeverity]string{
|
||||
TicketSeverityMinor: "轻微",
|
||||
TicketSeverityMajor: "严重",
|
||||
TicketSeverityCritical: "致命",
|
||||
}
|
||||
|
||||
func GetTicketSeverityLabel(severity TicketSeverity) string {
|
||||
return ticketSeverityLabelMap[severity]
|
||||
}
|
||||
|
||||
func IsValidTicketSeverity(severity int) bool {
|
||||
for _, item := range TicketSeverityValues {
|
||||
if int(item) == severity {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type TicketSource string
|
||||
|
||||
const (
|
||||
TicketSourceManual TicketSource = "manual"
|
||||
TicketSourceConversation TicketSource = "conversation"
|
||||
TicketSourcePortal TicketSource = "portal"
|
||||
TicketSourceAPI TicketSource = "api"
|
||||
TicketSourceRule TicketSource = "rule"
|
||||
)
|
||||
|
||||
var TicketSourceValues = []TicketSource{
|
||||
TicketSourceManual,
|
||||
TicketSourceConversation,
|
||||
TicketSourcePortal,
|
||||
TicketSourceAPI,
|
||||
TicketSourceRule,
|
||||
}
|
||||
|
||||
func IsValidTicketSource(source string) bool {
|
||||
for _, item := range TicketSourceValues {
|
||||
if string(item) == source {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type TicketCommentType string
|
||||
|
||||
const (
|
||||
TicketCommentTypePublicReply TicketCommentType = "public_reply"
|
||||
TicketCommentTypeInternalNote TicketCommentType = "internal_note"
|
||||
TicketCommentTypeSystemLog TicketCommentType = "system_log"
|
||||
)
|
||||
|
||||
type TicketEventType string
|
||||
|
||||
const (
|
||||
TicketEventTypeCreated TicketEventType = "created"
|
||||
TicketEventTypeUpdated TicketEventType = "updated"
|
||||
TicketEventTypeAssigned TicketEventType = "assigned"
|
||||
TicketEventTypeTransferred TicketEventType = "transferred"
|
||||
TicketEventTypeStatusChanged TicketEventType = "status_changed"
|
||||
TicketEventTypeReplied TicketEventType = "replied"
|
||||
TicketEventTypeInternalNoted TicketEventType = "internal_noted"
|
||||
TicketEventTypeClosed TicketEventType = "closed"
|
||||
TicketEventTypeReopened TicketEventType = "reopened"
|
||||
TicketEventTypeSLABreached TicketEventType = "sla_breached"
|
||||
TicketEventTypeLinkedConversation TicketEventType = "linked_conversation"
|
||||
TicketEventTypeMentioned TicketEventType = "mentioned"
|
||||
)
|
||||
|
||||
type TicketSLAType string
|
||||
|
||||
const (
|
||||
TicketSLATypeFirstResponse TicketSLAType = "first_response"
|
||||
TicketSLATypeResolution TicketSLAType = "resolution"
|
||||
)
|
||||
|
||||
type TicketSLAStatus string
|
||||
|
||||
const (
|
||||
TicketSLAStatusRunning TicketSLAStatus = "running"
|
||||
TicketSLAStatusPaused TicketSLAStatus = "paused"
|
||||
TicketSLAStatusCompleted TicketSLAStatus = "completed"
|
||||
TicketSLAStatusBreached TicketSLAStatus = "breached"
|
||||
)
|
||||
|
||||
type TicketRelationType string
|
||||
|
||||
const (
|
||||
TicketRelationTypeDuplicate TicketRelationType = "duplicate"
|
||||
TicketRelationTypeRelated TicketRelationType = "related"
|
||||
TicketRelationTypeParent TicketRelationType = "parent"
|
||||
TicketRelationTypeChild TicketRelationType = "child"
|
||||
)
|
||||
@@ -0,0 +1,50 @@
|
||||
package enums
|
||||
|
||||
type WxWorkKFMessageDirection string
|
||||
|
||||
const (
|
||||
WxWorkKFMessageDirectionIn WxWorkKFMessageDirection = "in"
|
||||
WxWorkKFMessageDirectionOut WxWorkKFMessageDirection = "out"
|
||||
)
|
||||
|
||||
type ChannelMessageOutboxStatus string
|
||||
|
||||
const (
|
||||
ChannelMessageOutboxStatusPending ChannelMessageOutboxStatus = "pending"
|
||||
ChannelMessageOutboxStatusSending ChannelMessageOutboxStatus = "sending"
|
||||
ChannelMessageOutboxStatusSent ChannelMessageOutboxStatus = "sent"
|
||||
ChannelMessageOutboxStatusFailed ChannelMessageOutboxStatus = "failed"
|
||||
)
|
||||
|
||||
const (
|
||||
ChannelTypeWeb = "web"
|
||||
ChannelTypeWxWorkKF = "wxwork_kf"
|
||||
)
|
||||
|
||||
type WxWorkKFMessageSendStatus string
|
||||
|
||||
const (
|
||||
WxWorkKFMessageSendStatusReceived WxWorkKFMessageSendStatus = "received"
|
||||
WxWorkKFMessageSendStatusSent WxWorkKFMessageSendStatus = "sent"
|
||||
WxWorkKFMessageSendStatusFailed WxWorkKFMessageSendStatus = "failed"
|
||||
)
|
||||
|
||||
type WxWorkKFSessionStatus string
|
||||
|
||||
const (
|
||||
WxWorkKFSessionStatusActive WxWorkKFSessionStatus = "active"
|
||||
WxWorkKFSessionStatusTransfer WxWorkKFSessionStatus = "transfer"
|
||||
WxWorkKFSessionStatusClosed WxWorkKFSessionStatus = "closed"
|
||||
)
|
||||
|
||||
const (
|
||||
WxWorkKFEventTypeEnterSession = "enter_session"
|
||||
WxWorkKFEventTypeSessionStatusChange = "session_status_change"
|
||||
WxWorkKFEventTypeMsgSendFail = "msg_send_fail"
|
||||
)
|
||||
|
||||
const (
|
||||
IMEventTypeWxWorkKFSync IMEventType = "wxwork_kf_sync"
|
||||
IMEventTypeWxWorkKFEvent IMEventType = "wxwork_kf_event"
|
||||
IMEventTypeWxWorkKFOutbound IMEventType = "wxwork_kf_outbound"
|
||||
)
|
||||
@@ -0,0 +1,36 @@
|
||||
package errorsx
|
||||
|
||||
import "github.com/mlogclub/simple/web"
|
||||
|
||||
const (
|
||||
CodeInvalidParam = 1000
|
||||
CodeBusinessError = 2000
|
||||
CodeAuthUnauthorized = 3000
|
||||
CodeAuthForbidden = 3001
|
||||
CodeAuthInvalidToken = 3002
|
||||
CodeAuthInvalidAccount = 3003
|
||||
)
|
||||
|
||||
func InvalidParam(message string) error {
|
||||
return web.NewError(CodeInvalidParam, message)
|
||||
}
|
||||
|
||||
func BusinessError(code int, message string) error {
|
||||
return web.NewError(CodeBusinessError+code, message)
|
||||
}
|
||||
|
||||
func Unauthorized(message string) error {
|
||||
return web.NewError(CodeAuthUnauthorized, message)
|
||||
}
|
||||
|
||||
func Forbidden(message string) error {
|
||||
return web.NewError(CodeAuthForbidden, message)
|
||||
}
|
||||
|
||||
func InvalidToken(message string) error {
|
||||
return web.NewError(CodeAuthInvalidToken, message)
|
||||
}
|
||||
|
||||
func InvalidAccount(message string) error {
|
||||
return web.NewError(CodeAuthInvalidAccount, message)
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package irisx
|
||||
|
||||
import (
|
||||
"cs-agent/internal/models"
|
||||
"cs-agent/internal/pkg/openidentity"
|
||||
|
||||
"github.com/kataras/iris/v12"
|
||||
)
|
||||
|
||||
const (
|
||||
ctxKeyOpenImChannel = "openImChannel"
|
||||
ctxKeyOpenImExternalInfo = "openImExternalInfo"
|
||||
)
|
||||
|
||||
func SetOpenImChannel(ctx iris.Context, channel *models.Channel) {
|
||||
ctx.Values().Set(ctxKeyOpenImChannel, channel)
|
||||
}
|
||||
|
||||
// GetChannel 返回 OpenImContextMiddleware 注入的接入渠道(未走中间件时为 nil)。
|
||||
func GetChannel(ctx iris.Context) *models.Channel {
|
||||
v := ctx.Values().Get(ctxKeyOpenImChannel)
|
||||
channel, _ := v.(*models.Channel)
|
||||
return channel
|
||||
}
|
||||
|
||||
func SetOpenImExternalInfo(ctx iris.Context, ext *openidentity.ExternalInfo) {
|
||||
ctx.Values().Set(ctxKeyOpenImExternalInfo, ext)
|
||||
}
|
||||
|
||||
// GetExternalInfo 返回中间件注入的外部访客身份;仅 widget 子路径或未启用中间件时为 nil。
|
||||
func GetExternalInfo(ctx iris.Context) *openidentity.ExternalInfo {
|
||||
v := ctx.Values().Get(ctxKeyOpenImExternalInfo)
|
||||
ext, _ := v.(*openidentity.ExternalInfo)
|
||||
return ext
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
package logx
|
||||
|
||||
import (
|
||||
"log/slog"
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Config 定义日志初始化参数。
|
||||
type Config struct {
|
||||
Level string `yaml:"level"`
|
||||
Format string `yaml:"format"`
|
||||
AddSource bool `yaml:"addSource"`
|
||||
}
|
||||
|
||||
// Init 初始化全局 slog logger,并设置为默认 logger。
|
||||
func Init(cfg Config) *slog.Logger {
|
||||
level := parseLevel(cfg.Level)
|
||||
opts := &slog.HandlerOptions{
|
||||
Level: level,
|
||||
AddSource: cfg.AddSource,
|
||||
}
|
||||
|
||||
var handler slog.Handler
|
||||
if strings.EqualFold(cfg.Format, "json") {
|
||||
handler = slog.NewJSONHandler(os.Stdout, opts)
|
||||
} else {
|
||||
handler = slog.NewTextHandler(os.Stdout, opts)
|
||||
}
|
||||
|
||||
logger := slog.New(handler)
|
||||
slog.SetDefault(logger)
|
||||
return logger
|
||||
}
|
||||
|
||||
func parseLevel(level string) slog.Level {
|
||||
switch strings.ToLower(strings.TrimSpace(level)) {
|
||||
case "debug":
|
||||
return slog.LevelDebug
|
||||
case "warn", "warning":
|
||||
return slog.LevelWarn
|
||||
case "error":
|
||||
return slog.LevelError
|
||||
default:
|
||||
return slog.LevelInfo
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
// Package openidentity 解析开放 IM 场景下的外部访客身份(HTTP Header / Query),与 JSON 请求体 DTO 解耦。
|
||||
package openidentity
|
||||
|
||||
import (
|
||||
"cs-agent/internal/pkg/enums"
|
||||
"cs-agent/internal/pkg/errorsx"
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
"github.com/kataras/iris/v12"
|
||||
"github.com/mlogclub/simple/common/strs"
|
||||
"github.com/mlogclub/simple/web/params"
|
||||
)
|
||||
|
||||
// ExternalInfo 外部访客身份(IM 客户),与站内 AuthPrincipal 区分。
|
||||
type ExternalInfo struct {
|
||||
ExternalSource enums.ExternalSource `json:"externalSource"`
|
||||
ExternalID string `json:"externalId"`
|
||||
ExternalName string `json:"externalName"`
|
||||
}
|
||||
|
||||
// GetExternalInfo 从 Header(X-External-*)或 query(externalSource、externalId、externalName)解析身份。
|
||||
func GetExternalInfo(ctx iris.Context) (*ExternalInfo, error) {
|
||||
externalSource, err := parseExternalSource(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !enums.IsAllowedOpenImExternalSource(externalSource) {
|
||||
return nil, errorsx.InvalidParam("不支持的外部来源")
|
||||
}
|
||||
externalID, err := parseExternalID(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &ExternalInfo{
|
||||
ExternalSource: externalSource,
|
||||
ExternalID: externalID,
|
||||
ExternalName: parseExternalName(ctx),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func parseExternalSource(ctx iris.Context) (enums.ExternalSource, error) {
|
||||
externalSource := ctx.GetHeader("X-External-Source")
|
||||
if strs.IsBlank(externalSource) {
|
||||
externalSource, _ = params.Get(ctx, "externalSource")
|
||||
}
|
||||
if strs.IsBlank(externalSource) {
|
||||
return "", errorsx.Unauthorized("用户来源不能为空")
|
||||
}
|
||||
return enums.ExternalSource(strings.TrimSpace(externalSource)), nil
|
||||
}
|
||||
|
||||
func parseExternalID(ctx iris.Context) (string, error) {
|
||||
externalID := ctx.GetHeader("X-External-Id")
|
||||
if strs.IsBlank(externalID) {
|
||||
externalID, _ = params.Get(ctx, "externalId")
|
||||
}
|
||||
if strs.IsBlank(externalID) {
|
||||
return "", errorsx.Unauthorized("用户标识不能为空")
|
||||
}
|
||||
return strings.TrimSpace(externalID), nil
|
||||
}
|
||||
|
||||
func parseExternalName(ctx iris.Context) string {
|
||||
externalName := ctx.GetHeader("X-External-Name")
|
||||
if strs.IsBlank(externalName) {
|
||||
externalName, _ = params.Get(ctx, "externalName")
|
||||
}
|
||||
return decodeExternalDisplayName(externalName)
|
||||
}
|
||||
|
||||
// decodeExternalDisplayName 将客户端对 X-External-Name / externalName 做的 encodeURIComponent 还原为 UTF-8。
|
||||
// 无百分号编码时 QueryUnescape 原样返回,解码失败则保留原串(兼容异常或旧客户端明文)。
|
||||
func decodeExternalDisplayName(s string) string {
|
||||
s = strings.TrimSpace(s)
|
||||
if s == "" {
|
||||
return ""
|
||||
}
|
||||
dec, err := url.QueryUnescape(s)
|
||||
if err != nil {
|
||||
return s
|
||||
}
|
||||
return strings.TrimSpace(dec)
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"golang.org/x/net/html"
|
||||
)
|
||||
|
||||
type ContentChunkType string
|
||||
|
||||
const (
|
||||
ContentChunkTypeText ContentChunkType = "text"
|
||||
ContentChunkTypeImage ContentChunkType = "image"
|
||||
)
|
||||
|
||||
type ContentChunk struct {
|
||||
Type ContentChunkType //
|
||||
Content string // text content or image url
|
||||
}
|
||||
|
||||
func SplitHTMLContentChunks(content string) ([]ContentChunk, error) {
|
||||
root, err := html.Parse(strings.NewReader("<div>" + strings.TrimSpace(content) + "</div>"))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var (
|
||||
chunks []ContentChunk
|
||||
buffer strings.Builder
|
||||
)
|
||||
flushText := func() {
|
||||
text := normalizeContentChunkText(buffer.String())
|
||||
buffer.Reset()
|
||||
if text == "" {
|
||||
return
|
||||
}
|
||||
chunks = append(chunks, ContentChunk{
|
||||
Type: ContentChunkTypeText,
|
||||
Content: text,
|
||||
})
|
||||
}
|
||||
|
||||
var walk func(*html.Node)
|
||||
walk = func(node *html.Node) {
|
||||
if node == nil {
|
||||
return
|
||||
}
|
||||
switch node.Type {
|
||||
case html.TextNode:
|
||||
buffer.WriteString(node.Data)
|
||||
case html.ElementNode:
|
||||
switch node.Data {
|
||||
case "br":
|
||||
buffer.WriteString("\n")
|
||||
case "p", "div", "li", "blockquote":
|
||||
buffer.WriteString("\n")
|
||||
case "img":
|
||||
flushText()
|
||||
src := strings.TrimSpace(findContentChunkHTMLAttr(node, "src"))
|
||||
if src == "" {
|
||||
return
|
||||
}
|
||||
chunks = append(chunks, ContentChunk{
|
||||
Type: ContentChunkTypeImage,
|
||||
Content: src,
|
||||
})
|
||||
return
|
||||
}
|
||||
}
|
||||
for child := node.FirstChild; child != nil; child = child.NextSibling {
|
||||
walk(child)
|
||||
}
|
||||
if node.Type == html.ElementNode {
|
||||
switch node.Data {
|
||||
case "p", "div", "li", "blockquote":
|
||||
buffer.WriteString("\n")
|
||||
}
|
||||
}
|
||||
}
|
||||
walk(root)
|
||||
flushText()
|
||||
return chunks, nil
|
||||
}
|
||||
|
||||
func normalizeContentChunkText(value string) string {
|
||||
value = strings.ReplaceAll(value, "\u00a0", " ")
|
||||
lines := strings.Split(value, "\n")
|
||||
normalizedLines := make([]string, 0, len(lines))
|
||||
for _, line := range lines {
|
||||
line = strings.Join(strings.Fields(strings.TrimSpace(line)), " ")
|
||||
if line == "" {
|
||||
if len(normalizedLines) > 0 && normalizedLines[len(normalizedLines)-1] != "" {
|
||||
normalizedLines = append(normalizedLines, "")
|
||||
}
|
||||
continue
|
||||
}
|
||||
normalizedLines = append(normalizedLines, line)
|
||||
}
|
||||
for len(normalizedLines) > 0 && normalizedLines[0] == "" {
|
||||
normalizedLines = normalizedLines[1:]
|
||||
}
|
||||
for len(normalizedLines) > 0 && normalizedLines[len(normalizedLines)-1] == "" {
|
||||
normalizedLines = normalizedLines[:len(normalizedLines)-1]
|
||||
}
|
||||
return strings.Join(normalizedLines, "\n")
|
||||
}
|
||||
|
||||
func findContentChunkHTMLAttr(node *html.Node, key string) string {
|
||||
for _, attr := range node.Attr {
|
||||
if strings.EqualFold(attr.Key, key) {
|
||||
return attr.Val
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestSplitHTMLContentChunks(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
content string
|
||||
want []ContentChunk
|
||||
}{
|
||||
{
|
||||
name: "plain text paragraph",
|
||||
content: "<p>你好,微信用户</p>",
|
||||
want: []ContentChunk{
|
||||
{Type: ContentChunkTypeText, Content: "你好,微信用户"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "single image",
|
||||
content: `<p><img src="https://example.com/a.png" alt="a"></p>`,
|
||||
want: []ContentChunk{
|
||||
{Type: ContentChunkTypeImage, Content: "https://example.com/a.png"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "mixed text and images keep order",
|
||||
content: `<p>第一段</p><p><img src="https://example.com/1.png"></p><p>第二段<img src="https://example.com/2.png">第三段</p>`,
|
||||
want: []ContentChunk{
|
||||
{Type: ContentChunkTypeText, Content: "第一段"},
|
||||
{Type: ContentChunkTypeImage, Content: "https://example.com/1.png"},
|
||||
{Type: ContentChunkTypeText, Content: "第二段"},
|
||||
{Type: ContentChunkTypeImage, Content: "https://example.com/2.png"},
|
||||
{Type: ContentChunkTypeText, Content: "第三段"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "normalize blank lines and spaces",
|
||||
content: "<div> 第一行 <br><br> 第二行 </div>",
|
||||
want: []ContentChunk{
|
||||
{Type: ContentChunkTypeText, Content: "第一行\n\n第二行"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "ignore image without src",
|
||||
content: `<p>前文</p><img alt="missing-src"><p>后文</p>`,
|
||||
want: []ContentChunk{
|
||||
{Type: ContentChunkTypeText, Content: "前文"},
|
||||
{Type: ContentChunkTypeText, Content: "后文"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "empty html returns empty chunks",
|
||||
content: "<p><br></p>",
|
||||
want: nil,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got, err := SplitHTMLContentChunks(tt.content)
|
||||
if err != nil {
|
||||
t.Fatalf("SplitHTMLContentChunks() error = %v", err)
|
||||
}
|
||||
if !reflect.DeepEqual(got, tt.want) {
|
||||
t.Fatalf("SplitHTMLContentChunks() = %#v, want %#v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"cs-agent/internal/models"
|
||||
"cs-agent/internal/pkg/dto"
|
||||
"cs-agent/internal/pkg/errorsx"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/spf13/cast"
|
||||
)
|
||||
|
||||
func NormalizeNullableString(value *string) *string {
|
||||
if value == nil {
|
||||
return nil
|
||||
}
|
||||
v := strings.TrimSpace(*value)
|
||||
if v == "" {
|
||||
return nil
|
||||
}
|
||||
return &v
|
||||
}
|
||||
|
||||
func BuildAuditFields(operator *dto.AuthPrincipal) models.AuditFields {
|
||||
now := time.Now()
|
||||
fields := models.AuditFields{
|
||||
CreatedAt: now,
|
||||
UpdatedAt: now,
|
||||
}
|
||||
if operator != nil {
|
||||
fields.CreateUserID = operator.UserID
|
||||
fields.CreateUserName = operator.Username
|
||||
fields.UpdateUserID = operator.UserID
|
||||
fields.UpdateUserName = operator.Username
|
||||
}
|
||||
return fields
|
||||
}
|
||||
|
||||
func FormatTimePtr(t *time.Time) string {
|
||||
if t == nil || t.IsZero() {
|
||||
return ""
|
||||
}
|
||||
return t.Format(time.DateTime)
|
||||
}
|
||||
|
||||
func FormatTime(t time.Time) string {
|
||||
if t.IsZero() {
|
||||
return ""
|
||||
}
|
||||
return t.Format(time.DateTime)
|
||||
}
|
||||
|
||||
func GenerateRandomPassword(length int) (string, error) {
|
||||
if length <= 0 {
|
||||
return "", errorsx.InvalidParam("密码长度不合法")
|
||||
}
|
||||
|
||||
const charset = "ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz23456789"
|
||||
buf := make([]byte, length)
|
||||
random := make([]byte, length)
|
||||
if _, err := rand.Read(random); err != nil {
|
||||
return "", err
|
||||
}
|
||||
for i := range buf {
|
||||
buf[i] = charset[int(random[i])%len(charset)]
|
||||
}
|
||||
return string(buf), nil
|
||||
}
|
||||
|
||||
func JoinInt64s(values []int64) string {
|
||||
if len(values) == 0 {
|
||||
return ""
|
||||
}
|
||||
parts := make([]string, 0, len(values))
|
||||
for _, value := range values {
|
||||
parts = append(parts, cast.ToString(value))
|
||||
}
|
||||
return strings.Join(parts, ",")
|
||||
}
|
||||
|
||||
func SplitInt64s(raw string) []int64 {
|
||||
parts := strings.Split(strings.TrimSpace(raw), ",")
|
||||
ret := make([]int64, 0, len(parts))
|
||||
seen := make(map[int64]struct{})
|
||||
for _, part := range parts {
|
||||
value := strings.TrimSpace(part)
|
||||
if value == "" {
|
||||
continue
|
||||
}
|
||||
id, err := strconv.ParseInt(value, 10, 64)
|
||||
if err != nil || id <= 0 {
|
||||
continue
|
||||
}
|
||||
if _, exists := seen[id]; exists {
|
||||
continue
|
||||
}
|
||||
seen[id] = struct{}{}
|
||||
ret = append(ret, id)
|
||||
}
|
||||
return ret
|
||||
}
|
||||
Reference in New Issue
Block a user