فهرست منبع

添加步骤负责人模块
修正获取部门人员Bug

luocaiyang 3 سال پیش
والد
کامیت
34e3334401

+ 143 - 0
wispro.sp.api/Controllers/ConditinController.cs

@@ -0,0 +1,143 @@
+using Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.Mvc;
+using System;
+using System.Collections.Concurrent;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Linq;
+using System.Linq.Expressions;
+using System.Reflection;
+using System.Threading.Tasks;
+using wispro.sp.entity;
+using wispro.sp.entity.workflowDefine;
+using wispro.sp.share.Utility;
+
+namespace wispro.sp.api.Controllers
+{
+    [Route("api/[controller]")]
+    [ApiController]
+    public class ConditinController : ControllerBase
+    {
+        spDbContext Context;
+        public ConditinController(spDbContext context)
+        {
+            Context = context;
+        }
+
+        
+        
+        private List<Staff> GetStaffList(UserField userField,object dynBindObject,entity.workflowInstance.WorkflowInstance Instance)
+        {
+            switch (userField.UserConditionType)
+            {
+                case UserConditionType.Department:
+                    try
+                    {
+                        var deptId = int.Parse(userField.Department);
+                        return Context.Staffs.Where<Staff>(s =>
+                            (s.Positions.Where<DepartmentPosition>(p => p.departmentId == deptId).Count() > 0))
+                            .ToList<Staff>();
+                    }
+                    catch(Exception ex)
+                    {
+                        throw ex;
+                    }
+                    
+                    break;
+                case UserConditionType.DepartmentPosition:
+                    try {
+                        var deptId = int.Parse(userField.Department);
+                        var pId = int.Parse(userField.Positon);
+
+                        return Context.Staffs.Where<Staff>(s =>
+                            (s.Positions.Where<DepartmentPosition>(p => p.departmentId == deptId && p.PositionId == pId).Count() > 0))
+                            .ToList<Staff>();
+                    }
+                    catch (Exception ex)
+                    {
+                        throw new ApplicationException("没有找到指定的部门或职位");
+                    }
+                    break;
+                    
+                case UserConditionType.Staff:
+                    return new List<Staff>{ GetUser(userField, dynBindObject)};
+                    break;
+                case UserConditionType.UserDepartment:
+                    Staff temUser =  GetUser(userField, dynBindObject);
+
+                    if (temUser != null)
+                    {
+                        var temDeptPosition = Context.DepartmentPositions.Where<DepartmentPosition>(d =>
+                            d.departmentId == int.Parse(userField.Department)
+                            && d.StaffId == temUser.Id).FirstOrDefault();
+                        var temDeptId = temDeptPosition.departmentId;
+                        var retList = Context.DepartmentPositions.Where<DepartmentPosition>(dp => 
+                            dp.departmentId == temDeptId)
+                            .Select(s => s.Staff)
+                            .ToList();
+
+                        return retList;
+                    }
+                    else
+                    {
+                        throw new ApplicationException("指定的员工不存在");
+                    }
+                    break;
+                case UserConditionType.UserDepartmentPosition:
+                    Staff temUser1 = GetUser(userField, dynBindObject);
+
+                    if (temUser1 != null)
+                    {
+                        var temDeptPosition = Context.DepartmentPositions.Where<DepartmentPosition>(d =>
+                            d.departmentId == int.Parse(userField.Department)
+                            && d.StaffId == temUser1.Id).FirstOrDefault();
+                        var temDeptId = temDeptPosition.departmentId;
+                        var retList = Context.DepartmentPositions.Where<DepartmentPosition>(dp => 
+                            dp.departmentId == temDeptId && 
+                            dp.PositionId == int.Parse(userField.Positon))
+                            .Select(s => s.Staff)
+                            .ToList();
+
+                        return retList;
+                    }
+                    else
+                    {
+                        throw new ApplicationException("指定的员工不存在");
+                    }
+                    break;
+            }
+
+            return new List<Staff>();
+        }
+
+        private Staff GetUser(UserField userField, object dynBindObject)
+        {
+            Staff temUser = null;
+            switch (userField.UserType)
+            {
+                case UserType.BindObjectProperty:
+                    try
+                    {
+                        temUser = share.Utility.ObjectHelper.GetPropertyValue(userField.UserValue, dynBindObject) as Staff;
+
+                    }
+                    catch
+                    {
+                        throw new ApplicationException("指定的属性属性不是人员类型");
+                    }
+                    break;
+                case UserType.DoActionUser:
+
+                    break;
+                case UserType.LoginUser:
+                    temUser = Context.Staffs.Where<Staff>(s => s.Name == User.Identity.Name).FirstOrDefault();
+                    break;
+                case UserType.Staff:
+                    temUser = Context.Staffs.Where<Staff>(s => s.Id == int.Parse(userField.UserValue)).FirstOrDefault();
+                    break;
+            }
+
+            return temUser;
+        }
+    }
+}

+ 127 - 4
wispro.sp.api/Controllers/OrganizationController.cs

@@ -138,11 +138,11 @@ namespace wispro.sp.api.Controllers
             }
         }
 
+
         public List<Department> GetDepartments()
         {
             return Context.Departments.ToList();
         }
-
         
 
         public bool DeleteDept(int Id)
@@ -161,9 +161,19 @@ namespace wispro.sp.api.Controllers
 
         }
 
-        public List<Position> GetPositions()
+        public List<Position> GetPositions(int? deptId)
         {
-            return Context.Positions.ToList();
+            if (deptId == null)
+            {
+                return Context.Positions.ToList();
+            }
+            else
+            {
+                var retList = Context.DepartmentPositions
+                    .Where<DepartmentPosition>(p => p.departmentId == deptId)
+                    .Select(p => p.Position).Distinct<Position>().ToList();
+                return retList;
+            }
         }
 
         public Position GetPosition(int deptId,int staffId)
@@ -178,11 +188,124 @@ namespace wispro.sp.api.Controllers
                 return null;
             }
         }
+        #endregion
 
         public List<Customer> GetCustomers()
         {
             return Context.Customers.ToList();
         }
-        #endregion
+
+        public void InitUserDepartment()
+        {
+            Position ptPosition = Context.Positions.FirstOrDefault(s => s.Name == "普通员工");
+
+            if(ptPosition == null)
+            {
+                ptPosition = new Position() { Name = "普通员工" };
+                Context.Positions.Add(ptPosition);
+                Context.SaveChanges();
+            }
+            var lstStaff = Context.Staffs.ToList();
+
+            foreach(var sf in lstStaff)
+            {
+                if (!string.IsNullOrEmpty(sf.Department))
+                {
+                    string[] deptStrings = sf.Department.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
+
+                    if (deptStrings.Length > 0)
+                    {
+                        System.Text.RegularExpressions.Regex r = new System.Text.RegularExpressions.Regex("\\((.+?)\\)");
+                        System.Text.RegularExpressions.Match m = r.Match(deptStrings[0]);
+
+                        Department pDept;
+                        if (m.Success)
+                        {
+                            string firstName = deptStrings[0].Substring(0, m.Index).Trim();
+                            string secondName = m.Groups[1].Value.Trim();
+                            pDept = Context.Departments.First<Department>(s=>s.Name == firstName);
+                            if(pDept == null)
+                            {
+                                pDept = new Department() { Name = firstName };
+                                Context.Departments.Add(pDept);
+                                Context.SaveChanges();
+
+                                Department secondDept = Context.Departments.FirstOrDefault<Department>(d => d.parentId == pDept.Id && d.Name == secondName);
+                                if (secondDept == null)
+                                {
+                                    secondDept = new Department() { Name = secondName, parentId = pDept.Id, ancestors = pDept.Id.ToString() };
+                                    Context.Departments.Add(secondDept);
+                                    Context.SaveChanges();
+                                }
+
+                                pDept = secondDept;
+                            }
+                            else
+                            {
+                                Department secondDept = Context.Departments.FirstOrDefault<Department>(d => d.parentId == pDept.Id && d.Name == secondName);
+                                if (secondDept == null)
+                                {
+                                    secondDept = new Department() { Name = secondName, parentId = pDept.Id, ancestors = pDept.Id.ToString() };
+                                    Context.Departments.Add(secondDept);
+                                    Context.SaveChanges();
+                                }
+
+                                pDept = secondDept;
+                            }
+                        }
+                        else
+                        {
+                            pDept = Context.Departments.FirstOrDefault<Department>(s => s.Name == deptStrings[0].Trim());
+                            if (pDept == null)
+                            {
+                                pDept = new Department() { Name = deptStrings[0].Trim() };
+                                Context.Departments.Add(pDept);
+                                Context.SaveChanges();
+                            }
+                        }
+
+                        for(int i = 1; i < deptStrings.Length; i++)
+                        {
+                            Department curDept = Context.Departments.FirstOrDefault<Department>(d=>d.parentId == pDept.Id && d.Name == deptStrings[i].Trim());
+                            if(curDept == null)
+                            {
+                                curDept = new Department()
+                                {
+                                    Name = deptStrings[i].Trim(),
+                                    parentId = pDept.Id,
+                                    ancestors = (pDept.parentId == null) ? pDept.parentId.ToString() : $"{pDept.ancestors},{pDept.Id}"
+                                };
+
+                                Context.Departments.Add(curDept);
+                                Context.SaveChanges();
+
+                                
+                            }
+
+                            pDept = curDept;
+                        }
+
+                        if(pDept != null)
+                        {
+
+                            DepartmentPosition dp = Context.DepartmentPositions.FirstOrDefault(p => p.StaffId == sf.Id && p.departmentId == pDept.Id && p.PositionId == ptPosition.Id);
+                            if (dp == null)
+                            {
+
+                                dp = new DepartmentPosition();
+                                dp.StaffId = sf.Id;
+                                dp.departmentId = pDept.Id;
+                                dp.PositionId = ptPosition.Id;
+
+                                Context.DepartmentPositions.Add(dp);
+                                Context.SaveChanges();
+                            }
+                        }
+                        
+                    }
+                }
+            }
+        }
+        
     }
 }

+ 3 - 1
wispro.sp.api/Controllers/StaffController.cs

@@ -46,10 +46,12 @@ namespace wispro.sp.api.Controllers
         {
             ListApiResponse<Staff> ret = new ListApiResponse<Staff>();
             var dept = Context.Departments.FirstOrDefault<Department>(d=>d.Id == deptId);
+            string strancestors = $"{dept.ancestors},{deptId}";
 
             if (dept != null)
             {
-                var retList = Context.Staffs.Where<Staff>(s => s.Positions.Where<DepartmentPosition>(dp => dp.department.ancestors.StartsWith(dept.ancestors)).Count() > 0);
+                var retList = Context.Staffs.Where<Staff>(s => 
+                    s.Positions.Where<DepartmentPosition>(dp => dp.department.ancestors.StartsWith(strancestors) || dp.department.Id  == deptId).Count() > 0 );
                 ret.TotalCount = retList.Count();
                 ret.Results = retList.Skip<Staff>((pageIndex - 1) * pageSize).Take(pageSize).ToList();
             }

+ 157 - 1
wispro.sp.api/Controllers/WorkflowEngineController.cs

@@ -74,6 +74,162 @@ namespace wispro.sp.api.Controllers
             return ret;
         }
 
+        public ApiSaveResponse SaveStep(NewStepObject stepObj)
+        {
+            var ret = new ApiSaveResponse();
+            ret.Success = true;
+            
+            using (var t = Context.Database.BeginTransaction())
+            {
+                try
+                {
+                    var step = stepObj.Step;
+                    var wf = GetWorkflow(step.workflowId);
+
+                    if(wf == null)
+                    {
+                        throw new ApplicationException("步骤所属流程不存在!");
+                    }
+
+                    if (step.Id == 0)
+                    {
+                        Context.Steps.Add(step);
+                        Context.SaveChanges();
+
+                        if (stepObj.isLastStep)
+                        {
+                            wf.EndStepId = step.Id;
+                        }
+                    }
+                    else
+                    {
+                        var temStep = Context.Steps.FirstOrDefault(a => a.Id == step.Id);
+                        if (temStep != null)
+                        {
+                            if(temStep.workflowId != step.workflowId)
+                            {
+                                throw new ApplicationException("修改步骤时,不能修改步骤所属流程!");
+                            }
+
+                            temStep.Name = step.Name;
+                            temStep.stepType = step.stepType;
+                            temStep.defaultResponseSetting = step.defaultResponseSetting;
+
+                            if (stepObj.isLastStep)
+                            {
+                                wf.EndStepId = step.Id;
+                            }
+                        }
+                        else
+                        {
+                            throw new ApplicationException("Id不存在!");
+                        }
+                    }
+
+                    Context.SaveChanges();
+                    t.Commit();
+                }
+                catch(Exception ex)
+                {
+                    t.Rollback();
+                    ret.Success = false;
+                    ret.ErrorMessage = ex.Message;
+                }
+            }
+
+            return ret;
+        }
+
+        public ApiSaveResponse SaveAction(entity.workflowDefine.Action action)
+        {
+            var ret = new ApiSaveResponse();
+            ret.Success = true;
+            using (var t = Context.Database.BeginTransaction())
+            {
+                try
+                {
+
+                    if (action.Id == 0)
+                    {
+                        Context.Actions.Add(action);
+                    }
+                    else
+                    {
+                        var temAtion = Context.Actions.FirstOrDefault(a => a.Id == action.Id);
+                        if (temAtion != null)
+                        {
+                            temAtion.InputForm = action.InputForm;
+                            temAtion.Name = action.Name;
+                            temAtion.StepId = action.StepId;
+                            temAtion.inputValuesSettings = action.inputValuesSettings;
+                            temAtion.OnActionObjectType = action.OnActionObjectType;
+                        }
+                        else
+                        {
+                            throw new ApplicationException("Id不存在!");
+                        }
+
+                    }
+                    Context.SaveChanges();
+
+                    t.Commit();
+                }
+                catch (Exception ex)
+                {
+                    t.Rollback();
+                    ret.Success = false;
+                    ret.ErrorMessage = ex.Message;
+                }
+            }
+
+            return ret;
+        }
+
+        public ApiSaveResponse SaveTransfer(entity.workflowDefine.TrasferCondition trasfer)
+        {
+            var ret = new ApiSaveResponse();
+            ret.Success = true;
+
+            using (var t = Context.Database.BeginTransaction())
+            {
+                try
+                {
+                    
+                    
+
+                    if (trasfer.Id == 0)
+                    {
+                        Context.TrasferConditions.Add(trasfer);
+                    }
+                    else
+                    {
+                        var temTransfer = Context.TrasferConditions.FirstOrDefault(a => a.Id == trasfer.Id);
+                        if (temTransfer != null)
+                        {
+                            temTransfer.StepId  = trasfer.StepId;
+                            temTransfer.nextStepId = trasfer.nextStepId;
+                            temTransfer.Condition = trasfer.Condition;
+                        }
+                        else
+                        {
+                            throw new ApplicationException("Id不存在!");
+                        }
+                    }
+
+                    Context.SaveChanges();
+                    t.Commit();
+                }
+                catch (Exception ex)
+                {
+                    t.Rollback();
+                    ret.Success = false;
+                    ret.ErrorMessage = ex.Message;
+                }
+            }
+
+            return ret;
+        }
+
         public List<entity.workflowDefine.Workflow> GetAllWorkflows()
         {
             return Context.Workflows.Include(d => d.CreateUser).ToList();
@@ -92,7 +248,7 @@ namespace wispro.sp.api.Controllers
         public List<entity.workflowDefine.Action> GetActions(int workflowId)
         {
             var workflow = Context.Workflows.FirstOrDefault<entity.workflowDefine.Workflow>(w => w.Id == workflowId);
-            return Context.Actions.Where<entity.workflowDefine.Action>(d => d.step.workflowId == workflowId || d.Id == workflow.InitActionId).ToList();
+            return Context.Actions.Include(s=>s.step).Where<entity.workflowDefine.Action>(d => d.step.workflowId == workflowId || d.Id == workflow.InitActionId).ToList();
         }
 
         public List<entity.workflowDefine.TrasferCondition> GetTrasfers(int workflowId)

+ 15 - 0
wispro.sp.share/NewStepObject.cs

@@ -0,0 +1,15 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace wispro.sp.share
+{
+    public class NewStepObject
+    {
+        public entity.workflowDefine.Step Step { get; set; }
+
+        public bool isLastStep { get; set; }
+    }
+}

+ 41 - 0
wispro.sp.share/Utility/ObjectHelper.cs

@@ -0,0 +1,41 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Linq;
+using System.Reflection;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace wispro.sp.share.Utility
+{
+    public class ObjectHelper
+    {
+        public static dynamic GetPropertyValue(string propertyName, object obj)
+        {
+            Type type = obj.GetType();
+            PropertyInfo property = type.GetProperty(propertyName);
+
+            dynamic value = property.GetValue(obj);
+            return value;
+
+        }
+
+        public static string GetPropertyDescription(string propertyName, string bindObjectType)
+        {
+            Type type = Type.GetType(bindObjectType);
+            PropertyInfo property = type.GetProperty(propertyName);
+            DescriptionAttribute att =
+                property.GetCustomAttribute(typeof(DescriptionAttribute)) as DescriptionAttribute;
+
+            if (att == null)
+            {
+                return propertyName.ToString();
+            }
+            else
+            {
+                return att.Description;
+            }
+
+        }
+    }
+}

+ 107 - 0
wispro.sp.share/Utility/UserConditionHelper.cs

@@ -0,0 +1,107 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Linq;
+using System.Reflection;
+using System.Text;
+using System.Threading.Tasks;
+using wispro.sp.entity.workflowDefine;
+
+namespace wispro.sp.share.Utility
+{
+    public class UserConditionHelper
+    {
+        public static string UserFieldLabel(UserField userField, string bindObjectType)
+        {
+            switch (userField.UserConditionType)
+            {
+                case UserConditionType.Department:
+                    return $"部门:{userField.Department}";
+                    break;
+                case UserConditionType.DepartmentPosition:
+                    return $"[部门:{userField.Department}].[职位:{userField.Positon}]";
+                    break;
+                case UserConditionType.UserDepartment:
+                    switch (userField.UserType)
+                    {
+                        case UserType.BindObjectProperty:
+                            Type t = Type.GetType(bindObjectType);
+                            return $"{ObjectHelper.GetPropertyDescription(userField.UserValue, bindObjectType)}部门";
+                            break;
+                        case UserType.DoActionUser:
+                            return $"[{userField.UserValue}处理人部门]";
+                            break;
+                        case UserType.LoginUser:
+                            return $"[登录用户部门]";
+                            break;
+                        case UserType.Staff:
+                            return $"[{userField.UserValue}部门]";
+                            break;
+                    }
+                    break;
+                case UserConditionType.UserDepartmentPosition:
+                    switch (userField.UserType)
+                    {
+                        case UserType.BindObjectProperty:
+                            return $"[{ObjectHelper.GetPropertyDescription(userField.UserValue, bindObjectType)}部门职位:{userField.Positon}]";
+                            break;
+                        case UserType.DoActionUser:
+                            return $"[{userField.UserValue}处理人部门职位:{userField.Positon}]";
+                            break;
+                        case UserType.LoginUser:
+                            return $"[登录用户部门职位:{userField.Positon}]";
+                            break;
+                        case UserType.Staff:
+                            break;
+                    }
+                    break;
+                case UserConditionType.Staff:
+                    switch (userField.UserType)
+                    {
+                        case UserType.BindObjectProperty:
+                            return $"[{ObjectHelper.GetPropertyDescription(userField.UserValue, bindObjectType)}";
+                            break;
+                        case UserType.DoActionUser:
+                            return $"[{userField.UserValue}处理人].[部门].[职位:{userField.Positon}]";
+                            break;
+                        case UserType.LoginUser:
+                            return "登录用户";
+                            break;
+                        case UserType.Staff:
+                            return $"用户:{userField.UserValue}";
+                            break;
+                    }
+                    break;
+
+            }
+
+            return "";
+        }
+
+        public static Dictionary<string,string> GetPropertyDescription<T>(string stringType)
+        {
+            Dictionary<string, string> retDic = new Dictionary<string, string>();
+
+            Type type = Type.GetType(stringType); 
+            foreach(var property in type.GetProperties())
+            {
+                if(property.PropertyType == typeof(T))
+                {
+                    DescriptionAttribute att =
+                        property.GetCustomAttribute(typeof(DescriptionAttribute)) as DescriptionAttribute;
+
+                    if (att == null)
+                    {
+                        retDic.Add(property.Name, property.Name);
+                    }
+                    else
+                    {
+                        retDic.Add(att.Description, property.Name);
+                    }
+                }
+            }
+
+            return retDic;
+        }
+    }
+}

+ 12 - 4
wispro.sp.web/Components/FlowChart.razor

@@ -1,7 +1,7 @@
 
     @if (shapeTrees != null)
     {
-<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="@ChartWidth" height="@ChartHeight">
+<svg width="@ChartWidth" height="@ChartHeight" id="FlowChartContainer">
     <defs>
         <marker id="idArrow"
                 viewBox="0 0 20 20" refX="0" refY="10"
@@ -27,7 +27,7 @@
             if (node.Type == 0)
             {
                 <circle cx="@(node.x)" cy="@node.y" r="@(node.width / 2) " stroke="black" stroke-width="2" fill="@(node.FillColor)" />
-                <a @ondblclick="()=>ClickNode(node)">
+                <a>
                     <text x="@(node.x)" y="@node.y" fill="black" alignment-baseline="middle" text-anchor="middle" font-size="14">
                         @if (node == startNode)
                         {
@@ -54,7 +54,8 @@
             if (node.Type == 1)
             {
                 <rect x="@(node.x - node.width / 2)" y="@(node.y - node.height / 2)" rx="10" ry="10" width="@node.width" height="@node.height" style="fill:@(node.FillColor);stroke:black;stroke-width:3;opacity:0.5" />
-                <a @ondblclick="() => ClickNode(node)">
+
+                <a @ondblclick="() => DoubleClickNode(node)" @onclick="()=>ClickNode(node)">
                     <text x="@node.x" y="@node.y" fill="black" alignment-baseline="middle" text-anchor="middle" font-size="@rectFontSize" font-weight="700">
                         @if (node.NodeObject is entity.workflowDefine.Action)
                         {
@@ -66,6 +67,13 @@
                         }
                     </text>
                 </a>
+                @if (SelectedShape == node)
+                {
+                    <circle cx="@(node.x - node.width / 2)" cy="@(node.y)" r="3" stroke="black" stroke-width="1" fill="white" />
+                    <circle cx="@(node.x + node.width / 2)" cy="@(node.y)" r="3" stroke="black" stroke-width="1" fill="white" />
+                    <circle cx="@(node.x)" cy="@(node.y - node.height / 2)" r="3" stroke="black" stroke-width="1" fill="white" />
+                    <circle cx="@(node.x)" cy="@(node.y + node.height / 2)" r="3" stroke="black" stroke-width="1" fill="white" />
+                }
             }
         }
     }
@@ -76,7 +84,7 @@
         <line x1="@ret.x1" y1="@ret.y1" x2="@ret.x2" y2="@ret.y2" stroke="black" stroke-width="2" marker-end="url(#idArrow)" />
 
         <circle cx="@((ret.x1 + ret.x2) / 2)" cy="@((ret.y1 + ret.y2) / 2)" r="7" stroke="black" stroke-width="1.5" fill="white" />
-        <a @onclick="() => ClickTrasfer(t)">
+        <a @ondblclick="() => DoubleClickTrasfer(t)" @onclick ="()=>ClickTrasfer(t)">
             <text x="@((ret.x1 + ret.x2) / 2)" y="@((ret.y1 + ret.y2) / 2)" fill="black" alignment-baseline="middle" text-anchor="middle" font-size="12">c</text>
         </a>
 

+ 77 - 24
wispro.sp.web/Components/FlowChart.razor.cs

@@ -189,7 +189,7 @@ namespace wispro.sp.web.Components
             //shapeTrees.Add(endNode);
 
             #region 将步骤对象生成形状Node并添加到列表中
-            if (Steps == null || Steps.Count == 0 || Steps.FirstOrDefault(s => s.Id == workflow.EndStepId) == null)
+            if (Steps == null || Steps.Count == 0 || (Steps.FirstOrDefault(s => s.Id == workflow.EndStepId) == null ))
             {
                 InitShape.Childrens = new List<shapeNode>();
                 InitShape.Childrens.Add(endNode);
@@ -206,7 +206,7 @@ namespace wispro.sp.web.Components
                 {
                     var temNode = new shapeNode() { NodeObject = step, InCount = 0, OutCount = 0, Type = 1,FillColor = StepShapeColor };
 
-                    if (workflow.EndStepId == step.Id)
+                    if (workflow.EndStepId == step.Id && workflow.EndStepId>0)
                     {
                         temNode.Childrens = new List<shapeNode>();
                         temNode.Childrens.Add(endNode);
@@ -263,12 +263,13 @@ namespace wispro.sp.web.Components
                     }
                 }
 
-                endNode.Level = endNode.Parents[0].Level + 1;
+                if (endNode.Parents != null && endNode.Parents[0].NodeObject is entity.workflowDefine.Step)
+                {
+                    endNode.Level = endNode.Parents[0].Level + 1;
+                }
             }
             #endregion
 
-
-
             GetShapeLevelNodes(LevelNodes, shapeTrees);
 
             #region 添加跨层连接的中间层的虚拟节点
@@ -469,7 +470,6 @@ namespace wispro.sp.web.Components
             double y3 = 0.0;
             GetArrorEndPoint(ret, out x3, out y3);
 
-            Console.WriteLine($"x1:{ret.x1};y1:{ret.y1}\r\nx2:{ret.x2};y2:{ret.y2}\r\nx3:{x3};y3:{y3}\r\n");
             ret.x2 = x3;
             ret.y2 = y3;
 
@@ -509,7 +509,6 @@ namespace wispro.sp.web.Components
                 {
                     double k = (ret.y1 - ret.y2) / (ret.x1 - ret.x2);
                     double b = ret.y2 - k * ret.x2;
-                    Console.WriteLine($"k={k};b={b}");
 
                     double a = k * k + 1;
                     double B = 2 * k * (b - ret.y2) - 2 * ret.x2;
@@ -535,7 +534,11 @@ namespace wispro.sp.web.Components
 
         public dynamic GetEndStepLine()
         {
-            var startNode = endNode.Parents[0];
+            var startNode = InitShape;
+            if (endNode.Parents != null)
+            {
+                startNode = endNode.Parents[0];
+            }
             dynamic ret = new ExpandoObject();
             ret.x1 = startNode.x;
             ret.y1 = startNode.y + startNode.height / 2;
@@ -575,34 +578,25 @@ namespace wispro.sp.web.Components
 
         protected  override  void OnInitialized()
         {
-            initShapeTree();
+            Refresh();
         }
 
         public void Refresh()
         {
-            System.Text.Json.JsonSerializer.Serialize(Actions);
+            //System.Text.Json.JsonSerializer.Serialize(Actions);
             initShapeTree();
             StateHasChanged();
         }
 
-        void ClickStep(entity.workflowDefine.Step step)
-        {
-
-        }
-
-        void ClickTrasfer(entity.workflowDefine.TrasferCondition trasferCondition)
-        {
-            if (OnClickTransfer.HasDelegate)
-            {
-                OnClickTransfer.InvokeAsync(trasferCondition);
-            }
-        }
+        
+        
 
         void InitAction()
         {
 
         }
 
+        #region 单击/双击事件
         [Parameter]
         public EventCallback<entity.workflowDefine.Step> OnClickStep { get; set; }
 
@@ -612,9 +606,23 @@ namespace wispro.sp.web.Components
         [Parameter]
         public EventCallback<entity.workflowDefine.TrasferCondition> OnClickTransfer { get; set; }
 
+        [Parameter]
+        public EventCallback<entity.workflowDefine.Step> OnDoubleClickStep { get; set; }
+
+        [Parameter]
+        public EventCallback<entity.workflowDefine.Action> OnDoubleClickAction { get; set; }
+
+        [Parameter]
+        public EventCallback<entity.workflowDefine.TrasferCondition> OnDoubleClickTransfer { get; set; }
+
+        private shapeNode SelectedShape;
+
         void ClickNode(shapeNode node)
         {
-            if(node.NodeObject is entity.workflowDefine.Step)
+            SelectedShape = node;
+            StateHasChanged();
+
+            if (node.NodeObject is entity.workflowDefine.Step)
             {
                 if (OnClickStep.HasDelegate)
                 {
@@ -629,10 +637,55 @@ namespace wispro.sp.web.Components
                     OnClickAction.InvokeAsync((entity.workflowDefine.Action)node.NodeObject);
                 }
             }
+        }
+
+        void DoubleClickNode(shapeNode node)
+        {
+            SelectedShape = node;
+            StateHasChanged();
+            if (node.NodeObject is entity.workflowDefine.Step)
+            {
+                if (OnDoubleClickStep.HasDelegate)
+                {
+                    OnDoubleClickStep.InvokeAsync((entity.workflowDefine.Step)node.NodeObject);
+                }
+            }
+
+            if (node.NodeObject is entity.workflowDefine.Action)
+            {
+                if (OnDoubleClickAction.HasDelegate)
+                {
+                    OnDoubleClickAction.InvokeAsync((entity.workflowDefine.Action)node.NodeObject);
+                }
+            }
 
         }
 
-        
+        void ClickTrasfer(entity.workflowDefine.TrasferCondition trasferCondition)
+        {
+            SelectedShape = null;
+
+            if (OnClickTransfer.HasDelegate)
+            {
+                OnClickTransfer.InvokeAsync(trasferCondition);
+            }
+        }
+
+        void DoubleClickTrasfer(entity.workflowDefine.TrasferCondition trasferCondition)
+        {
+            SelectedShape = null;
+
+            if (OnDoubleClickTransfer.HasDelegate)
+            {
+                OnDoubleClickTransfer.InvokeAsync(trasferCondition);
+            }
+        }
+        #endregion
+
+        public string GetSvgString()
+        {
+            return null;
+        }
     }
 
 }

+ 2 - 2
wispro.sp.web/Components/PositionSelect.razor.cs

@@ -24,9 +24,9 @@ namespace wispro.sp.web.Components
 
         protected override async System.Threading.Tasks.Task OnInitializedAsync()
         {
-            base.OnInitialized();
+            base.OnInitializedAsync();
 
-            _allPositions = await _Service.getPositions();
+            _allPositions = await _Service.getPositions(null);
         }
 
         private void OnSelectedItemChangedHandler(Position value)

+ 85 - 0
wispro.sp.web/Components/ResponseManCondition.razor

@@ -0,0 +1,85 @@
+<Space>
+    <SpaceItem>
+        <Select DataSource="@uctItems"
+                @bind-Value="@UserField.UserConditionType"
+                ValueName="@nameof(UserConditionTpyeItem.Type)"
+                LabelName="@nameof(UserConditionTpyeItem.Description)"
+                OnSelectedItemChanged="OnUCTItemChangedHandler"
+                DefaultActiveFirstOption
+                Style="width: 160px;">
+        </Select>
+    </SpaceItem>
+    <SpaceItem>
+
+
+
+        @switch (UserField.UserConditionType)
+        {
+            case entity.workflowDefine.UserConditionType.Department:
+                <Cascader Options="@optoins" @bind-Value="UserField.Department" ExpandTrigger="hover" SelectedNodesChanged="OnDeptChange"></Cascader>
+                break;
+            case entity.workflowDefine.UserConditionType.DepartmentPosition:
+                <Space>
+                    <SpaceItem>
+                        <Cascader Options="@optoins" @bind-Value="UserField.Department" ExpandTrigger="hover" SelectedNodesChanged="OnDeptChange"></Cascader>
+                    </SpaceItem>
+                    <SpaceItem>
+                        @if (lstPosition != null)
+                        {
+                            <Select DataSource="@lstPosition"
+                                    @bind-Value="SelectPositionsId"
+                                    ValueName="@nameof(Position.Id)"
+                                    LabelName="@nameof(Position.Name)"
+                                    DefaultActiveFirstOption
+                                    OnSelectedItemChanged="OnPositionChangedHandler"
+                                    Style="width: 150px;">
+                            </Select>
+                        }
+                    </SpaceItem>
+                </Space>
+
+
+                break;
+            case entity.workflowDefine.UserConditionType.Staff:
+                <div style="width:200px;">
+                    <wispro.sp.web.Components.UserConditionInput Workflow="Workflow" UserType="@UserField.UserType" UserValue="@UserField.UserValue" />
+                </div>
+                break;
+            case entity.workflowDefine.UserConditionType.UserDepartment:
+                <Space>
+                    <SpaceItem>
+                        <div style="width:180px;"><wispro.sp.web.Components.UserConditionInput Workflow="Workflow" UserType="@UserField.UserType" UserValue="@UserField.UserValue" /></div>
+                    </SpaceItem>
+                    <SpaceItem>
+                        的部门
+                    </SpaceItem>
+                </Space>
+                break;
+            case entity.workflowDefine.UserConditionType.UserDepartmentPosition:
+                <Space>
+                    <SpaceItem>
+                        <div style="width:200px;">
+                            <wispro.sp.web.Components.UserConditionInput Workflow="Workflow" UserType="@UserField.UserType" UserValue="@UserField.UserValue" />
+                        </div>
+                    </SpaceItem>
+                    <SpaceItem>
+                        部门的
+                    </SpaceItem>
+                    <SpaceItem>
+                        @if (lstPosition != null)
+                        {
+                        <Select DataSource="@lstPosition"
+                                @bind-Value="SelectPositionsId"
+                                ValueName="@nameof(Position.Id)"
+                                LabelName="@nameof(Position.Name)"
+                                DefaultActiveFirstOption
+                                OnSelectedItemChanged="OnPositionChangedHandler"
+                                Style="width: 150px;">
+                        </Select>
+                        }
+                    </SpaceItem>
+                </Space>
+                break;
+        }
+    </SpaceItem>
+</Space>

+ 154 - 0
wispro.sp.web/Components/ResponseManCondition.razor.cs

@@ -0,0 +1,154 @@
+using AntDesign;
+using Microsoft.AspNetCore.Components;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+using wispro.sp.entity;
+using wispro.sp.entity.workflowDefine;
+using wispro.sp.web.Services;
+
+namespace wispro.sp.web.Components
+{
+    public partial class ResponseManCondition
+    {
+        
+        UserConditionType userConditionType;
+        
+        UserType _userType;
+
+        List<Department> departments;
+        List<Position> lstPosition;
+        int SelectPositionsId;
+
+        internal class UserConditionTpyeItem
+        {
+            public UserConditionType Type { get; set; }
+
+            public string Description
+            {
+                get
+                {
+                    return EnumHelper.GetDescription<UserConditionType>(Type);
+                }
+            }
+        }
+
+        List<UserConditionTpyeItem> uctItems = new List<UserConditionTpyeItem>();
+        List<CascaderNode> optoins = new List<CascaderNode>();
+
+        private List<CascaderNode> GetFromDepartment(List<Department> _departments)
+        {
+            List<CascaderNode> retList = new List<CascaderNode>();
+            foreach(var dept in _departments)
+            {
+                CascaderNode node = new CascaderNode() { Label = dept.Name, Value = dept.Id.ToString() };
+                retList.Add(node);
+            }
+
+            foreach(var dept in _departments)
+            {
+                if(dept.parentId != null)
+                {
+                    var parentNode = FindNode(dept.parentId.Value.ToString(),retList);
+                    var currentNode = FindNode(dept.Id.ToString(), retList);
+
+                    Console.WriteLine($"Find:{dept.parentId},return:{System.Text.Json.JsonSerializer.Serialize(parentNode)}");
+                    Console.WriteLine($"Find:{dept.Id},return:{System.Text.Json.JsonSerializer.Serialize(currentNode)}");
+
+                    if (parentNode != null)
+                    {
+                        if (parentNode.Children == null)
+                        {
+                            parentNode.Children = new List<CascaderNode>();
+                        }
+
+                        ((List<CascaderNode>)parentNode.Children).Add(currentNode);
+                        retList.Remove(currentNode);
+                    }
+
+                    
+
+                }
+                
+            }
+
+            return retList;
+        }
+
+        private CascaderNode FindNode(string deptId,List<CascaderNode> retList)
+        {
+            
+            foreach(var node in retList)
+            {
+                
+                if (node.Value == deptId)
+                {
+                    Console.WriteLine($"Founded:{System.Text.Json.JsonSerializer.Serialize(node)}");
+                    return node;
+                }
+                else
+                {
+                    if (node.Children != null)
+                    {
+                        var temNode = FindNode(deptId, (List<CascaderNode>)node.Children);
+                        if (temNode != null)
+                        {
+                            
+                            return temNode;
+                        }
+                    }
+                }
+                
+            }
+
+            
+            return null;
+        }
+
+        [Inject] OrganizationService _orgService { get; set; }
+
+        [Parameter]
+        public Workflow Workflow { get; set; }
+
+        [Parameter]
+        public UserField UserField { get; set; }
+
+        protected async override Task OnInitializedAsync()
+        {
+            departments =await  _orgService.GetDepartments();
+            lstPosition = await _orgService.getPositions(null);
+
+            optoins = GetFromDepartment(departments);
+
+            uctItems.Add(new UserConditionTpyeItem() { Type = UserConditionType.Department });
+            uctItems.Add(new UserConditionTpyeItem() { Type = UserConditionType.DepartmentPosition });
+            uctItems.Add(new UserConditionTpyeItem() { Type = UserConditionType.Staff });
+            uctItems.Add(new UserConditionTpyeItem() { Type = UserConditionType.UserDepartment });
+            uctItems.Add(new UserConditionTpyeItem() { Type = UserConditionType.UserDepartmentPosition });
+
+
+            await base.OnInitializedAsync();
+        }
+
+
+        private void OnUCTItemChangedHandler(UserConditionTpyeItem value)
+        {
+            userConditionType = value.Type;
+        }
+
+        private async Task OnDeptChange(CascaderNode[] selectedNodes)
+        {
+            int deptId = int.Parse(selectedNodes[0].Value);
+            if(userConditionType == UserConditionType.DepartmentPosition || userConditionType == UserConditionType.DepartmentPosition)
+            {
+                lstPosition =await _orgService.getPositions(deptId);
+            }
+        }
+
+        void OnPositionChangedHandler(Position position)
+        {
+            UserField.Positon = position.Id.ToString();
+        }
+    }
+}

+ 9 - 0
wispro.sp.web/Components/UserConditionInput.razor

@@ -0,0 +1,9 @@
+<Select DataSource="@UserItems"
+        @bind-Value="@_selectedValue"
+        ValueName="@nameof(UserItem.Value)"
+        LabelName="@nameof(UserItem.Label)"
+        GroupName="@nameof(UserItem.GroupName)"
+        OnSelectedItemChanged="OnSelectedItemChangedHandler"
+        EnableSearch
+        Style="width: 100%;">
+</Select>

+ 124 - 0
wispro.sp.web/Components/UserConditionInput.razor.cs

@@ -0,0 +1,124 @@
+using Microsoft.AspNetCore.Components;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+using wispro.sp.entity;
+using wispro.sp.entity.workflowDefine;
+using wispro.sp.web.Services;
+
+namespace wispro.sp.web.Components
+{
+    public partial class UserConditionInput
+    {
+        protected class UserItem
+        {
+            public UserType UserType { get; set; }
+
+            public string Label { get; set; }
+
+            public string Value { get; set; }
+
+            public string GroupName { get; set; }
+        }
+
+        List<UserItem> UserItems = new List<UserItem>();
+
+        UserItem SelectedUserItem;
+        string _selectedValue ;
+
+        [Parameter]
+        public Workflow Workflow { get; set; }
+
+        [Parameter]
+        public UserType UserType { get; set; }
+
+        [Parameter]
+        public string UserValue { get; set; }
+
+        [Parameter]
+        public EventCallback<UserType> UserTypeChanged { get; set; }
+
+        [Parameter]
+        public EventCallback<string> UserValueChanged { get; set; }
+
+
+
+        [Inject] public WorkflowService wfService { get; set; }
+
+        [Inject] IUserService _UserService { get; set; }
+
+        protected async override Task OnInitializedAsync()
+        {
+            UserItems = new List<UserItem>();
+            string temString = wfService.GetBindObjectName(Workflow.ContentObjectType);
+            var dic = share.Utility.UserConditionHelper.GetPropertyDescription<Staff>(Workflow.ContentObjectType);
+            foreach(string key in dic.Keys)
+            {
+                UserItems.Add(new UserItem()
+                {
+                    Value = dic[key].ToString(),
+                    Label = $"{temString}.{key}",
+                    UserType = UserType.BindObjectProperty,
+                    GroupName = temString //EnumHelper.GetDescription<UserType>(UserType.BindObjectProperty)
+                }) ;
+            }
+
+            var actions =await wfService.GetActions(Workflow.Id);
+            //Console.WriteLine(System.Text.Json.JsonSerializer.Serialize(actions));
+            foreach(var action in actions)
+            {
+                if (action.Id == Workflow.InitActionId)
+                {
+                    UserItems.Add(new UserItem()
+                    {
+                        Value = action.Id.ToString(),
+                        Label = $"流程创建人",
+                        UserType = UserType.DoActionUser,
+                        GroupName = EnumHelper.GetDescription<UserType>(UserType.DoActionUser)
+                    });
+                }
+                else
+                {
+                    UserItems.Add(new UserItem()
+                    {
+                        Value = action.Id.ToString(),
+                        Label = $"{action.step.Name}.{action.Name}处理人",
+                        UserType = UserType.DoActionUser,
+                        GroupName = EnumHelper.GetDescription<UserType>(UserType.DoActionUser)
+                    });
+                }
+            }
+
+            UserItems.Add(new UserItem()
+            {
+                Value = "",
+                Label = "登录用户",
+                UserType = UserType.LoginUser,
+                GroupName = EnumHelper.GetDescription<UserType>(UserType.LoginUser)
+            });
+
+            var Staffs =await  _UserService.GetAll();
+            //Console.WriteLine(System.Text.Json.JsonSerializer.Serialize(Staffs));
+            foreach (var sf in Staffs)
+            {
+                UserItems.Add(new UserItem()
+                {
+                    Value = sf.Id.ToString(),
+                    Label = sf.Name,
+                    UserType = UserType.Staff,
+                    GroupName = EnumHelper.GetDescription<UserType>(UserType.Staff)
+                });
+            }
+            
+        }
+
+        private void OnSelectedItemChangedHandler(UserItem value)
+        {
+            SelectedUserItem = value;
+            UserType = SelectedUserItem.UserType;
+            UserValue = SelectedUserItem.Value;
+            //Console.WriteLine($"selected: ${value?.Name}");
+        }
+    }
+}

+ 5 - 2
wispro.sp.web/Pages/Organization/Department.razor.cs

@@ -37,7 +37,7 @@ namespace wispro.sp.web.Pages.Organization
             _total = data.TotalCount;
 
             _StaffGrade = await orgService.GetStaffGrades();
-            _allPositions = await orgService.getPositions();
+            _allPositions = await orgService.getPositions(null);
             _loading = false;
         }
 
@@ -103,8 +103,10 @@ namespace wispro.sp.web.Pages.Organization
             _loading = true;
             var data = await orgService.GetStaffs(_editDepartment, 1, 1000);
             forecasts = data.Results;
+            _pageIndex = 1;
             _total = data.TotalCount;
             _loading = false;
+            StateHasChanged();
 
         }
 
@@ -172,7 +174,8 @@ namespace wispro.sp.web.Pages.Organization
                     break;
                 }
             }
-            return (pageIndex - 1) * pageSize + iIndex;
+
+            return  iIndex;
         }
 
         private async Task Edit(Staff staff)

+ 129 - 11
wispro.sp.web/Pages/Workflow/WorkflowDetail.razor

@@ -1,4 +1,4 @@
-@page "/Workflow/Detail/{WorkflowId}"
+@page "/Workflow/Detail/{WorkflowId:int}"
 
 <PageContainer>
     <Breadcrumb>
@@ -12,23 +12,141 @@
         </Breadcrumb>
     </Breadcrumb>
     <Content>
-        <Button Type="primary" Icon="plus" OnClick="AddNewStep" Style="float:right">添加新步骤</Button>
+        <Space>
+            <SpaceItem>
+                <Button Type="primary" Icon="plus" OnClick="AddNewStep" Style="float:right">添加步骤</Button>
+            </SpaceItem>
+
+            <SpaceItem>
+                <Button Type="primary" Icon="plus" OnClick="AddNewAction" Style="float:right">添加操作</Button>
+            </SpaceItem>
+
+            <SpaceItem>
+                <Button Type="primary" Icon="plus" OnClick="AddNewTransfer" Style="float:right">添加步骤转移条件</Button>
+            </SpaceItem>
+        </Space>
+        
     </Content>
     <ChildContent>
         @if (workflow == null)
         {
-            <Spin/>
+            <Spin />
         }
         else
         {
-        <div style="height:800px;width:100%;overflow:auto;background:#FFFFFF;">
-            <wispro.sp.web.Components.FlowChart @ref="chart" 
-                            workflow="@workflow" Actions="@Actions" 
-                            Transfers="@Transfers" Steps="@Steps" 
-                            OnClickAction="OnClickAction"
-                            OnClickStep="OnClickStep"
-                            OnClickTransfer="OnClickTransfer"/>
-        </div>
+            <div style="height:800px;width:100%;overflow:auto;background:#FFFFFF;">
+                <wispro.sp.web.Components.FlowChart @ref="chart"
+                                                    workflow="@workflow" Actions="@Actions"
+                                                    Transfers="@Transfers" Steps="@Steps"
+                                                    OnClickAction="OnClickAction"
+                                                    OnClickStep="OnClickStep"
+                                                    OnClickTransfer="OnClickTransfer" 
+                                                    OnDoubleClickStep="OnDblClickStep"/>
+            </div>
         }
     </ChildContent>
 </PageContainer>
+
+<Modal Title="步骤"
+       Visible="@StepModalShow"
+       OnOk="@EditStepOK"
+       OnCancel="@EditStepCancel"
+       OkText="@("保存")"
+       CancelText="@("取消")"
+       Width="1000"
+       MaskClosable="false">
+
+    <Form Model="EditStep" LabelColSpan="6"
+          WrapperColSpan="16">
+        <FormItem Label="步骤名称">
+            <Input @bind-Value="context.Step.Name" />
+        </FormItem>
+        <FormItem Label="责任人">
+            <wispro.sp.web.Components.ResponseManCondition Workflow="workflow" UserField="userField"/>
+        </FormItem>
+
+        <FormItem Label="最后步骤">
+            <Checkbox @bind-Value="context.isLastStep" />
+        </FormItem>
+    </Form>
+
+</Modal>
+
+<Modal Title="步骤操作"
+       Visible="@ActionModalShow"
+       OnOk="@EditActionOK"
+       OnCancel="@EditActionCancel"
+       OkText="@("保存")"
+       CancelText="@("取消")"
+       Width="1000" MaskClosable="false">
+
+    <Form Model="EditAction" LabelColSpan="6"
+          WrapperColSpan="16">
+        <FormItem Label="所属步骤">
+            <Select DataSource="@Steps"
+                DefaultValue="@EditAction.StepId"
+                @bind-Value="@EditAction.StepId"
+                LabelName="@nameof(wispro.sp.entity.workflowDefine.Step.Name)"
+                ValueName="@nameof(wispro.sp.entity.workflowDefine.Step.Id)"
+                Style="width: 200px"
+                Placeholder="请选择"
+                IgnoreItemChanges="false"
+                EnableSearch="true"
+                AllowClear>
+        </Select>
+        </FormItem>
+        <FormItem Label="初始化操作名称">
+            <Input @bind-Value="@EditAction.Name" />
+        </FormItem>
+        <FormItem Label="初始化界面">
+            <Input @bind-Value="@EditAction.InputForm" />
+        </FormItem>
+        <wispro.sp.web.Components.InputValueSetting DataSource="@EditAction.inputValuesSettings" />
+    </Form>
+
+</Modal>
+
+<Modal Title="步骤转移条件"
+       Visible="@TransferModalShow"
+       OnOk="@EditTransferOK"
+       OnCancel="@EditTransferCancel"
+       OkText="@("保存")"
+       CancelText="@("取消")"
+       Width="1000" MaskClosable="false">
+
+    <Form Model="EditTransfer" LabelColSpan="6"
+          WrapperColSpan="16">
+        <FormItem Label="从步骤">
+            <Select DataSource="@Steps"
+                    DefaultValue="@(EditTransfer.StepId.HasValue?EditTransfer.StepId.Value:0)"
+                    @bind-Value="@EditTransfer.StepId"
+                    LabelName="@nameof(wispro.sp.entity.workflowDefine.Step.Name)"
+                    ValueName="@nameof(wispro.sp.entity.workflowDefine.Step.Id)"
+                    Style="width: 200px"
+                    Placeholder="@workflow.InitAction.Name"
+                    EnableSearch="true"
+                    AllowClear>
+            </Select>
+        </FormItem>
+
+        <FormItem Label="到步骤">
+            <Select DataSource="@Steps"
+                    DefaultValue="@EditTransfer.nextStepId"
+                    @bind-Value="@EditTransfer.nextStepId"
+                    LabelName="@nameof(wispro.sp.entity.workflowDefine.Step.Name)"
+                    ValueName="@nameof(wispro.sp.entity.workflowDefine.Step.Id)"
+                    Style="width: 200px"
+                    Placeholder="请选择"
+                    EnableSearch="true"
+                    AllowClear>
+            </Select>
+        </FormItem>
+        <FormItem Label="条件">
+            <Input @bind-Value="@EditTransfer.Condition" />
+        </FormItem>
+
+        
+    </Form>
+
+</Modal>
+

+ 142 - 17
wispro.sp.web/Pages/Workflow/WorkflowDetail.razor.cs

@@ -4,6 +4,7 @@ using System;
 using System.Collections.Generic;
 using System.Linq;
 using System.Threading.Tasks;
+using wispro.sp.entity.workflowDefine;
 using wispro.sp.web.Services;
 
 namespace wispro.sp.web.Pages.Workflow
@@ -17,8 +18,11 @@ namespace wispro.sp.web.Pages.Workflow
         List<entity.workflowDefine.Action> Actions;
         List<entity.workflowDefine.TrasferCondition> Transfers;
 
+
+        UserField userField = new UserField();
+
         [Parameter]
-        public string WorkflowId { get; set; }
+        public int WorkflowId { get; set; }
         
         [Inject] protected MessageService _msgService { get; set; }
 
@@ -26,11 +30,11 @@ namespace wispro.sp.web.Pages.Workflow
 
         async Task InitData()
         {
-            int Id = int.Parse(WorkflowId.ToString());
-            workflow = await _wfService.GetWorkflow(Id);
-            Steps = await _wfService.GetSteps(Id);
-            Actions = await _wfService.GetActions(Id);
-            Transfers = await _wfService.GetTransfers(Id);
+            //int Id = int.Parse(WorkflowId.ToString());
+            workflow = await _wfService.GetWorkflow(WorkflowId);
+            Steps = await _wfService.GetSteps(WorkflowId);
+            Actions = await _wfService.GetActions(WorkflowId);
+            Transfers = await _wfService.GetTransfers(WorkflowId);
         }
         
         protected async override Task OnInitializedAsync()
@@ -100,29 +104,150 @@ namespace wispro.sp.web.Pages.Workflow
             #endregion
         }
 
-        void AddNewStep()
-        {
-            var newStep = new entity.workflowDefine.Step();
-            newStep.Name = "新步骤";
-            newStep.workflowId = workflow.Id;
-            Steps.Add(newStep);
+        
 
-            chart.Refresh();
+        void OnClickStep(entity.workflowDefine.Step step)
+        {
+            //_msgService.Info($"您点击了:【{step.Name}】步骤");
         }
 
-        void OnClickStep(entity.workflowDefine.Step step)
+        void OnDblClickStep(entity.workflowDefine.Step step)
         {
-            _msgService.Info($"您点击了:【{step.Name}】步骤");
+            bool b = (workflow.EndStepId != null && workflow.EndStepId.Value == step.Id);
+            EditStep = new share.NewStepObject() { Step = step, isLastStep = b };
+            try
+            {
+                userField = System.Text.Json.JsonSerializer.Deserialize<UserField>(step.defaultResponseSetting);
+            }
+            catch {
+                userField = new UserField();
+            }
+            //Console.WriteLine(System.Text.Json.JsonSerializer.Serialize(EditStep));
+            StepModalShow = true;
+
         }
 
         void OnClickAction(entity.workflowDefine.Action action)
         {
-            _msgService.Info($"您点击了:【{action.Name}】操作");
+            //_msgService.Info($"您点击了:【{action.Name}】操作");
         }
 
         void OnClickTransfer(entity.workflowDefine.TrasferCondition transfer)
         {
-            _msgService.Info($"您点击了:从步骤【{transfer.StepId}】到步骤【{transfer.nextStepId}】的移转条件!");
+            //_msgService.Info($"您点击了:从步骤【{transfer.StepId}】到步骤【{transfer.nextStepId}】的移转条件!");
+        }
+
+        share.NewStepObject EditStep;
+         
+        entity.workflowDefine.Action EditAction;
+        entity.workflowDefine.TrasferCondition EditTransfer;
+
+        bool StepModalShow = false;
+        bool ActionModalShow = false;
+        bool TransferModalShow = false;
+        
+        void AddNewStep()
+        {
+            EditStep = new share.NewStepObject();
+            EditStep.Step = new entity.workflowDefine.Step() { Name = "新步骤", stepType = 2, workflowId = workflow.Id };
+            EditStep.isLastStep = false;
+            userField = new UserField();
+
+            StepModalShow = true;
+        }
+
+        void AddNewAction()
+        {
+            EditAction = new entity.workflowDefine.Action();
+            EditAction.Name = "新操作";
+            EditAction.inputValuesSettings = new List<entity.workflowDefine.InputValueSetting>();
+
+            ActionModalShow = true;
+        }
+
+        void AddNewTransfer()
+        {
+            EditTransfer = new entity.workflowDefine.TrasferCondition();
+            
+            TransferModalShow = true;
+        }
+        async Task EditStepOK()
+        {
+            Console.WriteLine(System.Text.Json.JsonSerializer.Serialize(userField));
+            EditStep.Step.defaultResponseSetting = System.Text.Json.JsonSerializer.Serialize(userField);
+            var ret = await _wfService.SaveStep(EditStep);
+            if (ret.Success)
+            {
+                StepModalShow = false;
+                await InitData();
+                chart.Refresh();
+                StateHasChanged();
+                
+            }
+            else
+            {
+                await _msgService.Error("保存出现错误!");
+            }
         }
+
+        void EditStepCancel()
+        {
+            StepModalShow = false;
+        }
+
+        async Task EditActionOK()
+        {
+            var ret =await _wfService.SaveAction(EditAction);
+            if (ret.Success)
+            {
+                ActionModalShow = false;
+                await InitData();
+                chart.Refresh();
+                StateHasChanged();
+                
+            }
+            else
+            {
+                await _msgService.Error("保存出现错误!");
+            }
+        }
+
+        void EditActionCancel()
+        {
+            ActionModalShow = false;
+        }
+
+        int EditTransferStepId = 0;
+        async Task EditTransferOK()
+        {
+            
+            Console.WriteLine(System.Text.Json.JsonSerializer.Serialize(EditTransfer));
+
+            if(EditTransfer.StepId!= null && EditTransfer.StepId.Value == 0)
+            {
+                EditTransfer.StepId = null;
+            }
+
+            var ret = await _wfService.SaveTransfer(EditTransfer);
+
+            if (ret.Success)
+            {
+                TransferModalShow = false;
+                await InitData();
+                chart.Refresh();
+                StateHasChanged();
+                
+            }
+            else {
+               await _msgService.Error("保存出现错误!");
+            }
+        }
+
+        void EditTransferCancel()
+        {
+            TransferModalShow = false;
+        }
+
+
     }
 }

+ 2 - 2
wispro.sp.web/Services/OrganizationService.cs

@@ -31,9 +31,9 @@ namespace wispro.sp.web.Services
             return data;
         }
 
-        public async Task<List<Position>> getPositions()
+        public async Task<List<Position>> getPositions(int? deptId)
         {
-            var ret = await _httpClient.Get<List<Position>>($"Organization/GetPositions");
+            var ret = await _httpClient.Get<List<Position>>($"Organization/GetPositions?deptId={deptId}");
             return ret;
         }
 

+ 21 - 2
wispro.sp.web/Services/WorkflowService.cs

@@ -18,8 +18,8 @@ namespace wispro.sp.web.Services
 
         private List<BindObjectType> bindObjectTypes = new List<BindObjectType>()
         {
-            new BindObjectType(){ Name ="绩效记录",ObjectTypeFullName = typeof(wispro.sp.entity.PerformanceItem).FullName},
-                new BindObjectType(){ Name ="人员",ObjectTypeFullName = typeof(wispro.sp.entity.Staff).FullName}
+            new BindObjectType(){ Name ="绩效记录",ObjectTypeFullName = typeof(wispro.sp.entity.PerformanceItem).AssemblyQualifiedName },
+                new BindObjectType(){ Name ="人员",ObjectTypeFullName = typeof(wispro.sp.entity.Staff).AssemblyQualifiedName}
         };
 
         public List<BindObjectType> GetBindObjects()
@@ -40,6 +40,7 @@ namespace wispro.sp.web.Services
                 return "";
             }
         }
+        
 
         List<entity.workflowDefine.Workflow> Workflows = new List<Workflow>();
         Dictionary<int, List<entity.workflowDefine.InputValueSetting>> InitInputValues = new Dictionary<int, List<InputValueSetting>>();
@@ -88,5 +89,23 @@ namespace wispro.sp.web.Services
             var ret = await _httpClient.Get<List<entity.workflowDefine.TrasferCondition>>($"WorkflowEngine/GetTrasfers?workflowId={workflowId}");
             return ret;
         }
+
+        public async Task<ApiSaveResponse> SaveStep(NewStepObject editStep)
+        {
+            var ret = await _httpClient.Post<ApiSaveResponse>("WorkflowEngine/SaveStep", editStep);
+            return ret;
+        }
+
+        public async Task<ApiSaveResponse> SaveAction(entity.workflowDefine.Action editAction)
+        {
+            var ret = await _httpClient.Post<ApiSaveResponse>("WorkflowEngine/SaveAction", editAction);
+            return ret;
+        }
+
+        public async Task<ApiSaveResponse> SaveTransfer(entity.workflowDefine.TrasferCondition  trasfer)
+        {
+            var ret = await _httpClient.Post<ApiSaveResponse>("WorkflowEngine/SaveTransfer", trasfer);
+            return ret;
+        }
     }
 }

+ 1 - 0
wispro.sp.web/wispro.sp.web.csproj

@@ -25,6 +25,7 @@
   </ItemGroup>
 
   <ItemGroup>
+    <PackageReference Include="AntDesign" Version="0.10.2" />
     <PackageReference Include="AntDesign.Charts" Version="0.2.1" />
     <PackageReference Include="AntDesign.ProLayout" Version="0.1.8" />
     <PackageReference Include="Blazor.ContextMenu" Version="1.10.1" />

+ 19 - 17
wispro.sp.winClient/Form1.cs

@@ -180,16 +180,18 @@ namespace wispro.sp.winClient
 
         private async void button3_Click(object sender, EventArgs e)
         {
+            share.Utility.UserConditionHelper.GetPropertyDescription<Staff>(typeof(PerformanceItem).AssemblyQualifiedName);
+
             #region Demo流程数据
-            entity.workflowDefine.Workflow workflow = new entity.workflowDefine.Workflow();
-            workflow.Name = "专案绩效流程";
-            workflow.Id = 1;
-            workflow.EndStepId = -1;
+            //entity.workflowDefine.Workflow workflow = new entity.workflowDefine.Workflow();
+            //workflow.Name = "专案绩效流程";
+            //workflow.Id = 1;
+            //workflow.EndStepId = -1;
 
-            workflow.InitAction = new entity.workflowDefine.Action();
-            workflow.InitAction.Name = "填写请教条";
+            //workflow.InitAction = new entity.workflowDefine.Action();
+            //workflow.InitAction.Name = "填写请教条";
 
-            List<entity.workflowDefine.Step> Steps = new List<entity.workflowDefine.Step>();
+            //List<entity.workflowDefine.Step> Steps = new List<entity.workflowDefine.Step>();
             //var step1 = new entity.workflowDefine.Step();
             //step1.Name = "部门主管申核";
             //step1.Id = 1;
@@ -218,7 +220,7 @@ namespace wispro.sp.winClient
 
             //workflow.EndStepId = 3;
 
-            List<entity.workflowDefine.TrasferCondition> Transfers = new List<entity.workflowDefine.TrasferCondition>();
+            //List<entity.workflowDefine.TrasferCondition> Transfers = new List<entity.workflowDefine.TrasferCondition>();
             //var t = new entity.workflowDefine.TrasferCondition();
             //t.StepId = null;
             //t.nextStepId = 1;
@@ -239,17 +241,17 @@ namespace wispro.sp.winClient
             //t3.nextStepId = 3;
             //Transfers.Add(t3);
             #endregion
-            FlowChart flowChart = new FlowChart();
-            flowChart.workflow = workflow;
-            flowChart.Steps = Steps;
-            flowChart.Transfers = Transfers;
+            //FlowChart flowChart = new FlowChart();
+            //flowChart.workflow = workflow;
+            //flowChart.Steps = Steps;
+            //flowChart.Transfers = Transfers;
 
-            var newStep = new entity.workflowDefine.Step();
-            newStep.Name = "新步骤";
-            newStep.workflowId = workflow.Id;
-            Steps.Add(newStep);
+            //var newStep = new entity.workflowDefine.Step();
+            //newStep.Name = "新步骤";
+            //newStep.workflowId = workflow.Id;
+            //Steps.Add(newStep);
 
-            flowChart.Refresh();
+            //flowChart.Refresh();
 
             //flowChart.Refresh();
 

+ 2 - 0
wospro.sp.entity/ItemStaff.cs

@@ -1,5 +1,6 @@
 using System;
 using System.Collections.Generic;
+using System.ComponentModel;
 using System.Linq;
 using System.Text;
 using System.Text.Json.Serialization;
@@ -23,6 +24,7 @@ namespace wispro.sp.entity
         /// <summary>
         /// 处理人
         /// </summary>
+        [Description("处理人")]
         public virtual Staff DoPerson { get; set; }
 
         [JsonIgnore]

+ 3 - 0
wospro.sp.entity/PerformanceItem.cs

@@ -1,5 +1,6 @@
 using System;
 using System.Collections.Generic;
+using System.ComponentModel;
 using System.ComponentModel.DataAnnotations.Schema;
 using System.Linq;
 using System.Text;
@@ -187,6 +188,7 @@ namespace wispro.sp.entity
         /// <summary>
         /// 前一次OA处理人
         /// </summary>
+        [Description("前一次OA处理人")]
         public virtual Staff PreOastaff { get; set; }
 
         public virtual ICollection<ItemStaff> ItemStaffs { get; set; }
@@ -194,6 +196,7 @@ namespace wispro.sp.entity
         /// <summary>
         /// 核稿人
         /// </summary>
+        [Description("核稿人")]
         public virtual Staff Reviewer { get; set; }
 
         public virtual CalMonth CalMonth { get; set; }

+ 60 - 9
wospro.sp.entity/workflowDefine/ConditionTree.cs

@@ -81,23 +81,35 @@ namespace wispro.sp.entity.workflowDefine
         DoAction,
         [Description("绑定对象属性值")]
         BindObjectProperty,
-        [Description("操作用户")]
+        [Description("流程操作用户")]
         DoActionUser
 
     }
 
-    public enum UserType
+    public enum UserConditionType 
     {
-        [Description("指定用户")]
+        [Description("指定个人")]
         Staff,
         [Description("指定部门")]
         Department,
         [Description("指定部门职位")]
         DepartmentPosition,
-        [Description("指定操作处理人")]
-        DoActionUser,
-        [Description("绑定对象包含人员")]
-        BindObjectProperty
+        [Description("指定用户部门")]
+        UserDepartment,
+        [Description("指定用户部门职位")]
+        UserDepartmentPosition
+    }
+
+    public enum UserType
+    {
+        [Description("指定用户")]
+        Staff,
+        [Description("登录用户")]
+        LoginUser,
+        [Description("流程对象人员属性")]
+        BindObjectProperty,
+        [Description("操作处理人")]
+        DoActionUser
     }
     #endregion
 
@@ -134,11 +146,50 @@ namespace wispro.sp.entity.workflowDefine
         public FieldType FieldType { get; set; }
     }
 
+    public class UserFieldNode : ConditionTreeNode
+    {
+        public UserField Field { get; set; }
+
+        /// <summary>
+        /// 比较符号
+        /// </summary>
+        public ComparisonSymbol Operator { get; set; }
+
+        /// <summary>
+        /// 值
+        /// </summary>
+        public string Value { get; set; }
+    }
+
     
-    public class UserCondition
+    public class UserField
     {
+        /// <summary>
+        /// 用户条件类型
+        /// </summary>
+        public UserConditionType UserConditionType { get; set; }
+
+        /// <summary>
+        /// 指定用户类型
+        /// </summary>
         public UserType UserType { get; set; }
 
-        public string Value { get; set; }
+        /// <summary>
+        /// 指定用户值
+        /// </summary>
+        public string UserValue { get; set; }
+
+        /// <summary>
+        /// 指定部门值
+        /// </summary>
+        public string Department { get; set; }
+
+        /// <summary>
+        /// 指定职位值
+        /// </summary>
+        public string Positon { get; set; }
+
+        
+        
     }
 }

+ 1 - 1
wospro.sp.entity/workflowDefine/workflow.cs

@@ -39,7 +39,7 @@ namespace wispro.sp.entity.workflowDefine
         /// 每个流程都有一个结束步骤,结束步骤只是一个标志,
         /// 不能做任何操作
         /// </summary>
-        public int EndStepId { get; set; }
+        public int? EndStepId { get; set; }
 
         /// <summary>
         /// 创建日期