WiiCITMS/servers/oaTools.go
2025-11-07 14:14:34 +08:00

418 lines
14 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package servers
import (
"WiiCITMS/process/common"
"WiiCITMS/process/oa"
"context"
"encoding/json"
"fmt"
"github.com/mark3labs/mcp-go/mcp"
"github.com/mark3labs/mcp-go/server"
)
// OA 工作流相关工具
var OATools = []server.ServerTool{
// 创建工作流
{
Tool: mcp.NewTool(
"createWorkflow",
mcp.WithDescription("创建一个工作流定义"),
mcp.WithString("workflowName", mcp.Required(), mcp.Description("工作流名称")),
mcp.WithNumber("workflowType", mcp.Required(), mcp.Description("工作流类型: 1-请假, 2-报销, 3-采购, ...")),
mcp.WithString("description", mcp.Description("工作流描述")),
mcp.WithString("creatorGuid", mcp.Description("创建人GUID")),
),
Handler: func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
workflowName := request.GetString("workflowName", "")
if workflowName == "" {
return nil, fmt.Errorf("工作流名称不能为空")
}
workflowType := request.GetInt("workflowType", 0)
if workflowType <= 0 {
return nil, fmt.Errorf("工作流类型必须大于0")
}
description := request.GetString("description", "")
creatorGuid := request.GetString("creatorGuid", "")
rep, proc := oa.CreateWorkflow(oa.CreateWorkflowRequest{
WorkflowName: workflowName,
WorkflowType: workflowType,
Description: description,
CreatorGuid: creatorGuid,
})
if proc.IsError() {
return mcp.NewToolResultText(""), proc.Error
}
repStr, err := json.Marshal(rep)
if err != nil {
return mcp.NewToolResultText(""), err
}
return mcp.NewToolResultText(string(repStr)), nil
},
},
// 查询工作流列表
{
Tool: mcp.NewTool(
"queryWorkflows",
mcp.WithDescription("查询工作流定义列表"),
mcp.WithString("workflowName", mcp.Description("工作流名称,模糊查询")),
mcp.WithNumber("workflowType", mcp.Description("工作流类型,-1表示所有类型")),
mcp.WithBoolean("isActive", mcp.Description("是否只查询启用的工作流")),
mcp.WithNumber("limit", mcp.Description("分页参数,每页数量")),
mcp.WithNumber("offset", mcp.Description("分页参数,偏移量")),
),
Handler: func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
workflowName := request.GetString("workflowName", "")
workflowType := request.GetInt("workflowType", -1)
isActive := request.GetBool("isActive", false)
limit := request.GetInt("limit", 20)
offset := request.GetInt("offset", 0)
rep, proc := oa.QueryWorkflows(oa.QueryWorkflowsRequest{
WorkflowName: workflowName,
WorkflowType: workflowType,
IsActive: isActive,
Limit: limit,
Offset: offset,
})
if proc.IsError() {
return mcp.NewToolResultText(""), proc.Error
}
repStr, err := json.Marshal(rep)
if err != nil {
return mcp.NewToolResultText(""), err
}
return mcp.NewToolResultText(string(repStr)), nil
},
},
// 创建工作流节点
{
Tool: mcp.NewTool(
"createWorkflowNode",
mcp.WithDescription("创建工作流节点"),
mcp.WithString("workflowGuid", mcp.Required(), mcp.Description("所属工作流ID")),
mcp.WithString("nodeName", mcp.Required(), mcp.Description("节点名称")),
mcp.WithNumber("nodeType", mcp.Required(), mcp.Description("节点类型1-开始, 2-审批, 3-抄送, 4-条件, 5-结束")),
mcp.WithNumber("nodeOrder", mcp.Required(), mcp.Description("节点顺序")),
mcp.WithNumber("approverType", mcp.Description("审批人类型1-指定人, 2-角色, 3-部门负责人")),
mcp.WithString("approverValue", mcp.Description("审批人值用户ID、角色ID或JSON")),
mcp.WithString("conditionExp", mcp.Description("条件表达式(如果是条件节点)")),
mcp.WithString("description", mcp.Description("节点描述")),
),
Handler: func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
workflowGuid := request.GetString("workflowGuid", "")
if workflowGuid == "" {
return nil, fmt.Errorf("工作流ID不能为空")
}
nodeName := request.GetString("nodeName", "")
if nodeName == "" {
return nil, fmt.Errorf("节点名称不能为空")
}
nodeType := request.GetInt("nodeType", 0)
if nodeType <= 0 || nodeType > 5 {
return nil, fmt.Errorf("无效的节点类型")
}
nodeOrder := request.GetInt("nodeOrder", 0)
approverType := request.GetInt("approverType", 0)
approverValue := request.GetString("approverValue", "")
conditionExp := request.GetString("conditionExp", "")
description := request.GetString("description", "")
rep, proc := oa.CreateWorkflowNode(oa.CreateNodeRequest{
WorkflowGuid: workflowGuid,
NodeName: nodeName,
NodeType: nodeType,
NodeOrder: nodeOrder,
ApproverType: approverType,
ApproverValue: approverValue,
ConditionExp: conditionExp,
Description: description,
})
if proc.IsError() {
return mcp.NewToolResultText(""), proc.Error
}
repStr, err := json.Marshal(rep)
if err != nil {
return mcp.NewToolResultText(""), err
}
return mcp.NewToolResultText(string(repStr)), nil
},
},
// 查询工作流节点
{
Tool: mcp.NewTool(
"queryWorkflowNodes",
mcp.WithDescription("查询工作流节点"),
mcp.WithString("workflowGuid", mcp.Required(), mcp.Description("工作流ID")),
mcp.WithNumber("nodeType", mcp.Description("节点类型,-1表示所有类型")),
),
Handler: func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
workflowGuid := request.GetString("workflowGuid", "")
if workflowGuid == "" {
return nil, fmt.Errorf("工作流ID不能为空")
}
nodeType := request.GetInt("nodeType", -1)
rep, proc := oa.QueryWorkflowNodes(oa.QueryNodesRequest{
WorkflowGuid: workflowGuid,
NodeType: nodeType,
})
if proc.IsError() {
return mcp.NewToolResultText(""), proc.Error
}
repStr, err := json.Marshal(rep)
if err != nil {
return mcp.NewToolResultText(""), err
}
return mcp.NewToolResultText(string(repStr)), nil
},
},
// 启动工作流实例
{
Tool: mcp.NewTool(
"startWorkflowInstance",
mcp.WithDescription("启动一个工作流实例"),
mcp.WithString("workflowGuid", mcp.Required(), mcp.Description("工作流ID")),
mcp.WithString("title", mcp.Required(), mcp.Description("实例标题")),
mcp.WithNumber("businessType", mcp.Required(), mcp.Description("业务类型: 1-请假, 2-报销, 3-采购, ...")),
mcp.WithString("businessID", mcp.Required(), mcp.Description("业务ID如请假记录ID")),
mcp.WithString("initiatorGuid", mcp.Required(), mcp.Description("发起人ID")),
mcp.WithString("formData", mcp.Description("表单数据(JSON格式)")),
),
Handler: func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
workflowGuid := request.GetString("workflowGuid", "")
if workflowGuid == "" {
return nil, fmt.Errorf("工作流ID不能为空")
}
title := request.GetString("title", "")
if title == "" {
return nil, fmt.Errorf("实例标题不能为空")
}
businessType := request.GetInt("businessType", 0)
if businessType <= 0 {
return nil, fmt.Errorf("业务类型必须大于0")
}
businessID := request.GetString("businessID", "")
if businessID == "" {
return nil, fmt.Errorf("业务ID不能为空")
}
initiatorGuid := request.GetString("initiatorGuid", "")
if initiatorGuid == "" {
return nil, fmt.Errorf("发起人ID不能为空")
}
formData := request.GetString("formData", "")
// 在服务器端调用时启用权限检查
rep, proc := oa.StartWorkflowInstance(oa.CreateInstanceRequest{
WorkflowGuid: workflowGuid,
Title: title,
BusinessType: businessType,
BusinessID: businessID,
InitiatorGuid: initiatorGuid,
FormData: formData,
}, true) // 启用权限检查
if proc.IsError() {
return mcp.NewToolResultText(""), proc.Error
}
repStr, err := json.Marshal(rep)
if err != nil {
return mcp.NewToolResultText(""), err
}
return mcp.NewToolResultText(string(repStr)), nil
},
},
// 查询工作流实例
{
Tool: mcp.NewTool(
"queryWorkflowInstances",
mcp.WithDescription("查询工作流实例"),
mcp.WithString("workflowGuid", mcp.Description("工作流ID可选")),
mcp.WithNumber("businessType", mcp.Description("业务类型,-1表示所有类型")),
mcp.WithString("initiatorGuid", mcp.Description("发起人ID可选")),
mcp.WithNumber("status", mcp.Description("状态,-1表示所有状态")),
mcp.WithNumber("limit", mcp.Description("分页参数,每页数量")),
mcp.WithNumber("offset", mcp.Description("分页参数,偏移量")),
),
Handler: func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
workflowGuid := request.GetString("workflowGuid", "")
businessType := request.GetInt("businessType", -1)
initiatorGuid := request.GetString("initiatorGuid", "")
status := request.GetInt("status", -1)
limit := request.GetInt("limit", 20)
offset := request.GetInt("offset", 0)
rep, proc := oa.QueryWorkflowInstances(oa.QueryInstancesRequest{
WorkflowGuid: workflowGuid,
BusinessType: businessType,
InitiatorGuid: initiatorGuid,
Status: status,
Limit: limit,
Offset: offset,
})
if proc.IsError() {
return mcp.NewToolResultText(""), proc.Error
}
repStr, err := json.Marshal(rep)
if err != nil {
return mcp.NewToolResultText(""), err
}
return mcp.NewToolResultText(string(repStr)), nil
},
},
// 取消工作流实例
{
Tool: mcp.NewTool(
"cancelWorkflowInstance",
mcp.WithDescription("取消工作流实例"),
mcp.WithString("instanceGuid", mcp.Required(), mcp.Description("工作流实例ID")),
),
Handler: func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
instanceGuid := request.GetString("instanceGuid", "")
if instanceGuid == "" {
return nil, fmt.Errorf("工作流实例ID不能为空")
}
proc := oa.CancelWorkflowInstance(instanceGuid)
if proc.IsError() {
return mcp.NewToolResultText(""), proc.Error
}
return mcp.NewToolResultText("工作流实例取消成功"), nil
},
},
// 查询审批任务
{
Tool: mcp.NewTool(
"queryMyApprovalTasks",
mcp.WithDescription("查询我的审批任务"),
mcp.WithString("approverGuid", mcp.Required(), mcp.Description("审批人ID")),
mcp.WithNumber("status", mcp.Description("状态,-1表示所有状态")),
mcp.WithNumber("limit", mcp.Description("分页参数,每页数量")),
mcp.WithNumber("offset", mcp.Description("分页参数,偏移量")),
),
Handler: func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
approverGuid := request.GetString("approverGuid", "")
if approverGuid == "" {
return nil, fmt.Errorf("审批人ID不能为空")
}
status := request.GetInt("status", -1)
limit := request.GetInt("limit", 20)
offset := request.GetInt("offset", 0)
rep, proc := oa.QueryMyApprovalTasks(oa.QueryMyApprovalTasksRequest{
ApproverGuid: approverGuid,
Status: status,
Limit: limit,
Offset: offset,
})
if proc.IsError() {
return mcp.NewToolResultText(""), proc.Error
}
repStr, err := json.Marshal(rep)
if err != nil {
return mcp.NewToolResultText(""), err
}
return mcp.NewToolResultText(string(repStr)), nil
},
},
// 查询审批历史
{
Tool: mcp.NewTool(
"queryApprovalHistory",
mcp.WithDescription("查询流程审批历史"),
mcp.WithString("instanceGuid", mcp.Required(), mcp.Description("工作流实例ID")),
),
Handler: func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
instanceGuid := request.GetString("instanceGuid", "")
if instanceGuid == "" {
return nil, fmt.Errorf("工作流实例ID不能为空")
}
rep, proc := oa.QueryApprovalHistory(instanceGuid)
if proc.IsError() {
return mcp.NewToolResultText(""), proc.Error
}
repStr, err := json.Marshal(rep)
if err != nil {
return mcp.NewToolResultText(""), err
}
return mcp.NewToolResultText(string(repStr)), nil
},
},
// 处理审批
{
Tool: mcp.NewTool(
"processApproval",
mcp.WithDescription("处理审批任务"),
mcp.WithString("recordGuid", mcp.Required(), mcp.Description("审批记录ID")),
mcp.WithNumber("status", mcp.Required(), mcp.Description("操作结果1-同意2-拒绝3-转交4-委托")),
mcp.WithString("comment", mcp.Description("审批意见")),
mcp.WithString("targetGuid", mcp.Description("转交/委托目标人ID如果是转交或委托操作")),
),
Handler: func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
recordGuid := request.GetString("recordGuid", "")
if recordGuid == "" {
return nil, fmt.Errorf("审批记录ID不能为空")
}
// 获取审批人和实例信息
approverGuid := request.GetString("approverGuid", "")
if approverGuid == "" {
return nil, fmt.Errorf("审批人ID不能为空")
}
// 获取审批记录对应的实例ID
instanceGuid, err := oa.GetInstanceGuidByApprovalRecord(recordGuid)
if err != nil {
return nil, fmt.Errorf("获取工作流实例ID失败: %v", err)
}
// 检查权限
proc := oa.CheckWorkflowPermission(approverGuid, common.OperationApprove, instanceGuid)
if proc.IsError() {
return nil, fmt.Errorf("权限检查失败: %v", proc.Error)
}
status := request.GetInt("status", 0)
if status < 1 || status > 4 {
return nil, fmt.Errorf("无效的操作类型")
}
comment := request.GetString("comment", "")
targetGuid := request.GetString("targetGuid", "")
rep, proc := oa.ProcessApproval(oa.ApprovalActionRequest{
RecordGuid: recordGuid,
Status: status,
Comment: comment,
TargetGuid: targetGuid,
})
if proc.IsError() {
return mcp.NewToolResultText(""), proc.Error
}
repStr, err := json.Marshal(rep)
if err != nil {
return mcp.NewToolResultText(""), err
}
return mcp.NewToolResultText(string(repStr)), nil
},
},
}