Prechádzať zdrojové kódy

Merge branch 'master' into tangj-knowledge

TANG JIANG 2 rokov pred
rodič
commit
0e0ad68275

+ 56 - 0
src/Hotline.Api/Controllers/CommonPController.cs

@@ -0,0 +1,56 @@
+using Hotline.Orders;
+using Hotline.Settings;
+using Hotline.Share.Dtos.Order;
+using MapsterMapper;
+using Microsoft.AspNetCore.Mvc;
+using MongoDB.Driver;
+
+namespace Hotline.Api.Controllers
+{
+    public class CommonPController: BaseController
+    {
+        private readonly ICommonOpinionDomainService _commonOpinionDomainService;
+        private readonly IMapper _mapper;
+
+        public CommonPController(ICommonOpinionDomainService commonOpinionDomainService,IMapper mapper)
+        {
+            _commonOpinionDomainService = commonOpinionDomainService;
+            _mapper = mapper;
+        }
+
+        /// <summary>
+        /// 获取常用意见
+        /// </summary>
+        /// <returns></returns>
+        [HttpGet("common-list")]
+        public async Task<IReadOnlyList<CommonOpinion>> GetCommon(string typecode)
+        {
+            return await _commonOpinionDomainService.GetCommonOpinions(typecode);
+        }
+
+        /// <summary>
+        /// 新增常用意见
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        [HttpPost("add-common")]
+        public async Task AddCommon([FromBody]AddCommonDto dto)
+        {
+            var entity = _mapper.Map<CommonOpinion>(dto);
+            await _commonOpinionDomainService.AddCommonOpinion(entity,HttpContext.RequestAborted);
+        }
+
+        /// <summary>
+        /// 批量删除常用意见
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        [HttpPost("del-common")]
+        public async Task DelCommon([FromBody]DelCommonDto dto)
+        {
+            await _commonOpinionDomainService.DelCommonOpinion(dto.Ids, HttpContext.RequestAborted);
+        }
+
+
+    }
+}

+ 16 - 5
src/Hotline.Api/Controllers/OrderController.cs

@@ -59,7 +59,7 @@ public class OrderController : BaseController
         var (total, items) = await _orderRepository.Queryable()
             //.Includes(d => d.Employee)
             //.Includes(d => d.Workflow, d => d.Assigns)
-            .Where(d => d.Workflows.Any(x => x.ModuleCode == WorkflowModuleConsts.Order))
+            .Where(d => d.Workflows.Any(x => x.ModuleCode == WorkflowModuleConsts.OrderManage))
             .WhereIF(!string.IsNullOrEmpty(dto.Keyword), d => d.Title.Contains(dto.Keyword) || d.No.Contains(dto.Keyword))
             .WhereIF(!string.IsNullOrEmpty(dto.Content), d => d.Content.Contains(dto.Content))
             .WhereIF(dto.AcceptType.HasValue, d => d.AcceptType == dto.AcceptType)
@@ -101,7 +101,7 @@ public class OrderController : BaseController
             .Includes(d => d.OrderComplain)
             .Includes(d => d.OrderReport)
             .FirstAsync(d => d.Id == id);
-        var workflow = await _workflowDomainService.GetWorkflowAsync(WorkflowModuleConsts.Order, order.Id,
+        var workflow = await _workflowDomainService.GetWorkflowAsync(WorkflowModuleConsts.OrderManage, order.Id,
             withSupplements: true, cancellationToken: HttpContext.RequestAborted);
         order.Workflows = new List<Workflow> { workflow };
 
@@ -148,14 +148,26 @@ public class OrderController : BaseController
     /// <param name="dto">流程开启参数</param>
     /// <returns></returns>
     [HttpPost("{id}/startflow")]
-    public async Task StartFlow(string id, [FromBody] StartWorkflowDto dto)
+    public async Task<string> StartFlow(string id, [FromBody] StartWorkflowDto dto)
     {
         var order = await _orderRepository.GetAsync(id, HttpContext.RequestAborted);
         if (order == null)
             throw UserFriendlyException.SameMessage("无效工单编号");
         if (order.Status != EOrderStatus.Temporary)
             throw UserFriendlyException.SameMessage("工单已发起流程");
-        await _workflowApplication.StartWorkflowAsync(dto, order.Id, HttpContext.RequestAborted);
+        return await _workflowApplication.StartWorkflowAsync(dto, order.Id, HttpContext.RequestAborted);
+    }
+
+    /// <summary>
+    /// 查询工单办理流程编号
+    /// </summary>
+    /// <param name="id"></param>
+    /// <returns></returns>
+    [HttpGet("flowId-manage")]
+    public async Task<string> GetWorkflowId(string id)
+    {
+        var workflow = await _workflowDomainService.GetWorkflowAsync(WorkflowModuleConsts.OrderManage, id, cancellationToken: HttpContext.RequestAborted);
+        return workflow?.Id;
     }
 
     /// <summary>
@@ -228,5 +240,4 @@ public class OrderController : BaseController
     {
         return await _hotSpotTypeRepository.Queryable().Where(x => x.ParentId == parentId).ToListAsync();
     }
-
 }

+ 6 - 55
src/Hotline.Api/Controllers/WorkflowController.cs

@@ -1,4 +1,5 @@
-using Hotline.FlowEngine.Definitions;
+using Hotline.Application.FlowEngine;
+using Hotline.FlowEngine.Definitions;
 using Hotline.FlowEngine.Workflows;
 using Hotline.Identity.Roles;
 using Hotline.Repository.SqlSugar.Extensions;
@@ -25,6 +26,7 @@ public class WorkflowController : BaseController
 {
     private readonly IDefinitionDomainService _definitionDomainService;
     private readonly IDefinitionRepository _definitionRepository;
+    private readonly IWorkflowApplication _workflowApplication;
     private readonly IWorkflowDomainService _workflowDomainService;
     private readonly IWorkflowRepository _workflowRepository;
     private readonly IUserRepository _userRepository;
@@ -37,6 +39,7 @@ public class WorkflowController : BaseController
     public WorkflowController(
         IDefinitionDomainService definitionDomainService,
         IDefinitionRepository definitionRepository,
+        IWorkflowApplication workflowApplication,
         IWorkflowDomainService workflowDomainService,
         IWorkflowRepository workflowRepository,
         IUserRepository userRepository,
@@ -48,6 +51,7 @@ public class WorkflowController : BaseController
     {
         _definitionDomainService = definitionDomainService;
         _definitionRepository = definitionRepository;
+        _workflowApplication = workflowApplication;
         _workflowDomainService = workflowDomainService;
         _workflowRepository = workflowRepository;
         _userRepository = userRepository;
@@ -237,60 +241,7 @@ public class WorkflowController : BaseController
     public async Task<IReadOnlyList<NextStepOptions>> GetNextStepOptions(string workflowId)
     {
         var workflow = await _workflowDomainService.GetWorkflowAsync(workflowId, true, true, cancellationToken: HttpContext.RequestAborted);
-        var nextStepDefines = _workflowDomainService.GetNextStepOptions(workflow, HttpContext.RequestAborted);
-
-        //todo 性能问题
-        var items = new List<NextStepOptions>();
-        foreach (var nextStepDefine in nextStepDefines)
-        {
-            var options = new NextStepOptions
-            {
-                Code = nextStepDefine.Code,
-                Name = nextStepDefine.Name,
-            };
-
-            switch (nextStepDefine.HandlerType)
-            {
-                case EHandlerType.AssignUser:
-                    var users = await _userRepository.QueryAsync(d => nextStepDefine.HandlerClassifies.Select(d => d.Id).Contains(d.Id));
-                    options.NextSteps = users.Select(d => new KeyValuePair<string, string>(d.Id, d.Name)).ToList();
-                    break;
-                case EHandlerType.AssignOrg:
-                    var orgs = await _organizeRepository.QueryAsync(d => nextStepDefine.HandlerClassifies.Select(d => d.Id).Contains(d.OrgCode));
-                    options.NextSteps = orgs.Select(d => new KeyValuePair<string, string>(d.OrgCode, d.OrgName)).ToList();
-                    break;
-                case EHandlerType.Role:
-                    var roles = await _roleRepository.Queryable().Includes(d => d.Accounts, d => d.User)
-                        .Where(d => nextStepDefine.HandlerClassifies.Select(d => d.Id).Contains(d.Name)).ToListAsync();
-                    var users1 = roles.SelectMany(d => d.Accounts).Select(d => d.User);
-                    if (nextStepDefine.OnlySelfOrg ?? false)
-                        users1 = users1.Where(d => d.OrgCode == _sessionContext.RequiredOrgCode);
-                    options.NextSteps = users1.Select(d => new KeyValuePair<string, string>(d.Id, d.Name)).ToList();
-                    break;
-                case EHandlerType.OrgLevel:
-                    //当前操作人所属部门的下级部门并且属于配置orgLevel的部门
-                    var levels = nextStepDefine.HandlerClassifies.Select(d => d.Id).Select(d => int.Parse(d));
-                    var orgs1 = await _organizeRepository.QueryAsync(d =>
-                        d.IsEnable && d.OrgCode.StartsWith(_sessionContext.RequiredOrgCode) &&
-                        levels.Contains(d.OrgLevel));
-                    options.NextSteps = orgs1.Select(d => new KeyValuePair<string, string>(d.OrgCode, d.OrgName)).ToList();
-                    break;
-                case EHandlerType.OrgType:
-                    var types = nextStepDefine.HandlerClassifies.Select(d => d.Id).Select(d => Enum.Parse<EOrgType>(d));
-                    var org2 = await _organizeRepository.QueryAsync(d =>
-                        d.IsEnable && d.OrgCode.StartsWith(_sessionContext.RequiredOrgCode) &&
-                        types.Contains(d.OrgType));
-                    options.NextSteps = org2.Select(d => new KeyValuePair<string, string>(d.OrgCode, d.OrgName)).ToList();
-                    break;
-
-                default:
-                    throw new ArgumentOutOfRangeException();
-            }
-
-            items.Add(options);
-        }
-
-        return items;
+        return await _workflowApplication.GetNextStepOptionsAsync(workflow, HttpContext.RequestAborted);
     }
 
     /// <summary>

+ 12 - 1
src/Hotline.Application/FlowEngine/IWorkflowApplication.cs

@@ -1,4 +1,5 @@
-using Hotline.Share.Dtos.FlowEngine;
+using Hotline.FlowEngine.Workflows;
+using Hotline.Share.Dtos.FlowEngine;
 
 namespace Hotline.Application.FlowEngine
 {
@@ -13,5 +14,15 @@ namespace Hotline.Application.FlowEngine
         /// <param name="cancellationToken"></param>
         /// <returns></returns>
         Task NextAsync(NextWorkflowDto dto, CancellationToken cancellationToken);
+
+        /// <summary>
+        /// 查询流程下一节点配置参数
+        /// </summary>
+        /// <param name="moduleCode"></param>
+        /// <param name="externalId"></param>
+        /// <returns></returns>
+        Task<IReadOnlyList<NextStepOptions>> GetNextStepOptionsAsync(string moduleCode, string externalId, CancellationToken cancellationToken);
+
+        Task<IReadOnlyList<NextStepOptions>> GetNextStepOptionsAsync(Workflow workflow, CancellationToken cancellationToken);
     }
 }

+ 80 - 0
src/Hotline.Application/FlowEngine/WorkflowApplication.cs

@@ -1,6 +1,7 @@
 using Hotline.FlowEngine.Definitions;
 using Hotline.FlowEngine.Workflows;
 using Hotline.Identity.Accounts;
+using Hotline.Identity.Roles;
 using Hotline.SeedData;
 using Hotline.Settings;
 using Hotline.Share.Dtos.FlowEngine;
@@ -21,6 +22,8 @@ public class WorkflowApplication : IWorkflowApplication, IScopeDependency
     private readonly IWorkflowAssignRepository _workflowAssignRepository;
     private readonly IUserRepository _userRepository;
     private readonly IAccountRepository _accountRepository;
+    private readonly ISystemOrganizeRepository _organizeRepository;
+    private readonly IRoleRepository _roleRepository;
     private readonly IUserDomainService _userDomainService;
     private readonly IAccountDomainService _accountDomainService;
     private readonly ISessionContext _sessionContext;
@@ -32,6 +35,8 @@ public class WorkflowApplication : IWorkflowApplication, IScopeDependency
         IWorkflowAssignRepository workflowAssignRepository,
         IUserRepository userRepository,
         IAccountRepository accountRepository,
+        ISystemOrganizeRepository organizeRepository,
+        IRoleRepository roleRepository,
         ISessionContext sessionContext)
     {
         _definitionDomainService = definitionDomainService;
@@ -40,6 +45,8 @@ public class WorkflowApplication : IWorkflowApplication, IScopeDependency
         _workflowAssignRepository = workflowAssignRepository;
         _userRepository = userRepository;
         _accountRepository = accountRepository;
+        _organizeRepository = organizeRepository;
+        _roleRepository = roleRepository;
         _sessionContext = sessionContext;
     }
 
@@ -84,6 +91,79 @@ public class WorkflowApplication : IWorkflowApplication, IScopeDependency
         await AddOrUpdateAssignAsync(workflow, dto, nextStepBoxDefine, cancellationToken);
     }
 
+    /// <summary>
+    /// 查询流程下一节点配置参数
+    /// </summary>
+    /// <param name="moduleCode"></param>
+    /// <param name="externalId"></param>
+    /// <returns></returns>
+    public async Task<IReadOnlyList<NextStepOptions>> GetNextStepOptionsAsync(string moduleCode, string externalId, CancellationToken cancellationToken)
+    {
+        var workflow = await _workflowDomainService.GetWorkflowAsync(moduleCode, externalId, true, true, cancellationToken: cancellationToken);
+        if (workflow == null)
+            throw new UserFriendlyException($"未查询到流程, moduleCode:{moduleCode}, externalId: {externalId}", "未查询到该流程");
+        return await GetNextStepOptionsAsync(workflow, cancellationToken);
+    }
+
+    public async Task<IReadOnlyList<NextStepOptions>> GetNextStepOptionsAsync(Workflow workflow, CancellationToken cancellationToken)
+    {
+        var nextStepDefines = _workflowDomainService.GetNextStepOptions(workflow, cancellationToken);
+
+        //todo 性能问题
+        var items = new List<NextStepOptions>();
+        foreach (var nextStepDefine in nextStepDefines)
+        {
+            var options = new NextStepOptions
+            {
+                Code = nextStepDefine.Code,
+                Name = nextStepDefine.Name,
+            };
+
+            switch (nextStepDefine.HandlerType)
+            {
+                case EHandlerType.AssignUser:
+                    var users = await _userRepository.QueryAsync(d => nextStepDefine.HandlerClassifies.Select(d => d.Id).Contains(d.Id));
+                    options.NextSteps = users.Select(d => new KeyValuePair<string, string>(d.Id, d.Name)).ToList();
+                    break;
+                case EHandlerType.AssignOrg:
+                    var orgs = await _organizeRepository.QueryAsync(d => nextStepDefine.HandlerClassifies.Select(d => d.Id).Contains(d.OrgCode));
+                    options.NextSteps = orgs.Select(d => new KeyValuePair<string, string>(d.OrgCode, d.OrgName)).ToList();
+                    break;
+                case EHandlerType.Role:
+                    var roles = await _roleRepository.Queryable().Includes(d => d.Accounts, d => d.User)
+                        .Where(d => nextStepDefine.HandlerClassifies.Select(d => d.Id).Contains(d.Name)).ToListAsync();
+                    var users1 = roles.SelectMany(d => d.Accounts).Select(d => d.User);
+                    if (nextStepDefine.OnlySelfOrg ?? false)
+                        users1 = users1.Where(d => d.OrgCode == _sessionContext.RequiredOrgCode);
+                    options.NextSteps = users1.Select(d => new KeyValuePair<string, string>(d.Id, d.Name)).ToList();
+                    break;
+                case EHandlerType.OrgLevel:
+                    //当前操作人所属部门的下级部门并且属于配置orgLevel的部门
+                    var levels = nextStepDefine.HandlerClassifies.Select(d => d.Id).Select(d => int.Parse(d));
+                    var orgs1 = await _organizeRepository.QueryAsync(d =>
+                        d.IsEnable && d.OrgCode.StartsWith(_sessionContext.RequiredOrgCode) &&
+                        levels.Contains(d.OrgLevel));
+                    options.NextSteps = orgs1.Select(d => new KeyValuePair<string, string>(d.OrgCode, d.OrgName)).ToList();
+                    break;
+                case EHandlerType.OrgType:
+                    var types = nextStepDefine.HandlerClassifies.Select(d => d.Id).Select(d => Enum.Parse<EOrgType>(d));
+                    var org2 = await _organizeRepository.QueryAsync(d =>
+                        d.IsEnable && d.OrgCode.StartsWith(_sessionContext.RequiredOrgCode) &&
+                        types.Contains(d.OrgType));
+                    options.NextSteps = org2.Select(d => new KeyValuePair<string, string>(d.OrgCode, d.OrgName)).ToList();
+                    break;
+
+                default:
+                    throw new ArgumentOutOfRangeException();
+            }
+
+            items.Add(options);
+        }
+
+        return items;
+    }
+
+
     #region private
 
     /// <summary>

+ 1 - 1
src/Hotline.Application/Handlers/FlowEngine/NextStepHandler.cs

@@ -28,7 +28,7 @@ public class NextStepHandler : INotificationHandler<NextStepNotify>
         var data = notification.Dto;
         switch (workflow.ModuleCode)
         {
-            case WorkflowModuleConsts.Order:
+            case WorkflowModuleConsts.OrderManage:
                 await _orderDomainService.OrderManageAsync(EOrderStatus.WaitForSign, 
                     notification.FlowAssignType, notification.IsCountersignEnd, notification.IsCountersignStart,
                     workflow.ExternalId, workflow.CurrentStepTime, workflow.CurrentStepName, 

+ 1 - 1
src/Hotline.Application/Handlers/FlowEngine/StartWorkflowHandler.cs

@@ -30,7 +30,7 @@ namespace Hotline.Application.Handlers.FlowEngine
 
             switch (workflow.ModuleCode)
             {
-                case WorkflowModuleConsts.Order:
+                case WorkflowModuleConsts.OrderManage:
                     await _orderDomainService.OrderManageAsync(EOrderStatus.WaitForSign, notification.FlowAssignType, 
                         false, notification.IsCountersignStart,
                         workflow.ExternalId, workflow.CurrentStepTime, workflow.CurrentStepName,

+ 2 - 29
src/Hotline.Repository.SqlSugar/DataPermissions/DataPermissionManager.cs

@@ -21,35 +21,8 @@ public class DataPermissionManager : IDataPermissionManager, IScopeDependency
 
     public DataPermissionScheme GetQueryFilter<TEntity>(ISessionContext sessionContext) where TEntity : class, IEntity<string>, IDataPermission, new()
     {
-        EAuthorityType? queryFilter = GetCurrentQueryFilter(sessionContext.Roles, typeof(TEntity).Name);
-
-        if (queryFilter == null)
-        {
-            
-            //todo 未配置数据查询权限处理方案
-            //TODO 不处理
-        }
-
-        //全部
-        if (queryFilter == EAuthorityType.All)
-            return new DataPermissionScheme(EAuthorityType.All);
-
-        //本部
-        if (queryFilter == EAuthorityType.Org)
-            return new DataPermissionScheme(EAuthorityType.Org);
-
-        //本部及本部以下
-        if (queryFilter == EAuthorityType.OrgAndBelow)
-        {
-            //todo 查询对应部门编码
-            return new DataPermissionScheme(EAuthorityType.OrgAndBelow, "");
-        }
-
-        //创建人
-        if (queryFilter == EAuthorityType.Create)
-            return new DataPermissionScheme(EAuthorityType.Create);
-
-        throw new NotImplementedException();
+        EAuthorityType queryFilter = GetCurrentQueryFilter(sessionContext.Roles, typeof(TEntity).Name);
+        return new DataPermissionScheme(queryFilter);
     }
 
     public (string orgId,string departmentCode, string creatorId, string? areaId) GetDataPermissionOptions()

+ 15 - 0
src/Hotline.Repository.SqlSugar/Orders/CommonOpinionRepository.cs

@@ -0,0 +1,15 @@
+using Hotline.Orders;
+using Hotline.Repository.SqlSugar.DataPermissions;
+using SqlSugar;
+using XF.Domain.Dependency;
+
+namespace Hotline.Repository.SqlSugar.Orders
+{
+    public class CommonOpinionRepository : BaseRepository<CommonOpinion>, ICommonOpinionRepository, IScopeDependency
+    {
+        public CommonOpinionRepository(ISugarUnitOfWork<HotlineDbContext> uow, IDataPermissionFilterBuilder dataPermissionFilterBuilder) : base(uow, dataPermissionFilterBuilder)
+        {
+
+        }
+    }
+}

+ 29 - 0
src/Hotline.Share/Dtos/Order/CommonDto.cs

@@ -0,0 +1,29 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Hotline.Share.Dtos.Order
+{
+    public class AddCommonDto
+    {
+        /// <summary>
+        /// 类型Code(对应常量)
+        /// </summary>
+        public string TypeCode { get; set; }
+
+        /// <summary>
+        /// 内容
+        /// </summary>
+        public string Content { get; set; }
+    }
+
+    public class DelCommonDto
+    {
+        /// <summary>
+        /// 主键ID集合
+        /// </summary>
+        public string[] Ids { get; set; }
+    }
+}

+ 13 - 0
src/Hotline/Orders/CommonOpinion.cs

@@ -0,0 +1,13 @@
+using XF.Domain.Repository;
+
+namespace Hotline.Orders
+{
+    public class CommonOpinion: CreationEntity
+    {
+        public string TypeCode { get; set; }
+
+        public string Content { get; set; }
+
+        public int OrderBy { get; set; }
+    }
+}

+ 34 - 0
src/Hotline/Orders/CommonOpinionDomainService.cs

@@ -0,0 +1,34 @@
+using XF.Domain.Dependency;
+using XF.Domain.Exceptions;
+
+namespace Hotline.Orders
+{
+    public class CommonOpinionDomainService : ICommonOpinionDomainService, IScopeDependency
+    {
+        private readonly ICommonOpinionRepository _commonOpinionRepository;
+
+        public CommonOpinionDomainService(ICommonOpinionRepository commonOpinionRepository)
+        {
+            _commonOpinionRepository = commonOpinionRepository;
+        }
+        public async Task AddCommonOpinion(CommonOpinion entity,CancellationToken cancellationToken)
+        {
+            await _commonOpinionRepository.AddAsync(entity, cancellationToken);
+        }
+
+        public async Task<IReadOnlyList<CommonOpinion>> GetCommonOpinions(string code)
+        {
+            return await _commonOpinionRepository.Queryable(true).Where(x => x.TypeCode == code).ToListAsync();
+        }
+
+        public async Task DelCommonOpinion(string[] Ids,CancellationToken cancellationToken)
+        {
+            var list =await _commonOpinionRepository.Queryable(true).In(Ids).ToListAsync();
+            if (list.Count!=Ids.Length)
+            {
+                throw new UserFriendlyException("数据异常,无权限操作");
+            }
+            await _commonOpinionRepository.RemoveRangeAsync(list,cancellationToken);
+        }
+    }
+}

+ 61 - 0
src/Hotline/Orders/CommonOpinionTypeConsts.cs

@@ -0,0 +1,61 @@
+
+namespace Hotline.Orders
+{
+    public class CommonOpinionTypeConsts
+    {
+        /// <summary>
+        /// 甄别常用意见
+        /// </summary>
+        public const string Discriminate = "Discriminate";
+
+        /// <summary>
+        /// 退回常用意见
+        /// </summary>
+        public const string Return = "Return";
+
+        /// <summary>
+        /// 归档常用意见
+        /// </summary>
+        public const string Archive = "Archive";
+
+        /// <summary>
+        /// 特提常用意见
+        /// </summary>
+        public const string Teti = "Teti";
+
+        /// <summary>
+        /// 坐席常用意见
+        /// </summary>
+        public const string Seat = "Seat";
+
+        /// <summary>
+        /// 流转常用意见
+        /// </summary>
+        public const string Circulation = "Circulation";
+
+        /// <summary>
+        /// 回访常用意见
+        /// </summary>
+        public const string ReturnVisit = "ReturnVisit";
+
+        /// <summary>
+        /// 办理常用意见
+        /// </summary>
+        public const string HandleAgain = "HandleAgain";
+
+        /// <summary>
+        /// 延期常用意见
+        /// </summary>
+        public const string Delay = "Delay";
+
+        /// <summary>
+        /// 督办常用意见
+        /// </summary>
+        public const string Supervise = "Supervise";
+
+        /// <summary>
+        /// 知识诉求常用意见
+        /// </summary>
+        public const string KnowledgeLocution = "KnowledgeLocution";
+    }
+}

+ 17 - 0
src/Hotline/Orders/ICommonOpinionDomainService.cs

@@ -0,0 +1,17 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Hotline.Orders
+{
+    public interface ICommonOpinionDomainService
+    {
+        Task<IReadOnlyList<CommonOpinion>> GetCommonOpinions(string code);
+
+        Task AddCommonOpinion(CommonOpinion entity, CancellationToken cancellationToken);
+
+        Task DelCommonOpinion(string[] Ids,CancellationToken cancellationToken);
+    }
+}

+ 9 - 0
src/Hotline/Orders/ICommonOpinionRepository.cs

@@ -0,0 +1,9 @@
+using XF.Domain.Repository;
+
+namespace Hotline.Orders
+{
+    public interface ICommonOpinionRepository : IRepository<CommonOpinion>
+    {
+
+    }
+}

+ 2 - 2
src/Hotline/Settings/WorkflowModule.cs

@@ -21,7 +21,7 @@ public class WorkflowModule
     public static Dictionary<string, string> Modules { get; } =
         new Dictionary<string, string>
         {
-            { WorkflowModuleConsts.Order, "工单办理" },
+            { WorkflowModuleConsts.OrderManage, "工单办理" },
             { WorkflowModuleConsts.KnowledgeAdd, "新增知识审批" },
             { WorkflowModuleConsts.KnowledgeUpdate, "知识更新" },
             { WorkflowModuleConsts.KnowledgeDelete, "知识删除" },
@@ -34,7 +34,7 @@ public class WorkflowModuleConsts
     /// <summary>
     /// 工单办理
     /// </summary>
-    public const string Order = "Order";
+    public const string OrderManage = "Order";
 
     /// <summary>
     /// 新增知识审批