refactor: 将客服后端重构为宿主可嵌入模块
- 注入数据库、运行时配置、统一响应、文件存储和平台 AI 能力,补充业务读写工具与客户快捷操作契约。 - 移除模块内重复的组织、客户、工单、标签、技能、旧工作流、MCP 和迁移实现,将身份权限与业务主体交由宿主管理。 - 使用 libSQL 重构向量存储,并完善图片消息、访客身份、排队调度、企业微信和支持聊天页面。 - 统一 HTTP、DTO 与 WebSocket 的 snake_case 协议,补齐模块初始化、业务动作和公共载荷等回归测试。
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"log/slog"
|
||||
|
||||
"code.tczkiot.com/wlw/ai-agent/internal/builders"
|
||||
"code.tczkiot.com/wlw/ai-agent/internal/pkg/dto/request"
|
||||
"code.tczkiot.com/wlw/ai-agent/internal/pkg/dto/response"
|
||||
@@ -13,6 +15,68 @@ import (
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
func ConversationGetQuick_actions(ctx *gin.Context) {
|
||||
if services.ChannelService.GetEnabledChannel(ctx) == nil {
|
||||
httpx.WriteJSON(ctx, httpx.JsonErrorMsg(ctx, "error.e0211"))
|
||||
return
|
||||
}
|
||||
external := httpx.GetExternalUser(ctx)
|
||||
if external == nil {
|
||||
httpx.WriteJSON(ctx, httpx.JsonErrorMsg(ctx, "error.e0150"))
|
||||
return
|
||||
}
|
||||
conversationID, _ := params.GetInt64(ctx, "conversation_id")
|
||||
conversation := services.ConversationService.Get(conversationID)
|
||||
if conversation == nil {
|
||||
httpx.WriteJSON(ctx, httpx.JsonErrorMsg(ctx, "error.e0116"))
|
||||
return
|
||||
}
|
||||
if !services.ConversationService.IsCustomerConversationOwner(conversation, *external) {
|
||||
httpx.WriteJSON(ctx, httpx.JsonErrorMsg(ctx, "error.e0222"))
|
||||
return
|
||||
}
|
||||
actions, err := services.CustomerQuickActionService.ListForConversation(ctx, conversation)
|
||||
if err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
results := make([]response.CustomerQuickActionResponse, 0, len(actions))
|
||||
for _, action := range actions {
|
||||
results = append(results, response.CustomerQuickActionResponse{
|
||||
Code: action.Code, Title: action.Title, Description: action.Description,
|
||||
})
|
||||
}
|
||||
httpx.WriteJSON(ctx, results)
|
||||
}
|
||||
|
||||
func ConversationPostQuick_action(ctx *gin.Context) {
|
||||
if services.ChannelService.GetEnabledChannel(ctx) == nil {
|
||||
httpx.WriteJSON(ctx, httpx.JsonErrorMsg(ctx, "error.e0211"))
|
||||
return
|
||||
}
|
||||
external := httpx.GetExternalUser(ctx)
|
||||
if external == nil {
|
||||
httpx.WriteJSON(ctx, httpx.JsonErrorMsg(ctx, "error.e0150"))
|
||||
return
|
||||
}
|
||||
req := request.ExecuteCustomerQuickActionRequest{}
|
||||
if err := params.ReadJSON(ctx, &req); err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
customerMessage, replyMessage, err := services.CustomerQuickActionService.ExecuteAndRecord(
|
||||
ctx, req.ConversationID, req.Code, req.ClientMsgID, *external, httpx.GetRequestID(ctx),
|
||||
)
|
||||
if err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
httpx.WriteJSON(ctx, response.CustomerQuickActionExecutionResponse{
|
||||
CustomerMessage: builders.BuildMessageWithLocale(customerMessage, i18nx.Locale(ctx)),
|
||||
ReplyMessage: builders.BuildMessageWithLocale(replyMessage, i18nx.Locale(ctx)),
|
||||
})
|
||||
}
|
||||
|
||||
func ConversationGetBy(ctx *gin.Context) {
|
||||
id, ok := httpx.GetPathInt64(ctx, "id")
|
||||
if !ok {
|
||||
@@ -59,6 +123,11 @@ func ConversationPostCreate_or_match(ctx *gin.Context) {
|
||||
|
||||
item, err := services.ConversationService.Create(*external, channel.ID, channel.AIAgentID)
|
||||
if err != nil {
|
||||
slog.ErrorContext(ctx.Request.Context(), "create or match conversation failed",
|
||||
"channel_id", channel.ID,
|
||||
"ai_agent_id", channel.AIAgentID,
|
||||
"error", err,
|
||||
)
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ func MessageAnyList(ctx *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
conversationID, _ := params.GetInt64(ctx, "conversationId")
|
||||
conversationID, _ := params.GetInt64(ctx, "conversation_id")
|
||||
if conversationID <= 0 {
|
||||
httpx.WriteJSON(ctx, httpx.JsonErrorMsg(ctx, "error.e0064"))
|
||||
return
|
||||
@@ -43,8 +43,8 @@ func MessageAnyList(ctx *gin.Context) {
|
||||
}
|
||||
|
||||
var (
|
||||
senderType, _ = params.Get(ctx, "senderType")
|
||||
messageType, _ = params.Get(ctx, "messageType")
|
||||
senderType, _ = params.Get(ctx, "sender_type")
|
||||
messageType, _ = params.Get(ctx, "message_type")
|
||||
cursor, _ = params.GetInt64(ctx, "cursor")
|
||||
limit, _ = params.GetInt(ctx, "limit")
|
||||
)
|
||||
@@ -72,7 +72,7 @@ func MessagePostSend(ctx *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
item, err := services.MessageService.SendCustomerMessageWithRequestID(req.ConversationID, req.ClientMsgID, req.MessageType, req.Content, req.Payload, *external, httpx.GetRequestID(ctx))
|
||||
item, err := services.MessageService.SendCustomerMessageWithContextAndRequestID(ctx.Request.Context(), req.ConversationID, req.ClientMsgID, req.MessageType, req.Content, req.Payload, *external, httpx.GetRequestID(ctx))
|
||||
if err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
@@ -114,7 +114,7 @@ func MessagePostUpload_image(ctx *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
rawConv := strings.TrimSpace(params.FormValue(ctx, "conversationId"))
|
||||
rawConv := strings.TrimSpace(params.FormValue(ctx, "conversation_id"))
|
||||
if rawConv == "" {
|
||||
httpx.WriteJSON(ctx, httpx.JsonErrorMsg(ctx, "error.e0064"))
|
||||
return
|
||||
@@ -148,7 +148,7 @@ func MessagePostUpload_image(ctx *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
item, err := services.AssetService.UploadFile(header, "images", nil)
|
||||
item, err := services.AssetService.UploadConversationImageFile(header, "images", conversationID, nil)
|
||||
if err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
@@ -167,7 +167,7 @@ func MessagePostUpload_attachment(ctx *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
rawConv := strings.TrimSpace(params.FormValue(ctx, "conversationId"))
|
||||
rawConv := strings.TrimSpace(params.FormValue(ctx, "conversation_id"))
|
||||
if rawConv == "" {
|
||||
httpx.WriteJSON(ctx, httpx.JsonErrorMsg(ctx, "error.e0064"))
|
||||
return
|
||||
@@ -187,7 +187,7 @@ func MessagePostUpload_attachment(ctx *gin.Context) {
|
||||
httpx.WriteJSON(ctx, httpx.JsonErrorMsg(ctx, "error.e0324"))
|
||||
return
|
||||
}
|
||||
item, err := services.AssetService.UploadFile(header, "attachments", nil)
|
||||
item, err := services.AssetService.UploadConversationFile(header, "attachments", conversationID, nil)
|
||||
if err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"code.tczkiot.com/wlw/ai-agent/internal/pkg/constants"
|
||||
"code.tczkiot.com/wlw/ai-agent/internal/pkg/dto/request"
|
||||
"code.tczkiot.com/wlw/ai-agent/internal/pkg/dto/response"
|
||||
"code.tczkiot.com/wlw/ai-agent/internal/pkg/enums"
|
||||
"code.tczkiot.com/wlw/ai-agent/internal/pkg/httpx"
|
||||
"code.tczkiot.com/wlw/ai-agent/internal/services"
|
||||
|
||||
@@ -20,11 +21,11 @@ func AgentAnyList(ctx *gin.Context) {
|
||||
return
|
||||
}
|
||||
list, paging := services.AgentProfileService.FindPageByCnd(params.NewPagedSqlCnd(ctx,
|
||||
params.QueryFilter{ParamName: "userId"},
|
||||
params.QueryFilter{ParamName: "teamId"},
|
||||
params.QueryFilter{ParamName: "serviceStatus"},
|
||||
params.QueryFilter{ParamName: "agentCode", Op: params.Like},
|
||||
params.QueryFilter{ParamName: "displayName", Op: params.Like},
|
||||
params.QueryFilter{ParamName: "user_id"},
|
||||
params.QueryFilter{ParamName: "team_id"},
|
||||
params.QueryFilter{ParamName: "service_status"},
|
||||
params.QueryFilter{ParamName: "agent_code", Op: params.Like},
|
||||
params.QueryFilter{ParamName: "display_name", Op: params.Like},
|
||||
).Desc("id"))
|
||||
results := builders.BuildAgentProfileList(list)
|
||||
httpx.WriteJSON(ctx, &web.PageResult{Results: results, Page: paging})
|
||||
@@ -36,11 +37,11 @@ func AgentGetList_all(ctx *gin.Context) {
|
||||
return
|
||||
}
|
||||
list := services.AgentProfileService.Find(params.NewPagedSqlCnd(ctx,
|
||||
params.QueryFilter{ParamName: "userId"},
|
||||
params.QueryFilter{ParamName: "teamId"},
|
||||
params.QueryFilter{ParamName: "serviceStatus"},
|
||||
params.QueryFilter{ParamName: "agentCode", Op: params.Like},
|
||||
).Desc("id"))
|
||||
params.QueryFilter{ParamName: "user_id"},
|
||||
params.QueryFilter{ParamName: "team_id"},
|
||||
params.QueryFilter{ParamName: "service_status"},
|
||||
params.QueryFilter{ParamName: "agent_code", Op: params.Like},
|
||||
).Eq("status", enums.StatusOk).Desc("id"))
|
||||
|
||||
httpx.WriteJSON(ctx, builders.BuildAgentProfileList(list))
|
||||
}
|
||||
|
||||
@@ -19,11 +19,11 @@ func AgentRunAnyList(ctx *gin.Context) {
|
||||
}
|
||||
queryParams := params.NewQueryParams(ctx)
|
||||
queryParams.Cnd = *params.NewPagedSqlCnd(ctx,
|
||||
params.QueryFilter{ParamName: "conversationId"},
|
||||
params.QueryFilter{ParamName: "aiAgentId"},
|
||||
params.QueryFilter{ParamName: "agentRevisionId"},
|
||||
params.QueryFilter{ParamName: "sourceMessageId"},
|
||||
params.QueryFilter{ParamName: "workflowRunId"},
|
||||
params.QueryFilter{ParamName: "conversation_id"},
|
||||
params.QueryFilter{ParamName: "ai_agent_id"},
|
||||
params.QueryFilter{ParamName: "agent_revision_id"},
|
||||
params.QueryFilter{ParamName: "source_message_id"},
|
||||
params.QueryFilter{ParamName: "workflow_run_id"},
|
||||
params.QueryFilter{ParamName: "status"},
|
||||
).Desc("id")
|
||||
list, paging := services.AgentRunService.FindPageByParams(queryParams)
|
||||
@@ -70,7 +70,7 @@ func AgentRunAnyMetrics(ctx *gin.Context) {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
aiAgentID, _ := params.GetInt64(ctx, "aiAgentId")
|
||||
aiAgentID, _ := params.GetInt64(ctx, "ai_agent_id")
|
||||
httpx.WriteJSON(ctx, services.AgentRunService.GetMetrics(aiAgentID))
|
||||
}
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ func AgentTeamAnyList(ctx *gin.Context) {
|
||||
}
|
||||
cnd := params.NewSqlCnd(ctx,
|
||||
params.QueryFilter{ParamName: "status"},
|
||||
params.QueryFilter{ParamName: "leaderUserId"},
|
||||
params.QueryFilter{ParamName: "leader_user_id"},
|
||||
params.QueryFilter{ParamName: "name", Op: params.Like},
|
||||
).Desc("id")
|
||||
if _, ok := params.Get(ctx, "status"); !ok {
|
||||
|
||||
@@ -22,7 +22,7 @@ func AgentTeamScheduleAnyList(ctx *gin.Context) {
|
||||
return
|
||||
}
|
||||
cnd := params.NewPagedSqlCnd(ctx,
|
||||
params.QueryFilter{ParamName: "teamId"},
|
||||
params.QueryFilter{ParamName: "team_id"},
|
||||
).Desc("start_at").Desc("id")
|
||||
list, paging := services.AgentTeamScheduleService.FindPageByCnd(cnd)
|
||||
results := make([]response.AgentTeamScheduleResponse, 0, len(list))
|
||||
@@ -37,9 +37,9 @@ func AgentTeamScheduleAnyCalendar(ctx *gin.Context) {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
startAt, _ := params.Get(ctx, "startAt")
|
||||
endAt, _ := params.Get(ctx, "endAt")
|
||||
teamID, _ := params.GetInt64(ctx, "teamId")
|
||||
startAt, _ := params.Get(ctx, "start_at")
|
||||
endAt, _ := params.Get(ctx, "end_at")
|
||||
teamID, _ := params.GetInt64(ctx, "team_id")
|
||||
list, err := services.AgentTeamScheduleService.FindCalendarSchedules(request.AgentTeamScheduleCalendarRequest{
|
||||
StartAt: startAt,
|
||||
EndAt: endAt,
|
||||
|
||||
@@ -3,8 +3,6 @@ package dashboard
|
||||
import (
|
||||
"code.tczkiot.com/wlw/ai-agent/internal/builders"
|
||||
"code.tczkiot.com/wlw/ai-agent/internal/pkg/httpx"
|
||||
"encoding/json"
|
||||
"strings"
|
||||
|
||||
"code.tczkiot.com/wlw/ai-agent/internal/models"
|
||||
"code.tczkiot.com/wlw/ai-agent/internal/pkg/constants"
|
||||
@@ -12,7 +10,6 @@ import (
|
||||
"code.tczkiot.com/wlw/ai-agent/internal/pkg/dto/response"
|
||||
"code.tczkiot.com/wlw/ai-agent/internal/pkg/enums"
|
||||
"code.tczkiot.com/wlw/ai-agent/internal/pkg/i18nx"
|
||||
"code.tczkiot.com/wlw/ai-agent/internal/pkg/toolx"
|
||||
"code.tczkiot.com/wlw/ai-agent/internal/pkg/utils"
|
||||
"code.tczkiot.com/wlw/ai-agent/internal/services"
|
||||
|
||||
@@ -240,6 +237,7 @@ func buildAIAgentResponseWithLocale(item *models.AIAgent, locale string) respons
|
||||
ret := response.AIAgentResponse{
|
||||
ID: item.ID,
|
||||
Name: item.Name,
|
||||
Avatar: item.Avatar,
|
||||
Description: item.Description,
|
||||
Status: item.Status,
|
||||
StatusName: enums.GetStatusLabel(item.Status),
|
||||
@@ -261,11 +259,7 @@ func buildAIAgentResponseWithLocale(item *models.AIAgent, locale string) respons
|
||||
FallbackModeName: enums.GetAIAgentFallbackModeLabel(item.FallbackMode),
|
||||
FallbackMessage: item.FallbackMessage,
|
||||
KnowledgeBaseIDs: utils.SplitInt64s(item.KnowledgeIDs),
|
||||
SkillIDs: utils.SplitInt64s(item.SkillIDs),
|
||||
Skills: make([]response.AIAgentSkillResponse, 0),
|
||||
Teams: make([]response.AIAgentTeamResponse, 0),
|
||||
MCPTools: make([]response.AIAgentMCPToolResponse, 0),
|
||||
WorkflowBindings: make([]response.AIAgentWorkflowBindingResponse, 0),
|
||||
PublishedRevisionID: item.PublishedRevisionID,
|
||||
SortNo: item.SortNo,
|
||||
CreatedAt: item.CreatedAt.Format("2006-01-02 15:04:05"),
|
||||
@@ -284,69 +278,5 @@ func buildAIAgentResponseWithLocale(item *models.AIAgent, locale string) respons
|
||||
})
|
||||
}
|
||||
}
|
||||
for _, id := range ret.SkillIDs {
|
||||
if skill := services.SkillDefinitionService.Get(id); skill != nil {
|
||||
ret.Skills = append(ret.Skills, response.AIAgentSkillResponse{
|
||||
ID: skill.ID,
|
||||
Name: skill.Name,
|
||||
})
|
||||
}
|
||||
}
|
||||
if raw := strings.TrimSpace(item.AllowedMCPTools); raw != "" {
|
||||
var mcpTools []request.AIAgentMCPToolRequest
|
||||
if err := json.Unmarshal([]byte(raw), &mcpTools); err == nil {
|
||||
for _, tool := range mcpTools {
|
||||
toolCode := strings.TrimSpace(tool.ToolCode)
|
||||
if toolCode == "" {
|
||||
toolCode = toolx.BuildMCPToolCode(tool.ServerCode, tool.ToolName)
|
||||
}
|
||||
toolCode = toolx.NormalizeToolCodeAlias(toolCode)
|
||||
if toolx.ResolveToolSourceType(toolCode) != enums.ToolSourceTypeMCP {
|
||||
continue
|
||||
}
|
||||
serverCode := strings.TrimSpace(tool.ServerCode)
|
||||
toolName := strings.TrimSpace(tool.ToolName)
|
||||
if registeredServerCode, registeredToolName, ok := toolx.GetRegisteredToolIdentity(toolCode); ok {
|
||||
serverCode = registeredServerCode
|
||||
toolName = registeredToolName
|
||||
} else if parsedServerCode, parsedToolName := toolx.SplitMCPToolCode(toolCode); parsedServerCode != "" && parsedToolName != "" {
|
||||
serverCode = parsedServerCode
|
||||
toolName = parsedToolName
|
||||
}
|
||||
title := strings.TrimSpace(tool.Title)
|
||||
if title == "" {
|
||||
if registeredTitle := toolx.GetRegisteredToolTitleLocale(toolCode, locale); registeredTitle != "" {
|
||||
title = registeredTitle
|
||||
}
|
||||
}
|
||||
description := strings.TrimSpace(tool.Description)
|
||||
if description == "" {
|
||||
if registeredDescription := toolx.GetRegisteredToolDescriptionLocale(toolCode, locale); registeredDescription != "" {
|
||||
description = registeredDescription
|
||||
}
|
||||
}
|
||||
ret.MCPTools = append(ret.MCPTools, response.AIAgentMCPToolResponse{
|
||||
ToolCode: toolCode,
|
||||
ServerCode: serverCode,
|
||||
ToolName: toolName,
|
||||
Title: title,
|
||||
Description: description,
|
||||
RiskLevel: tool.RiskLevel,
|
||||
RequireConfirmation: tool.RequireConfirmation,
|
||||
Arguments: tool.Arguments,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
for _, binding := range services.AIAgentService.ListWorkflowBindings(item.ID) {
|
||||
if binding.Workflow == nil || binding.Version == nil {
|
||||
continue
|
||||
}
|
||||
ret.WorkflowBindings = append(ret.WorkflowBindings, response.AIAgentWorkflowBindingResponse{
|
||||
ID: binding.Binding.ID, WorkflowID: binding.Binding.WorkflowID, WorkflowVersionID: binding.Binding.WorkflowVersionID,
|
||||
WorkflowName: binding.Workflow.Name, WorkflowVersion: binding.Version.Version, ToolName: binding.Binding.ToolName,
|
||||
TriggerInstruction: binding.Binding.TriggerInstruction, Priority: binding.Binding.Priority, Enabled: binding.Binding.Enabled,
|
||||
})
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
@@ -43,7 +43,6 @@ func setupAIAgentHandlerTestDB(t *testing.T) {
|
||||
&models.AIConfig{},
|
||||
&models.AgentTeam{},
|
||||
&models.KnowledgeBase{},
|
||||
&models.SkillDefinition{},
|
||||
); err != nil {
|
||||
t.Fatalf("auto migrate: %v", err)
|
||||
}
|
||||
|
||||
@@ -22,9 +22,9 @@ func AIConfigAnyList(ctx *gin.Context) {
|
||||
list, paging := services.AIConfigService.FindPageByCnd(params.NewPagedSqlCnd(ctx,
|
||||
params.QueryFilter{ParamName: "status"},
|
||||
params.QueryFilter{ParamName: "provider"},
|
||||
params.QueryFilter{ParamName: "modelType"},
|
||||
params.QueryFilter{ParamName: "model_type"},
|
||||
params.QueryFilter{ParamName: "name", Op: params.Like},
|
||||
params.QueryFilter{ParamName: "modelName", Op: params.Like},
|
||||
params.QueryFilter{ParamName: "model_name", Op: params.Like},
|
||||
).Asc("sort_no").Desc("id"))
|
||||
results := make([]response.AIConfigResponse, 0, len(list))
|
||||
for _, item := range list {
|
||||
@@ -40,7 +40,7 @@ func AIConfigAnyList_all(ctx *gin.Context) {
|
||||
}
|
||||
|
||||
list := services.AIConfigService.Find(params.NewSqlCnd(ctx,
|
||||
params.QueryFilter{ParamName: "modelType"},
|
||||
params.QueryFilter{ParamName: "model_type"},
|
||||
).Eq("status", enums.StatusOk).Desc("sort_no").Desc("id"))
|
||||
|
||||
results := make([]response.AIConfigResponse, 0, len(list))
|
||||
@@ -65,7 +65,7 @@ func AIConfigGetBy(ctx *gin.Context) {
|
||||
httpx.WriteJSON(ctx, httpx.JsonErrorMsg(ctx, "error.e0012"))
|
||||
return
|
||||
}
|
||||
httpx.WriteJSON(ctx, response.BuildAIConfigResponse(item))
|
||||
httpx.WriteJSON(ctx, response.BuildAIConfigDetailResponse(item))
|
||||
}
|
||||
|
||||
func AIConfigPostCreate(ctx *gin.Context) {
|
||||
|
||||
@@ -1,274 +0,0 @@
|
||||
package dashboard
|
||||
|
||||
import (
|
||||
"code.tczkiot.com/wlw/ai-agent/internal/builders"
|
||||
"code.tczkiot.com/wlw/ai-agent/internal/models"
|
||||
"code.tczkiot.com/wlw/ai-agent/internal/pkg/constants"
|
||||
"code.tczkiot.com/wlw/ai-agent/internal/pkg/dto/request"
|
||||
"code.tczkiot.com/wlw/ai-agent/internal/pkg/dto/response"
|
||||
"code.tczkiot.com/wlw/ai-agent/internal/pkg/enums"
|
||||
"code.tczkiot.com/wlw/ai-agent/internal/pkg/httpx"
|
||||
"code.tczkiot.com/wlw/ai-agent/internal/pkg/httpx/params"
|
||||
"code.tczkiot.com/wlw/ai-agent/internal/services"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/mlogclub/simple/web"
|
||||
)
|
||||
|
||||
func AIWorkflowAnyList(ctx *gin.Context) {
|
||||
if _, err := services.AuthService.RequirePermission(ctx, constants.PermissionAIAgentView); err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
cnd := params.NewPagedSqlCnd(ctx,
|
||||
params.QueryFilter{ParamName: "status"},
|
||||
params.QueryFilter{ParamName: "name", Op: params.Like},
|
||||
).NotEq("status", enums.StatusDeleted).Desc("id")
|
||||
list, paging := services.AIWorkflowService.FindPageByCnd(cnd)
|
||||
httpx.WriteJSON(ctx, &web.PageResult{Results: builders.BuildAIWorkflowList(list), Page: paging})
|
||||
}
|
||||
|
||||
func AIWorkflowGetBy(ctx *gin.Context) {
|
||||
id, ok := httpx.GetPathInt64(ctx, "id")
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
if _, err := services.AuthService.RequirePermission(ctx, constants.PermissionAIAgentView); err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
item := services.AIWorkflowService.Get(id)
|
||||
if item == nil {
|
||||
httpx.WriteJSON(ctx, httpx.JsonErrorMsg(ctx, "error.e0002"))
|
||||
return
|
||||
}
|
||||
httpx.WriteJSON(ctx, builders.BuildAIWorkflow(item))
|
||||
}
|
||||
|
||||
func AIWorkflowPostCreate(ctx *gin.Context) {
|
||||
operator, err := services.AuthService.RequirePermission(ctx, constants.PermissionAIAgentCreate)
|
||||
if err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
req := request.CreateAIWorkflowRequest{}
|
||||
if err := params.ReadJSON(ctx, &req); err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
item, err := services.AIWorkflowService.CreateWorkflow(req, operator)
|
||||
if err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
httpx.WriteJSON(ctx, builders.BuildAIWorkflow(item))
|
||||
}
|
||||
|
||||
func AIWorkflowPostUpdate(ctx *gin.Context) {
|
||||
operator, err := services.AuthService.RequirePermission(ctx, constants.PermissionAIAgentUpdate)
|
||||
if err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
req := request.UpdateAIWorkflowRequest{}
|
||||
if err := params.ReadJSON(ctx, &req); err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
if err := services.AIWorkflowService.UpdateWorkflow(req, operator); err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
httpx.WriteJSON(ctx, nil)
|
||||
}
|
||||
|
||||
func AIWorkflowPostDelete(ctx *gin.Context) {
|
||||
operator, err := services.AuthService.RequirePermission(ctx, constants.PermissionAIAgentDelete)
|
||||
if err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
req := request.DeleteAIWorkflowRequest{}
|
||||
if err := params.ReadJSON(ctx, &req); err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
if err := services.AIWorkflowService.DeleteWorkflow(req.ID, operator); err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
httpx.WriteJSON(ctx, nil)
|
||||
}
|
||||
|
||||
func AIWorkflowPostRestoreVersion(ctx *gin.Context) {
|
||||
operator, err := services.AuthService.RequirePermission(ctx, constants.PermissionAIAgentUpdate)
|
||||
if err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
req := request.RestoreAIWorkflowVersionRequest{}
|
||||
if err := params.ReadJSON(ctx, &req); err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
if err := services.AIWorkflowService.RestoreVersion(req, operator); err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
httpx.WriteJSON(ctx, nil)
|
||||
}
|
||||
|
||||
func AIWorkflowGetUsage(ctx *gin.Context) {
|
||||
id, ok := httpx.GetPathInt64(ctx, "id")
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
if _, err := services.AuthService.RequirePermission(ctx, constants.PermissionAIAgentView); err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
items := services.AIWorkflowService.ListUsage(id)
|
||||
ret := make([]response.AIWorkflowUsageResponse, 0, len(items))
|
||||
for _, item := range items {
|
||||
if item.Agent == nil || item.Version == nil {
|
||||
continue
|
||||
}
|
||||
ret = append(ret, response.AIWorkflowUsageResponse{AIAgentID: item.Agent.ID, AIAgentName: item.Agent.Name, WorkflowVersionID: item.Binding.WorkflowVersionID, WorkflowVersion: item.Version.Version, Enabled: item.Binding.Enabled})
|
||||
}
|
||||
httpx.WriteJSON(ctx, ret)
|
||||
}
|
||||
|
||||
func AIWorkflowGetNodeSpecList(ctx *gin.Context) {
|
||||
if _, err := services.AuthService.RequirePermission(ctx, constants.PermissionAIAgentView); err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
httpx.WriteJSON(ctx, builders.BuildAIWorkflowNodeSpecs(services.AIWorkflowService.ListNodeSpecs()))
|
||||
}
|
||||
|
||||
func AIWorkflowGetDefaultDefinition(ctx *gin.Context) {
|
||||
if _, err := services.AuthService.RequirePermission(ctx, constants.PermissionAIAgentView); err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
httpx.WriteJSON(ctx, services.AIWorkflowService.DefaultAgentWorkflowDefinition())
|
||||
}
|
||||
|
||||
func AIWorkflowGetTemplateList(ctx *gin.Context) {
|
||||
if _, err := services.AuthService.RequirePermission(ctx, constants.PermissionAIAgentView); err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
httpx.WriteJSON(ctx, builders.BuildAIWorkflowTemplates(services.AIWorkflowService.ListWorkflowTemplates()))
|
||||
}
|
||||
|
||||
func AIWorkflowPostValidate(ctx *gin.Context) {
|
||||
if _, err := services.AuthService.RequirePermission(ctx, constants.PermissionAIAgentView); err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
req := request.ValidateAIWorkflowRequest{}
|
||||
if err := params.ReadJSON(ctx, &req); err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
result := services.AIWorkflowService.ValidateDefinition(req.Definition)
|
||||
httpx.WriteJSON(ctx, response.AIWorkflowValidationResponse{
|
||||
Valid: result.Valid,
|
||||
Errors: result.Errors,
|
||||
})
|
||||
}
|
||||
|
||||
func AIWorkflowPostPublish(ctx *gin.Context) {
|
||||
operator, err := services.AuthService.RequirePermission(ctx, constants.PermissionAIAgentUpdate)
|
||||
if err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
req := request.PublishAIWorkflowRequest{}
|
||||
if err := params.ReadJSON(ctx, &req); err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
item, err := services.AIWorkflowService.PublishWorkflow(req, operator)
|
||||
if err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
httpx.WriteJSON(ctx, builders.BuildAIWorkflowVersion(item))
|
||||
}
|
||||
|
||||
func AIWorkflowAnyVersionList(ctx *gin.Context) {
|
||||
if _, err := services.AuthService.RequirePermission(ctx, constants.PermissionAIAgentView); err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
queryParams := params.NewQueryParams(ctx)
|
||||
cnd := params.NewPagedSqlCnd(ctx, params.QueryFilter{ParamName: "workflowId"}).Desc("version").Desc("id")
|
||||
queryParams.Cnd = *cnd
|
||||
list, paging := services.AIWorkflowService.FindVersionPageByParams(queryParams)
|
||||
httpx.WriteJSON(ctx, &web.PageResult{Results: builders.BuildAIWorkflowVersionList(list), Page: paging})
|
||||
}
|
||||
|
||||
func AIWorkflowGetVersionBy(ctx *gin.Context) {
|
||||
id, ok := httpx.GetPathInt64(ctx, "id")
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
if _, err := services.AuthService.RequirePermission(ctx, constants.PermissionAIAgentView); err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
item := services.AIWorkflowService.GetVersion(id)
|
||||
if item == nil {
|
||||
httpx.WriteJSON(ctx, httpx.JsonErrorMsg(ctx, "error.e0002"))
|
||||
return
|
||||
}
|
||||
httpx.WriteJSON(ctx, builders.BuildAIWorkflowVersion(item))
|
||||
}
|
||||
|
||||
func AIWorkflowAnyRunList(ctx *gin.Context) {
|
||||
if _, err := services.AuthService.RequirePermission(ctx, constants.PermissionAIAgentView); err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
cnd := params.NewPagedSqlCnd(ctx,
|
||||
params.QueryFilter{ParamName: "workflowId"},
|
||||
params.QueryFilter{ParamName: "workflowVersionId"},
|
||||
params.QueryFilter{ParamName: "conversationId"},
|
||||
params.QueryFilter{ParamName: "aiAgentId"},
|
||||
params.QueryFilter{ParamName: "messageId"},
|
||||
params.QueryFilter{ParamName: "status"},
|
||||
).Desc("id")
|
||||
list, paging := services.AIWorkflowService.FindRunPageByCnd(cnd)
|
||||
auditItems := services.AIWorkflowService.BuildRunAuditItems(list)
|
||||
results := make([]response.AIWorkflowRunResponse, 0, len(auditItems))
|
||||
for i := range auditItems {
|
||||
item := auditItems[i]
|
||||
results = append(results, builders.BuildAIWorkflowRunWithContext(&item.Run, item.Workflow, item.Version, item.Agent))
|
||||
}
|
||||
httpx.WriteJSON(ctx, &web.PageResult{Results: results, Page: paging})
|
||||
}
|
||||
|
||||
func AIWorkflowGetRunBy(ctx *gin.Context) {
|
||||
id, ok := httpx.GetPathInt64(ctx, "id")
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
if _, err := services.AuthService.RequirePermission(ctx, constants.PermissionAIAgentView); err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
item, nodes := services.AIWorkflowService.GetRunDetail(id)
|
||||
if item == nil {
|
||||
httpx.WriteJSON(ctx, httpx.JsonErrorMsg(ctx, "error.e0002"))
|
||||
return
|
||||
}
|
||||
auditItems := services.AIWorkflowService.BuildRunAuditItems([]models.AIWorkflowRun{*item})
|
||||
if len(auditItems) == 0 {
|
||||
httpx.WriteJSON(ctx, builders.BuildAIWorkflowRunDetail(item, nodes))
|
||||
return
|
||||
}
|
||||
auditItem := auditItems[0]
|
||||
httpx.WriteJSON(ctx, builders.BuildAIWorkflowRunDetailWithContext(&auditItem.Run, nodes, auditItem.Workflow, auditItem.Version, auditItem.Agent))
|
||||
}
|
||||
@@ -25,7 +25,7 @@ func AssetAnyList(ctx *gin.Context) {
|
||||
cnd := params.NewPagedSqlCnd(ctx,
|
||||
params.QueryFilter{ParamName: "provider"},
|
||||
params.QueryFilter{ParamName: "status"},
|
||||
params.QueryFilter{ParamName: "createUserId"},
|
||||
params.QueryFilter{ParamName: "create_user_id"},
|
||||
params.QueryFilter{ParamName: "filename", Op: params.Like},
|
||||
).Desc("id")
|
||||
if strings.TrimSpace(ctx.Query("status")) == "" {
|
||||
|
||||
@@ -25,8 +25,8 @@ func ChannelAnyList(ctx *gin.Context) {
|
||||
list, paging := services.ChannelService.FindPageByCnd(params.NewPagedSqlCnd(ctx,
|
||||
params.QueryFilter{ParamName: "status"},
|
||||
params.QueryFilter{ParamName: "name", Op: params.Like},
|
||||
params.QueryFilter{ParamName: "channelType"},
|
||||
params.QueryFilter{ParamName: "channelId", Op: params.Like},
|
||||
params.QueryFilter{ParamName: "channel_type"},
|
||||
params.QueryFilter{ParamName: "channel_id", Op: params.Like},
|
||||
).Where("status <> ?", enums.StatusDeleted).Desc("id"))
|
||||
results := make([]response.ChannelResponse, 0, len(list))
|
||||
for _, item := range list {
|
||||
@@ -71,10 +71,10 @@ func ChannelAnyWxworkOutboxFailedList(ctx *gin.Context) {
|
||||
return
|
||||
}
|
||||
cnd := params.NewPagedSqlCnd(ctx,
|
||||
params.QueryFilter{ParamName: "conversationId"},
|
||||
params.QueryFilter{ParamName: "messageId"},
|
||||
params.QueryFilter{ParamName: "conversation_id"},
|
||||
params.QueryFilter{ParamName: "message_id"},
|
||||
).Eq("channel_type", enums.ChannelTypeWxWorkKF)
|
||||
status := strings.TrimSpace(params.FormValue(ctx, "sendStatus"))
|
||||
status := strings.TrimSpace(params.FormValue(ctx, "send_status"))
|
||||
switch status {
|
||||
case "":
|
||||
cnd.Eq("send_status", string(enums.ChannelMessageOutboxStatusFailed))
|
||||
|
||||
@@ -1,130 +0,0 @@
|
||||
package dashboard
|
||||
|
||||
import (
|
||||
"code.tczkiot.com/wlw/ai-agent/internal/builders"
|
||||
"code.tczkiot.com/wlw/ai-agent/internal/pkg/constants"
|
||||
"code.tczkiot.com/wlw/ai-agent/internal/pkg/dto/request"
|
||||
"code.tczkiot.com/wlw/ai-agent/internal/pkg/enums"
|
||||
"code.tczkiot.com/wlw/ai-agent/internal/pkg/httpx"
|
||||
"code.tczkiot.com/wlw/ai-agent/internal/services"
|
||||
|
||||
"code.tczkiot.com/wlw/ai-agent/internal/pkg/httpx/params"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/mlogclub/simple/web"
|
||||
)
|
||||
|
||||
func CompanyAnyList(ctx *gin.Context) {
|
||||
if _, err := services.AuthService.RequirePermission(ctx, constants.PermissionCompanyView); err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
list, paging := services.CompanyService.FindPageByCnd(params.NewPagedSqlCnd(ctx,
|
||||
params.QueryFilter{ParamName: "status"},
|
||||
params.QueryFilter{ParamName: "name", Op: params.Like},
|
||||
params.QueryFilter{ParamName: "code", Op: params.Like},
|
||||
).Where("status <> ?", enums.StatusDeleted).Desc("id"))
|
||||
|
||||
results := builders.BuildCompanyList(list)
|
||||
companyIDs := make([]int64, 0, len(results))
|
||||
for _, item := range results {
|
||||
companyIDs = append(companyIDs, item.ID)
|
||||
}
|
||||
countMap := services.CustomerService.CountByCompanyIDs(companyIDs)
|
||||
for i := range results {
|
||||
results[i].CustomerCount = countMap[results[i].ID]
|
||||
}
|
||||
httpx.WriteJSON(ctx, &web.PageResult{Results: results, Page: paging})
|
||||
}
|
||||
|
||||
func CompanyGetBy(ctx *gin.Context) {
|
||||
id, ok := httpx.GetPathInt64(ctx, "id")
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
if _, err := services.AuthService.RequirePermission(ctx, constants.PermissionCompanyView); err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
item := services.CompanyService.Get(id)
|
||||
if item == nil || item.Status == enums.StatusDeleted {
|
||||
httpx.WriteJSON(ctx, nil)
|
||||
return
|
||||
}
|
||||
ret := builders.BuildCompany(item)
|
||||
httpx.WriteJSON(ctx, &ret)
|
||||
}
|
||||
|
||||
func CompanyPostCreate(ctx *gin.Context) {
|
||||
user, err := services.AuthService.RequirePermission(ctx, constants.PermissionCompanyCreate)
|
||||
if err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
req := request.CreateCompanyRequest{}
|
||||
if err := params.ReadJSON(ctx, &req); err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
item, err := services.CompanyService.CreateCompany(req, user)
|
||||
if err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
ret := builders.BuildCompany(item)
|
||||
httpx.WriteJSON(ctx, &ret)
|
||||
}
|
||||
|
||||
func CompanyPostUpdate(ctx *gin.Context) {
|
||||
user, err := services.AuthService.RequirePermission(ctx, constants.PermissionCompanyUpdate)
|
||||
if err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
req := request.UpdateCompanyRequest{}
|
||||
if err := params.ReadJSON(ctx, &req); err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
if err := services.CompanyService.UpdateCompany(req, user); err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
httpx.WriteJSON(ctx, nil)
|
||||
}
|
||||
|
||||
func CompanyPostDelete(ctx *gin.Context) {
|
||||
user, err := services.AuthService.RequirePermission(ctx, constants.PermissionCompanyDelete)
|
||||
if err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
req := request.DeleteCompanyRequest{}
|
||||
if err := params.ReadJSON(ctx, &req); err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
if err := services.CompanyService.DeleteCompany(req.ID, *user); err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
httpx.WriteJSON(ctx, nil)
|
||||
}
|
||||
|
||||
func CompanyPostUpdate_status(ctx *gin.Context) {
|
||||
user, err := services.AuthService.RequirePermission(ctx, constants.PermissionCompanyUpdate)
|
||||
if err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
req := request.UpdateCompanyStatusRequest{}
|
||||
if err := params.ReadJSON(ctx, &req); err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
if err := services.CompanyService.UpdateStatus(req.ID, req.Status, user); err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
httpx.WriteJSON(ctx, nil)
|
||||
}
|
||||
@@ -28,8 +28,8 @@ func ConversationAnyList(ctx *gin.Context) {
|
||||
|
||||
cnd := params.NewPagedSqlCnd(ctx,
|
||||
params.QueryFilter{ParamName: "status"},
|
||||
params.QueryFilter{ParamName: "serviceMode"},
|
||||
params.QueryFilter{ParamName: "currentAssigneeId"},
|
||||
params.QueryFilter{ParamName: "service_mode"},
|
||||
params.QueryFilter{ParamName: "current_assignee_id"},
|
||||
).Desc("last_message_at").Desc("id")
|
||||
|
||||
paging := params.GetPaging(ctx)
|
||||
@@ -39,19 +39,7 @@ func ConversationAnyList(ctx *gin.Context) {
|
||||
cnd.Where("customer_name LIKE ? OR last_message_summary LIKE ?", keywordLike, keywordLike)
|
||||
}
|
||||
|
||||
// 标签搜索
|
||||
if tagID, _ := params.GetInt64(ctx, "tagId"); tagID > 0 {
|
||||
tagIDs := services.TagService.GetSelfAndDescendantIDs(tagID)
|
||||
if len(tagIDs) == 0 {
|
||||
httpx.WriteJSON(ctx, &web.PageResult{
|
||||
Results: []response.ConversationResponse{},
|
||||
Page: paging,
|
||||
})
|
||||
return
|
||||
}
|
||||
cnd.Where("id IN (SELECT conversation_id FROM conversation_tag_rels WHERE tag_id IN (?))", tagIDs)
|
||||
}
|
||||
if agentTeamID, _ := params.GetInt64(ctx, "agentTeamId"); agentTeamID > 0 {
|
||||
if agentTeamID, _ := params.GetInt64(ctx, "agent_team_id"); agentTeamID > 0 {
|
||||
userIDs := services.AgentProfileService.GetUserIDsByTeamID(agentTeamID)
|
||||
if len(userIDs) == 0 {
|
||||
httpx.WriteJSON(ctx, &web.PageResult{
|
||||
@@ -130,9 +118,9 @@ func ConversationAnyMessage_list(ctx *gin.Context) {
|
||||
}
|
||||
|
||||
var (
|
||||
conversationID, _ = params.GetInt64(ctx, "conversationId")
|
||||
senderType, _ = params.Get(ctx, "senderType")
|
||||
messageType, _ = params.Get(ctx, "messageType")
|
||||
conversationID, _ = params.GetInt64(ctx, "conversation_id")
|
||||
senderType, _ = params.Get(ctx, "sender_type")
|
||||
messageType, _ = params.Get(ctx, "message_type")
|
||||
cursor, _ = params.GetInt64(ctx, "cursor")
|
||||
limit, _ = params.GetInt(ctx, "limit")
|
||||
)
|
||||
@@ -225,24 +213,6 @@ func ConversationPostClose(ctx *gin.Context) {
|
||||
httpx.WriteJSON(ctx, nil)
|
||||
}
|
||||
|
||||
func ConversationPostLink_customer(ctx *gin.Context) {
|
||||
operator, err := services.AuthService.RequirePermission(ctx, constants.PermissionConversationLinkCustomer)
|
||||
if err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
req := request.LinkConversationCustomerRequest{}
|
||||
if err := params.ReadJSON(ctx, &req); err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
if err := services.ConversationService.LinkConversationCustomer(req.ConversationID, req.CustomerID, operator); err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
httpx.WriteJSON(ctx, nil)
|
||||
}
|
||||
|
||||
func ConversationPostSend_message(ctx *gin.Context) {
|
||||
operator, err := services.AuthService.RequirePermission(ctx, constants.PermissionConversationSend)
|
||||
if err != nil {
|
||||
@@ -309,7 +279,7 @@ func ConversationPostUpload_image(ctx *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
rawConv := strings.TrimSpace(params.FormValue(ctx, "conversationId"))
|
||||
rawConv := strings.TrimSpace(params.FormValue(ctx, "conversation_id"))
|
||||
if rawConv == "" {
|
||||
httpx.WriteJSON(ctx, httpx.JsonErrorMsg(ctx, "error.e0064"))
|
||||
return
|
||||
@@ -334,7 +304,7 @@ func ConversationPostUpload_image(ctx *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
item, err := services.AssetService.UploadFile(header, "images", operator)
|
||||
item, err := services.AssetService.UploadConversationImageFile(header, "images", conversationID, operator)
|
||||
if err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
@@ -349,7 +319,7 @@ func ConversationPostUpload_attachment(ctx *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
rawConv := strings.TrimSpace(params.FormValue(ctx, "conversationId"))
|
||||
rawConv := strings.TrimSpace(params.FormValue(ctx, "conversation_id"))
|
||||
if rawConv == "" {
|
||||
httpx.WriteJSON(ctx, httpx.JsonErrorMsg(ctx, "error.e0064"))
|
||||
return
|
||||
@@ -369,47 +339,10 @@ func ConversationPostUpload_attachment(ctx *gin.Context) {
|
||||
httpx.WriteJSON(ctx, httpx.JsonErrorMsg(ctx, "error.e0324"))
|
||||
return
|
||||
}
|
||||
item, err := services.AssetService.UploadFile(header, "attachments", operator)
|
||||
item, err := services.AssetService.UploadConversationFile(header, "attachments", conversationID, operator)
|
||||
if err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
httpx.WriteJSON(ctx, builders.BuildAsset(item))
|
||||
}
|
||||
|
||||
func ConversationPostAdd_tag(ctx *gin.Context) {
|
||||
operator, err := services.AuthService.RequirePermission(ctx, constants.PermissionConversationTag)
|
||||
if err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
|
||||
req := request.AddConversationTagRequest{}
|
||||
if err := params.ReadJSON(ctx, &req); err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
if err := services.ConversationTagService.AddTag(req, operator); err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
httpx.WriteJSON(ctx, nil)
|
||||
}
|
||||
|
||||
func ConversationPostRemove_tag(ctx *gin.Context) {
|
||||
if _, err := services.AuthService.RequirePermission(ctx, constants.PermissionConversationTag); err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
|
||||
req := request.RemoveConversationTagRequest{}
|
||||
if err := params.ReadJSON(ctx, &req); err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
if err := services.ConversationTagService.RemoveTag(req); err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
httpx.WriteJSON(ctx, nil)
|
||||
}
|
||||
|
||||
@@ -1,84 +0,0 @@
|
||||
package dashboard
|
||||
|
||||
import (
|
||||
"code.tczkiot.com/wlw/ai-agent/internal/builders"
|
||||
"code.tczkiot.com/wlw/ai-agent/internal/pkg/constants"
|
||||
"code.tczkiot.com/wlw/ai-agent/internal/pkg/dto/request"
|
||||
"code.tczkiot.com/wlw/ai-agent/internal/pkg/httpx"
|
||||
"code.tczkiot.com/wlw/ai-agent/internal/services"
|
||||
|
||||
"code.tczkiot.com/wlw/ai-agent/internal/pkg/httpx/params"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// AnyList GET/POST /customer-contact/list?customerId=
|
||||
func CustomerContactAnyList(ctx *gin.Context) {
|
||||
if _, err := services.AuthService.RequirePermission(ctx, constants.PermissionCustomerView); err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
customerID, _ := params.GetInt64(ctx, "customerId")
|
||||
if customerID <= 0 {
|
||||
httpx.WriteJSON(ctx, httpx.JsonErrorMsg(ctx, "error.e0065"))
|
||||
return
|
||||
}
|
||||
list := services.CustomerContactService.FindActiveByCustomerID(customerID)
|
||||
httpx.WriteJSON(ctx, builders.BuildCustomerContactList(list))
|
||||
}
|
||||
|
||||
func CustomerContactPostCreate(ctx *gin.Context) {
|
||||
user, err := services.AuthService.RequirePermission(ctx, constants.PermissionCustomerUpdate)
|
||||
if err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
req := request.CreateCustomerContactRequest{}
|
||||
if err := params.ReadJSON(ctx, &req); err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
item, err := services.CustomerContactService.CreateCustomerContact(req, user)
|
||||
if err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
ret := builders.BuildCustomerContactResponse(item)
|
||||
httpx.WriteJSON(ctx, &ret)
|
||||
}
|
||||
|
||||
func CustomerContactPostUpdate(ctx *gin.Context) {
|
||||
user, err := services.AuthService.RequirePermission(ctx, constants.PermissionCustomerUpdate)
|
||||
if err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
req := request.UpdateCustomerContactRequest{}
|
||||
if err := params.ReadJSON(ctx, &req); err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
if err := services.CustomerContactService.UpdateCustomerContact(req, user); err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
httpx.WriteJSON(ctx, nil)
|
||||
}
|
||||
|
||||
func CustomerContactPostDelete(ctx *gin.Context) {
|
||||
user, err := services.AuthService.RequirePermission(ctx, constants.PermissionCustomerUpdate)
|
||||
if err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
req := request.DeleteCustomerContactRequest{}
|
||||
if err := params.ReadJSON(ctx, &req); err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
if err := services.CustomerContactService.DeleteCustomerContact(req.ID, user); err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
httpx.WriteJSON(ctx, nil)
|
||||
}
|
||||
@@ -1,150 +0,0 @@
|
||||
package dashboard
|
||||
|
||||
import (
|
||||
"code.tczkiot.com/wlw/ai-agent/internal/builders"
|
||||
"code.tczkiot.com/wlw/ai-agent/internal/pkg/constants"
|
||||
"code.tczkiot.com/wlw/ai-agent/internal/pkg/dto"
|
||||
"code.tczkiot.com/wlw/ai-agent/internal/pkg/dto/request"
|
||||
"code.tczkiot.com/wlw/ai-agent/internal/pkg/enums"
|
||||
"code.tczkiot.com/wlw/ai-agent/internal/pkg/httpx"
|
||||
"code.tczkiot.com/wlw/ai-agent/internal/services"
|
||||
|
||||
"code.tczkiot.com/wlw/ai-agent/internal/pkg/httpx/params"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/mlogclub/simple/web"
|
||||
)
|
||||
|
||||
func CustomerPostList(ctx *gin.Context) {
|
||||
if _, err := services.AuthService.RequirePermission(ctx, constants.PermissionCustomerView); err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
var req request.CustomerListRequest
|
||||
if err := params.ReadJSON(ctx, &req); err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
list, paging := services.CustomerService.ListCustomers(req)
|
||||
httpx.WriteJSON(ctx, &web.PageResult{Results: builders.BuildCustomerList(list), Page: paging})
|
||||
}
|
||||
|
||||
func CustomerGetBy(ctx *gin.Context) {
|
||||
id, ok := httpx.GetPathInt64(ctx, "id")
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
if _, err := services.AuthService.RequirePermission(ctx, constants.PermissionCustomerView); err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
item := services.CustomerService.Get(id)
|
||||
if item == nil || item.Status == enums.StatusDeleted {
|
||||
httpx.WriteJSON(ctx, nil)
|
||||
return
|
||||
}
|
||||
ret := builders.BuildCustomer(item)
|
||||
httpx.WriteJSON(ctx, &ret)
|
||||
}
|
||||
|
||||
// PostSave_profile POST /save_profile — 客户主信息与联系方式在同一事务中保存。
|
||||
func CustomerPostSave_profile(ctx *gin.Context) {
|
||||
req := request.SaveCustomerProfileRequest{}
|
||||
if err := params.ReadJSON(ctx, &req); err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
createMode := req.ID == nil || *req.ID <= 0
|
||||
var user *dto.AuthPrincipal
|
||||
var err error
|
||||
if createMode {
|
||||
user, err = services.AuthService.RequirePermission(ctx, constants.PermissionCustomerCreate)
|
||||
} else {
|
||||
user, err = services.AuthService.RequirePermission(ctx, constants.PermissionCustomerUpdate)
|
||||
}
|
||||
if err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
item, err := services.CustomerService.SaveCustomerProfile(req, user)
|
||||
if err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
ret := builders.BuildCustomer(item)
|
||||
httpx.WriteJSON(ctx, &ret)
|
||||
}
|
||||
|
||||
func CustomerPostCreate(ctx *gin.Context) {
|
||||
user, err := services.AuthService.RequirePermission(ctx, constants.PermissionCustomerCreate)
|
||||
if err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
req := request.CreateCustomerRequest{}
|
||||
if err := params.ReadJSON(ctx, &req); err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
item, err := services.CustomerService.CreateCustomer(req, user)
|
||||
if err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
ret := builders.BuildCustomer(item)
|
||||
httpx.WriteJSON(ctx, &ret)
|
||||
}
|
||||
|
||||
func CustomerPostUpdate(ctx *gin.Context) {
|
||||
user, err := services.AuthService.RequirePermission(ctx, constants.PermissionCustomerUpdate)
|
||||
if err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
req := request.UpdateCustomerRequest{}
|
||||
if err := params.ReadJSON(ctx, &req); err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
if err := services.CustomerService.UpdateCustomer(req, user); err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
httpx.WriteJSON(ctx, nil)
|
||||
}
|
||||
|
||||
func CustomerPostDelete(ctx *gin.Context) {
|
||||
user, err := services.AuthService.RequirePermission(ctx, constants.PermissionCustomerDelete)
|
||||
if err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
req := request.DeleteCustomerRequest{}
|
||||
if err := params.ReadJSON(ctx, &req); err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
if err := services.CustomerService.DeleteCustomer(req.ID, *user); err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
httpx.WriteJSON(ctx, nil)
|
||||
}
|
||||
|
||||
func CustomerPostUpdate_status(ctx *gin.Context) {
|
||||
user, err := services.AuthService.RequirePermission(ctx, constants.PermissionCustomerUpdate)
|
||||
if err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
req := request.UpdateCustomerStatusRequest{}
|
||||
if err := params.ReadJSON(ctx, &req); err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
if err := services.CustomerService.UpdateStatus(req.ID, req.Status, user); err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
httpx.WriteJSON(ctx, nil)
|
||||
}
|
||||
@@ -19,7 +19,7 @@ func KnowledgeDirectoryGetList_all(ctx *gin.Context) {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
knowledgeBaseID, ok := params.GetInt64(ctx, "knowledgeBaseId")
|
||||
knowledgeBaseID, ok := params.GetInt64(ctx, "knowledge_base_id")
|
||||
if !ok || knowledgeBaseID <= 0 {
|
||||
httpx.WriteJSON(ctx, errorsx.InvalidParamI18n("error.e0283"))
|
||||
return
|
||||
@@ -89,8 +89,8 @@ func KnowledgeDirectoryPostUpdate_sort(ctx *gin.Context) {
|
||||
return
|
||||
}
|
||||
var req struct {
|
||||
KnowledgeBaseID int64 `json:"knowledgeBaseId"`
|
||||
ParentID int64 `json:"parentId"`
|
||||
KnowledgeBaseID int64 `json:"knowledge_base_id"`
|
||||
ParentID int64 `json:"parent_id"`
|
||||
IDs []int64 `json:"ids"`
|
||||
}
|
||||
if err := params.ReadJSON(ctx, &req); err != nil {
|
||||
|
||||
@@ -22,11 +22,11 @@ func KnowledgeDocumentAnyList(ctx *gin.Context) {
|
||||
}
|
||||
|
||||
cnd := params.NewPagedSqlCnd(ctx,
|
||||
params.QueryFilter{ParamName: "knowledgeBaseId"},
|
||||
params.QueryFilter{ParamName: "knowledge_base_id"},
|
||||
params.QueryFilter{ParamName: "title", Op: params.Like},
|
||||
).Desc("id")
|
||||
knowledgeBaseID, _ := params.GetInt64(ctx, "knowledgeBaseId")
|
||||
if directoryID, ok := params.GetInt64(ctx, "directoryId"); ok {
|
||||
knowledgeBaseID, _ := params.GetInt64(ctx, "knowledge_base_id")
|
||||
if directoryID, ok := params.GetInt64(ctx, "directory_id"); ok {
|
||||
cnd.Where("directory_id = ?", directoryID)
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ func KnowledgeDocumentAnyList(ctx *gin.Context) {
|
||||
} else {
|
||||
cnd.Where("status != ?", enums.StatusDeleted)
|
||||
}
|
||||
if indexStatus, ok := params.Get(ctx, "indexStatus"); ok {
|
||||
if indexStatus, ok := params.Get(ctx, "index_status"); ok {
|
||||
if !enums.IsValidKnowledgeDocumentIndexStatus(indexStatus) {
|
||||
httpx.WriteJSON(ctx, httpx.JsonErrorMsg(ctx, "error.e0067"))
|
||||
return
|
||||
|
||||
@@ -36,7 +36,7 @@ func KnowledgeFAQGetExport(ctx *gin.Context) {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
knowledgeBaseID, ok := params.GetInt64(ctx, "knowledgeBaseId")
|
||||
knowledgeBaseID, ok := params.GetInt64(ctx, "knowledge_base_id")
|
||||
if !ok || knowledgeBaseID <= 0 {
|
||||
httpx.WriteJSON(ctx, errorsx.InvalidParamI18n("error.e0283"))
|
||||
return
|
||||
@@ -62,7 +62,7 @@ func KnowledgeFAQPostImport(ctx *gin.Context) {
|
||||
return
|
||||
}
|
||||
}
|
||||
knowledgeBaseID, ok := params.GetInt64(ctx, "knowledgeBaseId")
|
||||
knowledgeBaseID, ok := params.GetInt64(ctx, "knowledge_base_id")
|
||||
if !ok || knowledgeBaseID <= 0 {
|
||||
httpx.WriteJSON(ctx, errorsx.InvalidParamI18n("error.e0283"))
|
||||
return
|
||||
@@ -99,12 +99,12 @@ func KnowledgeFAQAnyList(ctx *gin.Context) {
|
||||
}
|
||||
|
||||
cnd := params.NewPagedSqlCnd(ctx,
|
||||
params.QueryFilter{ParamName: "knowledgeBaseId"},
|
||||
params.QueryFilter{ParamName: "knowledge_base_id"},
|
||||
params.QueryFilter{ParamName: "question", Op: params.Like},
|
||||
params.QueryFilter{ParamName: "indexStatus"},
|
||||
params.QueryFilter{ParamName: "index_status"},
|
||||
).Desc("id")
|
||||
knowledgeBaseID, _ := params.GetInt64(ctx, "knowledgeBaseId")
|
||||
if directoryID, ok := params.GetInt64(ctx, "directoryId"); ok {
|
||||
knowledgeBaseID, _ := params.GetInt64(ctx, "knowledge_base_id")
|
||||
if directoryID, ok := params.GetInt64(ctx, "directory_id"); ok {
|
||||
cnd.Where("directory_id = ?", directoryID)
|
||||
}
|
||||
list, paging := services.KnowledgeFAQService.FindPageByCnd(cnd)
|
||||
|
||||
@@ -57,8 +57,8 @@ func KnowledgeRetrievePostDebugAnswer(ctx *gin.Context) {
|
||||
|
||||
func KnowledgeRetrievePostBuild(ctx *gin.Context) {
|
||||
req := struct {
|
||||
DocumentID int64 `json:"documentId"`
|
||||
FAQID int64 `json:"faqId"`
|
||||
DocumentID int64 `json:"document_id"`
|
||||
FAQID int64 `json:"faq_id"`
|
||||
}{}
|
||||
if err := params.ReadJSON(ctx, &req); err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
|
||||
@@ -20,17 +20,17 @@ func KnowledgeRetrieveLogAnyList(ctx *gin.Context) {
|
||||
}
|
||||
|
||||
cnd := params.NewPagedSqlCnd(ctx,
|
||||
params.QueryFilter{ParamName: "knowledgeBaseId"},
|
||||
params.QueryFilter{ParamName: "knowledge_base_id"},
|
||||
params.QueryFilter{ParamName: "question", Op: params.Like},
|
||||
params.QueryFilter{ParamName: "channel"},
|
||||
params.QueryFilter{ParamName: "scene"},
|
||||
params.QueryFilter{ParamName: "chunkProvider"},
|
||||
params.QueryFilter{ParamName: "chunk_provider"},
|
||||
).Desc("id")
|
||||
|
||||
if answerStatus, ok := params.GetInt64(ctx, "answerStatus"); ok && answerStatus > 0 {
|
||||
if answerStatus, ok := params.GetInt64(ctx, "answer_status"); ok && answerStatus > 0 {
|
||||
cnd.Where("answer_status = ?", answerStatus)
|
||||
}
|
||||
if rerankEnabled, ok := params.GetInt64(ctx, "rerankEnabled"); ok {
|
||||
if rerankEnabled, ok := params.GetInt64(ctx, "rerank_enabled"); ok {
|
||||
cnd.Where("rerank_enabled = ?", rerankEnabled > 0)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,108 +0,0 @@
|
||||
package dashboard
|
||||
|
||||
import (
|
||||
"code.tczkiot.com/wlw/ai-agent/internal/pkg/httpx"
|
||||
"context"
|
||||
|
||||
"code.tczkiot.com/wlw/ai-agent/internal/pkg/constants"
|
||||
"code.tczkiot.com/wlw/ai-agent/internal/pkg/dto/request"
|
||||
"code.tczkiot.com/wlw/ai-agent/internal/pkg/dto/response"
|
||||
"code.tczkiot.com/wlw/ai-agent/internal/pkg/i18nx"
|
||||
"code.tczkiot.com/wlw/ai-agent/internal/services"
|
||||
|
||||
"code.tczkiot.com/wlw/ai-agent/internal/pkg/httpx/params"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
func MCPAnyList_servers(ctx *gin.Context) {
|
||||
if _, err := services.AuthService.RequirePermission(ctx, constants.PermissionMCPView); err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
httpx.WriteJSON(ctx, response.BuildMCPServerInfoResponses(services.MCPDebugService.ListServers()))
|
||||
}
|
||||
|
||||
func MCPAnyCatalog(ctx *gin.Context) {
|
||||
if _, err := services.AuthService.RequirePermission(ctx, constants.PermissionMCPView); err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
items, err := services.ToolCatalogService.ListMCPToolsWithLocale(context.Background(), i18nx.Locale(ctx))
|
||||
if err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
ret := make([]response.MCPToolCatalogResponse, 0, len(items))
|
||||
for _, item := range items {
|
||||
ret = append(ret, response.MCPToolCatalogResponse{
|
||||
ToolCode: item.ToolCode,
|
||||
ServerCode: item.ServerCode,
|
||||
ToolName: item.ToolName,
|
||||
SourceType: item.SourceType,
|
||||
AutoInjected: item.AutoInjected,
|
||||
Title: item.Title,
|
||||
Description: item.Description,
|
||||
InputSchema: item.InputSchema,
|
||||
OutputSchema: item.OutputSchema,
|
||||
RiskLevel: item.RiskLevel,
|
||||
RequireConfirmation: item.RequireConfirmation,
|
||||
RiskEditable: item.RiskEditable,
|
||||
})
|
||||
}
|
||||
httpx.WriteJSON(ctx, ret)
|
||||
}
|
||||
|
||||
func MCPPostTest_connection(ctx *gin.Context) {
|
||||
if _, err := services.AuthService.RequirePermission(ctx, constants.PermissionMCPView); err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
req := request.MCPServerDebugRequest{}
|
||||
if err := params.ReadJSON(ctx, &req); err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
result, err := services.MCPDebugService.TestConnection(context.Background(), req.ServerCode)
|
||||
if err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
httpx.WriteJSON(ctx, response.BuildMCPConnectionResponse(result))
|
||||
}
|
||||
|
||||
func MCPPostList_tools(ctx *gin.Context) {
|
||||
if _, err := services.AuthService.RequirePermission(ctx, constants.PermissionMCPView); err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
req := request.MCPServerDebugRequest{}
|
||||
if err := params.ReadJSON(ctx, &req); err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
result, err := services.MCPDebugService.ListTools(context.Background(), req.ServerCode)
|
||||
if err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
httpx.WriteJSON(ctx, response.BuildMCPToolInfoResponses(result))
|
||||
}
|
||||
|
||||
func MCPPostCall_tool(ctx *gin.Context) {
|
||||
if _, err := services.AuthService.RequirePermission(ctx, constants.PermissionMCPCall); err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
req := request.MCPCallToolRequest{}
|
||||
if err := params.ReadJSON(ctx, &req); err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
result, err := services.MCPDebugService.CallTool(context.Background(), req.ServerCode, req.ToolName, req.Arguments)
|
||||
if err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
httpx.WriteJSON(ctx, response.BuildMCPCallToolResponse(result))
|
||||
}
|
||||
@@ -31,7 +31,7 @@ func NotificationAnyList(ctx *gin.Context) {
|
||||
Eq("status", enums.StatusOk).
|
||||
Desc("id")
|
||||
|
||||
switch strings.TrimSpace(ctx.Query("readStatus")) {
|
||||
switch strings.TrimSpace(ctx.Query("read_status")) {
|
||||
case "unread":
|
||||
cnd.Where("read_at IS NULL")
|
||||
case "read":
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
package dashboard
|
||||
|
||||
import (
|
||||
"code.tczkiot.com/wlw/ai-agent/internal/pkg/constants"
|
||||
"code.tczkiot.com/wlw/ai-agent/internal/pkg/httpx"
|
||||
"code.tczkiot.com/wlw/ai-agent/internal/services"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
func PlatformAIGetStatus(ctx *gin.Context) {
|
||||
if _, err := services.AuthService.RequirePermission(ctx, constants.PermissionAIAgentView); err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
source, err := services.PlatformAIService.ModelSource(ctx.Request.Context())
|
||||
if err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
if source != "platform" {
|
||||
httpx.WriteJSON(ctx, map[string]any{"model_source": source})
|
||||
return
|
||||
}
|
||||
status, err := services.PlatformAIService.Status(ctx.Request.Context())
|
||||
if err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
httpx.WriteJSON(ctx, map[string]any{
|
||||
"model_source": source,
|
||||
"status": status,
|
||||
})
|
||||
}
|
||||
@@ -23,7 +23,7 @@ func QuickReplyAnyList(ctx *gin.Context) {
|
||||
|
||||
cnd := params.NewPagedSqlCnd(ctx,
|
||||
params.QueryFilter{ParamName: "status"},
|
||||
params.QueryFilter{ParamName: "groupName"},
|
||||
params.QueryFilter{ParamName: "group_name"},
|
||||
params.QueryFilter{ParamName: "title", Op: params.Like},
|
||||
).Asc("sort_no").Desc("id")
|
||||
|
||||
|
||||
@@ -0,0 +1,134 @@
|
||||
package dashboard
|
||||
|
||||
import (
|
||||
"go/ast"
|
||||
"go/parser"
|
||||
"go/token"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestHandlerRequestParametersUseSnakeCase(t *testing.T) {
|
||||
for _, dir := range []string{".", "../api", "../../middleware", "../../pkg/httpx"} {
|
||||
fset := token.NewFileSet()
|
||||
packages, err := parser.ParseDir(fset, dir, nil, 0)
|
||||
if err != nil {
|
||||
t.Fatalf("parse handler directory %s: %v", dir, err)
|
||||
}
|
||||
|
||||
for _, pkg := range packages {
|
||||
for filename, file := range pkg.Files {
|
||||
ast.Inspect(file, func(node ast.Node) bool {
|
||||
switch value := node.(type) {
|
||||
case *ast.CallExpr:
|
||||
checkHandlerParameterCall(t, filename, value)
|
||||
case *ast.CompositeLit:
|
||||
checkQueryFilterParameter(t, filename, value)
|
||||
case *ast.Field:
|
||||
checkHandlerRequestTag(t, filename, value)
|
||||
}
|
||||
return true
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func checkHandlerParameterCall(t *testing.T, filename string, call *ast.CallExpr) {
|
||||
if identifier, ok := call.Fun.(*ast.Ident); ok {
|
||||
if identifier.Name == "requestExternalValue" && len(call.Args) > 2 {
|
||||
checkSnakeCaseStringLiteral(t, filename, call.Args[2])
|
||||
}
|
||||
return
|
||||
}
|
||||
selector, ok := call.Fun.(*ast.SelectorExpr)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
identifier, ok := selector.X.(*ast.Ident)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
argIndex := -1
|
||||
if identifier.Name == "params" {
|
||||
switch selector.Sel.Name {
|
||||
case "Get", "GetInt", "GetInt64", "GetBool", "GetTime", "GetInt64Arr", "FormValue":
|
||||
argIndex = 1
|
||||
}
|
||||
} else if identifier.Name == "ctx" {
|
||||
switch selector.Sel.Name {
|
||||
case "Query", "DefaultQuery", "GetQuery", "QueryArray", "PostForm", "PostFormArray":
|
||||
argIndex = 0
|
||||
}
|
||||
}
|
||||
if argIndex < 0 || len(call.Args) <= argIndex {
|
||||
return
|
||||
}
|
||||
checkSnakeCaseStringLiteral(t, filename, call.Args[argIndex])
|
||||
}
|
||||
|
||||
func checkQueryFilterParameter(t *testing.T, filename string, literal *ast.CompositeLit) {
|
||||
selector, ok := literal.Type.(*ast.SelectorExpr)
|
||||
if !ok || selector.Sel.Name != "QueryFilter" {
|
||||
return
|
||||
}
|
||||
identifier, ok := selector.X.(*ast.Ident)
|
||||
if !ok || identifier.Name != "params" {
|
||||
return
|
||||
}
|
||||
for _, element := range literal.Elts {
|
||||
pair, ok := element.(*ast.KeyValueExpr)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
key, ok := pair.Key.(*ast.Ident)
|
||||
if ok && key.Name == "ParamName" {
|
||||
checkSnakeCaseStringLiteral(t, filename, pair.Value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func checkHandlerRequestTag(t *testing.T, filename string, field *ast.Field) {
|
||||
if field.Tag == nil {
|
||||
return
|
||||
}
|
||||
rawTag, err := strconv.Unquote(field.Tag.Value)
|
||||
if err != nil {
|
||||
t.Errorf("%s: invalid struct tag %s: %v", filename, field.Tag.Value, err)
|
||||
return
|
||||
}
|
||||
for _, key := range []string{"json", "form", "query", "uri"} {
|
||||
name := strings.Split(reflect.StructTag(rawTag).Get(key), ",")[0]
|
||||
if name != "" && name != "-" && !isSnakeCaseHandlerParameter(name) {
|
||||
t.Errorf("%s: %s tag %q must use snake_case", filename, key, name)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func checkSnakeCaseStringLiteral(t *testing.T, filename string, expression ast.Expr) {
|
||||
literal, ok := expression.(*ast.BasicLit)
|
||||
if !ok || literal.Kind != token.STRING {
|
||||
return
|
||||
}
|
||||
name, err := strconv.Unquote(literal.Value)
|
||||
if err != nil {
|
||||
t.Errorf("%s: invalid request parameter %s: %v", filename, literal.Value, err)
|
||||
return
|
||||
}
|
||||
if !isSnakeCaseHandlerParameter(name) {
|
||||
t.Errorf("%s: request parameter %q must use snake_case", filename, name)
|
||||
}
|
||||
}
|
||||
|
||||
func isSnakeCaseHandlerParameter(name string) bool {
|
||||
for _, r := range name {
|
||||
if r >= 'a' && r <= 'z' || r >= '0' && r <= '9' || r == '_' {
|
||||
continue
|
||||
}
|
||||
return false
|
||||
}
|
||||
return name != ""
|
||||
}
|
||||
@@ -1,273 +0,0 @@
|
||||
package dashboard
|
||||
|
||||
import (
|
||||
"code.tczkiot.com/wlw/ai-agent/internal/pkg/httpx"
|
||||
"context"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"code.tczkiot.com/wlw/ai-agent/internal/builders"
|
||||
"code.tczkiot.com/wlw/ai-agent/internal/pkg/constants"
|
||||
"code.tczkiot.com/wlw/ai-agent/internal/pkg/dto/request"
|
||||
"code.tczkiot.com/wlw/ai-agent/internal/pkg/dto/response"
|
||||
"code.tczkiot.com/wlw/ai-agent/internal/pkg/enums"
|
||||
"code.tczkiot.com/wlw/ai-agent/internal/services"
|
||||
|
||||
"code.tczkiot.com/wlw/ai-agent/internal/pkg/httpx/params"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/mlogclub/simple/web"
|
||||
)
|
||||
|
||||
func SkillDefinitionAnyList(ctx *gin.Context) {
|
||||
if _, err := services.AuthService.RequirePermission(ctx, constants.PermissionSkillDefinitionView); err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
|
||||
cnd := params.NewPagedSqlCnd(ctx,
|
||||
params.QueryFilter{ParamName: "status"},
|
||||
params.QueryFilter{ParamName: "name", Op: params.Like},
|
||||
).Desc("id")
|
||||
if _, ok := params.Get(ctx, "status"); !ok {
|
||||
cnd.Where("status <> ?", enums.StatusDeleted)
|
||||
}
|
||||
list, paging := services.SkillDefinitionService.FindPageByCnd(cnd)
|
||||
results := make([]response.SkillDefinitionResponse, 0, len(list))
|
||||
for _, item := range list {
|
||||
results = append(results, builders.BuildSkillDefinitionResponse(&item))
|
||||
}
|
||||
httpx.WriteJSON(ctx, &web.PageResult{Results: results, Page: paging})
|
||||
}
|
||||
|
||||
func SkillDefinitionGetList_all(ctx *gin.Context) {
|
||||
if _, err := services.AuthService.RequirePermission(ctx, constants.PermissionSkillDefinitionView); err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
|
||||
cnd := params.NewSqlCnd(ctx,
|
||||
params.QueryFilter{ParamName: "status"},
|
||||
).Desc("id")
|
||||
if status, ok := params.Get(ctx, "status"); !ok || strings.TrimSpace(status) == "" {
|
||||
cnd.Where("status <> ?", enums.StatusDeleted)
|
||||
}
|
||||
list := services.SkillDefinitionService.Find(cnd)
|
||||
results := make([]response.SkillDefinitionResponse, 0, len(list))
|
||||
for _, item := range list {
|
||||
results = append(results, builders.BuildSkillDefinitionResponse(&item))
|
||||
}
|
||||
httpx.WriteJSON(ctx, results)
|
||||
}
|
||||
|
||||
func SkillDefinitionGetBy(ctx *gin.Context) {
|
||||
id, ok := httpx.GetPathInt64(ctx, "id")
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
if _, err := services.AuthService.RequirePermission(ctx, constants.PermissionSkillDefinitionView); err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
|
||||
item := services.SkillDefinitionService.Get(id)
|
||||
if item == nil {
|
||||
httpx.WriteJSON(ctx, httpx.JsonErrorMsg(ctx, "error.e0053"))
|
||||
return
|
||||
}
|
||||
httpx.WriteJSON(ctx, builders.BuildSkillDefinitionResponse(item))
|
||||
}
|
||||
|
||||
func SkillDefinitionPostCreate(ctx *gin.Context) {
|
||||
operator, err := services.AuthService.RequirePermission(ctx, constants.PermissionSkillDefinitionCreate)
|
||||
if err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
|
||||
req := request.CreateSkillDefinitionRequest{}
|
||||
if err := params.ReadJSON(ctx, &req); err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
item, err := services.SkillDefinitionService.CreateSkillDefinition(req, operator)
|
||||
if err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
httpx.WriteJSON(ctx, builders.BuildSkillDefinitionResponse(item))
|
||||
}
|
||||
|
||||
func SkillDefinitionPostUpdate(ctx *gin.Context) {
|
||||
operator, err := services.AuthService.RequirePermission(ctx, constants.PermissionSkillDefinitionUpdate)
|
||||
if err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
|
||||
req := request.UpdateSkillDefinitionRequest{}
|
||||
if err := params.ReadJSON(ctx, &req); err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
if err := services.SkillDefinitionService.UpdateSkillDefinition(req, operator); err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
httpx.WriteJSON(ctx, nil)
|
||||
}
|
||||
|
||||
func SkillDefinitionPostUpdate_status(ctx *gin.Context) {
|
||||
operator, err := services.AuthService.RequirePermission(ctx, constants.PermissionSkillDefinitionUpdate)
|
||||
if err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
|
||||
req := request.UpdateSkillDefinitionStatusRequest{}
|
||||
if err := params.ReadJSON(ctx, &req); err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
if req.ID <= 0 {
|
||||
httpx.WriteJSON(ctx, httpx.JsonErrorMsg(ctx, "error.e0052"))
|
||||
return
|
||||
}
|
||||
if !enums.IsValidStatus(req.Status) {
|
||||
httpx.WriteJSON(ctx, httpx.JsonErrorMsg(ctx, "error.e0254"))
|
||||
return
|
||||
}
|
||||
item := services.SkillDefinitionService.Get(req.ID)
|
||||
if item == nil {
|
||||
httpx.WriteJSON(ctx, httpx.JsonErrorMsg(ctx, "error.e0053"))
|
||||
return
|
||||
}
|
||||
if item.Status == enums.StatusDeleted {
|
||||
httpx.WriteJSON(ctx, httpx.JsonErrorMsg(ctx, "error.e0184"))
|
||||
return
|
||||
}
|
||||
if req.Status == int(enums.StatusDeleted) {
|
||||
httpx.WriteJSON(ctx, httpx.JsonErrorMsg(ctx, "error.e0319"))
|
||||
return
|
||||
}
|
||||
|
||||
if err := services.SkillDefinitionService.Updates(req.ID, map[string]any{
|
||||
"status": req.Status,
|
||||
"update_user_id": operator.UserID,
|
||||
"update_user_name": operator.Username,
|
||||
"updated_at": time.Now(),
|
||||
}); err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
httpx.WriteJSON(ctx, nil)
|
||||
}
|
||||
|
||||
func SkillDefinitionPostDelete(ctx *gin.Context) {
|
||||
operator, err := services.AuthService.RequirePermission(ctx, constants.PermissionSkillDefinitionDelete)
|
||||
if err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
|
||||
req := request.DeleteSkillDefinitionRequest{}
|
||||
if err := params.ReadJSON(ctx, &req); err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
if req.ID <= 0 {
|
||||
httpx.WriteJSON(ctx, httpx.JsonErrorMsg(ctx, "error.e0052"))
|
||||
return
|
||||
}
|
||||
if services.SkillDefinitionService.Get(req.ID) == nil {
|
||||
httpx.WriteJSON(ctx, httpx.JsonErrorMsg(ctx, "error.e0053"))
|
||||
return
|
||||
}
|
||||
if err := services.SkillDefinitionService.Updates(req.ID, map[string]any{
|
||||
"status": enums.StatusDeleted,
|
||||
"update_user_id": operator.UserID,
|
||||
"update_user_name": operator.Username,
|
||||
"updated_at": time.Now(),
|
||||
}); err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
httpx.WriteJSON(ctx, nil)
|
||||
}
|
||||
|
||||
func SkillDefinitionPostRestore(ctx *gin.Context) {
|
||||
operator, err := services.AuthService.RequirePermission(ctx, constants.PermissionSkillDefinitionDelete)
|
||||
if err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
|
||||
req := request.RestoreSkillDefinitionRequest{}
|
||||
if err := params.ReadJSON(ctx, &req); err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
if req.ID <= 0 {
|
||||
httpx.WriteJSON(ctx, httpx.JsonErrorMsg(ctx, "error.e0052"))
|
||||
return
|
||||
}
|
||||
|
||||
item := services.SkillDefinitionService.Get(req.ID)
|
||||
if item == nil {
|
||||
httpx.WriteJSON(ctx, httpx.JsonErrorMsg(ctx, "error.e0053"))
|
||||
return
|
||||
}
|
||||
if item.Status != enums.StatusDeleted {
|
||||
httpx.WriteJSON(ctx, httpx.JsonErrorMsg(ctx, "error.e0088"))
|
||||
return
|
||||
}
|
||||
|
||||
if err := services.SkillDefinitionService.Updates(req.ID, map[string]any{
|
||||
"status": enums.StatusDisabled,
|
||||
"update_user_id": operator.UserID,
|
||||
"update_user_name": operator.Username,
|
||||
"updated_at": time.Now(),
|
||||
}); err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
httpx.WriteJSON(ctx, nil)
|
||||
}
|
||||
|
||||
func SkillDefinitionPostDebug_run(ctx *gin.Context) {
|
||||
if _, err := services.AuthService.RequirePermission(ctx, constants.PermissionSkillDefinitionView); err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
|
||||
req := request.SkillDebugRunRequest{}
|
||||
if err := params.ReadJSON(ctx, &req); err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
resp, err := services.SkillRuntimeService.DebugRun(context.Background(), req)
|
||||
if err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
httpx.WriteJSON(ctx, resp)
|
||||
}
|
||||
|
||||
func SkillDefinitionPostDebug_resume(ctx *gin.Context) {
|
||||
if _, err := services.AuthService.RequirePermission(ctx, constants.PermissionSkillDefinitionView); err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
|
||||
req := request.SkillDebugResumeRequest{}
|
||||
if err := params.ReadJSON(ctx, &req); err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
resp, err := services.SkillRuntimeService.DebugResume(context.Background(), req)
|
||||
if err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
httpx.WriteJSON(ctx, resp)
|
||||
}
|
||||
@@ -1,147 +0,0 @@
|
||||
package dashboard
|
||||
|
||||
import (
|
||||
"code.tczkiot.com/wlw/ai-agent/internal/builders"
|
||||
"code.tczkiot.com/wlw/ai-agent/internal/pkg/constants"
|
||||
"code.tczkiot.com/wlw/ai-agent/internal/pkg/dto/request"
|
||||
"code.tczkiot.com/wlw/ai-agent/internal/pkg/httpx"
|
||||
"code.tczkiot.com/wlw/ai-agent/internal/services"
|
||||
|
||||
"code.tczkiot.com/wlw/ai-agent/internal/pkg/httpx/params"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/mlogclub/simple/web"
|
||||
)
|
||||
|
||||
func TagAnyList(ctx *gin.Context) {
|
||||
if _, err := services.AuthService.RequirePermission(ctx, constants.PermissionTagView); err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
list, paging := services.TagService.FindPageByCnd(params.NewPagedSqlCnd(ctx,
|
||||
params.QueryFilter{ParamName: "status"},
|
||||
params.QueryFilter{ParamName: "parentId"},
|
||||
params.QueryFilter{ParamName: "name", Op: params.Like},
|
||||
).Asc("sort_no").Desc("id"))
|
||||
results := builders.BuildTagResponses(list)
|
||||
httpx.WriteJSON(ctx, &web.PageResult{Results: results, Page: paging})
|
||||
}
|
||||
|
||||
func TagGetList_all(ctx *gin.Context) {
|
||||
if _, err := services.AuthService.RequirePermission(ctx, constants.PermissionTagView); err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
list := services.TagService.FindAll()
|
||||
results := builders.BuildTagTreeResponses(list)
|
||||
httpx.WriteJSON(ctx, results)
|
||||
}
|
||||
|
||||
func TagGetBy(ctx *gin.Context) {
|
||||
id, ok := httpx.GetPathInt64(ctx, "id")
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
if _, err := services.AuthService.RequirePermission(ctx, constants.PermissionTagView); err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
|
||||
item := services.TagService.Get(id)
|
||||
if item == nil {
|
||||
httpx.WriteJSON(ctx, httpx.JsonErrorMsg(ctx, "error.e0238"))
|
||||
return
|
||||
}
|
||||
result := builders.BuildTagResponse(item)
|
||||
httpx.WriteJSON(ctx, &result)
|
||||
}
|
||||
|
||||
func TagPostCreate(ctx *gin.Context) {
|
||||
user, err := services.AuthService.RequirePermission(ctx, constants.PermissionTagCreate)
|
||||
if err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
|
||||
req := request.CreateTagRequest{}
|
||||
if err := params.ReadJSON(ctx, &req); err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
item, err := services.TagService.CreateTag(req, user)
|
||||
if err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
result := builders.BuildTagResponse(item)
|
||||
httpx.WriteJSON(ctx, &result)
|
||||
}
|
||||
|
||||
func TagPostUpdate(ctx *gin.Context) {
|
||||
user, err := services.AuthService.RequirePermission(ctx, constants.PermissionTagUpdate)
|
||||
if err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
|
||||
req := request.UpdateTagRequest{}
|
||||
if err := params.ReadJSON(ctx, &req); err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
if err := services.TagService.UpdateTag(req, user); err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
httpx.WriteJSON(ctx, nil)
|
||||
}
|
||||
|
||||
func TagPostDelete(ctx *gin.Context) {
|
||||
if _, err := services.AuthService.RequirePermission(ctx, constants.PermissionTagDelete); err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
|
||||
req := request.DeleteTagRequest{}
|
||||
if err := params.ReadJSON(ctx, &req); err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
if err := services.TagService.DeleteTag(req.ID); err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
httpx.WriteJSON(ctx, nil)
|
||||
}
|
||||
|
||||
func TagPostUpdate_sort(ctx *gin.Context) {
|
||||
var ids []int64
|
||||
if err := params.ReadJSON(ctx, &ids); err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
if err := services.TagService.UpdateSort(ids); err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
httpx.WriteJSON(ctx, nil)
|
||||
}
|
||||
|
||||
func TagPostUpdate_status(ctx *gin.Context) {
|
||||
user, err := services.AuthService.RequirePermission(ctx, constants.PermissionTagUpdate)
|
||||
if err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
|
||||
req := request.UpdateTagStatusRequest{}
|
||||
if err := params.ReadJSON(ctx, &req); err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
if err := services.TagService.UpdateStatus(req.ID, req.Status, user); err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
httpx.WriteJSON(ctx, nil)
|
||||
}
|
||||
@@ -1,287 +0,0 @@
|
||||
package dashboard
|
||||
|
||||
import (
|
||||
"code.tczkiot.com/wlw/ai-agent/internal/pkg/httpx"
|
||||
"strings"
|
||||
|
||||
"code.tczkiot.com/wlw/ai-agent/internal/builders"
|
||||
"code.tczkiot.com/wlw/ai-agent/internal/pkg/constants"
|
||||
"code.tczkiot.com/wlw/ai-agent/internal/pkg/dto/request"
|
||||
"code.tczkiot.com/wlw/ai-agent/internal/services"
|
||||
|
||||
"code.tczkiot.com/wlw/ai-agent/internal/pkg/httpx/params"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/mlogclub/simple/sqls"
|
||||
"github.com/mlogclub/simple/web"
|
||||
)
|
||||
|
||||
func TicketAnyList(ctx *gin.Context) {
|
||||
operator, err := services.AuthService.RequirePermission(ctx, constants.PermissionTicketView)
|
||||
if err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
cnd := params.NewPagedSqlCnd(ctx,
|
||||
params.QueryFilter{ParamName: "status"},
|
||||
params.QueryFilter{ParamName: "currentAssigneeId"},
|
||||
params.QueryFilter{ParamName: "customerId"},
|
||||
params.QueryFilter{ParamName: "conversationId"},
|
||||
params.QueryFilter{ParamName: "source"},
|
||||
params.QueryFilter{ParamName: "channel"},
|
||||
).Desc("updated_at").Desc("id")
|
||||
if keyword, _ := params.Get(ctx, "keyword"); strings.TrimSpace(keyword) != "" {
|
||||
keyword = "%" + strings.TrimSpace(keyword) + "%"
|
||||
cnd.Where("ticket_no LIKE ? OR title LIKE ? OR description LIKE ?", keyword, keyword, keyword)
|
||||
}
|
||||
if tagID, _ := params.GetInt64(ctx, "tagId"); tagID > 0 {
|
||||
cnd.Where("id IN (SELECT ticket_id FROM t_ticket_tag WHERE tag_id = ?)", tagID)
|
||||
}
|
||||
if mine, _ := params.Get(ctx, "mine"); mine == "1" || strings.EqualFold(mine, "true") {
|
||||
cnd.Eq("current_assignee_id", operator.UserID)
|
||||
}
|
||||
if unassigned, _ := params.Get(ctx, "unassigned"); unassigned == "1" || strings.EqualFold(unassigned, "true") {
|
||||
cnd.Eq("current_assignee_id", 0)
|
||||
}
|
||||
if staleHoursValue, _ := params.Get(ctx, "staleHours"); strings.TrimSpace(staleHoursValue) != "" {
|
||||
staleHours, _ := params.GetInt(ctx, "staleHours")
|
||||
services.TicketService.ApplyStaleFilter(cnd, staleHours)
|
||||
}
|
||||
aggregate, err := services.TicketService.FindPageAggregateByCnd(cnd, operator.UserID)
|
||||
if err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
httpx.WriteJSON(ctx, &web.PageResult{
|
||||
Results: builders.BuildTicketListWithContext(aggregate.List, &builders.TicketBuildContext{
|
||||
TagsByTicketID: aggregate.TagsByTicketID,
|
||||
Users: aggregate.Users,
|
||||
Customers: aggregate.Customers,
|
||||
}),
|
||||
Page: aggregate.Paging,
|
||||
})
|
||||
}
|
||||
|
||||
func TicketAnySummary(ctx *gin.Context) {
|
||||
operator, err := services.AuthService.RequirePermission(ctx, constants.PermissionTicketView)
|
||||
if err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
staleHours, _ := params.GetInt(ctx, "staleHours")
|
||||
httpx.WriteJSON(ctx, builders.BuildTicketSummary(services.TicketService.GetSummary(operator, staleHours)))
|
||||
}
|
||||
|
||||
func TicketAnyView_list(ctx *gin.Context) {
|
||||
operator, err := services.AuthService.RequirePermission(ctx, constants.PermissionTicketView)
|
||||
if err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
httpx.WriteJSON(ctx, builders.BuildTicketViewList(services.TicketViewService.ListByUser(operator.UserID)))
|
||||
}
|
||||
|
||||
func TicketPostSave_view(ctx *gin.Context) {
|
||||
operator, err := services.AuthService.RequirePermission(ctx, constants.PermissionTicketView)
|
||||
if err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
req := request.SaveTicketViewRequest{}
|
||||
if err := params.ReadJSON(ctx, &req); err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
item, err := services.TicketViewService.Save(req, operator)
|
||||
if err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
httpx.WriteJSON(ctx, builders.BuildTicketView(item))
|
||||
}
|
||||
|
||||
func TicketPostDelete_view(ctx *gin.Context) {
|
||||
operator, err := services.AuthService.RequirePermission(ctx, constants.PermissionTicketView)
|
||||
if err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
req := request.DeleteTicketViewRequest{}
|
||||
if err := params.ReadJSON(ctx, &req); err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
if err := services.TicketViewService.Delete(req.ID, operator); err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
httpx.WriteJSON(ctx, nil)
|
||||
}
|
||||
|
||||
func TicketGetBy(ctx *gin.Context) {
|
||||
id, ok := httpx.GetPathInt64(ctx, "id")
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
if _, err := services.AuthService.RequirePermission(ctx, constants.PermissionTicketView); err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
detail, err := services.TicketService.GetDetail(id)
|
||||
if err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
httpx.WriteJSON(ctx, builders.BuildTicketDetail(detail))
|
||||
}
|
||||
|
||||
func TicketPostCreate(ctx *gin.Context) {
|
||||
operator, err := services.AuthService.RequirePermission(ctx, constants.PermissionTicketCreate)
|
||||
if err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
req := request.CreateTicketRequest{}
|
||||
if err := params.ReadJSON(ctx, &req); err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
item, err := services.TicketService.CreateTicket(req, operator)
|
||||
if err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
httpx.WriteJSON(ctx, builders.BuildTicket(item))
|
||||
}
|
||||
|
||||
func TicketPostCreate_from_conversation(ctx *gin.Context) {
|
||||
operator, err := services.AuthService.RequirePermission(ctx, constants.PermissionTicketCreate)
|
||||
if err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
req := request.CreateTicketFromConversationRequest{}
|
||||
if err := params.ReadJSON(ctx, &req); err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
item, err := services.TicketService.CreateFromConversation(req, operator)
|
||||
if err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
httpx.WriteJSON(ctx, builders.BuildTicket(item))
|
||||
}
|
||||
|
||||
func TicketPostUpdate(ctx *gin.Context) {
|
||||
operator, err := services.AuthService.RequirePermission(ctx, constants.PermissionTicketUpdate)
|
||||
if err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
req := request.UpdateTicketRequest{}
|
||||
if err := params.ReadJSON(ctx, &req); err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
if err := services.TicketService.UpdateTicket(req, operator); err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
httpx.WriteJSON(ctx, nil)
|
||||
}
|
||||
|
||||
func TicketPostLink_customer(ctx *gin.Context) {
|
||||
operator, err := services.AuthService.RequirePermission(ctx, constants.PermissionTicketUpdate)
|
||||
if err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
req := request.LinkTicketCustomerRequest{}
|
||||
if err := params.ReadJSON(ctx, &req); err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
if err := services.TicketService.LinkCustomer(req.TicketID, req.CustomerID, operator); err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
httpx.WriteJSON(ctx, nil)
|
||||
}
|
||||
|
||||
func TicketPostAssign(ctx *gin.Context) {
|
||||
operator, err := services.AuthService.RequirePermission(ctx, constants.PermissionTicketAssign)
|
||||
if err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
req := request.AssignTicketRequest{}
|
||||
if err := params.ReadJSON(ctx, &req); err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
if err := services.TicketService.AssignTicket(req, operator); err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
httpx.WriteJSON(ctx, nil)
|
||||
}
|
||||
|
||||
func TicketPostChange_status(ctx *gin.Context) {
|
||||
operator, err := services.AuthService.RequirePermission(ctx, constants.PermissionTicketChangeStatus)
|
||||
if err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
req := request.ChangeTicketStatusRequest{}
|
||||
if err := params.ReadJSON(ctx, &req); err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
if err := services.TicketService.ChangeStatus(req, operator); err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
httpx.WriteJSON(ctx, nil)
|
||||
}
|
||||
|
||||
func TicketAnyProgressList(ctx *gin.Context) {
|
||||
if _, err := services.AuthService.RequirePermission(ctx, constants.PermissionTicketView); err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
ticketID, _ := params.GetInt64(ctx, "ticketId")
|
||||
if ticketID <= 0 {
|
||||
httpx.WriteJSON(ctx, httpx.JsonErrorMsg(ctx, "error.e0178"))
|
||||
return
|
||||
}
|
||||
if services.TicketService.Get(ticketID) == nil {
|
||||
httpx.WriteJSON(ctx, httpx.JsonErrorMsg(ctx, "error.e0178"))
|
||||
return
|
||||
}
|
||||
progresses := services.TicketProgressService.Find(sqls.NewCnd().Eq("ticket_id", ticketID).Asc("id"))
|
||||
httpx.WriteJSON(ctx, builders.BuildTicketProgressList(progresses))
|
||||
}
|
||||
|
||||
func TicketPostProgressCreate(ctx *gin.Context) {
|
||||
ticketCreateProgress(ctx)
|
||||
}
|
||||
|
||||
func ticketCreateProgress(ctx *gin.Context) {
|
||||
operator, err := services.AuthService.RequirePermission(ctx, constants.PermissionTicketProgress)
|
||||
if err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
req := request.CreateTicketProgressRequest{}
|
||||
if err := params.ReadJSON(ctx, &req); err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
item, err := services.TicketService.AddProgress(req, operator)
|
||||
if err != nil {
|
||||
httpx.WriteJSON(ctx, err)
|
||||
return
|
||||
}
|
||||
httpx.WriteJSON(ctx, builders.BuildTicketProgress(item))
|
||||
}
|
||||
Reference in New Issue
Block a user