qinchaoyue 5 tháng trước cách đây
mục cha
commit
849a65386c
41 tập tin đã thay đổi với 1048 bổ sung46 xóa
  1. 1 1
      src/Hotline.Api/Controllers/Snapshot/IndustryController.cs
  2. 27 1
      src/Hotline.Api/Controllers/Snapshot/SnapshotController.cs
  3. 229 3
      src/Hotline.Api/Controllers/TestController.cs
  4. 11 3
      src/Hotline.Application.Tests/Application/SnapshotApplicationMockTest.cs
  5. 86 2
      src/Hotline.Application.Tests/Application/SnapshotApplicationTest.cs
  6. 8 3
      src/Hotline.Application.Tests/Application/SystemSettingCacheManagerTest.cs
  7. 1 1
      src/Hotline.Application.Tests/Controller/SnapshotControllerTest.cs
  8. 36 2
      src/Hotline.Application.Tests/Mock/OrderServiceMock.cs
  9. 1 0
      src/Hotline.Application/Identity/IdentityAppService.cs
  10. 4 1
      src/Hotline.Application/Snapshot/DefaultSnapshotApplication.cs
  11. 45 1
      src/Hotline.Application/Snapshot/ISnapshotApplication.cs
  12. 1 0
      src/Hotline.Application/Snapshot/IndustryApplication.cs
  13. 136 8
      src/Hotline.Application/Snapshot/SnapshotApplicationBase.cs
  14. 4 1
      src/Hotline.Application/Snapshot/ZiGongSnapshotApplication.cs
  15. 1 0
      src/Hotline.Repository.SqlSugar/Extensions/SqlSugarStartupExtensions.cs
  16. 1 0
      src/Hotline.Repository.SqlSugar/Snapshot/IndustryRepository.cs
  17. 1 0
      src/Hotline.Repository.SqlSugar/Snapshot/OrderSnapshotRepository.cs
  18. 19 0
      src/Hotline.Repository.SqlSugar/Snapshot/SnapshotBulletinRepository.cs
  19. 36 0
      src/Hotline.Repository.SqlSugar/Snapshot/SnapshotOrderPublishRepository.cs
  20. 1 0
      src/Hotline.Repository.SqlSugar/Snapshot/ThirdAccountRepository.cs
  21. 4 1
      src/Hotline.Share/Dtos/Article/BulletinDto.cs
  22. 12 2
      src/Hotline.Share/Dtos/Snapshot/HomePageDto.cs
  23. 118 0
      src/Hotline.Share/Dtos/Snapshot/OrderPublishDto.cs
  24. 38 0
      src/Hotline.Share/Dtos/Snapshot/SnapshotBulletinDto.cs
  25. 5 0
      src/Hotline/Caching/Interfaces/ISysDicDataCacheManager.cs
  26. 5 0
      src/Hotline/Caching/Services/SysDicDataCacheManager.cs
  27. 0 4
      src/Hotline/Hotline.csproj
  28. 13 0
      src/Hotline/Orders/OldSendProData.cs
  29. 3 3
      src/Hotline/SeedData/SnapshotSeedData.cs
  30. 22 2
      src/Hotline/SeedData/SystemDicDataSeedData.cs
  31. 10 0
      src/Hotline/Settings/SettingConstants.cs
  32. 5 0
      src/Hotline/Settings/SysDicTypeConsts.cs
  33. 3 3
      src/Hotline/Snapshot/Industry.cs
  34. 1 1
      src/Hotline/Snapshot/Interfaces/IIndustryRepository.cs
  35. 1 1
      src/Hotline/Snapshot/Interfaces/IOrderSnapshotRepository.cs
  36. 11 0
      src/Hotline/Snapshot/Interfaces/ISnapshotBulletinRepository.cs
  37. 11 0
      src/Hotline/Snapshot/Interfaces/ISnapshotOrderPublishRepository.cs
  38. 1 1
      src/Hotline/Snapshot/Interfaces/IThirdAccountRepository.cs
  39. 7 1
      src/Hotline/Snapshot/OrderSnapshot.cs
  40. 73 0
      src/Hotline/Snapshot/SnapshotBulletin.cs
  41. 56 0
      src/Hotline/Snapshot/SnapshotOrderPublish.cs

+ 1 - 1
src/Hotline.Api/Controllers/Snapshot/IndustryController.cs

@@ -1,6 +1,6 @@
 using Hotline.Application.Snapshot;
 using Hotline.Share.Dtos.Snapshot;
-using Hotline.Snapshot;
+using Hotline.Snapshot.Interfaces;
 using Microsoft.AspNetCore.Mvc;
 
 namespace Hotline.Api.Controllers.Snapshot;

+ 27 - 1
src/Hotline.Api/Controllers/Snapshot/SnapshotController.cs

@@ -13,6 +13,7 @@ using Hotline.Share.Enums.Order;
 using Hotline.Share.Enums.Snapshot;
 using Hotline.Share.Tools;
 using Hotline.Snapshot;
+using Hotline.Snapshot.Interfaces;
 using Hotline.Tools;
 using Mapster;
 using Microsoft.AspNetCore.Authorization;
@@ -98,6 +99,31 @@ public class SnapshotController : BaseController
         return order.Adapt<AddSnapshotOrderOutDto>();
     }
 
+    /// <summary>
+    /// 获取行业集合
+    /// </summary>
+    /// <returns></returns>
+    [HttpGet("industry")]
+    public async Task<IList<IndustryOutDto>> GetIndustresAsync()
+        => await _snapshotApplication.GetIndustresAsync();
+
+    /// <summary>
+    /// 获取公开的工单集合
+    /// </summary>
+    /// <returns></returns>
+    [HttpGet("order/published")]
+    public async Task<IList<OrderPublishOutDto>> GetPublishOrderAsync([FromQuery] OrderPublishInDto dto)
+        => await _snapshotApplication.GetOrderPublishAsync(dto, HttpContext.RequestAborted);
+
+    /// <summary>
+    /// 获取公开的工单详情
+    /// </summary>
+    /// <param name="id"></param>
+    /// <returns></returns>
+    [HttpGet("order/published/{id}")]
+    public async Task<OrderPublishDetailOutDto> GetOrderPublishDetailAsync(string id)
+        => await _snapshotApplication.GetOrderPublishDetailAsync(id, HttpContext.RequestAborted);
+
     /// <summary>
     /// 获取小程序公告列表
     /// </summary>
@@ -106,7 +132,7 @@ public class SnapshotController : BaseController
     [HttpGet("bulletions")]
     [AllowAnonymous]
     public virtual async Task<IReadOnlyList<BulletinOutDto>> QueryBulletinsAsync([FromQuery] BulletinInDto dto)
-        => await _snapshotApplication.GetBulletinsAsync(dto);
+        => await _snapshotApplication.GetBulletinsAsync(dto, HttpContext.RequestAborted);
 
     /// <summary>
     /// 公告详情

+ 229 - 3
src/Hotline.Api/Controllers/TestController.cs

@@ -1,4 +1,5 @@
 using DocumentFormat.OpenXml.Drawing.Charts;
+using DocumentFormat.OpenXml.Office2016.Drawing.ChartDrawing;
 using DotNetCore.CAP;
 using Hotline.Ai.Visit;
 using Hotline.Application.CallCenter;
@@ -39,6 +40,7 @@ using Hotline.Share.Dtos.FlowEngine.Workflow;
 using Hotline.Share.Dtos.Order;
 using Hotline.Share.Dtos.Realtime;
 using Hotline.Share.Dtos.TrCallCenter;
+using Hotline.Share.Enums.CallCenter;
 using Hotline.Share.Enums.FlowEngine;
 using Hotline.Share.Enums.JudicialManagement;
 using Hotline.Share.Enums.Order;
@@ -54,6 +56,7 @@ using Microsoft.AspNetCore.Mvc;
 using Microsoft.Extensions.Options;
 using MiniExcelLibs;
 using Newtonsoft.Json;
+using NPOI.POIFS.Crypt.Dsig;
 using SqlSugar;
 using StackExchange.Redis;
 using System.Threading;
@@ -134,6 +137,7 @@ public class TestController : BaseController
     //private readonly ICacheManager<User> _cache;
     private readonly ICalcExpireTime _expireTime;
     private readonly ICallNativeRepository _callNativeRepository;
+    private readonly IRepository<OldSendProData> _oldSendProDataRepository;
 
 
     public TestController(
@@ -187,7 +191,8 @@ ICallApplication callApplication,
         ISystemSettingCacheManager systemSettingCacheManager,
         ICalcExpireTime expireTime
 ,
-        ICallNativeRepository callNativeRepository)
+        ICallNativeRepository callNativeRepository,
+        IRepository<OldSendProData> oldSendProDataRepository)
     {
         _logger = logger;
         //_authorizeGenerator = authorizeGenerator;
@@ -221,7 +226,6 @@ ICallApplication callApplication,
         _qualityApplication = qualityApplication;
         _enforcementApplication = enforcementApplication;
         _workflowDomainService = workflowDomainService;
-        _orderRepository = orderRepository;
         _mapper = mapper;
         _orderReportApplication = orderReportApplication;
         _enforcementOrdersRepository = enforcementOrdersRepository;
@@ -237,8 +241,230 @@ ICallApplication callApplication,
         _systemSettingCacheManager = systemSettingCacheManager;
         _expireTime = expireTime;
         _callNativeRepository = callNativeRepository;
+        _oldSendProDataRepository = oldSendProDataRepository;
+    }
+
+    /// <summary>
+    /// 修改泸州省工单编码区域
+    /// </summary>
+    /// <returns></returns>
+    [HttpPost("updateoldsendprodata")]
+    [AllowAnonymous]
+    public async Task UpdateOldSendProData()
+    {
+        var list = await _oldSendProDataRepository.Queryable().Where(p => p.ProvinceNo.Contains("99511500")).ToListAsync();
+        if (list != null && list.Any())
+        {
+            foreach (var item in list)
+            {
+                var prono = item.ProvinceNo;
+                prono = prono.Replace("99511500", "99510500");
+                item.NewProvinceNo = prono;
+                await _oldSendProDataRepository.UpdateAsync(item);
+            }
+        }
+    }
+
+    /// <summary>
+    /// 修改工单省编号
+    /// </summary>
+    /// <returns></returns>
+    [HttpPost("updatesendprodata")]
+    [AllowAnonymous]
+    public async Task UpdateSendProData()
+    {
+        var list = await _oldSendProDataRepository.Queryable().Where(p => p.ProvinceNo.Contains("99511500")).ToListAsync();
+        if (list != null && list.Any())
+        {
+            foreach (var item in list)
+            {
+                var data = await _orderRepository.GetAsync(p => p.Id == item.Id, HttpContext.RequestAborted);
+                if (data != null)
+                {
+                    data.ProvinceNo = item.NewProvinceNo;
+                    await _orderRepository.Updateable(data).UpdateColumns(d => d.ProvinceNo).ExecuteCommandAsync(HttpContext.RequestAborted);
+                }
+            }
+        }
     }
 
+    /// <summary>
+    /// 从新推送省上数据
+    /// </summary>
+    /// <returns></returns>
+    [HttpGet("sendpushprodata")]
+    [AllowAnonymous]
+    public async Task SendPushProData(string provinceNo)
+    {
+        //推送 受理信息、结果信息、过程信息、话务信息、回访信息
+        var list = await _oldSendProDataRepository.Queryable()
+            .Where(p => p.CreatorName == null)
+            .WhereIF(!string.IsNullOrEmpty(provinceNo), p => p.ProvinceNo == provinceNo).ToListAsync();
+        if (list != null && list.Any())
+        {
+            foreach (var item in list)
+            {
+                var order = await _orderRepository.GetAsync(p => p.Id == item.Id, HttpContext.RequestAborted);
+                if (order != null)
+                {
+                    item.CreatorName = item.NewProvinceNo;
+                    await _oldSendProDataRepository.Updateable(item).UpdateColumns(d => d.CreatorName).ExecuteCommandAsync(HttpContext.RequestAborted);
+
+                    //受理信息
+                    #region 受理信息
+                    //var publishCallRecordDto = new PublishCallRecrodDto() { };
+                    //if (order.SourceChannelCode == AppDefaults.SourceChannel.DianHua &&
+                    //    !string.IsNullOrEmpty(order.CallId))
+                    //{
+                    //    if (_appOptions.Value.GetDefaultAppScopeConfiguration().CallCenterType == AppDefaults.CallCenterType.TianRun)
+                    //    {
+                    //        var callRecord = await _callApplication.GetTianrunCallAsync(order?.CallId, HttpContext.RequestAborted);
+                    //        if (callRecord != null)
+                    //        {
+                    //            publishCallRecordDto.TrCallRecordDto = _mapper.Map<TrCallDto>(callRecord);
+                    //        }
+                    //    }
+                    //    else if (_appOptions.Value.GetDefaultAppScopeConfiguration().CallCenterType == AppDefaults.CallCenterType.XingTang)
+                    //    {
+                    //        var call = await _callApplication.GetCallAsync(order?.CallId, HttpContext.RequestAborted);
+                    //        if (call is not null)
+                    //        {
+                    //            publishCallRecordDto.TrCallRecordDto = _mapper.Map<TrCallDto>(call);
+
+                    //            // 工单开始办理如果获取的通话记录是呼出并且录音文件是空就不推送通话记录
+                    //            // 如果 通话记录是呼入, 并且没有录音文件
+                    //            if (_systemSettingCacheManager.OrderStartHandlerPushCallIsNull && call.Direction == ECallDirection.Out && !string.IsNullOrEmpty(call.AudioFile))
+                    //            {
+                    //                publishCallRecordDto.TrCallRecordDto = null;
+                    //            }
+                    //        }
+                    //    }
+                    //}
+                    //publishCallRecordDto.Order = _mapper.Map<OrderDto>(order);
+
+                    //await _capPublisher.PublishAsync(EventNames.HotlineOrderFlowStarted, publishCallRecordDto,
+                    //    cancellationToken: HttpContext.RequestAborted);
+                    #endregion
+
+                    //结果信息
+                    #region 受理信息、话务信息、结果信息
+                    if (order != null)
+                    {
+                        var trace = await _workflowTraceRepository.Queryable()
+                            .FirstAsync(d => d.WorkflowId == order.WorkflowId && d.StepType == EStepType.End, HttpContext.RequestAborted);
+                        var orderFlowDto = new OrderFlowDto
+                        {
+                            Order = _mapper.Map<OrderDto>(order),
+                            WorkflowTrace = _mapper.Map<WorkflowTraceDto>(trace)
+                        };
+                        if (order.SourceChannelCode == AppDefaults.SourceChannel.DianHua &&
+                            !string.IsNullOrEmpty(order.CallId))
+                        {
+                            if (_appOptions.Value.GetDefaultAppScopeConfiguration().CallCenterType == AppDefaults.CallCenterType.TianRun)
+                            {
+                                var callRecord = await _callApplication.GetTianrunCallAsync(order?.CallId, HttpContext.RequestAborted);
+                                if (callRecord != null)
+                                {
+                                    orderFlowDto.TrCallRecordDto = _mapper.Map<TrCallDto>(callRecord);
+                                }
+                            }
+                            else if (_appOptions.Value.GetDefaultAppScopeConfiguration().CallCenterType == AppDefaults.CallCenterType.XingTang)
+                            {
+                                var call = await _callApplication.GetCallAsync(order?.CallId, HttpContext.RequestAborted);
+                                if (call is not null)
+                                {
+                                    orderFlowDto.TrCallRecordDto = _mapper.Map<TrCallDto>(call);
+
+                                    // 工单开始办理如果获取的通话记录是呼出并且录音文件是空就不推送通话记录
+                                    // 如果 通话记录是呼入, 并且没有录音文件
+                                    if (_systemSettingCacheManager.OrderStartHandlerPushCallIsNull && call.Direction == ECallDirection.Out && !string.IsNullOrEmpty(call.AudioFile))
+                                    {
+                                        orderFlowDto.TrCallRecordDto = null;
+                                    }
+                                }
+                            }
+                        }
+                        //这里需要判断是否是警情退回
+                        orderFlowDto.IsNonPoliceReturn = false;
+                        await _capPublisher.PublishAsync(Hotline.Share.Mq.EventNames.HotlineOrderFiled, orderFlowDto, cancellationToken: HttpContext.RequestAborted);
+                        //_logger.LogWarning($"推送完成: {order.ProvinceNo}");
+                    }
+
+                    #endregion
+
+                    //过程信息
+                    #region 过程信息
+                    //查询过程数据
+
+                    if (order != null)
+                    {
+                        var listStep = await _workflowTraceRepository.Queryable()
+                             .Where(p => p.WorkflowId == order.WorkflowId && p.TraceState == EWorkflowTraceState.Normal).ToListAsync();
+                        if (listStep != null && listStep.Any())
+                        {
+                            foreach (var itemStep in listStep)
+                            {
+                                var orderDto = _mapper.Map<OrderDto>(order);
+                                var flowDto = new OrderFlowDto
+                                {
+                                    Order = orderDto,
+                                    WorkflowTrace = _mapper.Map<WorkflowTraceDto>(itemStep),
+                                    ExpiredTimeChanged = false,
+                                    HandlerOrgLevel = itemStep.HandlerOrgId.CalcOrgLevel()
+                                };
+                                await _capPublisher.PublishAsync(Hotline.Share.Mq.EventNames.HotlineOrderFlowHandled, flowDto, cancellationToken: HttpContext.RequestAborted);
+                            }
+                        }
+                    }
+
+                    #endregion
+                    //话务信息
+
+                    //回访信息
+                    #region 回访信息
+
+                    if (order != null && order.Status == EOrderStatus.Visited)
+                    {
+                        var listVist = await _orderRepository.Queryable()
+                        .Includes(x => x.OrderVisits.Where(q => q.VisitState == EVisitState.Visited).ToList(), d => d.OrderVisitDetails)
+                        .Where(x => x.Id == item.Id && x.Status == EOrderStatus.Visited).ToListAsync();
+
+                        foreach (var itemVisit in listVist)
+                        {
+                            try
+                            {
+                                var visit = itemVisit.OrderVisits.FirstOrDefault();
+                                if (visit != null)
+                                {
+                                    var visitRemark = visit.OrderVisitDetails.Where(q => q.VisitTarget == EVisitTarget.Org).FirstOrDefault()?.VisitContent;
+                                    //推省上
+                                    await _capPublisher.PublishAsync(Hotline.Share.Mq.EventNames.HotlineOrderVisited,
+                                    new PublishVisitDto()
+                                    {
+                                        Order = _mapper.Map<OrderDto>(itemVisit),
+                                        No = visit.No,
+                                        VisitType = visit.VisitType,
+                                        VisitName = visit.CreatorName,
+                                        VisitTime = visit.VisitTime,
+                                        VisitRemark = string.IsNullOrEmpty(visitRemark) == true ? "满意" : visitRemark,
+                                        AreaCode = itemVisit.AreaCode!,
+                                        SubjectResultSatifyCode = visit.NowEvaluate.Key,
+                                        FirstSatisfactionCode = itemVisit.FirstVisitResultCode,
+                                        ClientGuid = ""
+                                    }, cancellationToken: HttpContext.RequestAborted);
+                                }
+                            }
+                            catch { }
+                        }
+                    }
+
+                    #endregion
+                }
+            }
+        }
+    }
+
+
 
     [HttpGet("time")]
     [AllowAnonymous]
@@ -1054,7 +1280,7 @@ ICallApplication callApplication,
     /// <returns></returns>
     [HttpPost("push_order_call")]
     [AllowAnonymous]
-    public async Task PushOrderCallAsync([FromBody]List<string> ProvinceNos)
+    public async Task PushOrderCallAsync([FromBody] List<string> ProvinceNos)
     {
         var orders = await _orderRepository.Queryable()
             .Where(m => ProvinceNos.Contains(m.ProvinceNo))

+ 11 - 3
src/Hotline.Application.Tests/Application/SnapshotApplicationMockTest.cs

@@ -3,6 +3,7 @@ using System.Threading.Tasks;
 using Hotline.Application.Snapshot;
 using Hotline.Caching.Interfaces;
 using Hotline.File;
+using Hotline.FlowEngine.Workflows;
 using Hotline.Orders;
 using Hotline.Repository.SqlSugar.Extensions;
 using Hotline.Settings;
@@ -10,6 +11,7 @@ using Hotline.Share.Dtos.Settings;
 using Hotline.Share.Dtos.Snapshot;
 using Hotline.Share.Enums.Snapshot;
 using Hotline.Snapshot;
+using Hotline.Snapshot.Interfaces;
 using Hotline.Users;
 using Mapster;
 using Moq;
@@ -23,7 +25,7 @@ namespace Hotline.Application.Tests.Snapshot
     {
         private readonly Mock<IThirdIdentiyService> _thirdLoginServiceMock;
         private readonly Mock<IRepository<Industry>> _industryRepositoryMock;
-        private readonly Mock<IRepository<Article.Bulletin>> _bulletinRepositoryMock;
+        private readonly Mock<ISnapshotBulletinRepository> _bulletinRepositoryMock;
         private readonly Mock<ISessionContext> _sessionContextMock;
         private readonly Mock<IRepository<RedPackRecord>> _redPackRecordRepositoryMock;
         private readonly Mock<IRepository<Order>> _orderRepositoryMock;
@@ -33,6 +35,8 @@ namespace Hotline.Application.Tests.Snapshot
         private readonly Mock<ISystemAreaDomainService> _systemAreaDomainServiceMock;
         private readonly Mock<IFileRepository> _fileRepositoryMock;
         private readonly Mock<ISystemDicDataCacheManager> _systemDicDataCacheManagerMock;
+        private readonly Mock<ISnapshotOrderPublishRepository> _snapshotOrderPublishRepositoryMock;
+        private readonly Mock<IRepository<WorkflowTrace>> _workflowTraceRepositoryMock;
 
         private readonly DefaultSnapshotApplication _snapshotApplication;
 
@@ -40,7 +44,7 @@ namespace Hotline.Application.Tests.Snapshot
         {
             _thirdLoginServiceMock = new Mock<IThirdIdentiyService>();
             _industryRepositoryMock = new Mock<IRepository<Industry>>();
-            _bulletinRepositoryMock = new Mock<IRepository<Article.Bulletin>>();
+            _bulletinRepositoryMock = new Mock<ISnapshotBulletinRepository>();
             _sessionContextMock = new Mock<ISessionContext>();
             _redPackRecordRepositoryMock = new Mock<IRepository<RedPackRecord>>();
             _orderRepositoryMock = new Mock<IRepository<Order>>();
@@ -50,6 +54,8 @@ namespace Hotline.Application.Tests.Snapshot
             _systemAreaDomainServiceMock = new Mock<ISystemAreaDomainService>();
             _fileRepositoryMock = new Mock<IFileRepository>();
             _systemDicDataCacheManagerMock = new Mock<ISystemDicDataCacheManager>();
+            _snapshotOrderPublishRepositoryMock = new Mock<ISnapshotOrderPublishRepository>();
+            _workflowTraceRepositoryMock = new Mock<IRepository<WorkflowTrace>>();
 
             _snapshotApplication = new DefaultSnapshotApplication(
                 _thirdLoginServiceMock.Object,
@@ -63,7 +69,9 @@ namespace Hotline.Application.Tests.Snapshot
                 _systemSettingCacheManagerMock.Object,
                 _systemAreaDomainServiceMock.Object,
                 _fileRepositoryMock.Object,
-                _systemDicDataCacheManagerMock.Object
+                _systemDicDataCacheManagerMock.Object,
+                _snapshotOrderPublishRepositoryMock.Object,
+                _workflowTraceRepositoryMock.Object
             );
         }
 

+ 86 - 2
src/Hotline.Application.Tests/Application/SnapshotApplicationTest.cs

@@ -2,15 +2,18 @@
 using Hotline.Api.Controllers;
 using Hotline.Application.Identity;
 using Hotline.Application.Snapshot;
+using Hotline.Application.Tests.Mock;
 using Hotline.File;
 using Hotline.Identity.Accounts;
 using Hotline.Identity.Roles;
+using Hotline.Orders;
 using Hotline.Share.Dtos.Article;
 using Hotline.Share.Dtos.Snapshot;
 using Hotline.Share.Enums;
 using Hotline.Share.Enums.Snapshot;
 using Hotline.Share.Tools;
 using Hotline.Snapshot;
+using Hotline.Snapshot.Interfaces;
 using Hotline.Users;
 using Microsoft.AspNetCore.Http;
 using Microsoft.Extensions.DependencyInjection;
@@ -27,8 +30,11 @@ public class SnapshotApplicationTest : TestBase
     private readonly IIndustryApplication _industryApplication;
     private readonly IIndustryRepository _industryRepository;
     private readonly IFileRepository _fileRepository;
+    private readonly OrderServiceMock _orderServiceMock;
+    private readonly IOrderRepository _orderRepository;
+    private readonly IOrderSnapshotRepository _orderSnapshotRepository;
 
-    public SnapshotApplicationTest(IAccountRepository accountRepository, IRepository<Role> roleRepository, UserController userController, IServiceScopeFactory scopeFactory, IRepository<User> userRepository, IHttpContextAccessor httpContextAccessor, ISnapshotApplication snapshotApplication, IIdentityAppService identityAppService, IRepository<RedPackRecord> redPackRecordRepository, IIndustryApplication industryApplication, IIndustryRepository industryRepository, IFileRepository fileRepository) : base(accountRepository, roleRepository, userController, scopeFactory, userRepository, httpContextAccessor)
+    public SnapshotApplicationTest(IAccountRepository accountRepository, IRepository<Role> roleRepository, UserController userController, IServiceScopeFactory scopeFactory, IRepository<User> userRepository, IHttpContextAccessor httpContextAccessor, ISnapshotApplication snapshotApplication, IIdentityAppService identityAppService, IRepository<RedPackRecord> redPackRecordRepository, IIndustryApplication industryApplication, IIndustryRepository industryRepository, IFileRepository fileRepository, OrderServiceMock orderServiceMock, IOrderRepository orderRepository, IOrderSnapshotRepository orderSnapshotRepository) : base(accountRepository, roleRepository, userController, scopeFactory, userRepository, httpContextAccessor)
     {
         _snapshotApplication = snapshotApplication;
         _identityAppService = identityAppService;
@@ -36,6 +42,9 @@ public class SnapshotApplicationTest : TestBase
         _industryApplication = industryApplication;
         _industryRepository = industryRepository;
         _fileRepository = fileRepository;
+        _orderServiceMock = orderServiceMock;
+        _orderRepository = orderRepository;
+        _orderSnapshotRepository = orderSnapshotRepository;
     }
 
     [Fact]
@@ -46,6 +55,81 @@ public class SnapshotApplicationTest : TestBase
         result.Industrys.First().DisplayOrder.ShouldBe(1, "排序异常");
     }
 
+    /// <summary>
+    /// 添加随手拍公告
+    /// </summary>
+    /// <returns></returns>
+    [Fact]
+    public async Task AddBulletin_Test()
+    {
+        var industry = await _industryRepository.Queryable()
+            .OrderBy(m => m.DisplayOrder)
+            .FirstAsync();
+        if (industry == null)
+        {
+            return;
+        }
+        var inDto = new AddSnapshotBulletinInDto 
+        {
+            Title = "单元测试" + DateTime.Now.ToLongDateTimeString(),
+            Content = "测试内容" + DateTime.Now.ToLongDateTimeString(),
+            SnapshotBulletinTypeId = industry.BulletinTypeGuideId!,
+            SnapshotBulletinTypeName = industry.BulletinTypeGuideName!
+        };
+        var bulletinId = await _snapshotApplication.AddBulletinAsync(inDto);
+        inDto = new AddSnapshotBulletinInDto
+        {
+            Title = "单元测试" + DateTime.Now.ToLongDateTimeString(),
+            Content = "测试内容" + DateTime.Now.ToLongDateTimeString(),
+            SnapshotBulletinTypeId = industry.BulletinTypePublicityId!,
+            SnapshotBulletinTypeName = industry.BulletinTypePublicityName!
+        };
+        bulletinId = await _snapshotApplication.AddBulletinAsync(inDto);
+        await _snapshotApplication.AuditBulletinAsync(new ExamineBulletinDto { Id = bulletinId, IsPass = true, Reason = "测试审核通过"});
+
+        var items = await _snapshotApplication.GetBulletinsAsync(new BulletinInDto { IndustryId = industry.Id }, CancellationToken.None);
+        items.Count.ShouldNotBe(0, "公告数量为0");
+    }
+
+    /// <summary>
+    /// 获取公开工单集合
+    /// </summary>
+    /// <returns></returns>
+    [Fact]
+    public async Task GetPublishOrder_Test()
+    {
+        var industry = await _industryRepository.Queryable()
+            .OrderBy(m => m.DisplayOrder)
+            .FirstAsync();
+
+        SetZuoXi();
+        var order = _orderServiceMock.CreateSnapshotOrder()
+            .办理到派单员()
+            .办理到归档(SetPaiDanYuan)
+            .GetCreateResult();
+        var orderEntity = await _orderRepository.GetAsync(order.Id);
+        var orderSnapshot = await _orderSnapshotRepository.GetAsync(order.Id);
+        var inDto = new AddSnapshotOrderPublishInDto
+        {
+            ArrangeContent = orderEntity.Content,
+            ArrangeOpinion = orderEntity.ActualOpinion,
+            ArrangeTitle = orderEntity.Title,
+            OrderId = orderEntity.Id,
+            Address = orderEntity.FullAddress,
+            HandleTime = DateTime.Now
+        };
+        await _snapshotApplication.AddOrderPublishAsync(inDto, CancellationToken.None);
+        var items = await _snapshotApplication.GetOrderPublishAsync(new OrderPublishInDto { IndustryId = industry.Id }, CancellationToken.None);
+        items.Count.ShouldNotBe(0);
+        var orderPublishDetail = await _snapshotApplication.GetOrderPublishDetailAsync(items.OrderByDescending(m => m.HandleTime).First().Id, CancellationToken.None);
+        orderPublishDetail.ShouldNotBeNull();
+    }
+
+    [Fact]
+    public async Task GetOrderPublishDetail_Test()
+    { 
+    }
+
     [Fact]
     public async Task GetBulletins_Test()
     {
@@ -54,7 +138,7 @@ public class SnapshotApplicationTest : TestBase
         {
             IndustryId = homePage.Industrys.First(m => m.Name == "文化旅游").Id,
         };
-        var items = await _snapshotApplication.GetBulletinsAsync(inDto);
+        var items = await _snapshotApplication.GetBulletinsAsync(inDto, CancellationToken.None);
         items.ShouldNotBeNull();
         items.Any().ShouldBe(true, "公告数据为空");
         items.Any(m => m.Title.IsNullOrEmpty()).ShouldBe(false, "标题错误");

+ 8 - 3
src/Hotline.Application.Tests/Application/SystemSettingCacheManagerTest.cs

@@ -34,8 +34,8 @@ public class SystemSettingCacheManagerTest : TestBase
     {
         var dd = DateTime.Parse("11/19/2024 18:08:00");
         _systemSettingCacheManager.CallSyncUnPushDateTime.ShouldBe(DateTime.Parse("2024/11/19 18:08:00"));
-        var result = _systemSettingCacheManager.CancelPublishOrderEnabled;
-        result.ShouldBeTrue();
+        //var result = _systemSettingCacheManager.CancelPublishOrderEnabled;
+        //result.ShouldBeTrue();
         var seconds = _systemSettingCacheManager.VisitCallDelaySecond;
         seconds.ShouldBe(60);
 
@@ -50,7 +50,7 @@ public class SystemSettingCacheManagerTest : TestBase
         _systemSettingCacheManager.WxOpenAppSecret.ShouldNotBeNull();
         _systemSettingCacheManager.VisitCallDelaySecond.ShouldNotBe(0);
         _systemSettingCacheManager.AutomaticPublishOrder.ShouldBe(true);
-        _systemSettingCacheManager.CancelPublishOrderEnabled.ShouldBe(true);
+        //_systemSettingCacheManager.CancelPublishOrderEnabled.ShouldBe(true);
 
         _systemDicDataCacheManager.RemoveSysDicDataCache(SysDicTypeConsts.Workplace);
         var workplace = _systemDicDataCacheManager.Workplace;
@@ -61,5 +61,10 @@ public class SystemSettingCacheManagerTest : TestBase
         var workArea = _systemDicDataCacheManager.WorkplaceName;
         workArea.ShouldNotBeNull();
         workArea.Count.ShouldNotBe(0);
+
+        _systemDicDataCacheManager.RemoveSysDicDataCache(SysDicTypeConsts.SnapshotBulletinType);
+        var snapshotBulletinType = _systemDicDataCacheManager.SnapshotBulletinType;
+        snapshotBulletinType.ShouldNotBeNull();
+        snapshotBulletinType.Count.ShouldNotBe(0);
     }
 }

+ 1 - 1
src/Hotline.Application.Tests/Controller/SnapshotControllerTest.cs

@@ -7,7 +7,7 @@ using Hotline.Orders;
 using Hotline.Share.Dtos.Snapshot;
 using Hotline.Share.Enums.Snapshot;
 using Hotline.Share.Tools;
-using Hotline.Snapshot;
+using Hotline.Snapshot.Interfaces;
 using Hotline.Users;
 using Microsoft.AspNetCore.Http;
 using Microsoft.AspNetCore.Mvc;

+ 36 - 2
src/Hotline.Application.Tests/Mock/OrderServiceMock.cs

@@ -1,10 +1,14 @@
-using Hotline.Api.Controllers;
+using AutoFixture;
+using Hotline.Api.Controllers;
+using Hotline.Api.Controllers.Snapshot;
 using Hotline.Application.Tests.Dto;
 using Hotline.Orders;
 using Hotline.Repository.SqlSugar.Orders;
 using Hotline.Share.Dtos.FlowEngine;
 using Hotline.Share.Dtos.Order;
+using Hotline.Share.Dtos.Snapshot;
 using Hotline.Share.Enums.FlowEngine;
+using Hotline.Share.Enums.Snapshot;
 using Hotline.Share.Tools;
 using Microsoft.AspNetCore.Http;
 using Microsoft.AspNetCore.Mvc;
@@ -24,8 +28,10 @@ public class OrderServiceMock
     private AddOrderDto AddOrderDto;
     private readonly IRepository<Order> _orderRepository;
     private readonly IOrderVisitRepository _orderVisitRepository;
+    private readonly SnapshotController _snapshotController;
+    public readonly IFixture _fixture;
 
-    public OrderServiceMock(OrderController orderController, IRepository<Order> orderRepository, IOrderVisitRepository orderVisitRepository)
+    public OrderServiceMock(OrderController orderController, IRepository<Order> orderRepository, IOrderVisitRepository orderVisitRepository, SnapshotController snapshotController)
     {
         _orderController = orderController;
         _orderController.ControllerContext = new ControllerContext
@@ -34,6 +40,34 @@ public class OrderServiceMock
         };
         _orderRepository = orderRepository;
         _orderVisitRepository = orderVisitRepository;
+        _snapshotController = snapshotController;
+        _snapshotController.ControllerContext = new ControllerContext
+        {
+            HttpContext = new DefaultHttpContext()
+        };
+        _fixture = new Fixture();
+    }
+
+    public OrderServiceMock CreateSnapshotOrder()
+    {
+        var homePage = _snapshotController.GetHomePageAsync().GetAwaiter().GetResult();
+        var industry = homePage.Industrys.Where(m => m.IndustryType == EIndustryType.Declare).FirstOrDefault();
+        var pageBase = _snapshotController.GetIndustryBaseAsync(industry.Id).GetAwaiter().GetResult();
+
+        var inDto = _fixture.Create<AddSnapshotOrderInDto>();
+        inDto.Street = "单元测试街道" + DateTime.Now.ToLongDateTimeString();
+        inDto.IndustryId = industry.Id;
+        inDto.Town = "仙市镇";
+        inDto.County = "沿滩区";
+        inDto.Description = "单元测试添加的时间描述";
+        inDto.IsSecret = false;
+        //inDto.JobType = 
+        foreach (var item in inDto.Files)
+        {
+            item.FileName = DateTime.Now.ToShortTimeString() + "文件.doc";
+        }
+        CreateOrderOutDto = _snapshotController.AddOrderAsync(inDto).GetAwaiter().GetResult().ToJson().FromJson<CreateOrderOutDto>();
+        return this;
     }
 
     public OrderServiceMock CreateOrder(string callId = "")

+ 1 - 0
src/Hotline.Application/Identity/IdentityAppService.cs

@@ -18,6 +18,7 @@ using Hotline.Share.Enums.Snapshot;
 using Hotline.Share.Enums.User;
 using Hotline.Share.Tools;
 using Hotline.Snapshot;
+using Hotline.Snapshot.Interfaces;
 using Hotline.Users;
 using IdentityModel;
 using Mapster;

+ 4 - 1
src/Hotline.Application/Snapshot/DefaultSnapshotApplication.cs

@@ -1,9 +1,12 @@
 using Hotline.Caching.Interfaces;
 using Hotline.DI;
 using Hotline.File;
+using Hotline.FlowEngine.Workflows;
 using Hotline.Orders;
 using Hotline.Settings;
+using Hotline.Share.Dtos.Snapshot;
 using Hotline.Snapshot;
+using Hotline.Snapshot.Interfaces;
 using Hotline.Users;
 using System;
 using System.Collections.Generic;
@@ -20,7 +23,7 @@ namespace Hotline.Application.Snapshot;
 public class DefaultSnapshotApplication : SnapshotApplicationBase
     , ISnapshotApplication, IScopeDependency
 {
-    public DefaultSnapshotApplication(IThirdIdentiyService thirdLoginService, IRepository<Industry> industryRepository, IRepository<Article.Bulletin> bulletinRepository, ISessionContext sessionContext, IRepository<RedPackRecord> redPackRecordRepository, IRepository<Order> orderRepository, IThirdAccountRepository thirdAccountRepository, IRepository<OrderSnapshot> orderSnapshotRepository, ISystemSettingCacheManager systemSettingCacheManager, ISystemAreaDomainService systemAreaDomainService, IFileRepository fileRepository, ISystemDicDataCacheManager systemDicDataCacheManager) : base(thirdLoginService, industryRepository, bulletinRepository, sessionContext, redPackRecordRepository, orderRepository, thirdAccountRepository, orderSnapshotRepository, systemSettingCacheManager, systemAreaDomainService, fileRepository, systemDicDataCacheManager)
+    public DefaultSnapshotApplication(IThirdIdentiyService thirdLoginService, IRepository<Industry> industryRepository, ISnapshotBulletinRepository bulletinRepository, ISessionContext sessionContext, IRepository<RedPackRecord> redPackRecordRepository, IRepository<Order> orderRepository, IThirdAccountRepository thirdAccountRepository, IRepository<OrderSnapshot> orderSnapshotRepository, ISystemSettingCacheManager systemSettingCacheManager, ISystemAreaDomainService systemAreaDomainService, IFileRepository fileRepository, ISystemDicDataCacheManager systemDicDataCacheManager, ISnapshotOrderPublishRepository snapshotOrderPublishRepository, IRepository<WorkflowTrace> workflowTraceRepository) : base(thirdLoginService, industryRepository, bulletinRepository, sessionContext, redPackRecordRepository, orderRepository, thirdAccountRepository, orderSnapshotRepository, systemSettingCacheManager, systemAreaDomainService, fileRepository, systemDicDataCacheManager, snapshotOrderPublishRepository, workflowTraceRepository)
     {
     }
 }

+ 45 - 1
src/Hotline.Application/Snapshot/ISnapshotApplication.cs

@@ -17,12 +17,18 @@ public interface ISnapshotApplication
     /// <returns></returns>
     Task<HomePageOutDto> GetHomePageAsync();
 
+    /// <summary>
+    /// 获取行业集合
+    /// </summary>
+    /// <returns></returns>
+    Task<IList<IndustryOutDto>> GetIndustresAsync();
+
     /// <summary>
     /// 获取小程序公告列表
     /// </summary>
     /// <param name="dto"></param>
     /// <returns></returns>
-    Task<IReadOnlyList<BulletinOutDto>> GetBulletinsAsync(BulletinInDto dto);
+    Task<IReadOnlyList<BulletinOutDto>> GetBulletinsAsync(BulletinInDto dto, CancellationToken cancellationToken);
     
     /// <summary>
     /// 获取工单列表
@@ -64,4 +70,42 @@ public interface ISnapshotApplication
     /// <param name="requestAborted"></param>
     /// <returns></returns>
     Task<IndustryBaseOutDto> GetIndustryBaseAsync(string id, CancellationToken requestAborted);
+
+    /// <summary>
+    /// 添加随手拍公告
+    /// </summary>
+    /// <param name="dto"></param>
+    /// <returns></returns>
+    Task<string> AddBulletinAsync(AddSnapshotBulletinInDto dto);
+
+    /// <summary>
+    /// 审核公告
+    /// </summary>
+    /// <param name="examineBulletinDto"></param>
+    /// <returns></returns>
+    Task AuditBulletinAsync(ExamineBulletinDto examineBulletinDto);
+
+    /// <summary>
+    /// 获取公开的工单集合
+    /// </summary>
+    /// <param name="dto"></param>
+    /// <param name="requestAborted"></param>
+    /// <returns></returns>
+    Task<IList<OrderPublishOutDto>> GetOrderPublishAsync(OrderPublishInDto dto, CancellationToken requestAborted);
+
+    /// <summary>
+    /// 获取公开的工单详情
+    /// </summary>
+    /// <param name="id"></param>
+    /// <param name="requestAborted"></param>
+    /// <returns></returns>
+    Task<OrderPublishDetailOutDto> GetOrderPublishDetailAsync(string id, CancellationToken requestAborted);
+
+    /// <summary>
+    /// 添加公开工单
+    /// </summary>
+    /// <param name="addSnapshotOrderPublishInDto"></param>
+    /// <param name="none"></param>
+    /// <returns></returns>
+    Task AddOrderPublishAsync(AddSnapshotOrderPublishInDto addSnapshotOrderPublishInDto, CancellationToken none);
 }

+ 1 - 0
src/Hotline.Application/Snapshot/IndustryApplication.cs

@@ -2,6 +2,7 @@
 using Hotline.Share.Dtos.Snapshot;
 using Hotline.Share.Tools;
 using Hotline.Snapshot;
+using Hotline.Snapshot.Interfaces;
 using Mapster;
 using System;
 using System.Collections.Generic;

+ 136 - 8
src/Hotline.Application/Snapshot/SnapshotApplicationBase.cs

@@ -22,6 +22,12 @@ using Hotline.Settings;
 using Hotline.Share.Dtos.Settings;
 using Hotline.File;
 using Hotline.Share.Enums.Article;
+using Hotline.Tools;
+using Hotline.Snapshot.Interfaces;
+using DotNetCore.CAP;
+using Microsoft.AspNetCore.Http;
+using Hotline.Share.Dtos.FlowEngine;
+using Hotline.FlowEngine.Workflows;
 
 namespace Hotline.Application.Snapshot;
 
@@ -32,7 +38,7 @@ public abstract class SnapshotApplicationBase
 {
     private readonly IThirdAccountRepository _thirdAccountRepository;
     private readonly IRepository<Order> _orderRepository;
-    private readonly IRepository<Article.Bulletin> _bulletinRepository;
+    private readonly ISnapshotBulletinRepository _bulletinRepository;
 
     /// <summary>
     /// 行业
@@ -46,8 +52,10 @@ public abstract class SnapshotApplicationBase
     private readonly ISystemAreaDomainService _systemAreaDomainService;
     private readonly IFileRepository _fileRepository;
     private readonly ISystemDicDataCacheManager _systemDicDataCacheManager;
+    private readonly ISnapshotOrderPublishRepository _snapshotOrderPublishRepository;
+    private readonly IRepository<WorkflowTrace> _workflowTraceRepository;
 
-    public SnapshotApplicationBase(IThirdIdentiyService thirdLoginService, IRepository<Industry> industryRepository, IRepository<Article.Bulletin> bulletinRepository, ISessionContext sessionContext, IRepository<RedPackRecord> redPackRecordRepository, IRepository<Order> orderRepository, IThirdAccountRepository thirdAccountRepository, IRepository<OrderSnapshot> orderSnapshotRepository, ISystemSettingCacheManager systemSettingCacheManager, ISystemAreaDomainService systemAreaDomainService, IFileRepository fileRepository, ISystemDicDataCacheManager systemDicDataCacheManager)
+    public SnapshotApplicationBase(IThirdIdentiyService thirdLoginService, IRepository<Industry> industryRepository, ISnapshotBulletinRepository bulletinRepository, ISessionContext sessionContext, IRepository<RedPackRecord> redPackRecordRepository, IRepository<Order> orderRepository, IThirdAccountRepository thirdAccountRepository, IRepository<OrderSnapshot> orderSnapshotRepository, ISystemSettingCacheManager systemSettingCacheManager, ISystemAreaDomainService systemAreaDomainService, IFileRepository fileRepository, ISystemDicDataCacheManager systemDicDataCacheManager, ISnapshotOrderPublishRepository snapshotOrderPublishRepository, IRepository<WorkflowTrace> workflowTraceRepository)
     {
         _thirdLoginService = thirdLoginService;
         _industryRepository = industryRepository;
@@ -61,6 +69,8 @@ public abstract class SnapshotApplicationBase
         _systemAreaDomainService = systemAreaDomainService;
         _fileRepository = fileRepository;
         _systemDicDataCacheManager = systemDicDataCacheManager;
+        _snapshotOrderPublishRepository = snapshotOrderPublishRepository;
+        _workflowTraceRepository = workflowTraceRepository;
     }
 
     /// <summary>
@@ -94,6 +104,21 @@ public abstract class SnapshotApplicationBase
         };
     }
 
+    /// <summary>
+    /// 获取行业集合
+    /// </summary>
+    /// <returns></returns>
+    public async Task<IList<IndustryOutDto>> GetIndustresAsync()
+    {
+        var fileServiceUrl = _systemSettingCacheManager.FileServerUrl;
+        var fileDownloadApi = fileServiceUrl + _systemSettingCacheManager.FileDownloadApi;
+        var items = await _industryRepository.Queryable()
+            .Where(m => m.IsEnable)
+            .OrderBy(m => m.DisplayOrder)
+            .ToListAsync(m => new IndustryOutDto());
+        return items;
+    }
+
     /// <summary>
     /// 行业页面基础数据
     /// </summary>
@@ -108,7 +133,7 @@ public abstract class SnapshotApplicationBase
             ?? throw UserFriendlyException.SameMessage("行业不存在:" + id);
 
         var bulletinId = await _bulletinRepository.Queryable()
-            .Where(m => m.BulletinTypeId == indurstry.BulletinTypeGuideId && m.BulletinState == EBulletinState.ReviewPass && m.IsArrive == true)
+            .Where(m => m.SnapshotBulletinTypeId == indurstry.BulletinTypeGuideId && m.BulletinState == EBulletinState.ReviewPass && m.IsArrive == true)
             .OrderByDescending(m => m.CreationTime)
             .Select(m => m.Id)
             .FirstAsync(requestAborted);
@@ -116,7 +141,7 @@ public abstract class SnapshotApplicationBase
         {
             Industry = indurstry.Adapt<IndustryOutDto>()
         };
-        outDto.Industry.BulletinId = bulletinId;
+        outDto.BulletinId = bulletinId;
         if (indurstry.IndustryType == EIndustryType.Declare)
         {
             outDto.AreaTree = (await _systemAreaDomainService.GetAreaTree(parentId: "510300")).Adapt<List<SystemAreaOutDto>>();
@@ -130,17 +155,74 @@ public abstract class SnapshotApplicationBase
         return outDto;
     }
 
+    public async Task AddOrderPublishAsync(AddSnapshotOrderPublishInDto dto, CancellationToken cancellation)
+    {
+        dto.ValidateObject();
+        var snapshotOrder = await _orderSnapshotRepository.GetAsync(dto.OrderId)
+            ?? throw UserFriendlyException.SameMessage("工单不存在");
+        var order = await _orderRepository.Queryable()
+            .Where(m => m.Id == dto.OrderId)
+            .Select(m => new { m.Id, m.No })
+            .FirstAsync(cancellation)
+            ?? throw UserFriendlyException.SameMessage("工单不存在");
+        var entity = dto.Adapt<SnapshotOrderPublish>();
+        entity.Id = order.Id;
+        entity.IndustryId = snapshotOrder.IndustryId;
+        entity.IndustryName = snapshotOrder.IndustryName;
+        entity.No = order.No;
+        await _snapshotOrderPublishRepository.AddAsync(entity);
+    }
+
+    /// <summary>
+    /// 获取公开工单集合
+    /// </summary>
+    /// <param name="dto"></param>
+    /// <param name="requestAborted"></param>
+    /// <returns></returns>
+    public async Task<IList<OrderPublishOutDto>> GetOrderPublishAsync(OrderPublishInDto dto, CancellationToken requestAborted)
+    {
+        dto.ValidateObject();
+        var items = await _snapshotOrderPublishRepository.Queryable()
+            .Where(m => m.IndustryId == dto.IndustryId)
+            .WhereIF(dto.Keyword.NotNullOrEmpty(), m => m.No.Contains(dto.Keyword) || m.ArrangeTitle.Contains(dto.Keyword))
+            .Select<OrderPublishOutDto>()
+            .ToFixedListAsync(dto, requestAborted);
+
+        return items;
+    }
+
+    /// <summary>
+    /// 获取公开的工单详情
+    /// </summary>
+    /// <param name="id"></param>
+    /// <param name="requestAborted"></param>
+    /// <returns></returns>
+    public async Task<OrderPublishDetailOutDto> GetOrderPublishDetailAsync(string id, CancellationToken requestAborted)
+    {
+        var publish = await _snapshotOrderPublishRepository.GetAsync(id) ??
+            throw UserFriendlyException.SameMessage("工单不存在");
+
+        var outDto = publish.Adapt<OrderPublishDetailOutDto>();
+        outDto.Workflow = await _workflowTraceRepository.Queryable()
+            .Where(m => m.ExternalId == publish.OrderId && m.AcceptTime != null && m.AcceptorOrgName != null)
+            .OrderBy(m => m.AcceptTime)
+            .Select<SnapshotWorkflow>()
+            .ToListAsync(requestAborted);
+
+        return outDto;
+    }
+
     /// <summary>
     /// 获取随手拍小程序公告
     /// </summary>
     /// <returns></returns>
-    public async Task<IReadOnlyList<BulletinOutDto>> GetBulletinsAsync(BulletinInDto dto)
+    public async Task<IReadOnlyList<BulletinOutDto>> GetBulletinsAsync(BulletinInDto dto, CancellationToken cancellationToken)
     {
         var items = await _bulletinRepository.Queryable()
             .Where(m => m.BulletinState == EBulletinState.ReviewPass)
-            .LeftJoin<Industry>((bulletin, industry) => bulletin.BulletinTypeId == industry.BulletinTypePublicityId)
+            .LeftJoin<Industry>((bulletin, industry) => bulletin.SnapshotBulletinTypeId == industry.BulletinTypePublicityId)
             .Where((bulletin, industry) => industry.Id == dto.IndustryId)
-            .ToPageListAsync(dto.PageIndex, dto.PageSize);
+            .ToFixedListAsync(dto, cancellationToken);
 
         return items.Adapt<IReadOnlyList<BulletinOutDto>>();
     }
@@ -272,6 +354,11 @@ public abstract class SnapshotApplicationBase
         return item;
     }
 
+    /// <summary>
+    /// 获取随手拍公告详情
+    /// </summary>
+    /// <param name="id"></param>
+    /// <returns></returns>
     public async Task<BulletinOutDto> GetBulletinsDetailAsync(string id)
     {
         var detail = await _bulletinRepository.Queryable()
@@ -281,9 +368,50 @@ public abstract class SnapshotApplicationBase
             {
                 Id = m.Id,
                 Title = m.Title,
-                Content = m.Content
+                Content = m.Content,
+                CreationTime = m.CreationTime
             })
             .FirstAsync();
         return detail;
     }
+
+    /// <summary>
+    /// 添加随手拍公告
+    /// </summary>
+    /// <returns></returns>
+    public async Task<string> AddBulletinAsync(AddSnapshotBulletinInDto dto)
+    {
+        dto.ValidateObject();
+        var entity = dto.Adapt<SnapshotBulletin>();
+        entity.BulletinState = EBulletinState.InReview;
+        entity.Id = await _bulletinRepository.AddAsync(entity);
+        return entity.Id;
+    }
+
+    /// <summary>
+    /// 审核公告
+    /// </summary>
+    /// <param name="examineBulletinDto"></param>
+    /// <returns></returns>
+    public async Task AuditBulletinAsync(ExamineBulletinDto dto)
+    {
+        var bulletin = await _bulletinRepository.GetAsync(dto.Id)
+            ?? throw UserFriendlyException.SameMessage("无效数据");
+        if (bulletin.BulletinState != EBulletinState.InReview)
+            throw UserFriendlyException.SameMessage("当前状态不能审核");
+
+        bulletin.ExaminOpinion = dto.Reason;
+        bulletin.ExaminTime = DateTime.Now;
+        bulletin.ExaminManId = _sessionContext.RequiredUserId;
+        if (dto.IsPass)
+        {
+            bulletin.BulletinState = EBulletinState.ReviewPass;
+        }
+        else
+        {
+            bulletin.BulletinState = EBulletinState.ReviewNoPass;
+        }
+        await _bulletinRepository.UpdateAsync(bulletin);
+    }
+
 }

+ 4 - 1
src/Hotline.Application/Snapshot/ZiGongSnapshotApplication.cs

@@ -1,9 +1,12 @@
 using Hotline.Caching.Interfaces;
 using Hotline.DI;
 using Hotline.File;
+using Hotline.FlowEngine.Workflows;
 using Hotline.Orders;
 using Hotline.Settings;
+using Hotline.Share.Dtos.Snapshot;
 using Hotline.Snapshot;
+using Hotline.Snapshot.Interfaces;
 using Hotline.Users;
 using System;
 using System.Collections.Generic;
@@ -19,7 +22,7 @@ namespace Hotline.Application.Snapshot;
 [Injection(AppScopes = EAppScope.ZiGong)]
 public class ZiGongSnapshotApplication : SnapshotApplicationBase, ISnapshotApplication, IScopeDependency
 {
-    public ZiGongSnapshotApplication(IThirdIdentiyService thirdLoginService, IRepository<Industry> industryRepository, IRepository<Article.Bulletin> bulletinRepository, ISessionContext sessionContext, IRepository<RedPackRecord> redPackRecordRepository, IRepository<Order> orderRepository, IThirdAccountRepository thirdAccountRepository, IRepository<OrderSnapshot> orderSnapshotRepository, ISystemSettingCacheManager systemSettingCacheManager, ISystemAreaDomainService systemAreaDomainService, IFileRepository fileRepository, ISystemDicDataCacheManager systemDicDataCacheManager) : base(thirdLoginService, industryRepository, bulletinRepository, sessionContext, redPackRecordRepository, orderRepository, thirdAccountRepository, orderSnapshotRepository, systemSettingCacheManager, systemAreaDomainService, fileRepository, systemDicDataCacheManager)
+    public ZiGongSnapshotApplication(IThirdIdentiyService thirdLoginService, IRepository<Industry> industryRepository, ISnapshotBulletinRepository bulletinRepository, ISessionContext sessionContext, IRepository<RedPackRecord> redPackRecordRepository, IRepository<Order> orderRepository, IThirdAccountRepository thirdAccountRepository, IRepository<OrderSnapshot> orderSnapshotRepository, ISystemSettingCacheManager systemSettingCacheManager, ISystemAreaDomainService systemAreaDomainService, IFileRepository fileRepository, ISystemDicDataCacheManager systemDicDataCacheManager, ISnapshotOrderPublishRepository snapshotOrderPublishRepository, IRepository<WorkflowTrace> workflowTraceRepository) : base(thirdLoginService, industryRepository, bulletinRepository, sessionContext, redPackRecordRepository, orderRepository, thirdAccountRepository, orderSnapshotRepository, systemSettingCacheManager, systemAreaDomainService, fileRepository, systemDicDataCacheManager, snapshotOrderPublishRepository, workflowTraceRepository)
     {
     }
 }

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

@@ -133,6 +133,7 @@ namespace Hotline.Repository.SqlSugar.Extensions
 
                 var types = typeof(User).Assembly.GetTypes()
                     .Where(d => d.GetInterfaces().Any(x => x == typeof(ITable) && !d.IsAbstract))
+                    .Where(d => d.Name != "Order" && d.Name != "OrderCopy" && d.Name != "Workflow" && d.Name != "WorkflowStep" && d.Name != "WorkflowTrace")
                     .Distinct()
                     .ToArray();
 

+ 1 - 0
src/Hotline.Repository.SqlSugar/Snapshot/IndustryRepository.cs

@@ -1,6 +1,7 @@
 using Hotline.Orders;
 using Hotline.Repository.SqlSugar.DataPermissions;
 using Hotline.Snapshot;
+using Hotline.Snapshot.Interfaces;
 using SqlSugar;
 using System;
 using System.Collections.Generic;

+ 1 - 0
src/Hotline.Repository.SqlSugar/Snapshot/OrderSnapshotRepository.cs

@@ -1,5 +1,6 @@
 using Hotline.Repository.SqlSugar.DataPermissions;
 using Hotline.Snapshot;
+using Hotline.Snapshot.Interfaces;
 using SqlSugar;
 using System;
 using System.Collections.Generic;

+ 19 - 0
src/Hotline.Repository.SqlSugar/Snapshot/SnapshotBulletinRepository.cs

@@ -0,0 +1,19 @@
+using Hotline.Repository.SqlSugar.DataPermissions;
+using Hotline.Snapshot;
+using Hotline.Snapshot.Interfaces;
+using SqlSugar;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using XF.Domain.Dependency;
+
+namespace Hotline.Repository.SqlSugar.Snapshot;
+public class SnapshotBulletinRepository : BaseRepository<SnapshotBulletin>, ISnapshotBulletinRepository, IScopeDependency
+{
+    public SnapshotBulletinRepository(ISugarUnitOfWork<HotlineDbContext> uow, IDataPermissionFilterBuilder dataPermissionFilterBuilder) : base(uow, dataPermissionFilterBuilder)
+    {
+    }
+}
+

+ 36 - 0
src/Hotline.Repository.SqlSugar/Snapshot/SnapshotOrderPublishRepository.cs

@@ -0,0 +1,36 @@
+using Hotline.Repository.SqlSugar.DataPermissions;
+using Hotline.Snapshot;
+using Hotline.Snapshot.Interfaces;
+using SqlSugar;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using XF.Domain.Dependency;
+
+namespace Hotline.Repository.SqlSugar.Snapshot;
+public class SnapshotOrderPublishRepository : BaseRepository<SnapshotOrderPublish>, ISnapshotOrderPublishRepository, IScopeDependency
+{
+    public SnapshotOrderPublishRepository(ISugarUnitOfWork<HotlineDbContext> uow, IDataPermissionFilterBuilder dataPermissionFilterBuilder) : base(uow, dataPermissionFilterBuilder)
+    {
+    }
+
+    /// <summary>
+    /// 添加公开工单并更新小程序工单公开状态
+    /// </summary>
+    /// <param name="entity"></param>
+    /// <param name="cancellationToken"></param>
+    /// <returns></returns>
+    new public async Task<string> AddAsync(SnapshotOrderPublish entity, CancellationToken cancellationToken = default)
+    {
+        await Uow.Db.Ado.BeginTranAsync();
+        await Uow.Db.Updateable<OrderSnapshot>()
+            .Where(m => m.Id == entity.OrderId)
+            .SetColumns(m => m.IsAppOpened, true)
+            .ExecuteCommandAsync(cancellationToken);
+        var id = await base.AddAsync(entity, cancellationToken);
+        await Uow.Db.Ado.CommitTranAsync();
+        return id;
+    }
+}

+ 1 - 0
src/Hotline.Repository.SqlSugar/Snapshot/ThirdAccountRepository.cs

@@ -1,5 +1,6 @@
 using Hotline.Repository.SqlSugar.DataPermissions;
 using Hotline.Snapshot;
+using Hotline.Snapshot.Interfaces;
 using SqlSugar;
 using XF.Domain.Dependency;
 using XF.Domain.Repository;

+ 4 - 1
src/Hotline.Share/Dtos/Article/BulletinDto.cs

@@ -8,6 +8,7 @@ using System.Text;
 using System.Threading.Tasks;
 using Hotline.Share.Dtos.Users;
 using XF.Utility.EnumExtensions;
+using Hotline.Share.Tools;
 
 namespace Hotline.Share.Dtos.Article
 {
@@ -508,7 +509,7 @@ namespace Hotline.Share.Dtos.Article
     /// <summary>
     /// 微信小程序获取宣传学习列表入参
     /// </summary>
-    public record BulletinInDto : PagedRequest
+    public class BulletinInDto : QueryFixedDto
     {
         /// <summary>
         /// 行业Id
@@ -536,5 +537,7 @@ namespace Hotline.Share.Dtos.Article
         /// 内容
         /// </summary>
         public string Content { get; set; }
+
+        public DateTime CreationTime { get; set; }
     }
 }

+ 12 - 2
src/Hotline.Share/Dtos/Snapshot/HomePageDto.cs

@@ -111,9 +111,14 @@ public class IndustryOutDto
     public string? TxtHelpRemarks { get; set; }
 
     /// <summary>
-    /// 通知公告Id
+    /// 宫格说明文本
     /// </summary>
-    public string? BulletinId { get; set; }
+    public string? TxtRemarks { get; set; }
+
+    /// <summary>
+    /// 关怀说明
+    /// </summary>
+    public string? TxtCareRemarks { get; set; }
 
     /// <summary>
     /// 页面Url
@@ -133,6 +138,11 @@ public class IndustryBaseOutDto
     /// </summary>
     public IndustryOutDto Industry { get; set; }
 
+    /// <summary>
+    /// 通知公告Id
+    /// </summary>
+    public string? BulletinId { get; set; }
+
     /// <summary>
     /// 作业区域集合
     /// </summary>

+ 118 - 0
src/Hotline.Share/Dtos/Snapshot/OrderPublishDto.cs

@@ -0,0 +1,118 @@
+using Hotline.Share.Dtos.File;
+using Hotline.Share.Requests;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Hotline.Share.Dtos.Snapshot;
+internal class OrderPublishDto
+{
+}
+
+public class AddSnapshotOrderPublishInDto
+{
+    [Required]
+    public string OrderId { get; set; }
+
+    /// <summary>
+    /// 整理标题
+    /// </summary>
+    [Required]
+    public string ArrangeTitle { get; set; }
+
+    /// <summary>
+    /// 整理内容
+    /// </summary>
+    [Required]
+    public string ArrangeContent { get; set; }
+
+    /// <summary>
+    /// 整理结果
+    /// </summary>
+    [Required]
+    public string ArrangeOpinion { get; set; }
+
+    /// <summary>
+    /// 受理时间
+    /// </summary>
+    [Required]
+    public DateTime HandleTime { get; set; }
+
+    /// <summary>
+    /// 整理地点
+    /// </summary>
+    [Required]
+    public string Address { get; set; }
+}
+
+public class OrderPublishInDto : QueryFixedDto
+{
+    /// <summary>
+    /// 搜索文本
+    /// </summary>
+    public string? Keyword { get; set; }
+
+    /// <summary>
+    /// 行业Id
+    /// </summary>
+    [Required]
+    public string IndustryId { get; set; }
+}
+
+public class OrderPublishDetailOutDto : OrderPublishOutDto
+{
+    /// <summary>
+    /// 是否保密
+    /// </summary>
+    public bool IsSecret { get; set; }
+
+    /// <summary>
+    /// 附件
+    /// </summary>
+    public List<FileJson> FileJson { get; set; }
+
+    /// <summary>
+    /// 办理流程
+    /// </summary>
+    public List<SnapshotWorkflow> Workflow { get; set; }
+}
+
+public class SnapshotWorkflow
+{
+    /// <summary>
+    /// 接办部门名称
+    /// </summary>
+    public string AcceptorOrgName { get; set; }
+
+    /// <summary>
+    /// 接办时间
+    /// </summary>
+    public DateTime AcceptTime { get; set; }
+}
+
+public class OrderPublishOutDto
+{
+    /// <summary>
+    /// Id
+    /// </summary>
+    public string Id { get; set; }
+
+    /// <summary>
+    /// 编号
+    /// </summary>
+    public string No { get; set; }
+
+    /// <summary>
+    /// 标题
+    /// </summary>
+    public string ArrangeTitle { get; set; }
+
+    /// <summary>
+    /// 受理时间
+    /// </summary>
+    public DateTime HandleTime { get; set; }
+}
+

+ 38 - 0
src/Hotline.Share/Dtos/Snapshot/SnapshotBulletinDto.cs

@@ -0,0 +1,38 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Hotline.Share.Dtos.Snapshot;
+class SnapshotBulletinDto
+{
+}
+
+public class AddSnapshotBulletinInDto
+{
+    /// <summary>
+    /// 标题
+    /// </summary>
+    [Required]
+    public string Title { get; set; }
+
+    /// <summary>
+    /// 内容
+    /// </summary>
+    [Required]
+    public string Content { get; set; }
+
+    /// <summary>
+    /// 公告类型
+    /// </summary>
+    [Required]
+    public string SnapshotBulletinTypeId { get; set; }
+
+    /// <summary>
+    /// 公告类型名称
+    /// </summary>
+    [Required]
+    public string SnapshotBulletinTypeName { get; set; }
+}

+ 5 - 0
src/Hotline/Caching/Interfaces/ISysDicDataCacheManager.cs

@@ -40,5 +40,10 @@ namespace Hotline.Caching.Interfaces
         /// 公告类型
         /// </summary>
         IReadOnlyList<SystemDicData> BulletinType { get; }
+
+        /// <summary>
+        /// 随手拍公告类型
+        /// </summary>
+        IReadOnlyList<SystemDicDataOutDto> SnapshotBulletinType { get; }
     }
 }

+ 5 - 0
src/Hotline/Caching/Services/SysDicDataCacheManager.cs

@@ -97,6 +97,11 @@ namespace Hotline.Caching.Services
 
         public IReadOnlyList<SystemDicData> BulletinType => GetSysDicDataCache(SysDicTypeConsts.AcceptType);
 
+        /// <summary>
+        /// 随手拍公告类型
+        /// </summary>
+        public IReadOnlyList<SystemDicDataOutDto> SnapshotBulletinType => GetOrAdd(SysDicTypeConsts.SnapshotBulletinType);
+
         public void RemoveSysDicDataCache(string code)
         {
             _cacheSysDicData.Remove(code);

+ 0 - 4
src/Hotline/Hotline.csproj

@@ -22,8 +22,4 @@
     <ProjectReference Include="..\XF.Domain.Repository\XF.Domain.Repository.csproj" />
   </ItemGroup>
 
-  <ItemGroup>
-    <Folder Include="Snapshot\Interfaces\" />
-  </ItemGroup>
-
 </Project>

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

@@ -0,0 +1,13 @@
+using XF.Domain.Repository;
+
+namespace Hotline.Orders
+{
+    public class OldSendProData : CreationEntity
+    {
+        public string No { get; set; }
+
+        public string ProvinceNo { get; set; }
+
+        public string? NewProvinceNo { get; set; }
+    }
+}

+ 3 - 3
src/Hotline/SeedData/SnapshotSeedData.cs

@@ -22,7 +22,7 @@ public class IndustrySeedData : ISeedData<Industry>
                 PageUrl = "/pagesBase/Write/WeldingOperations",
                 PageCareUrl = "/pagesCare/Write/WeldingOperations",
                 BulletinTypePublicityId = "", BulletinTypePublicityName = "",
-                BulletinTypeGuideId = "", BulletinTypeGuideame = "电气焊作业申报操作指引" ,
+                BulletinTypeGuideId = "", BulletinTypeGuideName = "电气焊作业申报操作指引" ,
                 BackgroundImgUrl = "",
                 BannerImgUrl = "",
                 CellImgUrl = "/App_Themes/_Temp/%e7%94%b5%e6%b0%94%e7%84%8a%e4%bd%9c%e4%b8%9a_SSP_Industry_ICO_9.png",
@@ -44,7 +44,7 @@ public class IndustrySeedData : ISeedData<Industry>
                 CellImgUrl = "/App_Themes/_Temp/%e6%96%87%e5%8c%96%e6%97%85%e6%b8%b8_SSP_Industry_ICO_8.png",
                 CareCellImgUrl = "/App_Themes/_Temp/%e6%96%87%e5%8c%96%e6%97%85%e6%b8%b8_SSP_Industry_CareICO_8.png",
                 BulletinTypePublicityId = "", BulletinTypePublicityName = "文化旅游宣传学习",
-                BulletinTypeGuideId = "", BulletinTypeGuideame = "文化旅游操作指引" ,
+                BulletinTypeGuideId = "", BulletinTypeGuideName = "文化旅游操作指引" ,
                 BackgroundImgUrl = "",
                 BannerImgUrl = "",
             },
@@ -57,7 +57,7 @@ public class IndustrySeedData : ISeedData<Industry>
                 IntervalTime = 0,
                 ApproveOrgId = "", ApproveOrgName = "自贡市公安局交通警察支队",
                 BulletinTypePublicityId = "", BulletinTypePublicityName = "交通管理设施隐患宣传学习",
-                BulletinTypeGuideId = "", BulletinTypeGuideame = "交通管理设施隐患操作指引",
+                BulletinTypeGuideId = "", BulletinTypeGuideName = "交通管理设施隐患操作指引",
                 PageUrl = "/pagesBase/Write/ReportHiddenDanger",
                 PageCareUrl = "/pagesCare/Write/ReportHiddenDanger",
                 TxtHelpRemarks = "交通管理设施隐患受理范围:一、交通信号灯故障,如:路口单方向或多方向灯组熄灯、单灯组多灯全亮、红灯闪烁、路口多方向全绿灯等;二、LED显示屏故障,如:显示屏中间断字(黑屏)、异常闪烁等情形。更多内容点击查看《操作指引》",

+ 22 - 2
src/Hotline/SeedData/SystemDicDataSeedData.cs

@@ -98,10 +98,26 @@ public class SystemDicDataSeedData : ISeedData<SystemDicData>
                 new() { Id = "08dc39c1-f1f8-4717-8b03-9d562884c8f9", DicDataValue = "geren", DicDataName = "个人" }
                 ];
         }
-        if (dicTypeCode == SysDicTypeConsts.BulletinType)
+        if (dicTypeCode == SysDicTypeConsts.SnapshotBulletinType)
         {
             return [
-                new() { Id = "08dc3c2a-a719-4e13-8f67-ce196528d3bf", DicDataValue = "9", DicDataName = "随手拍公告" }
+                new() { Id = "08dc0681-af58-458b-82c8-5e2eb67cf8dd", DicDataValue = "1", DicDataName = "电气焊作业申报操作指引", Sort = 1 },
+                new() { Id = "08dc0681-bda0-481e-88b0-1182c7a6c819", DicDataValue = "2", DicDataName = "文化旅游宣传学习", Sort = 2 },
+                new() { Id = "08dc0681-bf51-4715-8a10-2566c5152641", DicDataValue = "3", DicDataName = "文化旅游操作指引", Sort = 3 },
+                new() { Id = "08dc0681-bf56-4574-81c8-d2a570a2e41b", DicDataValue = "4", DicDataName = "交通管理设施隐患宣传学习", Sort = 4 },
+                new() { Id = "08dc0681-bf57-400e-88fc-c23288c7cc80", DicDataValue = "5", DicDataName = "交通管理设施隐患操作指引", Sort = 5 },
+                new() { Id = "08dc0681-bf69-41e5-8bac-ef2799cb79bb", DicDataValue = "6", DicDataName = "宣传学习民生实事", Sort = 6 },
+                new() { Id = "08dc0681-bf85-4779-84ea-e6629a004e63", DicDataValue = "7", DicDataName = "民生实事操作指引", Sort = 7 },
+                new() { Id = "08dc0681-bf8c-42c9-81c5-3765d11a21f5", DicDataValue = "8", DicDataName = "宣传学习好人好事", Sort = 8 },
+                new() { Id = "08dc0681-d32d-4c86-8f05-9a117950f528", DicDataValue = "9", DicDataName = "好人好事操作指引", Sort = 9 },
+                new() { Id = "08dc0681-d4f4-49a8-8d34-7b3786ccae6f", DicDataValue = "10", DicDataName = "宣传学习市场监管", Sort = 10 },
+                new() { Id = "08dc0681-d583-49bc-8f4b-4b7be0d0104b", DicDataValue = "11", DicDataName = "市场监管操作指引", Sort = 11 },
+                new() { Id = "08dc0681-db09-4002-8a4d-eb8a2a428b39", DicDataValue = "12", DicDataName = "宣传学习环境保护", Sort = 12 },
+                new() { Id = "08dc0681-dec9-475c-88a1-4791c532f5b9", DicDataValue = "13", DicDataName = "环境保护操作指引", Sort = 13 },
+                new() { Id = "08dc0681-e145-4ef1-8fbf-25e52e316cf8", DicDataValue = "14", DicDataName = "宣传学习城市管理", Sort = 14 },
+                new() { Id = "08dc0681-e9e1-493b-889d-3a238c2dde39", DicDataValue = "15", DicDataName = "城市管理操作指引", Sort = 15 },
+                new() { Id = "08dc0681-ed2e-40bb-829b-c8ee518b3229", DicDataValue = "16", DicDataName = "宣传学习安全隐患", Sort = 16 },
+                new() { Id = "08dc0681-ee29-4624-865c-58d5d9667c92", DicDataValue = "17", DicDataName = "安全隐患操作指引", Sort = 17 },
                 ];
         }
 
@@ -127,6 +143,10 @@ public class SystemDicDataSeedData : ISeedData<SystemDicData>
         {
             dicType = ["08dc39c1-b8bd-412d-8ad3-293c035bd14d", "经营单位类别"];
         }
+        if (dicTypeCode == SysDicTypeConsts.SnapshotBulletinType)
+        {
+            dicType = ["08dc0681-a6e1-473d-8b1d-1b0b67e0ec13", "随手拍公告类型"];
+        }
         return new SystemDicType
         {
             Id = dicType[0],

+ 10 - 0
src/Hotline/Settings/SettingConstants.cs

@@ -667,5 +667,15 @@ namespace Hotline.Settings
         /// 小程序Banner集合
         /// </summary>
         public static string AppBanner = "小程序Banner";
+
+		/// <summary>
+		/// 部门满意度明细不显示工单
+		/// </summary>
+		public const string OrgVisitDetailHiddenOrderNo = "OrgVisitDetailHiddenOrderNo";
+
+        /// <summary>
+        /// 交办单是否保密
+        /// </summary>
+        public const string IsTheAssignmentFormConfidential = "IsTheAssignmentFormConfidential";
     }
 }

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

@@ -281,4 +281,9 @@ public class SysDicTypeConsts
     /// 经营单位类别
     /// </summary>
     public const string BusinessUnitType = "BusinessUnitType";
+
+    /// <summary>
+    /// 随手拍公告类型
+    /// </summary>
+    public const string SnapshotBulletinType = "SnapshotBulletinType";
 }

+ 3 - 3
src/Hotline/Snapshot/Industry.cs

@@ -125,17 +125,17 @@ public class Industry : CreationSoftDeleteEntity
 
     /// <summary>
     /// 关联操作指引
-    /// 从字典中取"公告类型"
+    /// 从字典中取"随手拍公告类型"
     /// </summary>
     [SugarColumn(ColumnDescription = "关联操作指引")]
     public string? BulletinTypeGuideId { get; set; }
 
     /// <summary>
     /// 关联操作指引
-    /// 从字典中取"公告类型"
+    /// 从字典中取"随手拍公告类型"
     /// </summary>
     [SugarColumn(ColumnDescription = "关联操作指引")]
-    public string? BulletinTypeGuideame { get; set; }
+    public string? BulletinTypeGuideName { get; set; }
 
     /// <summary>
     /// 背景图片 url

+ 1 - 1
src/Hotline/Snapshot/IIndustryRepository.cs → src/Hotline/Snapshot/Interfaces/IIndustryRepository.cs

@@ -6,7 +6,7 @@ using System.Text;
 using System.Threading.Tasks;
 using XF.Domain.Repository;
 
-namespace Hotline.Snapshot;
+namespace Hotline.Snapshot.Interfaces;
 public interface IIndustryRepository : IRepository<Industry>
 {
 }

+ 1 - 1
src/Hotline/Snapshot/IOrderSnapshotRepository.cs → src/Hotline/Snapshot/Interfaces/IOrderSnapshotRepository.cs

@@ -5,7 +5,7 @@ using System.Text;
 using System.Threading.Tasks;
 using XF.Domain.Repository;
 
-namespace Hotline.Snapshot;
+namespace Hotline.Snapshot.Interfaces;
 public interface IOrderSnapshotRepository : IRepository<OrderSnapshot>
 {
 }

+ 11 - 0
src/Hotline/Snapshot/Interfaces/ISnapshotBulletinRepository.cs

@@ -0,0 +1,11 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using XF.Domain.Repository;
+
+namespace Hotline.Snapshot.Interfaces;
+public interface ISnapshotBulletinRepository : IRepository<SnapshotBulletin>
+{
+}

+ 11 - 0
src/Hotline/Snapshot/Interfaces/ISnapshotOrderPublishRepository.cs

@@ -0,0 +1,11 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using XF.Domain.Repository;
+
+namespace Hotline.Snapshot.Interfaces;
+public interface ISnapshotOrderPublishRepository : IRepository<SnapshotOrderPublish>
+{
+}

+ 1 - 1
src/Hotline/Snapshot/IThirdAccountRepository.cs → src/Hotline/Snapshot/Interfaces/IThirdAccountRepository.cs

@@ -1,6 +1,6 @@
 using XF.Domain.Repository;
 
-namespace Hotline.Snapshot;
+namespace Hotline.Snapshot.Interfaces;
 public interface IThirdAccountRepository : IRepository<ThirdAccount>
 {
     Task<ThirdAccount> QueryByOpenIdAsync(string openId);

+ 7 - 1
src/Hotline/Snapshot/OrderSnapshot.cs

@@ -24,7 +24,7 @@ public class OrderSnapshot : CreationSoftDeleteEntity
     /// <inheritdoc cref="Industry"/> 表的Name
     /// </summary>
     [SugarColumn(ColumnDescription = "行业名称")]
-    public string? IndustryName { get; set; }
+    public string IndustryName { get; set; }
 
     /// <summary>
     /// 社区Id
@@ -68,6 +68,12 @@ public class OrderSnapshot : CreationSoftDeleteEntity
     /// </summary>
     [SugarColumn(ColumnDescription = "作业时间")]
     public DateTime? EndWorkTime { get; set; }
+
+    /// <summary>
+    /// 小程序公开
+    /// </summary>
+    public bool? IsAppOpened { get; set; }
+
     #region 网格员回复
 
     /// <summary>

+ 73 - 0
src/Hotline/Snapshot/SnapshotBulletin.cs

@@ -0,0 +1,73 @@
+using Hotline.Share.Dtos;
+using Hotline.Share.Enums.Article;
+using Hotline.Users;
+using SqlSugar;
+using System.ComponentModel;
+using XF.Domain.Repository;
+
+namespace Hotline.Snapshot;
+/// <summary>
+/// 随手拍公告
+/// </summary>
+[Description("随手拍公告")]
+public class SnapshotBulletin : CreationEntity
+{
+    public string Title { get; set; }
+
+    [SugarColumn(ColumnDataType = "text")]
+    public string Content { get; set; }
+
+    public string SnapshotBulletinTypeId { get; set; }
+
+    public string SnapshotBulletinTypeName { get; set; }
+
+    /// <summary>
+    /// 阅读量
+    /// </summary>
+    public int ReadedNum { get; set; }
+
+    /// <summary>
+    /// 公告状态
+    /// </summary>
+    public EBulletinState BulletinState { get; set; }
+
+    /// <summary>
+    /// 提交时间
+    /// </summary>
+    public DateTime? CommitTime { get; set; }
+
+    /// <summary>
+    /// 审核意见
+    /// </summary>
+    public string? ExaminOpinion { get; set; }
+
+    /// <summary>
+    /// 审核人
+    /// </summary>
+    public string? ExaminManId { get; set; }
+
+    /// <summary>
+    /// 审核人
+    /// </summary>
+    [Navigate(NavigateType.OneToOne, nameof(ExaminManId))]
+    public User? ExaminMan { get; set; }
+
+    /// <summary>
+    /// 审核时间
+    /// </summary>
+    public DateTime? ExaminTime { get; set; }
+
+    /// <summary>
+    /// 是否上架
+    /// </summary>
+    public bool? IsArrive { get; set; }
+
+    /// <summary>
+    /// 阅读量+1
+    /// </summary>
+    public void Read()
+    {
+        ReadedNum++;
+    }
+}
+

+ 56 - 0
src/Hotline/Snapshot/SnapshotOrderPublish.cs

@@ -0,0 +1,56 @@
+using SqlSugar;
+using System.ComponentModel;
+using XF.Domain.Repository;
+
+namespace Hotline.Snapshot;
+
+/// <summary>
+/// 小程序公开工单
+/// </summary>
+[Description("小程序公开工单")]
+public class SnapshotOrderPublish : FullStateEntity
+{
+    public string OrderId { get; set; }
+
+    /// <summary>
+    /// 行业Id
+    /// </summary>
+    public string IndustryId { get; set; }
+
+    /// <summary>
+    /// 行业名称
+    /// </summary>
+    public string IndustryName { get; set; }
+
+    /// <summary>
+    /// 工单编码
+    /// </summary>
+    public string No { get; set; }
+
+    /// <summary>
+    /// 整理标题
+    /// </summary>
+    public string ArrangeTitle { get; set; }
+
+    /// <summary>
+    /// 整理内容
+    /// </summary>
+    [SugarColumn(ColumnDataType = "varchar(8000)")]
+    public string ArrangeContent { get; set; }
+
+    /// <summary>
+    /// 整理结果
+    /// </summary>
+    [SugarColumn(ColumnDataType = "varchar(8000)")]
+    public string ArrangeOpinion { get; set; }
+
+    /// <summary>
+    /// 受理时间
+    /// </summary>
+    public DateTime HandleTime { get; set; }
+
+    /// <summary>
+    /// 整理地点
+    /// </summary>
+    public string Address { get; set; }
+}