diff --git a/OpenAuth.App/WorkflowEngineApp.cs b/OpenAuth.App/WorkflowEngineApp.cs
index 0cb7e6f..2a51635 100644
--- a/OpenAuth.App/WorkflowEngineApp.cs
+++ b/OpenAuth.App/WorkflowEngineApp.cs
@@ -4,6 +4,7 @@ using OpenAuth.App.Interface;
using OpenAuth.Repository;
using OpenAuth.Repository.Domain;
using OpenAuth.Repository.Domain.workflow;
+using OpenAuth.WebApi.Controllers.ServerController;
using SqlSugar;
namespace workflow;
@@ -18,9 +19,21 @@ using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
+using Microsoft.AspNetCore.Http;
+using OpenAuth.App.BaseApp.Base;
+using OpenAuth.App.Interface;
+using OpenAuth.Repository;
+using OpenAuth.Repository.Domain;
+using OpenAuth.Repository.Domain.workflow;
+using SqlSugar;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
///
/// 完整工作流引擎(适配:区县→执法监督科→5个审核科会签→汇总归档/退回)
+/// 包含:流程发起/处理 + 拟办/待办/已办/未办结/已完成/全部事项查询
///
public class WorkflowEngineApp : SqlSugarBaseApp
{
@@ -45,12 +58,19 @@ public class WorkflowEngineApp : SqlSugarBaseApp
+ /// 发起流程(区县提交→流转至执法监督科)
+ ///
+ /// 发起人ID
+ /// 发起人姓名
+ /// 发起流程请求参数
+ /// 流程实例ID
+ public long InitiateFlow(long userId, string userName, InitiateFlowRequestDto requestDto)
{
// 参数校验
- if (string.IsNullOrEmpty(request.FlowCode) || string.IsNullOrEmpty(request.BusinessNo))
+ if (string.IsNullOrEmpty(requestDto.FlowCode) || string.IsNullOrEmpty(requestDto.BusinessNo))
throw new Exception("流程编码和业务编号不能为空");
if (userId <= 0 || string.IsNullOrEmpty(userName))
throw new Exception("发起人ID和姓名不能为空");
@@ -64,10 +84,10 @@ public class WorkflowEngineApp : SqlSugarBaseApp()
- .Where(t => t.FlowCode == request.FlowCode && t.IsEnabled == true)
+ .Where(t => t.FlowCode == requestDto.FlowCode && t.IsEnabled == true)
.First();
if (template == null)
- throw new Exception($"流程模板【{request.FlowCode}】不存在或未启用");
+ throw new Exception($"流程模板【{requestDto.FlowCode}】不存在或未启用");
// 步骤2:查询流程开始节点(区县提交)
var startNode = _sqlSugar.Queryable()
@@ -81,7 +101,7 @@ public class WorkflowEngineApp : SqlSugarBaseApp
{
- new ZyFlowVariable { InstanceId = instanceId, VarKey = "Title", VarValue = request.Title },
+ new ZyFlowVariable { InstanceId = instanceId, VarKey = "Title", VarValue = requestDto.Title },
new ZyFlowVariable { InstanceId = instanceId, VarKey = "AttachmentPaths", VarValue = attachmentPaths },
new ZyFlowVariable
{
@@ -135,14 +155,17 @@ public class WorkflowEngineApp : SqlSugarBaseApp
+ /// 处理工作项(执法监督科转发/审核科会签/汇总处理)
+ ///
+ /// 处理人ID
+ /// 处理人姓名
+ /// 处理工作项请求参数
+ /// 处理结果(成功/失败)
+ public bool HandleWorkitem(long userId, string userName, HandleWorkitemRequestDto requestDto)
{
// 参数校验
- if (request.WorkitemId <= 0)
+ if (requestDto.WorkitemId <= 0)
throw new Exception("工作项ID无效");
if (userId <= 0 || string.IsNullOrEmpty(userName))
throw new Exception("处理人ID和姓名不能为空");
@@ -154,7 +177,7 @@ public class WorkflowEngineApp : SqlSugarBaseApp()
- .Where(w => w.WorkitemId == request.WorkitemId && w.Status == "ToDo")
+ .Where(w => w.WorkitemId == requestDto.WorkitemId && w.Status == "ToDo")
.First();
if (workitem == null)
throw new Exception("工作项不存在、已处理或状态异常");
@@ -172,7 +195,7 @@ public class WorkflowEngineApp : SqlSugarBaseApp
- /// 查询我的待办工作项
+ /// 我的拟办(未认领/待分配给当前用户的事项)
///
- public List QueryMyToDo(long userId)
+ /// 当前用户ID
+ /// 分页参数
+ /// 分页结果
+ public PageQueryResultDto QueryMyDraft(long userId, PageQueryRequestDto pageQueryDto)
{
+ // 参数初始化
if (userId <= 0)
- return new List();
+ return new PageQueryResultDto();
+ pageQueryDto = pageQueryDto ?? new PageQueryRequestDto();
+ var pageIndex = pageQueryDto.PageIndex < 1 ? 1 : pageQueryDto.PageIndex;
+ var pageSize = pageQueryDto.PageSize < 1 ? 10 : pageQueryDto.PageSize;
- // 步骤1:查询当前用户的待办工作项
- var toDoWorkitems = _sqlSugar.Queryable()
- .Where(w => w.HandlerId == userId && w.Status == "ToDo")
+ // 拟办逻辑:工作项状态为"Draft"(拟办)、对应角色匹配当前用户、未分配具体处理人
+ var draftQuery = _sqlSugar
+ .Queryable((w, n) => new JoinQueryInfos(
+ JoinType.Inner, w.NodeId == n.NodeId))
+ .Where((w, n) =>
+ w.Status == "Draft" && _auditDeptRoleIds.Contains(n.RoleId)
+ && (w.HandlerId == null || w.HandlerId == 0)
+ && w.HandlerName != "")
+ .OrderByDescending((w, n) => w.ReceiveTime);
+
+ // 分页查询
+ var totalCount = draftQuery.Count();
+ var draftWorkitems = draftQuery
+ .Skip((pageIndex - 1) * pageSize)
+ .Take(pageSize)
.ToList();
- // 步骤2:组装返回结果
- var queryResults = new List();
+ // 组装返回结果
+ var dataList = new List();
+ foreach (var workitem in draftWorkitems)
+ {
+ var flowInstance = _sqlSugar.Queryable()
+ .Where(i => i.InstanceId == workitem.InstanceId)
+ .First();
+ if (flowInstance == null)
+ continue;
+
+ var flowTitle = _sqlSugar.Queryable()
+ .Where(v => v.InstanceId == flowInstance.InstanceId && v.VarKey == "Title")
+ .First()?.VarValue ?? string.Empty;
+
+ dataList.Add(new FlowQuerySingleResultDto
+ {
+ InstanceId = flowInstance.InstanceId,
+ BusinessNo = flowInstance.BusinessNo,
+ Title = flowTitle,
+ NodeName = workitem.NodeName,
+ Status = "Draft", // 拟办状态
+ CreateTime = flowInstance.CreateTime,
+ InitiatorName = flowInstance.InitiatorName
+ });
+ }
+
+ return new PageQueryResultDto
+ {
+ PageIndex = pageIndex,
+ PageSize = pageSize,
+ TotalCount = totalCount,
+ TotalPages = (int)Math.Ceiling((double)totalCount / pageSize),
+ DataList = dataList
+ };
+ }
+
+ ///
+ /// 我的待办(已分配给当前用户、待处理的事项)
+ ///
+ /// 当前用户ID
+ /// 分页参数
+ /// 分页结果
+ public PageQueryResultDto QueryMyToDo(long userId, PageQueryRequestDto pageQueryDto)
+ {
+ // 参数初始化
+ if (userId <= 0)
+ return new PageQueryResultDto();
+ pageQueryDto = pageQueryDto ?? new PageQueryRequestDto();
+ var pageIndex = pageQueryDto.PageIndex < 1 ? 1 : pageQueryDto.PageIndex;
+ var pageSize = pageQueryDto.PageSize < 1 ? 10 : pageQueryDto.PageSize;
+
+ // 待办逻辑:工作项状态为"ToDo"、处理人ID为当前用户
+ var toDoQuery = _sqlSugar.Queryable()
+ .Where(w => w.HandlerId == userId && w.Status == "ToDo")
+ .OrderByDescending(w => w.ReceiveTime);
+
+ // 分页查询
+ var totalCount = toDoQuery.Count();
+ var toDoWorkitems = toDoQuery
+ .Skip((pageIndex - 1) * pageSize)
+ .Take(pageSize)
+ .ToList();
+
+ // 组装返回结果
+ var dataList = new List();
foreach (var workitem in toDoWorkitems)
{
var flowInstance = _sqlSugar.Queryable()
@@ -238,12 +343,11 @@ public class WorkflowEngineApp : SqlSugarBaseApp()
.Where(v => v.InstanceId == flowInstance.InstanceId && v.VarKey == "Title")
.First()?.VarValue ?? string.Empty;
- queryResults.Add(new FlowQueryResult
+ dataList.Add(new FlowQuerySingleResultDto
{
InstanceId = flowInstance.InstanceId,
BusinessNo = flowInstance.BusinessNo,
@@ -255,27 +359,51 @@ public class WorkflowEngineApp : SqlSugarBaseApp
+ {
+ PageIndex = pageIndex,
+ PageSize = pageSize,
+ TotalCount = totalCount,
+ TotalPages = (int)Math.Ceiling((double)totalCount / pageSize),
+ DataList = dataList
+ };
}
///
- /// 查询我的已办工作项
+ /// 我的已办(当前用户已处理完成的事项)
///
- public List QueryMyDone(long userId)
+ /// 当前用户ID
+ /// 分页参数
+ /// 分页结果
+ public PageQueryResultDto QueryMyDone(long userId, PageQueryRequestDto pageQueryDto)
{
+ // 参数初始化
if (userId <= 0)
- return new List();
+ return new PageQueryResultDto();
+ pageQueryDto = pageQueryDto ?? new PageQueryRequestDto();
+ var pageIndex = pageQueryDto.PageIndex < 1 ? 1 : pageQueryDto.PageIndex;
+ var pageSize = pageQueryDto.PageSize < 1 ? 10 : pageQueryDto.PageSize;
- // 步骤1:查询当前用户已完成的工作项对应的流程实例ID(去重)
+ // 已办逻辑:工作项状态为"Done"、处理人ID为当前用户(去重流程实例)
var doneInstanceIds = _sqlSugar.Queryable()
.Where(w => w.HandlerId == userId && w.Status == "Done")
.Select(w => w.InstanceId)
.Distinct()
.ToList();
- // 步骤2:组装返回结果
- var queryResults = new List();
- foreach (var instanceId in doneInstanceIds)
+ if (!doneInstanceIds.Any())
+ return new PageQueryResultDto();
+
+ // 分页处理实例ID
+ var pagedInstanceIds = doneInstanceIds
+ .Skip((pageIndex - 1) * pageSize)
+ .Take(pageSize)
+ .ToList();
+ var totalCount = doneInstanceIds.Count;
+
+ // 组装返回结果
+ var dataList = new List();
+ foreach (var instanceId in pagedInstanceIds)
{
var flowInstance = _sqlSugar.Queryable()
.Where(i => i.InstanceId == instanceId)
@@ -283,18 +411,16 @@ public class WorkflowEngineApp : SqlSugarBaseApp()
.Where(v => v.InstanceId == flowInstance.InstanceId && v.VarKey == "Title")
.First()?.VarValue ?? string.Empty;
- // 查询最新的已完成工作项
var lastWorkitem = _sqlSugar.Queryable()
- .Where(w => w.InstanceId == instanceId && w.Status == "Done")
+ .Where(w => w.InstanceId == instanceId && w.HandlerId == userId && w.Status == "Done")
.OrderByDescending(w => w.HandleTime)
.First();
- queryResults.Add(new FlowQueryResult
+ dataList.Add(new FlowQuerySingleResultDto
{
InstanceId = flowInstance.InstanceId,
BusinessNo = flowInstance.BusinessNo,
@@ -306,12 +432,245 @@ public class WorkflowEngineApp : SqlSugarBaseApp
+ {
+ PageIndex = pageIndex,
+ PageSize = pageSize,
+ TotalCount = totalCount,
+ TotalPages = (int)Math.Ceiling((double)totalCount / pageSize),
+ DataList = dataList
+ };
+ }
+
+ ///
+ /// 我的未办结(当前用户参与过、流程尚未完成的事项)
+ ///
+ /// 当前用户ID
+ /// 分页参数
+ /// 分页结果
+ public PageQueryResultDto QueryMyUnfinished(long userId, PageQueryRequestDto pageQueryDto)
+ {
+ // 参数初始化
+ if (userId <= 0)
+ return new PageQueryResultDto();
+ pageQueryDto = pageQueryDto ?? new PageQueryRequestDto();
+ var pageIndex = pageQueryDto.PageIndex < 1 ? 1 : pageQueryDto.PageIndex;
+ var pageSize = pageQueryDto.PageSize < 1 ? 10 : pageQueryDto.PageSize;
+
+ // 未办结逻辑:
+ // 1. 当前用户参与过(处理过/待处理)
+ // 2. 流程状态不是"Completed"(未完成)
+ var unfinishedInstanceIds = _sqlSugar.Queryable((w, i) => new JoinQueryInfos(
+ JoinType.Inner, w.InstanceId == i.InstanceId))
+ .Where((w, i) => (w.HandlerId == userId || (w.Status == "Draft" && _auditDeptRoleIds.Contains(w.NodeId)))
+ && i.Status != "Completed")
+ .Select((w, i) => i.InstanceId)
+ .Distinct()
+ .ToList();
+
+ if (!unfinishedInstanceIds.Any())
+ return new PageQueryResultDto();
+
+ // 分页处理实例ID
+ var pagedInstanceIds = unfinishedInstanceIds
+ .Skip((pageIndex - 1) * pageSize)
+ .Take(pageSize)
+ .ToList();
+ var totalCount = unfinishedInstanceIds.Count;
+
+ // 组装返回结果
+ var dataList = new List();
+ foreach (var instanceId in pagedInstanceIds)
+ {
+ var flowInstance = _sqlSugar.Queryable()
+ .Where(i => i.InstanceId == instanceId)
+ .First();
+ if (flowInstance == null)
+ continue;
+
+ var flowTitle = _sqlSugar.Queryable()
+ .Where(v => v.InstanceId == flowInstance.InstanceId && v.VarKey == "Title")
+ .First()?.VarValue ?? string.Empty;
+
+ var currentNode = _sqlSugar.Queryable()
+ .Where(n => n.NodeId == flowInstance.CurrentNodeId)
+ .First();
+
+ dataList.Add(new FlowQuerySingleResultDto
+ {
+ InstanceId = flowInstance.InstanceId,
+ BusinessNo = flowInstance.BusinessNo,
+ Title = flowTitle,
+ NodeName = currentNode?.NodeName ?? string.Empty,
+ Status = flowInstance.Status,
+ CreateTime = flowInstance.CreateTime,
+ InitiatorName = flowInstance.InitiatorName
+ });
+ }
+
+ return new PageQueryResultDto
+ {
+ PageIndex = pageIndex,
+ PageSize = pageSize,
+ TotalCount = totalCount,
+ TotalPages = (int)Math.Ceiling((double)totalCount / pageSize),
+ DataList = dataList
+ };
+ }
+
+ ///
+ /// 我的已完成(当前用户参与过、流程已归档完成的事项)
+ ///
+ /// 当前用户ID
+ /// 分页参数
+ /// 分页结果
+ public PageQueryResultDto QueryMyCompleted(long userId, PageQueryRequestDto pageQueryDto)
+ {
+ // 参数初始化
+ if (userId <= 0)
+ return new PageQueryResultDto();
+ pageQueryDto = pageQueryDto ?? new PageQueryRequestDto();
+ var pageIndex = pageQueryDto.PageIndex < 1 ? 1 : pageQueryDto.PageIndex;
+ var pageSize = pageQueryDto.PageSize < 1 ? 10 : pageQueryDto.PageSize;
+
+ // 已完成逻辑:
+ // 1. 当前用户参与过(处理过/待处理)
+ // 2. 流程状态是"Completed"(已完成)
+ var completedInstanceIds = _sqlSugar.Queryable((w, i) => new JoinQueryInfos(
+ JoinType.Inner, w.InstanceId == i.InstanceId))
+ .Where((w, i) => (w.HandlerId == userId || (w.Status == "Draft" && _auditDeptRoleIds.Contains(w.NodeId)))
+ && i.Status == "Completed")
+ .Select((w, i) => i.InstanceId)
+ .Distinct()
+ .ToList();
+
+ if (!completedInstanceIds.Any())
+ return new PageQueryResultDto();
+
+ // 分页处理实例ID
+ var pagedInstanceIds = completedInstanceIds
+ .Skip((pageIndex - 1) * pageSize)
+ .Take(pageSize)
+ .ToList();
+ var totalCount = completedInstanceIds.Count;
+
+ // 组装返回结果
+ var dataList = new List();
+ foreach (var instanceId in pagedInstanceIds)
+ {
+ var flowInstance = _sqlSugar.Queryable()
+ .Where(i => i.InstanceId == instanceId)
+ .First();
+ if (flowInstance == null)
+ continue;
+
+ var flowTitle = _sqlSugar.Queryable()
+ .Where(v => v.InstanceId == flowInstance.InstanceId && v.VarKey == "Title")
+ .First()?.VarValue ?? string.Empty;
+
+ var lastNode = _sqlSugar.Queryable()
+ .Where(n => n.NodeId == flowInstance.CurrentNodeId)
+ .First();
+
+ dataList.Add(new FlowQuerySingleResultDto
+ {
+ InstanceId = flowInstance.InstanceId,
+ BusinessNo = flowInstance.BusinessNo,
+ Title = flowTitle,
+ NodeName = lastNode?.NodeName ?? "流程归档",
+ Status = flowInstance.Status,
+ CreateTime = flowInstance.CreateTime,
+ InitiatorName = flowInstance.InitiatorName
+ });
+ }
+
+ return new PageQueryResultDto
+ {
+ PageIndex = pageIndex,
+ PageSize = pageSize,
+ TotalCount = totalCount,
+ TotalPages = (int)Math.Ceiling((double)totalCount / pageSize),
+ DataList = dataList
+ };
+ }
+
+ ///
+ /// 我的全部事项(拟办+待办+已办+未办结+已完成,去重整合)
+ ///
+ /// 当前用户ID
+ /// 分页参数
+ /// 分页结果
+ public PageQueryResultDto QueryMyAllItems(long userId, PageQueryRequestDto pageQueryDto)
+ {
+ // 参数初始化
+ if (userId <= 0)
+ return new PageQueryResultDto();
+ pageQueryDto = pageQueryDto ?? new PageQueryRequestDto();
+ var pageIndex = pageQueryDto.PageIndex < 1 ? 1 : pageQueryDto.PageIndex;
+ var pageSize = pageQueryDto.PageSize < 1 ? 10 : pageQueryDto.PageSize;
+
+ // 全部事项逻辑:当前用户相关的所有流程实例(去重)
+ var allInstanceIds = _sqlSugar.Queryable((w, i) => new JoinQueryInfos(
+ JoinType.Inner, w.InstanceId == i.InstanceId))
+ .Where((w, i) => w.HandlerId == userId || (w.Status == "Draft" && _auditDeptRoleIds.Contains(w.NodeId))
+ || i.InitiatorId == userId)
+ .Select((w, i) => i.InstanceId)
+ .Distinct()
+ .ToList();
+
+ if (!allInstanceIds.Any())
+ return new PageQueryResultDto();
+
+ // 分页处理实例ID
+ var pagedInstanceIds = allInstanceIds
+ .Skip((pageIndex - 1) * pageSize)
+ .Take(pageSize)
+ .ToList();
+ var totalCount = allInstanceIds.Count;
+
+ // 组装返回结果
+ var dataList = new List();
+ foreach (var instanceId in pagedInstanceIds)
+ {
+ var flowInstance = _sqlSugar.Queryable()
+ .Where(i => i.InstanceId == instanceId)
+ .First();
+ if (flowInstance == null)
+ continue;
+
+ var flowTitle = _sqlSugar.Queryable()
+ .Where(v => v.InstanceId == flowInstance.InstanceId && v.VarKey == "Title")
+ .First()?.VarValue ?? string.Empty;
+
+ var currentNode = _sqlSugar.Queryable()
+ .Where(n => n.NodeId == flowInstance.CurrentNodeId)
+ .First();
+
+ dataList.Add(new FlowQuerySingleResultDto
+ {
+ InstanceId = flowInstance.InstanceId,
+ BusinessNo = flowInstance.BusinessNo,
+ Title = flowTitle,
+ NodeName = currentNode?.NodeName ?? string.Empty,
+ Status = flowInstance.Status,
+ CreateTime = flowInstance.CreateTime,
+ InitiatorName = flowInstance.InitiatorName
+ });
+ }
+
+ return new PageQueryResultDto
+ {
+ PageIndex = pageIndex,
+ PageSize = pageSize,
+ TotalCount = totalCount,
+ TotalPages = (int)Math.Ceiling((double)totalCount / pageSize),
+ DataList = dataList
+ };
}
#endregion
- #region 4. 核心辅助方法(流转/会签/汇总/附件等)
+ #region 三、内部核心辅助方法(仅内部调用,不对外暴露)
///
/// 流程节点流转核心方法
@@ -377,10 +736,10 @@ public class WorkflowEngineApp : SqlSugarBaseApp
private void ProcessParallelAudit(long instanceId, long nodeId, long userId, string userName,
- HandleWorkitemRequest request)
+ HandleWorkitemRequestDto requestDto)
{
// 校验会签结果
- if (string.IsNullOrEmpty(request.AuditResult))
+ if (string.IsNullOrEmpty(requestDto.AuditResult))
throw new Exception("会签需选择审核结果(Pass/Reject)");
// 步骤1:获取当前用户所属科室名称
@@ -392,8 +751,8 @@ public class WorkflowEngineApp : SqlSugarBaseApp()
+ var hasReject = _sqlSugar.Queryable()
.Where(a => a.InstanceId == flowInstance.InstanceId)
- .Any(a=> a.AuditResult != "Pass");
+ .Any(a => a.AuditResult != "Pass");
+ var isAllPass = !hasReject;
- // todo
// 步骤2:解析汇总节点下一节点(归档/退回)
var nextNodeIds = summaryNode.NextNodeIds?.Split(',', StringSplitOptions.RemoveEmptyEntries)
.Select(long.Parse)
@@ -429,13 +788,13 @@ public class WorkflowEngineApp : SqlSugarBaseApp()
.Where(n => n.NodeId == targetNodeId)
.First();
if (targetNode == null)
- return;
+ throw new Exception($"汇总节点目标节点【{(isAllPass ? "归档" : "退回区县")}】不存在");
// 步骤4:创建目标节点工作项
var summaryWorkitem = new ZyFlowWorkitem
@@ -448,7 +807,7 @@ public class WorkflowEngineApp : SqlSugarBaseApp
- /// 获取角色下第一个用户ID
- ///
- private long GetRoleFirstUserId(long roleId)
- {
- var userInfo = GetRoleFirstUserInfo(roleId);
- return userInfo.userId;
- }
-
- ///
- /// 获取角色下第一个用户姓名
- ///
- private string GetRoleFirstUserName(long roleId)
- {
- var userInfo = GetRoleFirstUserInfo(roleId);
- return userInfo.userName;
- }
-
///
/// 获取角色下第一个用户的完整信息
///
private (long userId, string userName, string deptName) GetRoleFirstUserInfo(long roleId)
{
- var sql = @"
- SELECT
- u.""Id"" as UserId,
- u.""Name"" as UserName,
- o.""Name"" as DeptName
- FROM sys_user u
- INNER JOIN sys_userrole r ON u.""Id"" = r.""UserId""
- INNER JOIN sys_userorg uo ON u.""Id"" = uo.""UserId""
- INNER JOIN sys_org o ON uo.""OrgId"" = o.""Id""
- WHERE r.""RoleId"" = @RoleId
- LIMIT 1";
-
- var userInfo = _sqlSugar.SqlQueryable(sql)
- .AddParameters(new { RoleId = roleId })
+ var userInfo = _sqlSugar
+ .Queryable((o, uo, u) => new JoinQueryInfos(
+ JoinType.Inner, o.Id == uo.OrgId && uo.UserId == u.Id))
+ .Select((o, uo, u) => new
+ {
+ UserId = u.Id,
+ UserName = u.Name,
+ DeptName = o.Name
+ })
.First();
+ if (userInfo == null)
+ return (0, string.Empty, string.Empty);
+
return (userInfo.UserId, userInfo.UserName ?? string.Empty, userInfo.DeptName ?? string.Empty);
}
diff --git a/OpenAuth.Repository/Domain/workflow/ApiResult.cs b/OpenAuth.Repository/Domain/workflow/ApiResult.cs
new file mode 100644
index 0000000..8118d8c
--- /dev/null
+++ b/OpenAuth.Repository/Domain/workflow/ApiResult.cs
@@ -0,0 +1,217 @@
+using Microsoft.AspNetCore.Http;
+
+namespace OpenAuth.WebApi.Controllers.ServerController;
+
+#region 一、接口入参DTO(所有请求参数,对应Controller接收的参数)
+
+///
+/// 发起流程请求参数
+///
+public class InitiateFlowRequestDto
+{
+ ///
+ /// 流程编码(唯一标识流程模板,如:IllegalConstructionFlow_2026)
+ ///
+ public string FlowCode { get; set; } = string.Empty;
+
+ ///
+ /// 业务编号(唯一标识该笔业务,如:WJ20260205001、XZ20260205002)
+ ///
+ public string BusinessNo { get; set; } = string.Empty;
+
+ ///
+ /// 流程标题(用于展示,如:"XX区域违法建设认定申请")
+ ///
+ public string Title { get; set; } = string.Empty;
+
+ ///
+ /// 上传附件列表(业务相关证明材料、表单等)
+ ///
+ public List Attachments { get; set; } = new List();
+}
+
+///
+/// 处理工作项请求参数
+///
+public class HandleWorkitemRequestDto
+{
+ ///
+ /// 工作项ID(待处理事项的唯一标识,从待办查询接口获取)
+ ///
+ public long WorkitemId { get; set; }
+
+ ///
+ /// 处理备注(可选,记录处理意见、流转说明等)
+ ///
+ public string? Comment { get; set; }
+
+ ///
+ /// 审核结果(仅会签节点必填,可选值:Pass(通过)/Reject(驳回))
+ ///
+ public string? AuditResult { get; set; }
+}
+
+///
+/// 分页查询通用请求参数(所有查询接口共用)
+///
+public class PageQueryRequestDto
+{
+ ///
+ /// 当前页码(默认1,从1开始计数)
+ ///
+ public int PageIndex { get; set; } = 1;
+
+ ///
+ /// 每页显示条数(默认10,可自定义,建议不超过50)
+ ///
+ public int PageSize { get; set; } = 10;
+}
+
+#endregion
+
+#region 二、接口出参DTO(所有返回结果,对应Controller返回的数据)
+
+///
+/// 流程查询单条结果返回值(所有查询接口的单条数据格式)
+///
+public class FlowQuerySingleResultDto
+{
+ ///
+ /// 流程实例ID(唯一标识该流程实例,用于后续操作)
+ ///
+ public long InstanceId { get; set; }
+
+ ///
+ /// 业务编号(对应发起流程时的BusinessNo)
+ ///
+ public string BusinessNo { get; set; } = string.Empty;
+
+ ///
+ /// 流程标题(对应发起流程时的Title)
+ ///
+ public string Title { get; set; } = string.Empty;
+
+ ///
+ /// 当前节点名称(如:"区县提交"、"政策法规科审核"、"汇总归档")
+ ///
+ public string NodeName { get; set; } = string.Empty;
+
+ ///
+ /// 流程状态(枚举值:Draft(拟办)、Submitted(已提交)、Forwarded(已转发)、Auditing(审核中)、Summarized(已汇总)、Completed(已完成)、Rejected(已驳回))
+ ///
+ public string Status { get; set; } = string.Empty;
+
+ ///
+ /// 流程发起时间
+ ///
+ public DateTime? CreateTime { get; set; }
+
+ ///
+ /// 发起人姓名
+ ///
+ public string InitiatorName { get; set; } = string.Empty;
+}
+
+///
+/// 分页查询通用返回值(所有分页查询接口共用,泛型适配不同数据列表)
+///
+/// 数据列表的泛型类型(如:FlowQuerySingleResultDto)
+public class PageQueryResultDto
+{
+ ///
+ /// 当前页码(与请求参数的PageIndex对应)
+ ///
+ public int PageIndex { get; set; }
+
+ ///
+ /// 每页显示条数(与请求参数的PageSize对应)
+ ///
+ public int PageSize { get; set; }
+
+ ///
+ /// 总记录数(符合查询条件的所有数据条数)
+ ///
+ public long TotalCount { get; set; }
+
+ ///
+ /// 总页数(自动计算:TotalCount / PageSize,向上取整)
+ ///
+ public int TotalPages { get; set; }
+
+ ///
+ /// 当前页的数据列表
+ ///
+ public List DataList { get; set; } = new List();
+}
+
+///
+/// 接口全局统一响应格式(所有接口返回结果的统一封装,提高前端对接效率)
+///
+/// 响应数据的泛型类型(如:long、bool、PageQueryResultDto)
+public class ApiResponseDto
+{
+ ///
+ /// 响应状态码(200:操作成功,500:操作失败,400:参数错误/未登录,404:资源不存在)
+ ///
+ public int Code { get; set; } = 200;
+
+ ///
+ /// 响应消息(成功时返回"操作成功",失败时返回具体错误信息)
+ ///
+ public string Message { get; set; } = "操作成功";
+
+ ///
+ /// 响应数据(成功时返回具体业务数据,失败时可返回null或附加说明数据)
+ ///
+ public T? Data { get; set; }
+
+ ///
+ /// 构建成功响应(静态方法,简化Controller调用)
+ ///
+ /// 成功时的业务数据
+ /// 自定义成功消息(可选,默认"操作成功")
+ /// 统一响应格式对象
+ public static ApiResponseDto Success(T? data = default, string message = "操作成功")
+ {
+ return new ApiResponseDto
+ {
+ Code = 200,
+ Message = message,
+ Data = data
+ };
+ }
+
+ ///
+ /// 构建失败响应(静态方法,简化Controller调用)
+ ///
+ /// 具体错误消息
+ /// 失败时的附加数据(可选,默认null)
+ /// 统一响应格式对象
+ public static ApiResponseDto Fail(string message = "操作失败", T? data = default)
+ {
+ return new ApiResponseDto
+ {
+ Code = 500,
+ Message = message,
+ Data = data
+ };
+ }
+
+ ///
+ /// 构建参数错误/未登录响应(静态方法,适配400状态码场景)
+ ///
+ /// 具体错误消息
+ /// 附加数据(可选)
+ /// 统一响应格式对象
+ public static ApiResponseDto BadRequest(string message = "参数错误或未登录", T? data = default)
+ {
+ return new ApiResponseDto
+ {
+ Code = 400,
+ Message = message,
+ Data = data
+ };
+ }
+}
+
+#endregion
\ No newline at end of file
diff --git a/OpenAuth.Repository/Domain/workflow/InitiateFlowRequest.cs b/OpenAuth.Repository/Domain/workflow/InitiateFlowRequest.cs
deleted file mode 100644
index c9f779f..0000000
--- a/OpenAuth.Repository/Domain/workflow/InitiateFlowRequest.cs
+++ /dev/null
@@ -1,91 +0,0 @@
-using Microsoft.AspNetCore.Http;
-
-namespace OpenAuth.Repository.Domain.workflow;
-
-///
-/// 发起流程请求DTO
-///
-public class InitiateFlowRequest
-{
- ///
- /// 流程编码
- ///
- public string FlowCode { get; set; } = string.Empty;
-
- ///
- /// 业务编号
- ///
- public string BusinessNo { get; set; } = string.Empty;
-
- ///
- /// 流程标题
- ///
- public string Title { get; set; } = string.Empty;
-
- ///
- /// 附件列表
- ///
- public List? Attachments { get; set; }
-}
-
-///
-/// 处理工作项请求DTO
-///
-public class HandleWorkitemRequest
-{
- ///
- /// 工作项ID
- ///
- public long WorkitemId { get; set; }
-
- ///
- /// 处理意见
- ///
- public string? Comment { get; set; }
-
- ///
- /// 会签结果(Pass/Reject)
- ///
- public string? AuditResult { get; set; }
-}
-
-///
-/// 流程查询结果DTO
-///
-public class FlowQueryResult
-{
- ///
- /// 流程实例ID
- ///
- public long InstanceId { get; set; }
-
- ///
- /// 业务编号
- ///
- public string BusinessNo { get; set; } = string.Empty;
-
- ///
- /// 流程标题
- ///
- public string Title { get; set; } = string.Empty;
-
- ///
- /// 当前节点名称
- ///
- public string NodeName { get; set; } = string.Empty;
-
- ///
- /// 流程状态
- ///
- public string Status { get; set; } = string.Empty;
-
- ///
- /// 创建时间
- ///
- public DateTime? CreateTime { get; set; }
-
- ///
- /// 发起人姓名
- ///
- public string InitiatorName { get; set; } = string.Empty;
-}
\ No newline at end of file
diff --git a/OpenAuth.WebApi/Controllers/ServerController/ApiResult.cs b/OpenAuth.WebApi/Controllers/ServerController/ApiResult.cs
deleted file mode 100644
index c87cfd6..0000000
--- a/OpenAuth.WebApi/Controllers/ServerController/ApiResult.cs
+++ /dev/null
@@ -1,95 +0,0 @@
-namespace OpenAuth.WebApi.Controllers.ServerController;
-
-///
-/// 统一API返回结果
-///
-///
-public class ApiResult
-{
- public bool Success { get; set; }
- public string Message { get; set; }
- public T Data { get; set; }
- public int TotalCount { get; set; } // 分页总条数
-
- public static ApiResult Ok(T data, int totalCount = 0, string message = "操作成功")
- {
- return new ApiResult
- {
- Success = true,
- Message = message,
- Data = data,
- TotalCount = totalCount
- };
- }
-
- public static ApiResult Error(string message = "操作失败")
- {
- return new ApiResult
- {
- Success = false,
- Message = message,
- Data = default(T),
- TotalCount = 0
- };
- }
-}
-
-// 通用分页输入
-public class PageInput
-{
- public int PageIndex { get; set; } = 1;
- public int PageSize { get; set; } = 10;
-}
-
-// 通用分页输出
-public class PageOutput
-{
- public int PageIndex { get; set; }
- public int PageSize { get; set; }
- public long TotalCount { get; set; }
- public int TotalPages { get; set; }
- public List Data { get; set; } = new List();
-}
-
-// 发起流程请求
-public class InitiateFlowRequest
-{
- public string FlowCode { get; set; } = string.Empty;
- public string BusinessNo { get; set; } = string.Empty;
- public string Title { get; set; } = string.Empty;
- public List? Attachments { get; set; }
-}
-
-// 处理工作项请求
-public class HandleWorkitemRequest
-{
- public long WorkitemId { get; set; }
- public string? Comment { get; set; }
- public string? AuditResult { get; set; } // Pass/Reject
-}
-
-// 工作项查询结果(拟办/待办/已办)
-public class FlowQueryResult
-{
- public long InstanceId { get; set; }
- public string BusinessNo { get; set; } = string.Empty;
- public string Title { get; set; } = string.Empty;
- public string NodeName { get; set; } = string.Empty;
- public string Status { get; set; } = string.Empty;
- public DateTime? CreateTime { get; set; }
- public string InitiatorName { get; set; } = string.Empty;
-}
-
-// 流程实例查询结果(未办结/已完成)
-public class FlowInstanceQueryResult
-{
- public long InstanceId { get; set; }
- public string BusinessNo { get; set; } = string.Empty;
- public string FlowName { get; set; } = string.Empty;
- public string Title { get; set; } = string.Empty;
- public string CurrentNodeName { get; set; } = string.Empty;
- public string Status { get; set; } = string.Empty;
- public string InitiatorName { get; set; } = string.Empty;
- public DateTime? CreateTime { get; set; }
- public DateTime? FinishTime { get; set; }
-}
\ No newline at end of file
diff --git a/OpenAuth.WebApi/Controllers/ServerController/CustomWorkflowController.cs b/OpenAuth.WebApi/Controllers/ServerController/CustomWorkflowController.cs
index b4cab19..382ed56 100644
--- a/OpenAuth.WebApi/Controllers/ServerController/CustomWorkflowController.cs
+++ b/OpenAuth.WebApi/Controllers/ServerController/CustomWorkflowController.cs
@@ -6,186 +6,235 @@ using workflow;
namespace OpenAuth.WebApi.Controllers.ServerController;
+using Microsoft.AspNetCore.Mvc;
+using OpenAuth.App.Interface;
+
+///
+/// 工作流核心API接口(流程发起/处理 + 拟办/待办/已办/未办结/已完成/全部事项查询)
+///
[ApiController]
-[Route("api/[controller]")]
-public class CustomWorkflowController : ControllerBase
+[Route("api/[controller]/[action]")]
+public class WorkflowController : ControllerBase
{
private readonly WorkflowEngineApp _workflowEngineApp;
private readonly IAuth _auth;
- public CustomWorkflowController(WorkflowEngineApp workflowEngineApp, IAuth auth)
+ // 构造函数注入依赖
+ public WorkflowController(WorkflowEngineApp workflowEngineApp, IAuth auth)
{
_workflowEngineApp = workflowEngineApp;
_auth = auth;
}
- #region 基础接口
+ #region 一、流程操作接口
- [HttpGet("user/by-role/{roleId:long}")]
- public IActionResult GetUserNameByRoleId(long roleId)
+ ///
+ /// 发起流程(区县提交)
+ ///
+ /// 发起流程请求参数
+ /// 流程实例ID
+ [HttpPost]
+ public ActionResult> InitiateFlow([FromForm] InitiateFlowRequestDto requestDto)
{
try
{
- var userName = _workflowEngineApp.GetUserNameByRoleId(roleId);
- return Ok(new { Success = true, Data = userName });
+ // 获取当前登录用户(实际项目中从Token/IAuth中解析)
+ var currentUser = _auth.GetCurrentUser().User;
+ if (currentUser == null)
+ return BadRequest(ApiResponseDto.Fail("未登录或登录过期"));
+
+ var instanceId = _workflowEngineApp.InitiateFlow(
+ currentUser.Id,
+ currentUser.Name,
+ requestDto);
+
+ return Ok(ApiResponseDto.Success(instanceId, "流程发起成功"));
}
catch (Exception ex)
{
- return BadRequest(new { Success = false, Message = ex.Message });
+ return StatusCode(500, ApiResponseDto.Fail(ex.Message));
+ }
+ }
+
+ ///
+ /// 处理工作项(执法监督科转发/审核科会签/汇总处理)
+ ///
+ /// 处理工作项请求参数
+ /// 处理结果
+ [HttpPost]
+ public ActionResult> HandleWorkitem([FromBody] HandleWorkitemRequestDto requestDto)
+ {
+ try
+ {
+ // 获取当前登录用户(实际项目中从Token/IAuth中解析)
+ var currentUser = _auth.GetCurrentUser().User;
+ if (currentUser == null)
+ return BadRequest(ApiResponseDto.Fail("未登录或登录过期"));
+
+ var result = _workflowEngineApp.HandleWorkitem(
+ currentUser.Id,
+ currentUser.Name,
+ requestDto);
+
+ return Ok(ApiResponseDto.Success(result, "工作项处理成功"));
+ }
+ catch (Exception ex)
+ {
+ return StatusCode(500, ApiResponseDto.Fail(ex.Message));
}
}
#endregion
- #region 流程表单接口
+ #region 二、完整查询接口(拟办/待办/已办/未办结/已完成/全部事项)
- [HttpPost("flow/initiate")]
- public IActionResult InitiateAssessmentFlow([FromBody] InitiateAssessmentFlowRequest request)
+ ///
+ /// 查询我的拟办(未认领/待分配事项)
+ ///
+ /// 分页查询参数
+ /// 分页拟办结果
+ [HttpGet]
+ public ActionResult>> QueryMyDraft(
+ [FromQuery] PageQueryRequestDto pageQueryDto)
{
try
{
- var currentUser = _auth.GetCurrentUser()?.User;
+ var currentUser = _auth.GetCurrentUser().User;
if (currentUser == null)
- return Unauthorized(new { Success = false, Message = "未登录" });
+ return BadRequest(ApiResponseDto>.Fail("未登录或登录过期"));
- var instanceId = _workflowEngineApp.InitiateAssessmentFlow(currentUser.Id, currentUser.Name, request);
- return Ok(new { Success = true, Data = new { FlowInstanceId = instanceId } });
+ var result = _workflowEngineApp.QueryMyDraft(currentUser.Id, pageQueryDto);
+
+ return Ok(ApiResponseDto>.Success(result, "拟办查询成功"));
}
catch (Exception ex)
{
- return BadRequest(new { Success = false, Message = ex.Message });
+ return StatusCode(500, ApiResponseDto>.Fail(ex.Message));
}
}
- [HttpGet("flow/by-business/{businessNumber}")]
- public IActionResult QueryAssessmentFlowByBusinessNo(string businessNumber)
+ ///
+ /// 查询我的待办(已分配/待处理事项)
+ ///
+ /// 分页查询参数
+ /// 分页待办结果
+ [HttpGet]
+ public ActionResult>> QueryMyToDo(
+ [FromQuery] PageQueryRequestDto pageQueryDto)
{
try
{
- var result = _workflowEngineApp.QueryAssessmentFlowByBusinessNo(businessNumber);
- return Ok(new { Success = true, Data = result });
- }
- catch (Exception ex)
- {
- return BadRequest(new { Success = false, Message = ex.Message });
- }
- }
-
- [HttpPut("form/update")]
- public IActionResult UpdateAssessmentForm([FromBody] IllegalConstructionAssessment form)
- {
- try
- {
- var currentUser = _auth.GetCurrentUser()?.User;
+ var currentUser = _auth.GetCurrentUser().User;
if (currentUser == null)
- return Unauthorized(new { Success = false, Message = "未登录" });
+ return BadRequest(ApiResponseDto>.Fail("未登录或登录过期"));
- var success = _workflowEngineApp.UpdateAssessmentForm(form, currentUser.Id);
- return Ok(new { Success = success, Message = success ? "更新成功" : "更新失败" });
+ var result = _workflowEngineApp.QueryMyToDo(currentUser.Id, pageQueryDto);
+
+ return Ok(ApiResponseDto>.Success(result, "待办查询成功"));
}
catch (Exception ex)
{
- return BadRequest(new { Success = false, Message = ex.Message });
+ return StatusCode(500, ApiResponseDto>.Fail(ex.Message));
}
}
- [HttpPost("form/page")]
- public IActionResult QueryAllAssessmentForms([FromBody] PageQueryInput pageInput)
+ ///
+ /// 查询我的已办(已处理完成事项)
+ ///
+ /// 分页查询参数
+ /// 分页已办结果
+ [HttpGet]
+ public ActionResult>> QueryMyDone(
+ [FromQuery] PageQueryRequestDto pageQueryDto)
{
try
{
- var result = _workflowEngineApp.QueryAllAssessmentForms(pageInput);
- return Ok(new { Success = true, Data = result });
- }
- catch (Exception ex)
- {
- return BadRequest(new { Success = false, Message = ex.Message });
- }
- }
-
- #endregion
-
- #region 待办查询接口
-
- [HttpPost("flow/draft/{userId:long}")]
- public IActionResult QueryMyDraft(long userId, [FromBody] PageQueryInput pageInput)
- {
- try
- {
- var result = _workflowEngineApp.QueryMyDraft(userId, pageInput);
- return Ok(new { Success = true, Data = result });
- }
- catch (Exception ex)
- {
- return BadRequest(new { Success = false, Message = ex.Message });
- }
- }
-
- [HttpPost("flow/todo/{userId:long}")]
- public IActionResult QueryMyToDo(long userId, [FromBody] PageQueryInput pageInput)
- {
- try
- {
- var result = _workflowEngineApp.QueryMyToDo(userId, pageInput);
- return Ok(new { Success = true, Data = result });
- }
- catch (Exception ex)
- {
- return BadRequest(new { Success = false, Message = ex.Message });
- }
- }
-
- [HttpPost("flow/done/{userId:long}")]
- public IActionResult QueryMyDone(long userId, [FromBody] PageQueryInput pageInput)
- {
- try
- {
- var result = _workflowEngineApp.QueryMyDone(userId, pageInput);
- return Ok(new { Success = true, Data = result });
- }
- catch (Exception ex)
- {
- return BadRequest(new { Success = false, Message = ex.Message });
- }
- }
-
- #endregion
-
- #region 待办处理接口
-
- [HttpPost("flow/workitem/claim/{workitemId:long}/{userId:long}")]
- public IActionResult ClaimDraftWorkitem(long workitemId, long userId)
- {
- try
- {
- var currentUser = _auth.GetCurrentUser()?.User;
+ var currentUser = _auth.GetCurrentUser().User;
if (currentUser == null)
- return Unauthorized(new { Success = false, Message = "未登录" });
+ return BadRequest(ApiResponseDto>.Fail("未登录或登录过期"));
- var success = _workflowEngineApp.ClaimDraftWorkitem(workitemId, userId, currentUser.Name);
- return Ok(new { Success = success, Message = success ? "认领成功" : "认领失败" });
+ var result = _workflowEngineApp.QueryMyDone(currentUser.Id, pageQueryDto);
+
+ return Ok(ApiResponseDto>.Success(result, "已办查询成功"));
}
catch (Exception ex)
{
- return BadRequest(new { Success = false, Message = ex.Message });
+ return StatusCode(500, ApiResponseDto>.Fail(ex.Message));
}
}
- [HttpPost("flow/workitem/handle/{userId:long}")]
- public IActionResult HandleWorkitem(long userId, [FromBody] HandleWorkitemRequest request)
+ ///
+ /// 查询我的未办结(参与过/流程未完成事项)
+ ///
+ /// 分页查询参数
+ /// 分页未办结结果
+ [HttpGet]
+ public ActionResult>> QueryMyUnfinished(
+ [FromQuery] PageQueryRequestDto pageQueryDto)
{
try
{
- var currentUser = _auth.GetCurrentUser()?.User;
+ var currentUser = _auth.GetCurrentUser().User;
if (currentUser == null)
- return Unauthorized(new { Success = false, Message = "未登录" });
+ return BadRequest(ApiResponseDto>.Fail("未登录或登录过期"));
- var success = _workflowEngineApp.HandleWorkitem(userId, currentUser.Name, request);
- return Ok(new { Success = success, Message = success ? "处理成功" : "处理失败" });
+ var result = _workflowEngineApp.QueryMyUnfinished(currentUser.Id, pageQueryDto);
+
+ return Ok(ApiResponseDto>.Success(result, "未办结查询成功"));
}
catch (Exception ex)
{
- return BadRequest(new { Success = false, Message = ex.Message });
+ return StatusCode(500, ApiResponseDto>.Fail(ex.Message));
+ }
+ }
+
+ ///
+ /// 查询我的已完成(参与过/流程已归档事项)
+ ///
+ /// 分页查询参数
+ /// 分页已完成结果
+ [HttpGet]
+ public ActionResult>> QueryMyCompleted(
+ [FromQuery] PageQueryRequestDto pageQueryDto)
+ {
+ try
+ {
+ var currentUser = _auth.GetCurrentUser().User;
+ if (currentUser == null)
+ return BadRequest(ApiResponseDto>.Fail("未登录或登录过期"));
+
+ var result = _workflowEngineApp.QueryMyCompleted(currentUser.Id, pageQueryDto);
+
+ return Ok(ApiResponseDto>.Success(result, "已完成查询成功"));
+ }
+ catch (Exception ex)
+ {
+ return StatusCode(500, ApiResponseDto>.Fail(ex.Message));
+ }
+ }
+
+ ///
+ /// 查询我的全部事项(拟办+待办+已办+未办结+已完成)
+ ///
+ /// 分页查询参数
+ /// 分页全部事项结果
+ [HttpGet]
+ public ActionResult>> QueryMyAllItems(
+ [FromQuery] PageQueryRequestDto pageQueryDto)
+ {
+ try
+ {
+ var currentUser = _auth.GetCurrentUser().User;
+ if (currentUser == null)
+ return BadRequest(ApiResponseDto>.Fail("未登录或登录过期"));
+
+ var result = _workflowEngineApp.QueryMyAllItems(currentUser.Id, pageQueryDto);
+
+ return Ok(ApiResponseDto>.Success(result, "全部事项查询成功"));
+ }
+ catch (Exception ex)
+ {
+ return StatusCode(500, ApiResponseDto>.Fail(ex.Message));
}
}