TANG JIANG 2 年之前
父節點
當前提交
b1f28df2b6
共有 80 個文件被更改,包括 1138 次插入359 次删除
  1. 14 4
      src/Hotline.Api/Controllers/CommonPController.cs
  2. 191 0
      src/Hotline.Api/Controllers/HotSpotController.cs
  3. 77 34
      src/Hotline.Api/Controllers/OrderController.cs
  4. 1 1
      src/Hotline.Api/Controllers/RoleController.cs
  5. 17 0
      src/Hotline.Api/StartupHelper.cs
  6. 2 1
      src/Hotline.Application/Handlers/FlowEngine/NextStepHandler.cs
  7. 1 1
      src/Hotline.Application/Handlers/FlowEngine/StartWorkflowHandler.cs
  8. 16 27
      src/Hotline.Application/Mappers/MapperConfigs.cs
  9. 22 4
      src/Hotline.Repository.SqlSugar/BaseRepository.cs
  10. 30 2
      src/Hotline.Repository.SqlSugar/BaseRepositoryWorkflow.cs
  11. 34 28
      src/Hotline.Repository.SqlSugar/DataPermissions/DataPermissionFilterBuilder.cs
  12. 3 2
      src/Hotline.Repository.SqlSugar/DataPermissions/DataPermissionManager.cs
  13. 3 2
      src/Hotline.Repository.SqlSugar/DataPermissions/IDataPermissionManager.cs
  14. 8 0
      src/Hotline.Repository.SqlSugar/Extensions/DataPermissionExtensions.cs
  15. 4 1
      src/Hotline.Repository.SqlSugar/Extensions/SqlSugarStartupExtensions.cs
  16. 59 0
      src/Hotline.Repository.SqlSugar/Orders/OrderRepository.cs
  17. 3 3
      src/Hotline.Repository.SqlSugar/System/CommonOpinionRepository.cs
  18. 4 4
      src/Hotline.Repository.SqlSugar/System/HotspotTypeRepository.cs
  19. 14 0
      src/Hotline.Repository.SqlSugar/System/SystemAreaRepository.cs
  20. 3 3
      src/Hotline.Repository.SqlSugar/System/SystemOrganizeRepository.cs
  21. 14 0
      src/Hotline.Repository.SqlSugar/System/TimeLimitRepository.cs
  22. 1 0
      src/Hotline.Share/Dtos/FlowEngine/WorkflowDto.cs
  23. 19 9
      src/Hotline.Share/Dtos/Order/OrderComplainDto.cs
  24. 24 10
      src/Hotline.Share/Dtos/Order/OrderDto.cs
  25. 3 2
      src/Hotline.Share/Dtos/Order/OrderReportDto.cs
  26. 1 1
      src/Hotline.Share/Dtos/Order/QueryOrderDto.cs
  27. 14 0
      src/Hotline.Share/Dtos/Order/QueryOrderHistoryDto.cs
  28. 141 0
      src/Hotline.Share/Dtos/Order/TimeLimitDto.cs
  29. 10 1
      src/Hotline.Share/Enums/Order/EAcceptType.cs
  30. 0 13
      src/Hotline.Share/Enums/Order/EAgeRange.cs
  31. 8 1
      src/Hotline.Share/Enums/Order/EChannel.cs
  32. 0 6
      src/Hotline.Share/Enums/Order/ECitizenStatus1.cs
  33. 8 9
      src/Hotline.Share/Enums/Order/EComplainType.cs
  34. 7 1
      src/Hotline.Share/Enums/Order/EEmergencyLevel.cs
  35. 2 2
      src/Hotline.Share/Enums/Order/EGender.cs
  36. 0 29
      src/Hotline.Share/Enums/Order/ELicenceType.cs
  37. 0 6
      src/Hotline.Share/Enums/Order/ENationality.cs
  38. 0 6
      src/Hotline.Share/Enums/Order/EOrderTarget.cs
  39. 5 1
      src/Hotline.Share/Enums/Order/EOrderType.cs
  40. 0 6
      src/Hotline.Share/Enums/Order/EPatentType.cs
  41. 0 6
      src/Hotline.Share/Enums/Order/EProviderType.cs
  42. 0 31
      src/Hotline.Share/Enums/Order/EPushType.cs
  43. 0 6
      src/Hotline.Share/Enums/Order/ESalesMode.cs
  44. 19 0
      src/Hotline.Share/Enums/Order/ETimeLimitState.cs
  45. 35 0
      src/Hotline/FileStorage/File.cs
  46. 11 2
      src/Hotline/Orders/Citizen.cs
  47. 0 9
      src/Hotline/Orders/IHotSpotTypeRepository.cs
  48. 1 1
      src/Hotline/Orders/IOrderDomainService.cs
  49. 2 0
      src/Hotline/Orders/IOrderRepository.cs
  50. 22 5
      src/Hotline/Orders/Order.cs
  51. 8 3
      src/Hotline/Orders/OrderComplain.cs
  52. 8 6
      src/Hotline/Orders/OrderDomainService.cs
  53. 6 2
      src/Hotline/Orders/OrderExtensionEntity.cs
  54. 5 1
      src/Hotline/Orders/OrderReport.cs
  55. 2 2
      src/Hotline/Settings/CommonOpinions/CommonOpinion.cs
  56. 6 6
      src/Hotline/Settings/CommonOpinions/CommonOpinionDomainService.cs
  57. 1 2
      src/Hotline/Settings/CommonOpinions/CommonOpinionTypeConsts.cs
  58. 2 8
      src/Hotline/Settings/CommonOpinions/ICommonOpinionDomainService.cs
  59. 1 1
      src/Hotline/Settings/CommonOpinions/ICommonOpinionRepository.cs
  60. 6 4
      src/Hotline/Settings/Hotspots/HotSpotType.cs
  61. 9 0
      src/Hotline/Settings/Hotspots/IHotspotTypeRepository.cs
  62. 0 13
      src/Hotline/Settings/ISysDicDataDomainRepository.cs
  63. 8 0
      src/Hotline/Settings/ISystemAreaDomainService.cs
  64. 8 0
      src/Hotline/Settings/ISystemAreaRepository.cs
  65. 2 0
      src/Hotline/Settings/ISystemDomainService.cs
  66. 0 18
      src/Hotline/Settings/SysDicDataDomainRepository.cs
  67. 15 0
      src/Hotline/Settings/SysDicTypeConsts.cs
  68. 28 0
      src/Hotline/Settings/SystemArea.cs
  69. 19 0
      src/Hotline/Settings/SystemAreaDomainService.cs
  70. 10 2
      src/Hotline/Settings/SystemDataAuthority.cs
  71. 10 1
      src/Hotline/Settings/SystemDomainService.cs
  72. 4 2
      src/Hotline/Settings/SystemOrganize.cs
  73. 20 0
      src/Hotline/Settings/TimeLimits/ITimeLimitDomainService.cs
  74. 9 0
      src/Hotline/Settings/TimeLimits/ITimeLimitRepository.cs
  75. 36 0
      src/Hotline/Settings/TimeLimits/TimeLimit.cs
  76. 30 0
      src/Hotline/Settings/TimeLimits/TimeLimitDomainService.cs
  77. 19 7
      src/XF.Domain.Repository/Entity.cs
  78. 7 0
      src/XF.Domain.Repository/IRepositorySqlSugar.cs
  79. 1 1
      src/XF.Domain.Repository/IRepositoryWorkflow.cs
  80. 5 0
      src/XF.Domain/Entities/IDataPermission.cs

+ 14 - 4
src/Hotline.Api/Controllers/CommonPController.cs

@@ -1,5 +1,5 @@
-using Hotline.Orders;
-using Hotline.Settings;
+using Hotline.Settings;
+using Hotline.Settings.CommonOpinions;
 using Hotline.Share.Dtos.Order;
 using MapsterMapper;
 using Microsoft.AspNetCore.Mvc;
@@ -13,11 +13,13 @@ namespace Hotline.Api.Controllers
     public class CommonPController: BaseController
     {
         private readonly ICommonOpinionDomainService _commonOpinionDomainService;
+        private readonly ISystemAreaDomainService _systemAreaDomainService;
         private readonly IMapper _mapper;
 
-        public CommonPController(ICommonOpinionDomainService commonOpinionDomainService,IMapper mapper)
+        public CommonPController(ICommonOpinionDomainService commonOpinionDomainService,ISystemAreaDomainService systemAreaDomainService, IMapper mapper)
         {
             _commonOpinionDomainService = commonOpinionDomainService;
+            _systemAreaDomainService= systemAreaDomainService;
             _mapper = mapper;
         }
 
@@ -54,6 +56,14 @@ namespace Hotline.Api.Controllers
             await _commonOpinionDomainService.DelCommonOpinion(dto.Ids, HttpContext.RequestAborted);
         }
 
-
+        /// <summary>
+        /// 获取省市区树形
+        /// </summary>
+        /// <returns></returns>
+        [HttpGet("tree-area")]
+        public async Task<List<SystemArea>> GetAearTree()
+        {
+            return await _systemAreaDomainService.GetAreaTree();
+        }
     }
 }

+ 191 - 0
src/Hotline.Api/Controllers/HotSpotController.cs

@@ -0,0 +1,191 @@
+using Hotline.Repository.SqlSugar.Extensions;
+using Hotline.Settings.Hotspots;
+using Hotline.Settings.TimeLimits;
+using Hotline.Share.Dtos;
+using Hotline.Share.Dtos.Order;
+using MapsterMapper;
+using Microsoft.AspNetCore.Mvc;
+using XF.Domain.Exceptions;
+
+namespace Hotline.Api.Controllers
+{
+    /// <summary>
+    /// 热点
+    /// </summary>
+    public class HotspotController : BaseController
+    {
+        private readonly IHotspotTypeRepository _hotspotTypeRepository;
+        private readonly IMapper _mapper;
+        private readonly ITimeLimitDomainService _timeLimitDomainService;
+        private readonly ITimeLimitRepository _timeLimitRepository;
+
+        public HotspotController(IHotspotTypeRepository hotspotTypeRepository,IMapper mapper, ITimeLimitDomainService timeLimitDomainService, ITimeLimitRepository timeLimitRepository)
+        {
+            _hotspotTypeRepository = hotspotTypeRepository;
+            _mapper = mapper;
+            _timeLimitDomainService = timeLimitDomainService;
+            _timeLimitRepository = timeLimitRepository;
+        }
+
+        #region 热点
+        /// <summary>
+        /// 查询子项
+        /// </summary>
+        [HttpGet("children")]
+        public async Task<IReadOnlyList<HotSpotType>> GetChildren([FromQuery] string? id)
+        {
+            return await _hotspotTypeRepository.Queryable()
+                .Where(x => x.ParentId == id)
+                .OrderBy(d=>d.HotSpotName)
+                .ToListAsync();
+        }
+
+        /// <summary>
+        /// 查询热点数据(包含所有根目录及所查热点的所有上级对象)
+        /// <remarks>
+        /// 编辑页面使用
+        /// </remarks>
+        /// </summary>
+        /// <param name="id"></param>
+        /// <returns></returns>
+        [HttpGet("{id}/with-parents")]
+        public async Task<IReadOnlyList<HotSpotType>> GetWithParents(string id)
+        {
+            var targetList = await _hotspotTypeRepository.Queryable()
+                .ToTreeAsync(d => d.Children, d => d.ParentId, null, new[] { id });
+            var topIds = targetList.Select(d => d.Id);
+            var hotspots = await _hotspotTypeRepository.Queryable()
+                .Where(d => string.IsNullOrEmpty(d.ParentId) && !topIds.Contains(d.Id))
+                .ToListAsync();
+            hotspots.AddRange(targetList);
+            return hotspots.OrderBy(d=>d.HotSpotName).ToList();
+        }
+
+        #endregion
+
+
+        #region 时限管理
+        /// <summary>
+        /// 新增时限管理
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns>数据主键</returns>
+        [HttpPost("add-timelimit")]
+        public async Task<string> AddTimeLimit([FromBody]AddTimeLimitDto dto)
+        {
+            var model = _mapper.Map<TimeLimit>(dto);
+            model.TimeLimitState = Share.Enums.Order.ETimeLimitState.Draft;
+            return await _timeLimitDomainService.AddAsync(model, HttpContext.RequestAborted);
+        }
+
+
+        /// <summary>
+        /// 修改时限管理
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        [HttpPost("update-timelimit")]
+        public async Task UpdateTimeLimit([FromBody]UpdateTimeLimitDto dto)
+        {
+            var model = _mapper.Map<TimeLimit>(dto);
+            await _timeLimitDomainService.UpdateAsync(model, HttpContext.RequestAborted);
+        }
+
+        /// <summary>
+        /// 获取对象
+        /// </summary>
+        /// <param name="id"></param>
+        /// <returns></returns>
+        [HttpGet("timelimit/{id}")]
+        public async Task<TimeLimit?> GetTimeLimit(string id)
+        {
+            return await _timeLimitRepository.GetAsync(id, HttpContext.RequestAborted);
+        }
+
+
+        /// <summary>
+        /// 获取时限管理列表
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        [HttpGet("paged-timelimit")]
+        public async Task<PagedDto<TimeLimit>> QueryPagedTimeLimit([FromQuery] QueryPagedTimeLimitPagedDto dto)
+        {
+            var (total, items) = await _timeLimitRepository.Queryable()
+                .WhereIF(!string.IsNullOrEmpty(dto.Keyword), d => d.TimeLimitName.Contains(dto.Keyword!))
+                .OrderByDescending(d => d.CreationTime)
+                .ToPagedListAsync(dto.PageIndex,dto.PageSize, HttpContext.RequestAborted);
+            return new PagedDto<TimeLimit>(total, _mapper.Map<IReadOnlyList<TimeLimit>>(items));
+        }
+
+        /// <summary>
+        /// 删除时限(草稿)
+        /// </summary>
+        /// <param name="id"></param>
+        /// <returns></returns>
+        [HttpDelete("deltimelimit")]
+        public async Task DelTimeLimit(string id)
+        {
+            var model = await _timeLimitRepository.GetAsync(id, HttpContext.RequestAborted);
+            if (model==null)
+            {
+                throw UserFriendlyException.SameMessage("无效数据");
+            }
+            if (model.TimeLimitState != Share.Enums.Order.ETimeLimitState.Draft)
+            {
+                throw UserFriendlyException.SameMessage("无法删除,请刷新页面");
+            }
+            await _timeLimitRepository.RemoveAsync(id,true,HttpContext.RequestAborted);
+        }
+
+        /// <summary>
+        /// 启用时限
+        /// </summary>
+        /// <param name="id"></param>
+        /// <returns></returns>
+        [HttpGet("enable-timelimit/{id}")]
+        public async Task EnableTimeLimit(string id)
+        {
+            var model = await _timeLimitRepository.GetAsync(id, HttpContext.RequestAborted);
+            if (model==null)
+            {
+                throw UserFriendlyException.SameMessage("无效数据");
+            }
+            if (model.TimeLimitState == Share.Enums.Order.ETimeLimitState.Enable)
+            {
+                throw UserFriendlyException.SameMessage("该配置已生效");
+            }
+            var list = await _timeLimitRepository.QueryAsync(x => x.WorkflowCode == model.WorkflowCode && x.TimeLimitState == Share.Enums.Order.ETimeLimitState.Enable);
+            list.ForEach(x => x.TimeLimitState = Share.Enums.Order.ETimeLimitState.Disable);
+            model.TimeLimitState = Share.Enums.Order.ETimeLimitState.Enable;
+            list.Add(model);
+            await _timeLimitRepository.UpdateRangeAsync(list, HttpContext.RequestAborted);
+        }
+
+        /// <summary>
+        /// 禁用时限
+        /// </summary>
+        /// <param name="id"></param>
+        /// <returns></returns>
+        [HttpGet("disable-timelimit/{id}")]
+        public async Task DisableTimeLimit(string id)
+        {
+            var model = await _timeLimitRepository.GetAsync(id, HttpContext.RequestAborted);
+            if (model == null)
+            {
+                throw UserFriendlyException.SameMessage("无效数据");
+            }
+            if (model.TimeLimitState == Share.Enums.Order.ETimeLimitState.Draft)
+            {
+                throw UserFriendlyException.SameMessage("该配置未生效,无法禁用");
+            }
+            if (model.TimeLimitState == Share.Enums.Order.ETimeLimitState.Disable)
+            {
+                throw UserFriendlyException.SameMessage("该配置已禁用");
+            }
+            model.TimeLimitState = Share.Enums.Order.ETimeLimitState.Disable;
+            await _timeLimitRepository.UpdateAsync(model, HttpContext.RequestAborted);
+        }
+        #endregion
+    }
+}

+ 77 - 34
src/Hotline.Api/Controllers/OrderController.cs

@@ -1,8 +1,10 @@
 using Hotline.Application.FlowEngine;
+using Hotline.FlowEngine.Definitions;
 using Hotline.FlowEngine.Workflows;
 using Hotline.Orders;
 using Hotline.Repository.SqlSugar.Extensions;
 using Hotline.Settings;
+using Hotline.Settings.Hotspots;
 using Hotline.Share.Dtos;
 using Hotline.Share.Dtos.FlowEngine;
 using Hotline.Share.Dtos.Order;
@@ -27,8 +29,11 @@ public class OrderController : BaseController
     private readonly IOrderRepository _orderRepository;
     private readonly IWorkflowApplication _workflowApplication;
     private readonly IWorkflowDomainService _workflowDomainService;
-    private readonly IHotSpotTypeRepository _hotSpotTypeRepository;
+    private readonly IHotspotTypeRepository _hotspotTypeRepository;
+    private readonly ISystemDomainService _systemDomainService;
     private readonly ISystemOrganizeRepository _organizeRepository;
+    private readonly IDefinitionDomainService _definitionDomainService;
+    private readonly ISessionContext _sessionContext;
     private readonly IMapper _mapper;
 
     public OrderController(
@@ -36,16 +41,22 @@ public class OrderController : BaseController
         IOrderRepository orderRepository,
         IWorkflowApplication workflowApplication,
         IWorkflowDomainService workflowDomainService,
-        IHotSpotTypeRepository hotSpotTypeRepository,
+        IHotspotTypeRepository hotspotTypeRepository,
+        ISystemDomainService systemDomainService,
         ISystemOrganizeRepository organizeRepository,
+        IDefinitionDomainService definitionDomainService,
+        ISessionContext sessionContext,
         IMapper mapper)
     {
         _orderDomainService = orderDomainService;
         _orderRepository = orderRepository;
         _workflowApplication = workflowApplication;
         _workflowDomainService = workflowDomainService;
-        _hotSpotTypeRepository = hotSpotTypeRepository;
+        _hotspotTypeRepository = hotspotTypeRepository;
+        _systemDomainService = systemDomainService;
         _organizeRepository = organizeRepository;
+        _definitionDomainService = definitionDomainService;
+        _sessionContext = sessionContext;
         _mapper = mapper;
     }
 
@@ -57,7 +68,8 @@ public class OrderController : BaseController
     [HttpGet]
     public async Task<PagedDto<OrderDto>> Query([FromQuery] QueryOrderDto dto)
     {
-        var (total, items) = await _orderRepository.Queryable()
+        var (total, items) = await _orderRepository.Queryable(workflowFilter: false)
+            .Includes(d => d.Employee)
             .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.AcceptTypes.Any(), d => dto.AcceptTypes.Contains(d.AcceptType))
@@ -70,7 +82,7 @@ public class OrderController : BaseController
             .WhereIF(dto.CreationTimeEnd.HasValue, d => d.CreationTime <= dto.CreationTimeEnd)
             .WhereIF(dto.EmergencyLevels.Any(), d => dto.EmergencyLevels.Contains(d.EmergencyLevel))
             .WhereIF(!string.IsNullOrEmpty(dto.PhoneNo), d => d.FromPhone.Contains(dto.PhoneNo) || d.Contact.Contains(dto.PhoneNo))
-            .WhereIF(dto.PushType.HasValue, d => d.PushType == dto.PushType)
+            .WhereIF(!string.IsNullOrEmpty(dto.PushTypeCode), d => d.PushTypeCode == dto.PushTypeCode)
             .WhereIF(dto.ExpiredTimeStart.HasValue, d => d.ExpiredTime >= dto.ExpiredTimeStart)
             .WhereIF(dto.ExpiredTimeEnd.HasValue, d => d.ExpiredTime <= dto.ExpiredTimeEnd)
             .WhereIF(dto.Statuses.Any(), d => dto.Statuses.Contains(d.Status))
@@ -85,9 +97,11 @@ public class OrderController : BaseController
     /// <param name="dto"></param>
     /// <returns></returns>
     [HttpGet("history")]
-    public async Task<PagedDto<OrderDto>> Query([FromQuery] PagedRequest dto)
+    public async Task<PagedDto<OrderDto>> Query([FromQuery] QueryOrderHistoryDto dto)
     {
         var (total, items) = await _orderRepository.Queryable()
+            .Where(d => d.FromPhone == dto.PhoneNo)
+            .OrderByDescending(d => d.CreationTime)
             .ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted);
         return new PagedDto<OrderDto>(total, _mapper.Map<IReadOnlyList<OrderDto>>(items));
     }
@@ -100,7 +114,8 @@ public class OrderController : BaseController
     [HttpGet("{id}")]
     public async Task<OrderDto> Get(string id)
     {
-        var order = await _orderRepository.Queryable()
+        var order = await _orderRepository.Queryable(workflowFilter: false)
+            .Includes(d => d.Employee)
             .Includes(d => d.OrderComplain)
             .Includes(d => d.OrderReport)
             .FirstAsync(d => d.Id == id);
@@ -119,9 +134,15 @@ public class OrderController : BaseController
     public async Task<string> Add([FromBody] AddOrderDto dto)
     {
         var order = _mapper.Map<Order>(dto);
+        order.EmployeeId = _sessionContext.RequiredUserId;
         return await _orderDomainService.AddAsync(order, HttpContext.RequestAborted);
     }
 
+    /// <summary>
+    /// 删除工单
+    /// </summary>
+    /// <param name="id"></param>
+    /// <returns></returns>
     [HttpDelete("{id}")]
     public async Task Remove(string id)
     {
@@ -145,7 +166,8 @@ public class OrderController : BaseController
             throw UserFriendlyException.SameMessage("无效工单编号");
         if (order.Status != EOrderStatus.Temporary)
             throw UserFriendlyException.SameMessage("非草稿工单不可编辑");
-        await _orderRepository.UpdateAsync(order, HttpContext.RequestAborted);
+        _mapper.Map(dto, order);
+        await _orderRepository.UpdateOrderNavAsync(order, HttpContext.RequestAborted);
     }
 
     /// <summary>
@@ -162,27 +184,45 @@ public class OrderController : BaseController
             throw UserFriendlyException.SameMessage("无效工单编号");
         if (order.Status != EOrderStatus.Temporary || !string.IsNullOrEmpty(order.WorkflowId))
             throw UserFriendlyException.SameMessage("工单已发起流程");
+
+        var definition = await _definitionDomainService.GetLastVersionDefinitionByModuleCodeAsync(
+            WorkflowModuleConsts.OrderManage, HttpContext.RequestAborted);
+        if (definition is null)
+            throw UserFriendlyException.SameMessage("未配置流程模板");
+        dto.DefinitionCode = definition.Code;
+        dto.Title = order.Title;
         var workflowId = await _workflowApplication.StartWorkflowAsync(dto, HttpContext.RequestAborted);
         order.StartFlow(workflowId);
         await _orderRepository.UpdateAsync(order, HttpContext.RequestAborted);
     }
 
+    /// <summary>
+    /// 查询工单办理流程开启参数
+    /// </summary>
+    /// <returns></returns>
+    [HttpGet("flow-start")]
+    public async Task<IReadOnlyList<NextStepOptions>> GetFlowStartOptionsAsync()
+    {
+        return await _workflowApplication.GetStartOptionsAsync(WorkflowModuleConsts.OrderManage, HttpContext.RequestAborted);
+    }
+
     /// <summary>
     /// 列表页面基础数据
     /// </summary>
     /// <returns></returns>
     [HttpGet("base-data")]
-    public dynamic BaseData()
+    public async Task<object> BaseData()
     {
-        return new
+        var rsp = new
         {
             AcceptTypeOptions = EnumExts.GetDescriptions<EAcceptType>(),
             ChannelOptions = EnumExts.GetDescriptions<EChannel>(),
-            OrgsOptions = _organizeRepository.GetOrgJson(),
+            OrgsOptions = await _organizeRepository.GetOrgJson(),
             EmergencyLevelOptions = EnumExts.GetDescriptions<EEmergencyLevel>(),
-            PushTypeOptions = EnumExts.GetDescriptions<EPushType>(),
+            PushTypeOptions = await _systemDomainService.GetSysDicDataByCodeAsync(SysDicTypeConsts.PushType),
             OrderStatusOptions = EnumExts.GetDescriptions<EOrderStatus>(),
         };
+        return rsp;
     }
 
     /// <summary>
@@ -190,21 +230,21 @@ public class OrderController : BaseController
     /// </summary>
     /// <returns></returns>
     [HttpGet("base-data-add")]
-    public dynamic BaseDataAdd()
+    public async Task<object> BaseDataAdd()
     {
-        return new
+        var rsp = new
         {
             ChannelOptions = EnumExts.GetDescriptions<EChannel>(),
             GenderOptions = EnumExts.GetDescriptions<EGender>(),
             IdentityTypeOptions = EnumExts.GetDescriptions<EIdentityType>(),
-            LicenceTypeOptions = EnumExts.GetDescriptions<ELicenceType>(),
-            //AgeRangeOptions = 
+            LicenceTypeOptions = await _systemDomainService.GetSysDicDataByCodeAsync(SysDicTypeConsts.LicenceType),
+            AgeRangeOptions = await _systemDomainService.GetSysDicDataByCodeAsync(SysDicTypeConsts.AgeRange),
             OrderTypeOptions = EnumExts.GetDescriptions<EOrderType>(),
             AcceptTypeOptions = EnumExts.GetDescriptions<EAcceptType>(),
             EmergencyLevelOptions = EnumExts.GetDescriptions<EEmergencyLevel>(),
-            PushTypeOptions = EnumExts.GetDescriptions<EPushType>(),
-            //todo 是否重复
+            PushTypeOptions = await _systemDomainService.GetSysDicDataByCodeAsync(SysDicTypeConsts.PushType),
         };
+        return rsp;
     }
 
     /// <summary>
@@ -212,25 +252,28 @@ public class OrderController : BaseController
     /// </summary>
     /// <returns></returns>
     [HttpGet("base-data-ext")]
-    public dynamic BaseDataExtension()
+    public async Task<object> BaseDataExtension()
     {
-        //todo
-        return new
+        var rsp = new
         {
-            //LicenceTypeOptions = SysDicTypeConsts.LicenceType,
-            ComplainTypeOptions = EnumExts.GetDescriptions<EComplainType>()
+            LicenceTypeOptions = await _systemDomainService.GetSysDicDataByCodeAsync(SysDicTypeConsts.LicenceType),
+            IdentityTypeOptions = await _systemDomainService.GetSysDicDataByCodeAsync(SysDicTypeConsts.ProviderIdentityType),
+            IdentityOptions = await _systemDomainService.GetSysDicDataByCodeAsync(SysDicTypeConsts.Identity),
+            NationalityOptions = await _systemDomainService.GetSysDicDataByCodeAsync(SysDicTypeConsts.Nationality),
+            NationOptions = await _systemDomainService.GetSysDicDataByCodeAsync(SysDicTypeConsts.Nation),
+            MarketTypeOptions = await _systemDomainService.GetSysDicDataByCodeAsync(SysDicTypeConsts.MarketType),
+            IndustryClassifyOptions = await _systemDomainService.GetSysDicDataByCodeAsync(SysDicTypeConsts.IndustryClassify),
+            BrandOptions = await _systemDomainService.GetSysDicDataByCodeAsync(SysDicTypeConsts.Brand),
+            ObjectClassifyOptions = await _systemDomainService.GetSysDicDataByCodeAsync(SysDicTypeConsts.ObjectClassify),
+            ComplainClassifyOptions = await _systemDomainService.GetSysDicDataByCodeAsync(SysDicTypeConsts.ComplainClassify),
+            ReportClassifyOptions = await _systemDomainService.GetSysDicDataByCodeAsync(SysDicTypeConsts.ReportClassify),
+            SalesModeOptions = await _systemDomainService.GetSysDicDataByCodeAsync(SysDicTypeConsts.SalesMode),
+            ECommercePlatformOptions = await _systemDomainService.GetSysDicDataByCodeAsync(SysDicTypeConsts.ECommercePlatform),
+            PatentTypeOptions = await _systemDomainService.GetSysDicDataByCodeAsync(SysDicTypeConsts.PatentType),
+            AffairTargetOptions = await _systemDomainService.GetSysDicDataByCodeAsync(SysDicTypeConsts.AffairTarget),
+            ComplainTypeOptions = EnumExts.GetDescriptions<EComplainType>(),
         };
+        return rsp;
     }
 
-
-    /// <summary>
-    /// 获取热点
-    /// </summary>
-    /// <param name="parentId">父级ID</param>
-    /// <returns></returns>
-    [HttpGet("hotspottype-list-parent")]
-    public async Task<List<HotSpotType>> GetHotSpotType(string? parentId)
-    {
-        return await _hotSpotTypeRepository.Queryable().Where(x => x.ParentId == parentId).ToListAsync();
-    }
 }

+ 1 - 1
src/Hotline.Api/Controllers/RoleController.cs

@@ -224,7 +224,7 @@ public class RoleController : BaseController
     [HttpGet("getdataauthoritybyrole")]
     public async Task<IReadOnlyList<SystemDataAuthority>> GetDataAuthorityByRole(string roleid)
     {
-        return await _systemDataAuthorityRepository.QueryAsync(x => x.RoleId == roleid);
+        return await _systemDataAuthorityRepository.Queryable().Where(x => x.RoleId == roleid).Includes(x => x.Table).Includes(x => x.Role).ToListAsync();
     }
 
     #endregion

+ 17 - 0
src/Hotline.Api/StartupHelper.cs

@@ -6,6 +6,7 @@ using MapsterMapper;
 using Microsoft.AspNetCore.Authentication.JwtBearer;
 using Microsoft.IdentityModel.Tokens;
 using Microsoft.OpenApi.Models;
+using XF.Domain.Entities;
 using XF.Domain.Options;
 
 namespace Hotline.Api
@@ -165,6 +166,22 @@ namespace Hotline.Api
         public static IServiceCollection RegisterMapper(this IServiceCollection services)
         {
             var config = TypeAdapterConfig.GlobalSettings;
+            config.ForDestinationType<IDataPermission>()
+                .Ignore(d => d.CreatorId)
+                .Ignore(d => d.CreatorOrgId)
+                .Ignore(d => d.CreatorOrgCode)
+                .Ignore(d => d.AreaId);
+            config.ForDestinationType<IWorkflow>()
+                .Ignore(d => d.WorkflowId)
+                .Ignore(d => d.ExpiredTimeConfigId)
+                .Ignore(d => d.AssignOrgCodes)
+                .Ignore(d => d.AssignUserIds);
+            config.ForDestinationType<IHasCreationTime>()
+                .Ignore(d => d.CreationTime);
+            config.ForDestinationType<IHasDeletionTime>().Ignore(d => d.DeletionTime);
+            config.ForDestinationType<ISoftDelete>().Ignore(d => d.IsDeleted);
+            config.ForDestinationType<IHasModificationTime>().Ignore(d => d.LastModificationTime);
+
             services.AddSingleton(config);
             services.AddScoped<IMapper, ServiceMapper>();
 

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

@@ -39,7 +39,8 @@ public class NextStepHandler : INotificationHandler<NextStepNotify>
             case WorkflowModuleConsts.OrderManage:
                 await _orderDomainService.OrderManageAsync(EOrderStatus.WaitForSign,
                     assignMode, notification.IsCountersignEnd, notification.IsCountersignStart,
-                    workflow.Id, workflow.CurrentStepTime, workflow.CurrentStepName, cancellationToken);
+                    workflow.Id, workflow.CurrentStepTime, workflow.CurrentStepName, workflow.ExpiredTime,
+                    cancellationToken);
                 break;
         }
     }

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

@@ -45,7 +45,7 @@ namespace Hotline.Application.Handlers.FlowEngine
                 case WorkflowModuleConsts.OrderManage:
                     await _orderDomainService.OrderManageAsync(EOrderStatus.WaitForSign, assignMode,
                         false, notification.IsCountersignStart,
-                        workflow.Id, workflow.CurrentStepTime, workflow.CurrentStepName, cancellationToken);
+                        workflow.Id, workflow.CurrentStepTime, workflow.CurrentStepName, workflow.ExpiredTime, cancellationToken);
                     break;
             }
         }

+ 16 - 27
src/Hotline.Application/Mappers/MapperConfigs.cs

@@ -2,10 +2,10 @@
 using Hotline.FlowEngine.Definitions;
 using Hotline.FlowEngine.Workflows;
 using Hotline.Identity.Roles;
-using Hotline.KnowledgeBase;
+using Hotline.Orders;
 using Hotline.Share.Dtos.CallCenter;
 using Hotline.Share.Dtos.FlowEngine;
-using Hotline.Share.Dtos.Knowledge;
+using Hotline.Share.Dtos.Order;
 using Hotline.Share.Dtos.Roles;
 using Hotline.Share.Dtos.Users;
 using Hotline.Users;
@@ -17,11 +17,11 @@ namespace Hotline.Application.Mappers
     {
         public void Register(TypeAdapterConfig config)
         {
-            config.NewConfig<AddBlacklistDto, Blacklist>()
+            config.ForType<AddBlacklistDto, Blacklist>()
                 .Ignore(d => d.Expired)
                 .AfterMapping((s, t) => t.InitExpired());
 
-            config.NewConfig<AddUserDto, User>()
+            config.ForType<AddUserDto, User>()
                 .Map(d => d.Name, x => x.Name ?? x.UserName);
 
             config.NewConfig<User, UserDto>()
@@ -39,35 +39,24 @@ namespace Hotline.Application.Mappers
 
             #region workflow
 
-            config.NewConfig<UpdateDefinitionDto, Definition>()
+            config.ForType<UpdateDefinitionDto, Definition>()
                 .Ignore(d => d.Id);
 
-            config.NewConfig<WorkflowStep, WorkflowStep>()
+            config.ForType<WorkflowStep, WorkflowStep>()
                 .Ignore(d => d.Id);
 
-            config.NewConfig<KnowledgeApply, KnowledgeApplyPageDto>()
-              .Map(d => d.CreationName, x => x.User.Name)
-                .Map(d => d.CreationOrgName, x => x.SystemOrganize.OrgName);
-
-            config.NewConfig<Hotline.KnowledgeBase.Knowledge, KnowledgeDataDto>()
-              .Map(d => d.CreationName, x => x.User.Name)
-                .Map(d => d.KnowledgeTypeName, x => x.KnowledgeType.SpliceName);
+            #endregion
 
-            config.NewConfig<Hotline.KnowledgeBase.Knowledge, KnowledgeApprovalDataDto>()
-            .Map(d => d.CreationName, x => x.User.Name)
-              .Map(d => d.KnowledgeTypeName, x => x.KnowledgeType.SpliceName)
-                 .Map(d => d.CreateBMName, x => x.SystemOrganize.OrgName);
+            #region order
 
-            config.NewConfig<KnowledgeWorkFlow, KnowledgeApprovalDataDto>()
-                .Map(d => d.CreationName, x => x.Knowledge.User.Name)
-                .Map(d => d.KnowledgeTypeName, x => x.Knowledge.KnowledgeType.SpliceName)
-                .Map(d => d.CreateBMName, x => x.Knowledge.SystemOrganize.OrgName)
-                .Map(d => d.Id, x => x.Knowledge.Id)
-                .Map(d => d.Title, x => x.Knowledge.Title)
-                .Map(d => d.PageView, x => x.Knowledge.PageView)
-                .Map(d => d.Status, x => x.Knowledge.Status)
-                .Map(d => d.WorkflowModuleStatus, x => x.WorkflowModuleStatus)
-                .Map(d => d.Time, x => x.Workflow.CurrentStepTime);
+            config.ForType<Order, OrderDto>()
+                .IgnoreIf((s, d) => s.OrderComplain == null, d => d.OrderComplain)
+                .IgnoreIf((s, d) => s.OrderReport == null, d => d.OrderReport)
+                .IgnoreIf((s, d) => s.Workflow == null, d => d.Workflow)
+                .IgnoreIf((s, d) => s.Employee == null, d => d.EmployeeName, d => d.EmployeeStaffNo)
+                .Map(d => d.EmployeeName, x => x.Employee.Name)
+                .Map(d => d.EmployeeStaffNo, x => x.Employee.StaffNo)
+                ;
 
             #endregion
         }

+ 22 - 4
src/Hotline.Repository.SqlSugar/BaseRepository.cs

@@ -167,12 +167,30 @@ namespace Hotline.Repository.SqlSugar
 
         public UpdateNavTaskInit<TEntity, TEntity> UpdateNav(List<TEntity> entities, UpdateNavRootOptions options) => Db.UpdateNav(entities, options);
 
-        public InsertNavTaskInit<TEntity, TEntity> AddNav(TEntity entity) => Db.InsertNav(entity);
+        public InsertNavTaskInit<TEntity, TEntity> AddNav(TEntity entity)
+        {
+            var dataPermissionManager = _dataPermissionFilterBuilder.DataPermissionManager;
+            entity.InitDatePermission(dataPermissionManager);
+            return Db.InsertNav(entity);
+        }
+
+        public InsertNavTaskInit<TEntity, TEntity> AddNav(TEntity entity, InsertNavRootOptions options)
+        {
+            entity.InitDatePermission(_dataPermissionFilterBuilder.DataPermissionManager);
+            return Db.InsertNav(entity, options);
+        }
 
-        public InsertNavTaskInit<TEntity, TEntity> AddNav(TEntity entity, InsertNavRootOptions options) => Db.InsertNav(entity, options);
-        public InsertNavTaskInit<TEntity, TEntity> AddNav(List<TEntity> entities) => Db.InsertNav(entities);
+        public InsertNavTaskInit<TEntity, TEntity> AddNav(List<TEntity> entities)
+        {
+            entities.ForEach(d => d.InitDatePermission(_dataPermissionFilterBuilder.DataPermissionManager));
+            return Db.InsertNav(entities);
+        }
 
-        public InsertNavTaskInit<TEntity, TEntity> AddNav(List<TEntity> entities, InsertNavRootOptions options) => Db.InsertNav(entities, options);
+        public InsertNavTaskInit<TEntity, TEntity> AddNav(List<TEntity> entities, InsertNavRootOptions options)
+        {
+            entities.ForEach(d => d.InitDatePermission(_dataPermissionFilterBuilder.DataPermissionManager));
+            return Db.InsertNav(entities, options);
+        }
 
         public DeleteNavTaskInit<TEntity, TEntity> RemoveNav(TEntity entity) => Db.DeleteNav(entity);
         public DeleteNavTaskInit<TEntity, TEntity> RemoveNav(List<TEntity> entities) => Db.DeleteNav(entities);

+ 30 - 2
src/Hotline.Repository.SqlSugar/BaseRepositoryWorkflow.cs

@@ -17,11 +17,39 @@ public abstract class BaseRepositoryWorkflow<TEntity> : BaseRepository<TEntity>,
         _dataPermissionFilterBuilder = dataPermissionFilterBuilder;
     }
 
-    public ISugarQueryable<TEntity> Queryable(bool includeDeleted = false)
+    public ISugarQueryable<TEntity> Queryable(bool permissionVerify = false, bool includeDeleted = false, bool workflowFilter = true)
     {
         if (includeDeleted)
             Db.QueryFilter.Clear();
 
-        return Db.Queryable<TEntity>().WorkflowDataFiltering(_dataPermissionFilterBuilder);
+        //return Db.Queryable<TEntity>().WorkflowDataFiltering(_dataPermissionFilterBuilder);
+        var query = Db.Queryable<TEntity>();
+        if (permissionVerify)
+            query = query.DataPermissionFiltering(_dataPermissionFilterBuilder);
+
+        if (workflowFilter)
+            query = query.WorkflowDataFiltering(_dataPermissionFilterBuilder);
+        return query;
+    }
+
+    public async Task<string> AddAsync(TEntity entity, CancellationToken cancellationToken = default)
+    {
+        entity.InitDatePermission(_dataPermissionFilterBuilder.DataPermissionManager)
+            .AssignToCreator(_dataPermissionFilterBuilder.DataPermissionManager);
+        var excEntity = await Db.Insertable(entity).ExecuteReturnEntityAsync();
+        return excEntity.Id;
+    }
+
+    /// <summary>
+    /// 批量插入(应用场景:小数据量,超出1万条建议另行实现)
+    /// </summary>
+    /// <param name="entities"></param>
+    /// <param name="cancellationToken"></param>
+    /// <returns></returns>
+    public async Task AddRangeAsync(List<TEntity> entities, CancellationToken cancellationToken = default)
+    {
+        entities.ForEach(d => d.InitDatePermission(_dataPermissionFilterBuilder.DataPermissionManager)
+                .AssignToCreator(_dataPermissionFilterBuilder.DataPermissionManager));
+        await Db.Insertable(entities).ExecuteCommandAsync();
     }
 }

+ 34 - 28
src/Hotline.Repository.SqlSugar/DataPermissions/DataPermissionFilterBuilder.cs

@@ -22,15 +22,16 @@ public class DataPermissionFilterBuilder : IDataPermissionFilterBuilder, IScopeD
     public Expression<Func<TEntity, bool>> Build<TEntity>() where TEntity : class, IEntity<string>, IDataPermission, new()
     {
         var userId = _sessionContext.RequiredUserId;
-        var scheme = DataPermissionManager.GetQueryFilter<TEntity>(_sessionContext);
-        switch (scheme.QueryFilter)
+        var orgCode = _sessionContext.RequiredOrgCode;
+        var queryFilterType = DataPermissionManager.GetQueryFilter<TEntity>(_sessionContext);
+        switch (queryFilterType)
         {
             case EAuthorityType.Create:
                 return d => d.CreatorId == userId;
             case EAuthorityType.Org:
-                return d => d.CreatorOrgCode == scheme.OrgCode;
+                return d => d.CreatorOrgCode == orgCode;
             case EAuthorityType.OrgAndBelow:
-                return d => d.CreatorOrgCode.StartsWith(scheme.OrgCode);
+                return d => d.CreatorOrgCode.StartsWith(orgCode);
             case EAuthorityType.All:
                 return d => true;
             default:
@@ -41,34 +42,39 @@ public class DataPermissionFilterBuilder : IDataPermissionFilterBuilder, IScopeD
     public Expression<Func<TEntity, bool>> BuildIncludeFlowData<TEntity>() where TEntity : class, IEntity<string>, IDataPermission, IWorkflow, new()
     {
         var userId = _sessionContext.RequiredUserId;
-        var roles = _sessionContext.Roles;
         var orgCode = _sessionContext.RequiredOrgCode;
-        var scheme = DataPermissionManager.GetQueryFilter<TEntity>(_sessionContext);
-
-        switch (scheme.QueryFilter)
-        {
-            case EAuthorityType.Create:
-                return d => d.CreatorId == userId
-                            || d.AssignUserIds.Contains(userId)
-                            || d.AssignOrgCodes.Contains(orgCode);
-            case EAuthorityType.Org:
-                return d => d.CreatorOrgCode == scheme.OrgCode
-                            || d.AssignUserIds.Contains(userId)
-                            || d.AssignOrgCodes.Contains(orgCode)
 
-                            //todo 扩展sqlfunc || d.AssignRoles.Intersect(roles).Any()
-                            ;
-            case EAuthorityType.OrgAndBelow:
-                return d => d.CreatorOrgCode.StartsWith(scheme.OrgCode)
-                            || d.AssignUserIds.Contains(userId)
-                            || d.AssignOrgCodes.Contains(orgCode);
-            case EAuthorityType.All:
-                return d => true;
-            default:
-                return d => d.AssignUserIds.Contains(userId) || d.AssignOrgCodes.Contains(orgCode);
-        }
+        return d => d.AssignUserIds.Contains(userId) || d.AssignOrgCodes.Contains(orgCode);
     }
 
+    //public Expression<Func<TEntity, bool>> BuildIncludeFlowData<TEntity>() where TEntity : class, IEntity<string>, IDataPermission, IWorkflow, new()
+    //{
+    //    var userId = _sessionContext.RequiredUserId;
+    //    var orgCode = _sessionContext.RequiredOrgCode;
+    //    var queryFilterType = DataPermissionManager.GetQueryFilter<TEntity>(_sessionContext);
+
+    //    switch (queryFilterType)
+    //    {
+    //        case EAuthorityType.Create:
+    //            return d => d.CreatorId == userId
+    //                        || d.AssignUserIds.Contains(userId)
+    //                        || d.AssignOrgCodes.Contains(orgCode);
+    //        case EAuthorityType.Org:
+    //            return d => d.CreatorOrgCode == orgCode
+    //                        || d.AssignUserIds.Contains(userId)
+    //                        || d.AssignOrgCodes.Contains(orgCode)
+    //                ;
+    //        case EAuthorityType.OrgAndBelow:
+    //            return d => d.CreatorOrgCode.StartsWith(orgCode)
+    //                        || d.AssignUserIds.Contains(userId)
+    //                        || d.AssignOrgCodes.Contains(orgCode);
+    //        case EAuthorityType.All:
+    //            return d => true;
+    //        default:
+    //            return d => d.AssignUserIds.Contains(userId) || d.AssignOrgCodes.Contains(orgCode);
+    //    }
+    //}
+
     //private static bool FlowDataFiltering<TEntity>(TEntity entity, string userId, string orgCode, string[] roles) where TEntity : class, IEntity<string>, IDataPermission, IWorkflow, new()
     //{
     //    if (entity.AssignUserIds.Contains(userId)) return true;

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

@@ -20,10 +20,11 @@ public class DataPermissionManager : IDataPermissionManager, IScopeDependency
         _sessionContext = sessionContext;
     }
 
-    public DataPermissionScheme GetQueryFilter<TEntity>(ISessionContext sessionContext) where TEntity : class, IEntity<string>, IDataPermission, new()
+    public EAuthorityType GetQueryFilter<TEntity>(ISessionContext sessionContext) where TEntity : class, IEntity<string>, IDataPermission, new()
     {
         EAuthorityType queryFilter = GetCurrentQueryFilter(sessionContext.Roles, typeof(TEntity).Name);
-        return new DataPermissionScheme(queryFilter);
+        //return new DataPermissionScheme(queryFilter);
+        return queryFilter;
     }
 
     public (string orgId, string orgCode, string creatorId, string? areaId) GetDataPermissionOptions()

+ 3 - 2
src/Hotline.Repository.SqlSugar/DataPermissions/IDataPermissionManager.cs

@@ -1,10 +1,11 @@
-using XF.Domain.Authentications;
+using Hotline.Share.Enums.Settings;
+using XF.Domain.Authentications;
 using XF.Domain.Entities;
 
 namespace Hotline.Repository.SqlSugar.DataPermissions;
 
 public interface IDataPermissionManager
 {
-    DataPermissionScheme GetQueryFilter<TEntity>(ISessionContext sessionContext) where TEntity : class, IEntity<string>, IDataPermission, new();
+    EAuthorityType GetQueryFilter<TEntity>(ISessionContext sessionContext) where TEntity : class, IEntity<string>, IDataPermission, new();
     (string orgId, string orgCode, string creatorId, string? areaId) GetDataPermissionOptions();
 }

+ 8 - 0
src/Hotline.Repository.SqlSugar/Extensions/DataPermissionExtensions.cs

@@ -25,5 +25,13 @@ namespace Hotline.Repository.SqlSugar.Extensions
             entity.CreateDataPermission(orgId, departmentCode, creatorId, areaId);
             return entity;
         }
+
+        public static TEntity AssignToCreator<TEntity>(this TEntity entity, IDataPermissionManager dataPermissionManager)
+            where TEntity : class, IEntity<string>, IDataPermission, IWorkflow, new()
+        {
+            var (orgId, departmentCode, creatorId, areaId) = dataPermissionManager.GetDataPermissionOptions();
+            entity.Assign(EFlowAssignType.User, creatorId);
+            return entity;
+        }
     }
 }

+ 4 - 1
src/Hotline.Repository.SqlSugar/Extensions/SqlSugarStartupExtensions.cs

@@ -3,6 +3,8 @@ using System.ComponentModel;
 using System.ComponentModel.DataAnnotations;
 using System.Linq.Dynamic.Core;
 using System.Linq.Expressions;
+using Hotline.FlowEngine.Workflows;
+using Hotline.Orders;
 using Hotline.Users;
 using Microsoft.Extensions.Configuration;
 using Microsoft.Extensions.DependencyInjection;
@@ -114,8 +116,9 @@ namespace Hotline.Repository.SqlSugar.Extensions
             var dbOptions = configuration.GetSection("DatabaseConfiguration").Get<DatabaseOptions>() ?? new DatabaseOptions();
             if (dbOptions.ApplyDbMigrations)
             {
+                var nonTableTypes = new[] { typeof(OrderExtensionEntity), typeof(StepBasicEntity) };
                 var types = typeof(User).Assembly.GetTypes()
-                    .Where(d => d.GetInterfaces().Any(x => x == typeof(ITable)))
+                    .Where(d => d.GetInterfaces().Any(x => x == typeof(ITable) && !nonTableTypes.Contains(x)))
                     .Distinct()
                     .ToArray();
 

+ 59 - 0
src/Hotline.Repository.SqlSugar/Orders/OrderRepository.cs

@@ -3,17 +3,76 @@ using System.Collections.Generic;
 using System.Linq;
 using System.Text;
 using System.Threading.Tasks;
+using Hotline.Identity.Roles;
 using Hotline.Orders;
 using Hotline.Repository.SqlSugar.DataPermissions;
+using Hotline.Repository.SqlSugar.Extensions;
+using Hotline.Share.Enums.Order;
 using SqlSugar;
 using XF.Domain.Dependency;
+using XF.Domain.Exceptions;
 
 namespace Hotline.Repository.SqlSugar.Orders
 {
     public class OrderRepository : BaseRepositoryWorkflow<Order>, IOrderRepository, IScopeDependency
     {
+        private readonly IDataPermissionFilterBuilder _dataPermissionFilterBuilder;
+
         public OrderRepository(ISugarUnitOfWork<HotlineDbContext> uow, IDataPermissionFilterBuilder dataPermissionFilterBuilder) : base(uow, dataPermissionFilterBuilder)
         {
+            _dataPermissionFilterBuilder = dataPermissionFilterBuilder;
+        }
+
+        public async Task<string> AddOrderNavAsync(Order order, CancellationToken cancellationToken)
+        {
+            if (order.OrderType == EOrderType.MarketSupervisionBy12315)
+            {
+                //弥补AddNav方法没有自动指派到创建人
+                order.AssignToCreator(_dataPermissionFilterBuilder.DataPermissionManager);
+
+                if (order.AcceptType == EAcceptType.Complain)
+                {
+                    order.OrderComplain.InitDatePermission(_dataPermissionFilterBuilder.DataPermissionManager);
+                    await AddNav(order).Include(d => d.OrderComplain).ExecuteCommandAsync();
+                }
+                else if (order.AcceptType == EAcceptType.Report)
+                {
+                    order.OrderReport.InitDatePermission(_dataPermissionFilterBuilder.DataPermissionManager);
+                    await AddNav(order).Include(d=>d.OrderReport).ExecuteCommandAsync();
+                }
+                else
+                {
+                    throw UserFriendlyException.SameMessage("12315工单不支持该受理类型");
+                }
+            }
+            else
+            {
+                await AddAsync(order, cancellationToken);
+            }
+            return order.Id;
+        }
+
+        public async Task UpdateOrderNavAsync(Order order, CancellationToken cancellationToken)
+        {
+            if (order.OrderType == EOrderType.MarketSupervisionBy12315)
+            {
+                if (order.AcceptType == EAcceptType.Complain)
+                {
+                    await UpdateNav(order).Include(d => d.OrderComplain).ExecuteCommandAsync();
+                }
+                else if (order.AcceptType == EAcceptType.Report)
+                {
+                    await UpdateNav(order).Include(d => d.OrderReport).ExecuteCommandAsync();
+                }
+                else
+                {
+                    throw UserFriendlyException.SameMessage("12315工单不支持该受理类型");
+                }
+            }
+            else
+            {
+                await UpdateAsync(order, cancellationToken);
+            }
         }
     }
 }

+ 3 - 3
src/Hotline.Repository.SqlSugar/Orders/CommonOpinionRepository.cs → src/Hotline.Repository.SqlSugar/System/CommonOpinionRepository.cs

@@ -1,9 +1,9 @@
-using Hotline.Orders;
-using Hotline.Repository.SqlSugar.DataPermissions;
+using Hotline.Repository.SqlSugar.DataPermissions;
+using Hotline.Settings.CommonOpinions;
 using SqlSugar;
 using XF.Domain.Dependency;
 
-namespace Hotline.Repository.SqlSugar.Orders
+namespace Hotline.Repository.SqlSugar.System
 {
     public class CommonOpinionRepository : BaseRepository<CommonOpinion>, ICommonOpinionRepository, IScopeDependency
     {

+ 4 - 4
src/Hotline.Repository.SqlSugar/Orders/HotSpotTypeRepository.cs → src/Hotline.Repository.SqlSugar/System/HotspotTypeRepository.cs

@@ -1,14 +1,14 @@
 using Hotline.CallCenter.BlackLists;
-using Hotline.Orders;
 using Hotline.Repository.SqlSugar.DataPermissions;
+using Hotline.Settings.Hotspots;
 using SqlSugar;
 using XF.Domain.Dependency;
 
-namespace Hotline.Repository.SqlSugar.Orders
+namespace Hotline.Repository.SqlSugar.System
 {
-    public class HotSpotTypeRepository : BaseRepository<HotSpotType>, IHotSpotTypeRepository, IScopeDependency
+    public class HotspotTypeRepository : BaseRepository<HotSpotType>, IHotspotTypeRepository, IScopeDependency
     {
-        public HotSpotTypeRepository(ISugarUnitOfWork<HotlineDbContext> uow, IDataPermissionFilterBuilder dataPermissionFilterBuilder) : base(uow, dataPermissionFilterBuilder)
+        public HotspotTypeRepository(ISugarUnitOfWork<HotlineDbContext> uow, IDataPermissionFilterBuilder dataPermissionFilterBuilder) : base(uow, dataPermissionFilterBuilder)
         {
         }
     }

+ 14 - 0
src/Hotline.Repository.SqlSugar/System/SystemAreaRepository.cs

@@ -0,0 +1,14 @@
+using Hotline.Repository.SqlSugar.DataPermissions;
+using Hotline.Settings;
+using SqlSugar;
+using XF.Domain.Dependency;
+
+namespace Hotline.Repository.SqlSugar.System
+{
+    public class SystemAreaRepository : BaseRepository<SystemArea>, ISystemAreaRepository, IScopeDependency
+    {
+        public SystemAreaRepository(ISugarUnitOfWork<HotlineDbContext> uow, IDataPermissionFilterBuilder dataPermissionFilterBuilder) : base(uow, dataPermissionFilterBuilder)
+        {
+        }
+    }
+}

+ 3 - 3
src/Hotline.Repository.SqlSugar/System/SystemOrganizeRepository.cs

@@ -15,7 +15,7 @@ namespace Hotline.Repository.SqlSugar.System
         public async Task<IReadOnlyList<SystemOrganize>> GetOrgJson()
         {
             var list = await Db.Queryable<SystemOrganize>()
-                .ToTreeAsync(x => x.Children, it => it.ParentId, "");
+                .ToTreeAsync(x => x.Children, it => it.ParentId, null);
             return list;
         }
 
@@ -23,7 +23,7 @@ namespace Hotline.Repository.SqlSugar.System
         {
             var list = await Db.Queryable<SystemOrganize>()
                 .Where(x => x.IsEnable)
-                .ToTreeAsync(x => x.Children, it => it.ParentId, "");
+                .ToTreeAsync(x => x.Children, it => it.ParentId, null);
             return list;
         }
 
@@ -34,7 +34,7 @@ namespace Hotline.Repository.SqlSugar.System
                 .OrderByDescending(x => x.OrgCode)
                 .FirstAsync(x => x.ParentId == parentId);
             //如果存在下级
-            if (model!=null)
+            if (model != null)
             {
                 //return $"{int.Parse(model.OrgCode) +1:###}";
                 //return (int.Parse(model.OrgCode) + 1).ToString().PadLeft(3,'0');

+ 14 - 0
src/Hotline.Repository.SqlSugar/System/TimeLimitRepository.cs

@@ -0,0 +1,14 @@
+using Hotline.Repository.SqlSugar.DataPermissions;
+using Hotline.Settings.TimeLimits;
+using SqlSugar;
+using XF.Domain.Dependency;
+
+namespace Hotline.Repository.SqlSugar.System
+{
+    public class TimeLimitRepository : BaseRepository<TimeLimit>, ITimeLimitRepository, IScopeDependency
+    {
+        public TimeLimitRepository(ISugarUnitOfWork<HotlineDbContext> uow, IDataPermissionFilterBuilder dataPermissionFilterBuilder) : base(uow, dataPermissionFilterBuilder)
+        {
+        }
+    }
+}

+ 1 - 0
src/Hotline.Share/Dtos/FlowEngine/WorkflowDto.cs

@@ -27,6 +27,7 @@ namespace Hotline.Share.Dtos.FlowEngine
         public DateTime CurrentStepTime { get; set; }
         
         public EWorkflowStatus Status { get; set; }
+        public string StatusText => Status.ToString();
 
         public DefinitionDto Definition { get; set; }
 

+ 19 - 9
src/Hotline.Share/Dtos/Order/OrderComplainDto.cs

@@ -21,7 +21,9 @@ public class OrderComplainDto : OrderExtensionDto
     /// <summary>
     /// 投诉目标,销售方式为“网购”时展示该字段且必填
     /// </summary>
-    public EOrderTarget? ComplainTarget { get; set; }
+    public string? ComplainTargetCode { get; set; }
+
+    public string? ComplainTarget { get; set; }
 
     /// <summary>
     /// 经营地址,销售方式为“现场”时必填
@@ -34,7 +36,7 @@ public class OrderComplainDto : OrderExtensionDto
     /// <summary>
     /// 诉求类型,多选
     /// </summary>
-    public EComplainType? ComplainType { get; set; }
+    public List<EComplainType> ComplainTypes { get; set; } = new();
 
     #endregion
 }
@@ -56,19 +58,25 @@ public class OrderExtensionDto
     public string? LicenceNo { get; set; }
 
     /// <summary>
-    /// 提供方类型(投诉人类型)
+    /// 提供方身份类型
     /// </summary>
-    public EProviderType? ProviderType { get; set; }
+    public string? IdentityTypeCode { get; set; }
+
+    public string? IdentityType { get; set; }
 
     /// <summary>
     /// 提供方身份(投诉人身份)
     /// </summary>
-    public ECitizenStatus1? ProviderStatus { get; set; }
+    public string? IdentityCode { get; set; }
+
+    public string? Identity { get; set; }
 
     /// <summary>
     /// 国籍或地区
     /// </summary>
-    public ENationality? Nationality { get; set; }
+    public string? NationalityCode { get; set; }
+
+    public string? Nationality { get; set; }
 
     /// <summary>
     /// 民族
@@ -162,7 +170,8 @@ public class OrderExtensionDto
     /// <summary>
     /// 销售方式
     /// </summary>
-    public ESalesMode SalesMode { get; set; }
+    public string SalesModeCode { get; set; }
+    public string SalesMode { get; set; }
 
     /// <summary>
     /// 电商平台,销售方式为“网购”时展示该字段且必填
@@ -200,7 +209,8 @@ public class OrderExtensionDto
     /// <summary>
     /// 专利类型,“投诉问题类别”为“专利”时展示该字段,选填
     /// </summary>
-    public EPatentType? PatentType { get; set; }
+    public string? PatentTypeCode { get; set; }
+    public string? PatentType { get; set; }
 
     /// <summary>
     /// 专利号,“投诉问题类别”为“专利”时展示该字段,选填
@@ -230,7 +240,7 @@ public class OrderExtensionDto
     /// <summary>
     /// 产品有效期
     /// </summary>
-    public DateTime ProductExpriedTime { get; set; }
+    public DateTime ProductExpiredTime { get; set; }
 
     /// <summary>
     /// 生产厂家

+ 24 - 10
src/Hotline.Share/Dtos/Order/OrderDto.cs

@@ -3,6 +3,7 @@ using System.Collections.Generic;
 using System.Linq;
 using System.Text;
 using System.Threading.Tasks;
+using Hotline.Share.Dtos.FlowEngine;
 using Hotline.Share.Enums.Order;
 using XF.Utility.EnumExtensions;
 
@@ -20,13 +21,13 @@ namespace Hotline.Share.Dtos.Order
         /// <summary>
         /// 到达当前节点时间
         /// </summary>
-        public DateTime CurrentStepTime { get; set; }
+        public DateTime? CurrentStepTime { get; set; }
 
         /// <summary>
         /// 工单状态
         /// </summary>
         public EOrderStatus Status { get; set; }
-
+        
         /// <summary>
         /// 开始时间
         /// </summary>
@@ -55,8 +56,6 @@ namespace Hotline.Share.Dtos.Order
         /// </summary>
         public string No { get; set; }
 
-        public string? DuplicateName { get; set; }
-
         public string AcceptTypeText => AcceptType.GetDescription();
         public string EmergencyLevelText => EmergencyLevel.GetDescription();
 
@@ -76,7 +75,7 @@ namespace Hotline.Share.Dtos.Order
         /// 超期时间描述(需求:超期3天、0.5天后超期)
         /// </summary>
         public string ExpiredText => CalculateExpiredText();
-
+        
         private string CalculateExpiredText()
         {
             //todo 完整处理方案:1.创建待过期表,Id,过期时间,即将过期时间等字段。2.延迟消息通知处理过期,删除子表数据,处理order过期状态字段。3.此处即可采用expiredStatus进行判断
@@ -94,6 +93,8 @@ namespace Hotline.Share.Dtos.Order
                     return "超期不到1天";
             }
         }
+
+        public WorkflowDto Workflow { get; set; }
     }
 
     public class UpdateOrderDto : AddOrderDto
@@ -143,7 +144,9 @@ namespace Hotline.Share.Dtos.Order
         /// <summary>
         /// 证件类型
         /// </summary>
-        public ELicenceType? Licence { get; set; }
+        public string? LicenceTypeCode { get; set; }
+
+        public string? LicenceType { get; set; }
 
         /// <summary>
         /// 证件号码
@@ -153,7 +156,9 @@ namespace Hotline.Share.Dtos.Order
         /// <summary>
         /// 年龄段
         /// </summary>
-        public EAgeRange? AgeRange { get; set; }
+        public string? AgeRangeCode { get; set; }
+
+        public string? AgeRange { get; set; }
 
         /// <summary>
         /// 联系电话
@@ -203,6 +208,11 @@ namespace Hotline.Share.Dtos.Order
         public string Hotspot { get; set; }
         public string HotspotSpliceName { get; set; }
 
+        /// <summary>
+        /// 外部数据(为前端提供级联功能)
+        /// </summary>
+        public string HotspotExternal { get; set; }
+
         /// <summary>
         /// 事发时间
         /// </summary>
@@ -213,10 +223,14 @@ namespace Hotline.Share.Dtos.Order
         /// </summary>
         public string? DuplicateId { get; set; }
 
+        public string? DuplicateTitle { get; set; }
+
         /// <summary>
         /// 推送分类
         /// </summary>
-        public EPushType PushType { get; set; }
+        public string? PushTypeCode { get; set; }
+
+        public string? PushType { get; set; }
 
         /// <summary>
         /// 附件
@@ -233,11 +247,11 @@ namespace Hotline.Share.Dtos.Order
         /// <summary>
         /// 投诉
         /// </summary>
-        public OrderComplainDto OrderComplain { get; set; }
+        public OrderComplainDto OrderComplain { get; set; } = new();
 
         /// <summary>
         /// 举报
         /// </summary>
-        public OrderReportDto OrderReport { get; set; }
+        public OrderReportDto OrderReport { get; set; } = new();
     }
 }

+ 3 - 2
src/Hotline.Share/Dtos/Order/OrderReportDto.cs

@@ -2,7 +2,7 @@
 
 namespace Hotline.Share.Dtos.Order;
 
-public class OrderReportDto
+public class OrderReportDto : OrderExtensionDto
 {
     #region 举报详情
 
@@ -16,7 +16,8 @@ public class OrderReportDto
     /// <summary>
     /// 举报目标,销售方式为“网购”时展示该字段且必填
     /// </summary>
-    public EOrderTarget? ReportTarget { get; set; }
+    public string? ReportTargetCode { get; set; }
+    public string? ReportTarget { get; set; }
 
     #endregion
 }

+ 1 - 1
src/Hotline.Share/Dtos/Order/QueryOrderDto.cs

@@ -65,7 +65,7 @@ namespace Hotline.Share.Dtos.Order
         /// <summary>
         /// 推送分类
         /// </summary>
-        public EPushType? PushType { get; set; }
+        public string? PushTypeCode { get; set; }
 
         /// <summary>
         /// 过期时间

+ 14 - 0
src/Hotline.Share/Dtos/Order/QueryOrderHistoryDto.cs

@@ -0,0 +1,14 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Hotline.Share.Requests;
+
+namespace Hotline.Share.Dtos.Order
+{
+    public record QueryOrderHistoryDto : PagedRequest
+    {
+        public string PhoneNo { get; set; }
+    }
+}

+ 141 - 0
src/Hotline.Share/Dtos/Order/TimeLimitDto.cs

@@ -0,0 +1,141 @@
+using Hotline.Share.Enums.Order;
+using Hotline.Share.Requests;
+
+namespace Hotline.Share.Dtos.Order
+{
+    public record AddTimeLimitDto
+    {
+        /// <summary>
+        /// 配置名称
+        /// </summary>
+        public string TimeLimitName { get; set; }
+
+        /// <summary>
+        /// 业务名称
+        /// </summary>
+        public string WorkflowName { get; set; }
+
+        /// <summary>
+        /// 业务编码
+        /// </summary>
+        public string WorkflowCode { get; set; }
+
+        /// <summary>
+        /// 已配置参数
+        /// </summary>
+        public List<ParamTypeModel>? ParamArr { get; set; }
+
+        /// <summary>
+        /// 排序
+        /// </summary>
+        public List<PriorityModel>? Priority { get; set; }
+
+        /// <summary>
+        /// 组合
+        /// </summary>
+        public List<CombinationModel>? Combination { get; set; }
+    }
+
+    #region Model
+
+    public class CombinationModel
+    {
+        /// <summary>
+        /// 组合ID
+        /// </summary>
+        public string Id { get; set; }
+
+        /// <summary>
+        /// 组合名称
+        /// </summary>
+        public string CombinationName { get; set; }
+
+
+        /// <summary>
+        /// 组合参数
+        /// </summary>
+        public List<CombinationParamModel> CombinationParam { get; set; }
+
+
+        /// <summary>
+        /// 时限
+        /// </summary>
+        public int TimeLimitValue { get; set; }
+        /// <summary>
+        /// 时限类型
+        /// </summary>
+        public string TimeLimit { get; set; }
+
+        /// <summary>
+        /// 换算时间(小时)
+        /// </summary>
+        public int Hour { get; set; }
+    }
+
+
+    public class CombinationParamModel
+    {
+        /// <summary>
+        /// 组合参数ID
+        /// </summary>
+        public string Id { get; set; }
+
+        /// <summary>
+        /// 组合参数名称
+        /// </summary>
+        public string ParamName { get; set; }
+    }
+
+
+
+    public class PriorityModel
+    {
+        public string Id { get; set; }
+
+        public string ParamTypeName { get; set; }
+
+        public int Sort { get; set; }
+    }
+
+
+    public class ParamTypeModel
+    {
+        public string ParamType { get; set; }
+
+        public List<ParamValueModel> ParamValue { get; set; }
+    }
+
+    public class ParamValueModel
+    {
+        public string Id { get; set; }
+        /// <summary>
+        /// 
+        /// </summary>
+        public string ParamTypeName { get; set; }
+        /// <summary>
+        /// 时限
+        /// </summary>
+        public int TimeLimitValue { get; set; }
+        /// <summary>
+        /// 时限类型
+        /// </summary>
+        public string TimeLimit { get; set; }
+
+        /// <summary>
+        /// 换算时间(小时)
+        /// </summary>
+        public int Hour { get; set; }
+    }
+
+    #endregion
+
+    public record UpdateTimeLimitDto:AddTimeLimitDto
+    {
+        public string Id { get; set; }
+    }
+
+    public record QueryPagedTimeLimitPagedDto: PagedKeywordRequest
+    {
+
+    }
+}

+ 10 - 1
src/Hotline.Share/Enums/Order/EAcceptType.cs

@@ -1,39 +1,48 @@
-namespace Hotline.Share.Enums.Order;
+using System.ComponentModel;
+
+namespace Hotline.Share.Enums.Order;
 
 /// <summary>
 /// 受理类型
 /// </summary>
 public enum EAcceptType
 {
+    [Description("其他")]
     Other = 0,
 
     /// <summary>
     /// 咨询
     /// </summary>
+    [Description("咨询")]
     Consult = 1,
 
     /// <summary>
     /// 建议
     /// </summary>
+    [Description("建议")]
     Suggest = 2,
 
     /// <summary>
     /// 求助
     /// </summary>
+    [Description("求助")]
     SeekHelp = 3,
 
     /// <summary>
     /// 表扬
     /// </summary>
+    [Description("表扬")]
     Praise = 4,
 
     /// <summary>
     /// 举报
     /// </summary>
+    [Description("举报")]
     Report = 5,
 
     /// <summary>
     /// 投诉
     /// </summary>
+    [Description("投诉")]
     Complain = 6,
 }

+ 0 - 13
src/Hotline.Share/Enums/Order/EAgeRange.cs

@@ -1,13 +0,0 @@
-namespace Hotline.Share.Enums.Order;
-
-/// <summary>
-/// 年龄段
-/// </summary>
-public enum EAgeRange
-{
-    Unknown = 0,
-    LessThan12 = 1,
-    Between12And18 = 2,
-    Between19And65 = 3,
-    MoreThan65 = 4,
-}

+ 8 - 1
src/Hotline.Share/Enums/Order/EChannel.cs

@@ -1,27 +1,34 @@
-namespace Hotline.Share.Enums.Order;
+using System.ComponentModel;
+
+namespace Hotline.Share.Enums.Order;
 
 public enum EChannel
 {
     /// <summary>
     /// 电话
     /// </summary>
+    [Description("电话")]
     Phone = 0,
 
     /// <summary>
     /// 门户网站
     /// </summary>
+    [Description("门户网站")]
     Web = 1,
 
     /// <summary>
     /// 微信小程序
     /// </summary>
+    [Description("微信小程序")]
     WxMiniProgram = 2,
 
     /// <summary>
     /// 微信公众号
     /// </summary>
+    [Description("微信公众号")]
     WxOfficial = 3,
 
+    [Description("App")]
     App = 4,
 
 

+ 0 - 6
src/Hotline.Share/Enums/Order/ECitizenStatus1.cs

@@ -1,6 +0,0 @@
-namespace Hotline.Share.Enums.Order;
-
-public enum ECitizenStatus1
-{
-    //城镇、农村、港澳台同胞、外籍、军人、学生、其他
-}

+ 8 - 9
src/Hotline.Share/Enums/Order/EComplainType.cs

@@ -2,7 +2,6 @@
 
 namespace Hotline.Share.Enums.Order;
 
-[Flags]
 public enum EComplainType
 {
     //修理、重做、更换、退货、补足商品数量、退赔费用、赔偿损失、停止侵权、核定侵权责任
@@ -11,26 +10,26 @@ public enum EComplainType
     Repair = 1,
 
     [Description("重做")]
-    Redo = 1 << 1,
+    Redo = 2,
 
     [Description("更换")]
-    Change = 1 << 2,
+    Change = 3,
 
     [Description("退货")]
-    ReturnGoods = 1 << 3,
+    ReturnGoods = 4,
 
     [Description("补足商品数量")]
-    Complement = 1 << 4,
+    Complement = 5,
 
     [Description("退赔费用")]
-    Refund = 1 << 5,
+    Refund = 6,
 
     [Description("赔偿损失")]
-    Compensation = 1 << 6,
+    Compensation = 7,
 
     [Description("停止侵权")]
-    StopInfringement = 1 << 7,
+    StopInfringement = 8,
 
     [Description("核定侵权责任")]
-    AuthorizedInfringement = 1 << 8
+    AuthorizedInfringement = 9
 }

+ 7 - 1
src/Hotline.Share/Enums/Order/EEmergencyLevel.cs

@@ -1,4 +1,6 @@
-namespace Hotline.Share.Enums.Order;
+using System.ComponentModel;
+
+namespace Hotline.Share.Enums.Order;
 
 /// <summary>
 /// 紧急程度
@@ -8,20 +10,24 @@ public enum EEmergencyLevel
     /// <summary>
     /// 不紧急
     /// </summary>
+    [Description("不紧急")]
     UnEmergency = 0,
 
     /// <summary>
     /// 一般
     /// </summary>
+    [Description("一般")]
     Normal = 1,
 
     /// <summary>
     /// 紧急
     /// </summary>
+    [Description("紧急")]
     Emergency = 2,
 
     /// <summary>
     /// 非常紧急
     /// </summary>
+    [Description("非常紧急")]
     QuiteEmergency = 3,
 }

+ 2 - 2
src/Hotline.Share/Enums/Order/EGender.cs

@@ -11,9 +11,9 @@ public enum EGender
     [Description("未知")]
     Unknown = 0,
 
-    [Description("")]
+    [Description("先生")]
     Male = 1,
     
-    [Description("女")]
+    [Description("女")]
     Female = 2,
 }

+ 0 - 29
src/Hotline.Share/Enums/Order/ELicenceType.cs

@@ -1,29 +0,0 @@
-namespace Hotline.Share.Enums.Order;
-
-/// <summary>
-/// 证件类型
-/// </summary>
-public enum ELicenceType
-{
-    Unknown = 0,
-
-    /// <summary>
-    /// 身份证
-    /// </summary>
-    IdCard = 1,
-
-    /// <summary>
-    /// 护照
-    /// </summary>
-    Passport = 2,
-
-    /// <summary>
-    /// 港澳通行证
-    /// </summary>
-    HongKongMacaoTravelPermit = 3,
-
-    /// <summary>
-    /// 台湾通行证
-    /// </summary>
-    TaiwanTravelPermit = 4,
-}

+ 0 - 6
src/Hotline.Share/Enums/Order/ENationality.cs

@@ -1,6 +0,0 @@
-namespace Hotline.Share.Enums.Order;
-
-public enum ENationality
-{
-    //中国、外国、港澳台地区
-}

+ 0 - 6
src/Hotline.Share/Enums/Order/EOrderTarget.cs

@@ -1,6 +0,0 @@
-namespace Hotline.Share.Enums.Order;
-
-public enum EOrderTarget
-{
-    //平台、入驻商家
-}

+ 5 - 1
src/Hotline.Share/Enums/Order/EOrderType.cs

@@ -1,4 +1,6 @@
-namespace Hotline.Share.Enums.Order;
+using System.ComponentModel;
+
+namespace Hotline.Share.Enums.Order;
 
 /// <summary>
 /// 工单类型
@@ -8,10 +10,12 @@ public enum EOrderType
     /// <summary>
     /// 通用工单
     /// </summary>
+    [Description("通用工单")]
     Common = 0,
 
     /// <summary>
     /// 12315市场监管局受理单
     /// </summary>
+    [Description("12315市场监管局受理单")]
     MarketSupervisionBy12315 = 1,
 }

+ 0 - 6
src/Hotline.Share/Enums/Order/EPatentType.cs

@@ -1,6 +0,0 @@
-namespace Hotline.Share.Enums.Order;
-
-public enum EPatentType
-{
-    //发明专利、实用新型专利、外观设计专利
-}

+ 0 - 6
src/Hotline.Share/Enums/Order/EProviderType.cs

@@ -1,6 +0,0 @@
-namespace Hotline.Share.Enums.Order;
-
-public enum EProviderType
-{
-    //生产企业、销售企业、服务企业、其他企业、个体工商户、自然人、群诉、其他类型
-}

+ 0 - 31
src/Hotline.Share/Enums/Order/EPushType.cs

@@ -1,31 +0,0 @@
-using System.ComponentModel;
-
-namespace Hotline.Share.Enums.Order;
-
-/// <summary>
-/// 推送分类
-/// </summary>
-public enum EPushType
-{
-    //人力资源社会保障厅、交通运输厅、文旅和旅游厅、中小企业款项支付“指引诉求”、中小企业款项支付“跟办诉求”、中小企业款项支付“咨询诉求”、110
-    [Description("人力资源社会保障厅")]
-    Rlzyshbzt = 0,
-
-    [Description("交通运输厅")]
-    Jtyst = 1,
-
-    [Description("文旅和旅游厅")]
-    Wlt = 2,
-
-    [Description("中小企业款项支付“指引诉求”")]
-    ZxqyZysq = 3,
-
-    [Description("中小企业款项支付“跟办诉求”")]
-    ZxqyGbsq = 4,
-
-    [Description("中小企业款项支付“咨询诉求”")]
-    ZxqyZxsq = 5,
-
-    [Description("110")]
-    GongAn110 = 6,
-}

+ 0 - 6
src/Hotline.Share/Enums/Order/ESalesMode.cs

@@ -1,6 +0,0 @@
-namespace Hotline.Share.Enums.Order;
-
-public enum ESalesMode
-{
-    //网购、现场、电视购物、电话购物、邮购
-}

+ 19 - 0
src/Hotline.Share/Enums/Order/ETimeLimitState.cs

@@ -0,0 +1,19 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Hotline.Share.Enums.Order
+{
+    public enum ETimeLimitState
+    {
+        [Description("草稿")]
+        Draft = 0,
+        [Description("启用")]
+        Enable = 1,
+        [Description("禁用")]
+        Disable =2,
+    }
+}

+ 35 - 0
src/Hotline/FileStorage/File.cs

@@ -0,0 +1,35 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using XF.Domain.Repository;
+
+namespace Hotline.FileStorage
+{
+    public class File //: FullStateEntity
+    {
+        public EFileSType FileSType { get; set; }
+
+        public string Name { get; set; }
+
+        public string Extention { get; set; }
+
+        public string FullName { get; set; }
+
+        /// <summary>
+        /// 相对路劲
+        /// </summary>
+        public string Path { get; set; }
+
+        public string FullPath { get; set; }
+
+        public string Size { get; set; }
+    }
+
+    public enum EFileSType
+    {
+        Image = 0,
+
+    }
+}

+ 11 - 2
src/Hotline/Orders/Citizen.cs

@@ -33,7 +33,11 @@ namespace Hotline.Orders
         /// <summary>
         /// 证件类型
         /// </summary>
-        public ELicenceType? Licence { get; set; }
+        [SugarColumn(IsNullable = true)]
+        public string? LicenceTypeCode { get; set; }
+
+        [SugarColumn(IsNullable = true)]
+        public string? LicenceType { get; set; }
 
         /// <summary>
         /// 证件号码
@@ -43,7 +47,12 @@ namespace Hotline.Orders
         /// <summary>
         /// 年龄段
         /// </summary>
-        public EAgeRange? AgeRange { get; set; }
+        /// <summary>
+        /// 年龄段
+        /// </summary>
+        public string? AgeRangeCode { get; set; }
+
+        public string? AgeRange { get; set; }
 
         /// <summary>
         /// 联系电话

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

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

+ 1 - 1
src/Hotline/Orders/IOrderDomainService.cs

@@ -22,6 +22,6 @@ namespace Hotline.Orders
         /// 工单办理(每个节点都会触发)
         /// </summary>
         Task OrderManageAsync(EOrderStatus status, FlowAssignMode assignMode, bool isCountersignEnd, bool isCountersignStart,
-            string workflowId, DateTime? currentStepTime, string? CurrentStepName, CancellationToken cancellationToken);
+            string workflowId, DateTime? currentStepTime, string? CurrentStepName, DateTime expiredTime, CancellationToken cancellationToken);
     }
 }

+ 2 - 0
src/Hotline/Orders/IOrderRepository.cs

@@ -9,5 +9,7 @@ namespace Hotline.Orders
 {
     public interface IOrderRepository : IRepositoryWorkflow<Order>
     {
+        Task<string> AddOrderNavAsync(Order order, CancellationToken cancellationToken);
+        Task UpdateOrderNavAsync(Order order, CancellationToken cancellationToken);
     }
 }

+ 22 - 5
src/Hotline/Orders/Order.cs

@@ -27,11 +27,13 @@ namespace Hotline.Orders
         /// <summary>
         /// 来电号码
         /// </summary>
+        [SugarColumn(IsNullable = true)]
         public string? FromPhone { get; set; }
 
         /// <summary>
         /// 转接号码(转接来源)
         /// </summary>
+        [SugarColumn(IsNullable = true)]
         public string? TransferPhone { get; set; }
 
         /// <summary>
@@ -52,11 +54,16 @@ namespace Hotline.Orders
         /// <summary>
         /// 证件类型
         /// </summary>
-        public ELicenceType? LicenceType { get; set; }
+        [SugarColumn(IsNullable = true)]
+        public string? LicenceTypeCode { get; set; }
+
+        [SugarColumn(IsNullable = true)]
+        public string? LicenceType { get; set; }
 
         /// <summary>
         /// 证件号码
         /// </summary>
+        [SugarColumn(IsNullable = true)]
         public string? LicenceNo { get; set; }
 
         /// <summary>
@@ -126,6 +133,12 @@ namespace Hotline.Orders
         public string Hotspot { get; set; }
         public string HotspotSpliceName { get; set; }
 
+        /// <summary>
+        /// 外部数据(为前端提供级联功能)
+        /// </summary>
+        [SugarColumn(IsNullable = true)]
+        public string? HotspotExternal { get; set; }
+
         /// <summary>
         /// 事发时间
         /// </summary>
@@ -137,13 +150,17 @@ namespace Hotline.Orders
         [SugarColumn(ColumnDescription = "重复工单Id", IsNullable = true)]
         public string? DuplicateId { get; set; }
 
-        [SugarColumn(ColumnDescription = "重复工单", IsNullable = true)]
-        public string? DuplicateName { get; set; }
+        [SugarColumn(ColumnDescription = "重复工单标题", IsNullable = true)]
+        public string? DuplicateTitle { get; set; }
 
         /// <summary>
         /// 推送分类
         /// </summary>
-        public EPushType PushType { get; set; }
+        [SugarColumn(IsNullable = true)]
+        public string? PushTypeCode { get; set; }
+
+        [SugarColumn(IsNullable = true)]
+        public string? PushType { get; set; }
 
         /// <summary>
         /// 附件
@@ -188,7 +205,7 @@ namespace Hotline.Orders
         public DateTime? ExpiredTime { get; set; }
 
         /// <summary>
-        /// 过期状态
+        /// 过期状态 //todo 延迟消息更新此字段
         /// </summary>
         public EExpiredStatus ExpiredStatus { get; set; }
 

+ 8 - 3
src/Hotline/Orders/OrderComplain.cs

@@ -26,7 +26,11 @@ public class OrderComplain : OrderExtensionEntity
     /// <summary>
     /// 投诉目标,销售方式为“网购”时展示该字段且必填
     /// </summary>
-    public EOrderTarget? ComplainTarget { get; set; }
+    [SugarColumn(IsNullable = true)]
+    public string? ComplainTargetCode { get; set; }
+
+    [SugarColumn(IsNullable = true)]
+    public string? ComplainTarget { get; set; }
 
     /// <summary>
     /// 经营地址,销售方式为“现场”时必填
@@ -39,9 +43,10 @@ public class OrderComplain : OrderExtensionEntity
     public string? BussinessAddress { get; set; }
 
     /// <summary>
-    /// 诉求类型,多选
+    /// 诉求内容,多选
     /// </summary>
-    public EComplainType? ComplainType { get; set; }
+    [SugarColumn(ColumnDataType = "varchar(600)", IsJson = true)]
+    public List<EComplainType> ComplainTypes { get; set; } = new();
 
     #endregion
 }

+ 8 - 6
src/Hotline/Orders/OrderDomainService.cs

@@ -28,14 +28,15 @@ public class OrderDomainService : IOrderDomainService, IScopeDependency
 
     public async Task<string> AddAsync(Order order, CancellationToken cancellationToken)
     {
+        if (order.AcceptType == EAcceptType.Complain && order.OrderComplain == null)
+            throw UserFriendlyException.SameMessage("非法投诉参数");
+        if (order.AcceptType == EAcceptType.Complain && order.OrderReport == null)
+            throw UserFriendlyException.SameMessage("非法举报参数");
+
         order.Init(_sessionContext.RequiredUserId);
         order.No = GenerateNewOrderNo();
-        //order.ExpiredTime = Calculate();//todo 根据配置获取办理时长再计算过期时间
 
-        await _orderRepository.AddNav(order)
-            .Include(d => d.OrderComplain)
-            .ExecuteCommandAsync();
-        return order.Id;
+        return await _orderRepository.AddOrderNavAsync(order, cancellationToken);
     }
 
     /// <summary>
@@ -55,7 +56,7 @@ public class OrderDomainService : IOrderDomainService, IScopeDependency
     /// </summary>
     public async Task OrderManageAsync(EOrderStatus status, FlowAssignMode assignMode,
         bool isCountersignEnd, bool isCountersignStart,
-        string workflowId, DateTime? currentStepTime, string? CurrentStepName,
+        string workflowId, DateTime? currentStepTime, string? CurrentStepName, DateTime expiredTime,
         CancellationToken cancellationToken)
     {
         var order = await _orderRepository.GetAsync(d => d.WorkflowId == workflowId, cancellationToken);
@@ -78,6 +79,7 @@ public class OrderDomainService : IOrderDomainService, IScopeDependency
 
         order.CurrentStepTime = currentStepTime;
         order.CurrentStepName = CurrentStepName;
+        order.ExpiredTime = expiredTime;
         order.Status = status;
 
         await _orderRepository.UpdateAsync(order, cancellationToken);

+ 6 - 2
src/Hotline/Orders/OrderExtensionEntity.cs

@@ -198,7 +198,11 @@ public class OrderExtensionEntity : FullStateEntity
     /// <summary>
     /// 专利类型,“投诉问题类别”为“专利”时展示该字段,选填
     /// </summary>
-    public EPatentType? PatentType { get; set; }
+    [SugarColumn(IsNullable = true)]
+    public string? PatentTypeCode { get; set; }
+
+    [SugarColumn(IsNullable = true)]
+    public string? PatentType { get; set; }
 
     /// <summary>
     /// 专利号,“投诉问题类别”为“专利”时展示该字段,选填
@@ -233,7 +237,7 @@ public class OrderExtensionEntity : FullStateEntity
     /// <summary>
     /// 产品有效期
     /// </summary>
-    public DateTime ProductExpriedTime { get; set; }
+    public DateTime ProductExpiredTime { get; set; }
 
     /// <summary>
     /// 生产厂家

+ 5 - 1
src/Hotline/Orders/OrderReport.cs

@@ -20,7 +20,11 @@ public class OrderReport : OrderExtensionEntity
     /// <summary>
     /// 举报目标,销售方式为“网购”时展示该字段且必填
     /// </summary>
-    public EOrderTarget? ReportTarget { get; set; }
+    [SugarColumn(IsNullable = true)]
+    public string? ReportTargetCode { get; set; }
+
+    [SugarColumn(IsNullable = true)]
+    public string? ReportTarget { get; set; }
 
     #endregion
 }

+ 2 - 2
src/Hotline/Orders/CommonOpinion.cs → src/Hotline/Settings/CommonOpinions/CommonOpinion.cs

@@ -1,8 +1,8 @@
 using XF.Domain.Repository;
 
-namespace Hotline.Orders
+namespace Hotline.Settings.CommonOpinions
 {
-    public class CommonOpinion: CreationEntity
+    public class CommonOpinion : CreationEntity
     {
         public string TypeCode { get; set; }
 

+ 6 - 6
src/Hotline/Orders/CommonOpinionDomainService.cs → src/Hotline/Settings/CommonOpinions/CommonOpinionDomainService.cs

@@ -1,7 +1,7 @@
 using XF.Domain.Dependency;
 using XF.Domain.Exceptions;
 
-namespace Hotline.Orders
+namespace Hotline.Settings.CommonOpinions
 {
     public class CommonOpinionDomainService : ICommonOpinionDomainService, IScopeDependency
     {
@@ -11,7 +11,7 @@ namespace Hotline.Orders
         {
             _commonOpinionRepository = commonOpinionRepository;
         }
-        public async Task AddCommonOpinion(CommonOpinion entity,CancellationToken cancellationToken)
+        public async Task AddCommonOpinion(CommonOpinion entity, CancellationToken cancellationToken)
         {
             await _commonOpinionRepository.AddAsync(entity, cancellationToken);
         }
@@ -22,15 +22,15 @@ namespace Hotline.Orders
             return await _commonOpinionRepository.Queryable().Where(x => x.TypeCode == code).ToListAsync();
         }
 
-        public async Task DelCommonOpinion(string[] Ids,CancellationToken cancellationToken)
+        public async Task DelCommonOpinion(string[] Ids, CancellationToken cancellationToken)
         {
             //TODO 加权限
-            var list =await _commonOpinionRepository.Queryable().In(Ids).ToListAsync();
-            if (list.Count!=Ids.Length)
+            var list = await _commonOpinionRepository.Queryable().In(Ids).ToListAsync();
+            if (list.Count != Ids.Length)
             {
                 throw new UserFriendlyException("数据异常,无权限操作");
             }
-            await _commonOpinionRepository.RemoveRangeAsync(list,cancellationToken);
+            await _commonOpinionRepository.RemoveRangeAsync(list, cancellationToken);
         }
     }
 }

+ 1 - 2
src/Hotline/Orders/CommonOpinionTypeConsts.cs → src/Hotline/Settings/CommonOpinions/CommonOpinionTypeConsts.cs

@@ -1,5 +1,4 @@
-
-namespace Hotline.Orders
+namespace Hotline.Settings.CommonOpinions
 {
     public class CommonOpinionTypeConsts
     {

+ 2 - 8
src/Hotline/Orders/ICommonOpinionDomainService.cs → src/Hotline/Settings/CommonOpinions/ICommonOpinionDomainService.cs

@@ -1,10 +1,4 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace Hotline.Orders
+namespace Hotline.Settings.CommonOpinions
 {
     public interface ICommonOpinionDomainService
     {
@@ -12,6 +6,6 @@ namespace Hotline.Orders
 
         Task AddCommonOpinion(CommonOpinion entity, CancellationToken cancellationToken);
 
-        Task DelCommonOpinion(string[] Ids,CancellationToken cancellationToken);
+        Task DelCommonOpinion(string[] Ids, CancellationToken cancellationToken);
     }
 }

+ 1 - 1
src/Hotline/Orders/ICommonOpinionRepository.cs → src/Hotline/Settings/CommonOpinions/ICommonOpinionRepository.cs

@@ -1,6 +1,6 @@
 using XF.Domain.Repository;
 
-namespace Hotline.Orders
+namespace Hotline.Settings.CommonOpinions
 {
     public interface ICommonOpinionRepository : IRepository<CommonOpinion>
     {

+ 6 - 4
src/Hotline/Orders/HotSpotType.cs → src/Hotline/Settings/Hotspots/HotSpotType.cs

@@ -1,13 +1,12 @@
-
-using SqlSugar;
+using SqlSugar;
 using XF.Domain.Repository;
 
-namespace Hotline.Orders
+namespace Hotline.Settings.Hotspots
 {
     /// <summary>
     /// 热点基础数据
     /// </summary>
-    public class HotSpotType: CreationSoftDeleteEntity
+    public class HotSpotType : CreationSoftDeleteEntity
     {
         public string HotSpotName { get; set; }
         [SugarColumn(IsNullable = true)]
@@ -23,5 +22,8 @@ namespace Hotline.Orders
         /// 生成的时候写入
         /// </summary>
         public string HotSpotFullName { get; set; }
+
+        [SugarColumn(IsIgnore = true)]
+        public List<HotSpotType> Children { get; set; }
     }
 }

+ 9 - 0
src/Hotline/Settings/Hotspots/IHotspotTypeRepository.cs

@@ -0,0 +1,9 @@
+using XF.Domain.Repository;
+
+namespace Hotline.Settings.Hotspots
+{
+    public interface IHotspotTypeRepository : IRepository<HotSpotType>
+    {
+
+    }
+}

+ 0 - 13
src/Hotline/Settings/ISysDicDataDomainRepository.cs

@@ -1,13 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace Hotline.Settings
-{
-    public interface ISysDicDataDomainRepository
-    {
-        Task<IReadOnlyList<SysDicData>> GetSysDicDataByCode(string code);
-    }
-}

+ 8 - 0
src/Hotline/Settings/ISystemAreaDomainService.cs

@@ -0,0 +1,8 @@
+
+namespace Hotline.Settings
+{
+    public interface ISystemAreaDomainService
+    {
+        Task<List<SystemArea>> GetAreaTree();
+    }
+}

+ 8 - 0
src/Hotline/Settings/ISystemAreaRepository.cs

@@ -0,0 +1,8 @@
+using XF.Domain.Repository;
+
+namespace Hotline.Settings
+{
+    public interface ISystemAreaRepository: IRepository<SystemArea>
+    {
+    }
+}

+ 2 - 0
src/Hotline/Settings/ISystemDomainService.cs

@@ -15,5 +15,7 @@ namespace Hotline.Settings
         /// <returns></returns>
         Task<IEnumerable<KeyValuePair<int, string>>> QueryOrgLevelOptionsAsync(CancellationToken cancellationToken);
         Task<IEnumerable<KeyValuePair<string, string>>> QueryOrgLevelStringOptionsAsync(CancellationToken cancellationToken);
+
+        Task<IReadOnlyList<SysDicData>> GetSysDicDataByCodeAsync(string code, CancellationToken cancellationToken = default);
     }
 }

+ 0 - 18
src/Hotline/Settings/SysDicDataDomainRepository.cs

@@ -1,18 +0,0 @@
-using XF.Domain.Dependency;
-
-namespace Hotline.Settings
-{
-    public class SysDicDataDomainRepository : ISysDicDataDomainRepository, IScopeDependency
-    {
-        private readonly ISysDicDataRepository _sysDicDataRepository;
-        public SysDicDataDomainRepository(ISysDicDataRepository sysDicDataRepository)
-        {
-            _sysDicDataRepository = sysDicDataRepository;
-        }
-
-        public async Task<IReadOnlyList<SysDicData>> GetSysDicDataByCode(string code)
-        {
-            return await _sysDicDataRepository.Queryable().Where(x => x.DicTypeCode == code).ToTreeAsync(x => x.Children, x => x.ParentId, "");
-        }
-    }
-}

+ 15 - 0
src/Hotline/Settings/SysDicTypeConsts.cs

@@ -89,4 +89,19 @@ public class SysDicTypeConsts
     /// 紧急程度
     /// </summary>
     public const string Urgency = "Urgency";
+
+    /// <summary>
+    /// 专利类型
+    /// </summary>
+    public const string PatentType = "PatentType";
+
+    /// <summary>
+    /// 推送分类
+    /// </summary>
+    public const string PushType = "PushType";
+
+    /// <summary>
+    /// 投诉举报目标
+    /// </summary>
+    public const string AffairTarget = "AffairTarget";
 }

+ 28 - 0
src/Hotline/Settings/SystemArea.cs

@@ -0,0 +1,28 @@
+using SqlSugar;
+using XF.Domain.Repository;
+
+namespace Hotline.Settings
+{
+    public class SystemArea: CreationEntity
+    {
+        /// <summary>
+        /// 区域名称
+        /// </summary>
+        public string AreaName { get; set; }
+
+        /// <summary>
+        /// 上级ID
+        /// </summary>
+        [SugarColumn(IsNullable = true)]
+        public string ParentId { get; set; }
+
+        /// <summary>
+        /// 简称
+        /// </summary>
+        public string AreaNameAbbreviation { get; set; }
+
+
+        [SugarColumn(IsIgnore = true)]
+        public List<SystemArea> Children { get; set; }
+    }
+}

+ 19 - 0
src/Hotline/Settings/SystemAreaDomainService.cs

@@ -0,0 +1,19 @@
+using XF.Domain.Dependency;
+
+namespace Hotline.Settings
+{
+    public class SystemAreaDomainService : ISystemAreaDomainService, IScopeDependency
+    {
+        private readonly ISystemAreaRepository _systemAreaRepository;
+
+        public SystemAreaDomainService(ISystemAreaRepository systemAreaRepository)
+        {
+            _systemAreaRepository = systemAreaRepository;
+        }
+
+        public async Task<List<SystemArea>> GetAreaTree()
+        {
+           return await  _systemAreaRepository.Queryable().ToTreeAsync(x => x.Children,q=>q.ParentId, "");
+        }
+    }
+}

+ 10 - 2
src/Hotline/Settings/SystemDataAuthority.cs

@@ -1,18 +1,24 @@
-using Hotline.Share.Enums.Settings;
+using Hotline.Identity.Roles;
+using Hotline.Share.Enums.Settings;
+using SqlSugar;
 using System.ComponentModel;
+using System.Security.Cryptography;
 using XF.Domain.Entities;
 using XF.Domain.Repository;
 
 namespace Hotline.Settings
 {
     [Description("数据权限分配")]
-    public class SystemDataAuthority: CreationEntity
+    public class SystemDataAuthority : CreationEntity
     {
         /// <summary>
         /// 角色ID
         /// </summary>
         public string RoleId { get; set; }
 
+        [Navigate(NavigateType.OneToOne, nameof(RoleId))]
+        public Role Role { get; set; }
+
         /// <summary>
         /// 角色Code
         /// </summary>
@@ -29,5 +35,7 @@ namespace Hotline.Settings
         public string TableId { get; set; }
 
 
+        [Navigate(NavigateType.OneToOne, nameof(TableId))]
+        public SystemDataTable Table { get; set; }
     }
 }

+ 10 - 1
src/Hotline/Settings/SystemDomainService.cs

@@ -5,10 +5,14 @@ namespace Hotline.Settings;
 public class SystemDomainService : ISystemDomainService, IScopeDependency
 {
     private readonly ISystemOrganizeRepository _organizeRepository;
+    private readonly ISysDicDataRepository _sysDicDataRepository;
 
-    public SystemDomainService(ISystemOrganizeRepository organizeRepository)
+    public SystemDomainService(
+        ISystemOrganizeRepository organizeRepository,
+        ISysDicDataRepository sysDicDataRepository)
     {
         _organizeRepository = organizeRepository;
+        _sysDicDataRepository = sysDicDataRepository;
     }
 
     public async Task<IEnumerable<KeyValuePair<int, string>>> QueryOrgLevelOptionsAsync(CancellationToken cancellationToken)
@@ -30,4 +34,9 @@ public class SystemDomainService : ISystemDomainService, IScopeDependency
         var rsp = await QueryOrgLevelOptionsAsync(cancellationToken);
         return rsp.Select(d => new KeyValuePair<string, string>(d.Key.ToString(), d.Value));
     }
+
+    public async Task<IReadOnlyList<SysDicData>> GetSysDicDataByCodeAsync(string code, CancellationToken cancellationToken = default)
+    {
+        return await _sysDicDataRepository.Queryable().Where(x => x.DicTypeCode == code).ToTreeAsync(x => x.Children, x => x.ParentId, "");
+    }
 }

+ 4 - 2
src/Hotline/Settings/SystemOrganize.cs

@@ -34,12 +34,14 @@ public class SystemOrganize : CreationEntity
     /// <summary>
     /// 上级ID
     /// </summary>
-    public string ParentId { get; set; }
+    [SugarColumn(IsIgnore = true)]
+    public string? ParentId { get; set; }
 
     /// <summary>
     /// 上级名称
     /// </summary>
-    public string ParentName { get; set; }
+    [SugarColumn(IsIgnore = true)]
+    public string? ParentName { get; set; }
 
     /// <summary>
     /// 是否启用

+ 20 - 0
src/Hotline/Settings/TimeLimits/ITimeLimitDomainService.cs

@@ -0,0 +1,20 @@
+namespace Hotline.Settings.TimeLimits
+{
+    public interface ITimeLimitDomainService
+    {
+        /// <summary>
+        /// 新增
+        /// </summary>
+        /// <param name="model"></param>
+        /// <returns></returns>
+        Task<string> AddAsync(TimeLimit model, CancellationToken cancellationToken);
+
+        /// <summary>
+        /// 修改
+        /// </summary>
+        /// <param name="model"></param>
+        /// <param name="cancellationToken"></param>
+        /// <returns></returns>
+        Task UpdateAsync(TimeLimit model, CancellationToken cancellationToken);
+    }
+}

+ 9 - 0
src/Hotline/Settings/TimeLimits/ITimeLimitRepository.cs

@@ -0,0 +1,9 @@
+using XF.Domain.Repository;
+
+namespace Hotline.Settings.TimeLimits
+{
+    public interface ITimeLimitRepository : IRepository<TimeLimit>
+    {
+
+    }
+}

+ 36 - 0
src/Hotline/Settings/TimeLimits/TimeLimit.cs

@@ -0,0 +1,36 @@
+using Hotline.Share.Dtos.Order;
+using Hotline.Share.Enums.Order;
+using SqlSugar;
+using XF.Domain.Repository;
+
+namespace Hotline.Settings.TimeLimits
+{
+    public class TimeLimit : CreationEntity
+    {
+
+        public string TimeLimitName { get; set; }
+
+        public string WorkflowName { get; set; }
+
+        public string WorkflowCode { get; set; }
+
+        public ETimeLimitState TimeLimitState { get; set; }
+
+        [SugarColumn(ColumnDataType = "longtext", IsJson = true, IsNullable = true)]
+        public List<ParamTypeModel>? ParamArr { get; set; }
+
+        /// <summary>
+        /// 排序
+        /// </summary>
+        [SugarColumn(ColumnDataType = "longtext", IsJson = true, IsNullable = true)]
+        public List<PriorityModel>? Priority { get; set; }
+
+        /// <summary>
+        /// 组合
+        /// </summary>
+        [SugarColumn(ColumnDataType = "longtext", IsJson = true, IsNullable = true)]
+        public List<CombinationModel>? Combination { get; set; }
+
+
+    }
+}

+ 30 - 0
src/Hotline/Settings/TimeLimits/TimeLimitDomainService.cs

@@ -0,0 +1,30 @@
+using XF.Domain.Dependency;
+using XF.Domain.Exceptions;
+
+namespace Hotline.Settings.TimeLimits
+{
+    public class TimeLimitDomainService : ITimeLimitDomainService, IScopeDependency
+    {
+        private readonly ITimeLimitRepository _timeLimitRepository;
+
+        public TimeLimitDomainService(ITimeLimitRepository timeLimitRepository)
+        {
+            _timeLimitRepository = timeLimitRepository;
+        }
+
+        public async Task<string> AddAsync(TimeLimit model, CancellationToken cancellationToken)
+        {
+            return await _timeLimitRepository.AddAsync(model, cancellationToken);
+        }
+
+        public async Task UpdateAsync(TimeLimit model, CancellationToken cancellationToken)
+        {
+            var dbModel = await _timeLimitRepository.GetAsync(model.Id, cancellationToken);
+            if (dbModel == null)
+            {
+                throw new UserFriendlyException("无效数据");
+            }
+            await _timeLimitRepository.UpdateAsync(model, cancellationToken);
+        }
+    }
+}

+ 19 - 7
src/XF.Domain.Repository/Entity.cs

@@ -15,25 +15,25 @@ public abstract class Entity : IEntity<string>, IDomainEvents, IDataPermission,
     /// 组织Id
     /// </summary>
     [SugarColumn(ColumnDescription = "组织Id", IsNullable = true)]
-    public string? CreatorOrgId { get; private set; }
+    public string? CreatorOrgId { get; set; }
 
     /// <summary>
     /// 组织编码
     /// </summary>
     [SugarColumn(ColumnDescription = "组织编码", IsNullable = true)]
-    public string? CreatorOrgCode { get; private set; }
+    public string? CreatorOrgCode { get; set; }
 
     /// <summary>
     /// 创建人
     /// </summary>
     [SugarColumn(ColumnDescription = "创建人", IsNullable = true)]
-    public string? CreatorId { get; private set; }
+    public string? CreatorId { get; set; }
 
     /// <summary>
     /// 赋值部门Id
     /// </summary>
     [SugarColumn(ColumnDescription = "数据权限区域Id", IsNullable = true)]
-    public string AreaId { get; private set; }
+    public string AreaId { get; set; }
 
     public void CreateDataPermission(string orgId, string orgCode, string creatorId, string? areaId)
     {
@@ -75,10 +75,10 @@ public abstract class SoftDeleteEntity : Entity, IHasDeletionTime, ISoftDelete
     /// 删除时间
     /// </summary>
     [SugarColumn(ColumnDescription = "删除时间")]
-    public DateTime? DeletionTime { get; private set; }
+    public DateTime? DeletionTime { get; set; }
 
     [SugarColumn(ColumnDescription = "是否删除")]
-    public bool IsDeleted { get; private set; }
+    public bool IsDeleted { get; set; }
 
     public void SoftDelete()
     {
@@ -93,7 +93,7 @@ public abstract class SoftDeleteEntity : Entity, IHasDeletionTime, ISoftDelete
 public abstract class CreationSoftDeleteEntity : CreationEntity, IHasDeletionTime, ISoftDelete
 {
     [SugarColumn(ColumnDescription = "是否删除")]
-    public bool IsDeleted { get; private set; }
+    public bool IsDeleted { get; set; }
 
     /// <summary>
     /// 删除时间
@@ -140,6 +140,12 @@ public abstract class WorkflowEntity : FullStateEntity, IWorkflow
     [SugarColumn(IsNullable = true)]
     public string? WorkflowId { get; set; }
 
+    /// <summary>
+    /// 过期时间配置id
+    /// </summary>
+    [SugarColumn(IsNullable = true)]
+    public string? ExpiredTimeConfigId { get; set; }
+
     [SugarColumn(ColumnDataType = "varchar(1000)", IsJson = true)]
     public List<string> AssignOrgCodes { get; set; } = new();
 
@@ -227,6 +233,12 @@ public abstract class PositionWorkflowEntity : PositionEntity, IWorkflow
     [SugarColumn(IsNullable = true)]
     public string? WorkflowId { get; set; }
 
+    /// <summary>
+    /// 过期时间配置id
+    /// </summary>
+    [SugarColumn(IsNullable = true)]
+    public string? ExpiredTimeConfigId { get; set; }
+
     [SugarColumn(ColumnDataType = "varchar(1000)", IsJson = true)]
     public List<string> AssignOrgCodes { get; set; } = new();
 

+ 7 - 0
src/XF.Domain.Repository/IRepositorySqlSugar.cs

@@ -64,8 +64,15 @@ namespace XF.Domain.Repository
         UpdateNavTaskInit<TEntity, TEntity> UpdateNav(List<TEntity> entities);
         UpdateNavTaskInit<TEntity, TEntity> UpdateNav(List<TEntity> entities, UpdateNavRootOptions options);
 
+        /// <summary>
+        /// 未实现统一为子表赋值creatorId, creatorOrg等字段,插入前需手动赋值
+        /// </summary>
         InsertNavTaskInit<TEntity, TEntity> AddNav(TEntity entity);
         InsertNavTaskInit<TEntity, TEntity> AddNav(TEntity entity, InsertNavRootOptions options);
+
+        /// <summary>
+        /// 未实现统一为子表赋值creatorId, creatorOrg等字段,插入前需手动赋值
+        /// </summary>
         InsertNavTaskInit<TEntity, TEntity> AddNav(List<TEntity> entities);
         InsertNavTaskInit<TEntity, TEntity> AddNav(List<TEntity> entities, InsertNavRootOptions options);
 

+ 1 - 1
src/XF.Domain.Repository/IRepositoryWorkflow.cs

@@ -13,7 +13,7 @@ namespace XF.Domain.Repository
         where TEntity : class, IEntity<string>, new()
         where TKey : IEquatable<TKey>
     {
-        ISugarQueryable<TEntity> Queryable(bool includeDeleted = false);
+        ISugarQueryable<TEntity> Queryable(bool permissionVerify = false, bool includeDeleted = false, bool workflowFilter = true);
     }
 
     public interface IRepositoryWorkflow<TEntity> : IRepositoryWorkflow<TEntity, string> where TEntity : class, IEntity<string>, new()

+ 5 - 0
src/XF.Domain/Entities/IDataPermission.cs

@@ -18,6 +18,11 @@ namespace XF.Domain.Entities
     {
         string? WorkflowId { get; set; }
 
+        /// <summary>
+        /// 过期时间配置id
+        /// </summary>
+        string? ExpiredTimeConfigId { get; set; }
+
         /// <summary>
         /// 指派部门编码
         /// </summary>