Commit 3f3b8f29 authored by yuguo's avatar yuguo

fix

parent 04584395
......@@ -8,6 +8,7 @@ import (
"strings"
"internet-hospital/internal/model"
"internet-hospital/internal/service/notification"
"internet-hospital/pkg/agent"
"internet-hospital/pkg/agent/tools"
"internet-hospital/pkg/database"
......@@ -110,7 +111,10 @@ func WireCallbacks() {
return output.Response, nil
})
log.Println("[InitTools] AgentCallFn & WorkflowTriggerFn & SkillExecutor 注入完成")
// 注入通知回调
tools.NotifyFn = notification.Notify
log.Println("[InitTools] AgentCallFn & WorkflowTriggerFn & NotifyFn & SkillExecutor 注入完成")
}
// syncToolsToDB 将注册的工具元数据写入 AgentTool 表(不存在则创建,存在则不覆盖)
......
package admin
import (
"fmt"
"github.com/gin-gonic/gin"
"internet-hospital/internal/service/doctor"
......@@ -144,6 +146,7 @@ func (h *Handler) RegisterRoutes(r *gin.RouterGroup) {
adm.POST("/seed/rbac", h.SeedRBACHandler)
adm.POST("/seed/departments", h.SeedDepartmentsHandler)
adm.POST("/seed/medicines", h.SeedMedicinesHandler)
adm.POST("/seed/workflows", h.SeedWorkflowsHandler)
// 数据库维护
adm.GET("/db/extra-tables", h.ScanExtraTablesHandler)
......@@ -491,3 +494,14 @@ func (h *Handler) SeedMedicinesHandler(c *gin.Context) {
response.Success(c, gin.H{"message": "药品种子数据已导入"})
}
// SeedWorkflowsHandler 手动导入工作流种子数据
func (h *Handler) SeedWorkflowsHandler(c *gin.Context) {
created, skipped, errs := SeedWorkflows()
response.Success(c, gin.H{
"message": fmt.Sprintf("工作流种子数据导入完成:创建 %d 个,跳过 %d 个,失败 %d 个", created, skipped, len(errs)),
"created": created,
"skipped": skipped,
"errors": errs,
})
}
package admin
import (
"log"
"os"
"internet-hospital/internal/model"
"internet-hospital/pkg/database"
)
// SeedWorkflows 初始化工作流种子数据(幂等,表空时从 scripts/seed_workflows.sql 导入)
func SeedWorkflows() (created int, skipped int, errors []string) {
db := database.GetDB()
if db == nil {
errors = append(errors, "数据库未初始化")
return
}
var count int64
db.Model(&model.WorkflowDefinition{}).Count(&count)
if count > 0 {
skipped = int(count)
return
}
sqlBytes, err := os.ReadFile("scripts/seed_workflows.sql")
if err != nil {
errMsg := "无法读取 scripts/seed_workflows.sql: " + err.Error()
log.Printf("[SeedWorkflows] %s", errMsg)
errors = append(errors, errMsg)
return
}
if err := db.Exec(string(sqlBytes)).Error; err != nil {
errMsg := "执行 SQL 失败: " + err.Error()
log.Printf("[SeedWorkflows] %s", errMsg)
errors = append(errors, errMsg)
return
}
db.Model(&model.WorkflowDefinition{}).Count(&count)
created = int(count)
log.Printf("[SeedWorkflows] 工作流种子数据已导入(%d 个)", created)
return
}
......@@ -52,6 +52,7 @@ type CreateDoctorReq struct {
Hospital string `json:"hospital" binding:"required"`
Introduction string `json:"introduction"`
Specialties []string `json:"specialties"`
Price int `json:"price"`
}
// CreateAdminReq 创建管理员请求
......@@ -438,7 +439,7 @@ func (s *Service) CreateDoctor(ctx context.Context, req *CreateDoctorReq) error
Introduction: req.Introduction,
Specialties: req.Specialties,
Rating: 5.0,
Price: 5000, // 默认50元
Price: req.Price,
Status: "approved",
}
if err := s.db.Create(doctor).Error; err != nil {
......
......@@ -5,13 +5,13 @@ import (
"fmt"
"time"
"internet-hospital/internal/model"
"internet-hospital/pkg/agent"
"internet-hospital/pkg/database"
)
// NotifyFn 通知回调函数,由 WireCallbacks 注入 notification.Notify
var NotifyFn func(userID, title, content, nType, relatedID string)
// SendNotificationTool 向用户发送系统通知(站内信 + WebSocket 推送)
// 此工具之前在分类 map 中声明但从未注册,此次完整落地
type SendNotificationTool struct{}
func (t *SendNotificationTool) Name() string { return "send_notification" }
......@@ -46,21 +46,15 @@ func (t *SendNotificationTool) Parameters() []agent.ToolParameter {
Enum: []string{"reminder", "alert", "info", "followup", "system"},
},
{
Name: "priority",
Name: "related_id",
Type: "string",
Description: "优先级:normal/high/urgent",
Description: "关联业务ID(如问诊ID、处方ID等)",
Required: false,
Enum: []string{"normal", "high", "urgent"},
},
}
}
func (t *SendNotificationTool) Execute(_ context.Context, params map[string]interface{}) (interface{}, error) {
db := database.GetDB()
if db == nil {
return nil, fmt.Errorf("数据库未初始化")
}
userID, ok := params["user_id"].(string)
if !ok || userID == "" {
return nil, fmt.Errorf("user_id 必填")
......@@ -74,28 +68,19 @@ func (t *SendNotificationTool) Execute(_ context.Context, params map[string]inte
if nType == "" {
nType = "info"
}
priority, _ := params["priority"].(string)
if priority == "" {
priority = "normal"
}
relatedID, _ := params["related_id"].(string)
// 写入系统日志表作为站内信(复用 SystemLog)
log := model.SystemLog{
Action: "notification",
Resource: fmt.Sprintf("%s/%s", nType, priority),
Detail: fmt.Sprintf("[%s] %s: %s", nType, title, content),
UserID: userID,
}
if err := db.Create(&log).Error; err != nil {
return nil, fmt.Errorf("写入通知失败: %w", err)
if NotifyFn == nil {
return nil, fmt.Errorf("通知服务未初始化")
}
NotifyFn(userID, title, content, nType, relatedID)
return map[string]interface{}{
"notification_id": log.ID,
"user_id": userID,
"title": title,
"type": nType,
"priority": priority,
"related_id": relatedID,
"sent_at": time.Now().Format(time.RFC3339),
}, nil
}
......@@ -196,6 +196,20 @@ func (e *Engine) executeNode(ctx context.Context, wf *Workflow, node *Node, exec
execCtx.NodeOutputs[node.ID] = output
// 执行下一个节点
// 条件节点支持真正的分支:NextNodes[0] = true 分支,NextNodes[1] = false 分支
if node.Type == NodeTypeCondition && len(node.NextNodes) >= 2 {
condResult, _ := output.(map[string]interface{})
result, _ := condResult["result"].(bool)
targetIdx := 0
if !result {
targetIdx = 1
}
if next, ok := wf.Nodes[node.NextNodes[targetIdx]]; ok {
if _, err := e.executeNode(ctx, wf, next, execCtx); err != nil {
return nil, err
}
}
} else {
for _, nextID := range node.NextNodes {
if next, ok := wf.Nodes[nextID]; ok {
if _, err := e.executeNode(ctx, wf, next, execCtx); err != nil {
......@@ -203,6 +217,7 @@ func (e *Engine) executeNode(ctx context.Context, wf *Workflow, node *Node, exec
}
}
}
}
return output, nil
}
......
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment