ArticleController.cs 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322
  1. using Hotline.Application.FlowEngine;
  2. using Hotline.Article;
  3. using Hotline.FlowEngine.WorkflowModules;
  4. using Hotline.Permissions;
  5. using Hotline.Repository.SqlSugar.Extensions;
  6. using Hotline.Settings;
  7. using Hotline.Share.Dtos;
  8. using Hotline.Share.Dtos.Article;
  9. using Hotline.Share.Dtos.FlowEngine;
  10. using Hotline.Share.Dtos.Order;
  11. using Hotline.Share.Enums.Article;
  12. using MapsterMapper;
  13. using Microsoft.AspNetCore.Mvc;
  14. using Microsoft.OpenApi.Writers;
  15. using XF.Domain.Authentications;
  16. using XF.Domain.Exceptions;
  17. using XF.Domain.Repository;
  18. using XF.Utility.EnumExtensions;
  19. namespace Hotline.Api.Controllers
  20. {
  21. public class ArticleController: BaseController
  22. {
  23. private readonly IRepository<Bulletin> _bulletinRepository;
  24. private readonly IMapper _mapper;
  25. private readonly ISystemDomainService _systemDomainService;
  26. private readonly ISystemOrganizeRepository _organizeRepository;
  27. private readonly IWorkflowApplication _workflowApplication;
  28. private readonly IRepository<Circular> _circularRepository;
  29. private readonly ISessionContext _sessionContext;
  30. private readonly IRepository<CircularRecord> _circularRecordRepository;
  31. private readonly IRepository<CircularReadGroup> _circularReadGroupRepository;
  32. public ArticleController(IRepository<Bulletin> bulletinRepository,IMapper mapper, ISystemDomainService systemDomainService, ISystemOrganizeRepository organizeRepository, IWorkflowApplication workflowApplication, IRepository<Circular> circularRepository,ISessionContext sessionContext,IRepository<CircularRecord> circularRecordRepository,IRepository<CircularReadGroup> circularReadGroupRepository)
  33. {
  34. _bulletinRepository = bulletinRepository;
  35. _mapper = mapper;
  36. _systemDomainService = systemDomainService;
  37. _organizeRepository = organizeRepository;
  38. _workflowApplication = workflowApplication;
  39. _circularRepository = circularRepository;
  40. _sessionContext = sessionContext;
  41. _circularRecordRepository = circularRecordRepository;
  42. _circularReadGroupRepository = circularReadGroupRepository;
  43. }
  44. #region 通知
  45. /// <summary>
  46. /// 查询通知列表
  47. /// </summary>
  48. /// <param name="dto"></param>
  49. /// <returns></returns>
  50. [Permission(EPermission.QueryCircularList)]
  51. [HttpGet("circular/query")]
  52. public async Task<PagedDto<CircularDto>> QueryCircularList([FromQuery] QueryCircularListRequestDto dto)
  53. {
  54. var (total,items) = await _circularRepository.Queryable()
  55. .Includes(x=>x.CircularReadGroups)
  56. .WhereIF(!string.IsNullOrEmpty(dto.CircularTypeId), d => d.CircularTypeId == dto.CircularTypeId)
  57. .WhereIF(!string.IsNullOrEmpty(dto.Title), d => d.Title.Contains(dto.Title))
  58. .WhereIF(dto.CircularTimeStart.HasValue, d => d.CircularTime >= dto.CircularTimeStart)
  59. .WhereIF(dto.CircularTimeEnd.HasValue, d => d.CircularTime <= dto.CircularTimeEnd)
  60. .OrderByDescending(d => d.CreationTime)
  61. .ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted);
  62. return new PagedDto<CircularDto>(total, _mapper.Map<IReadOnlyList<CircularDto>>(items));
  63. }
  64. /// <summary>
  65. /// 通知详情(内部)
  66. /// </summary>
  67. /// <param name="id"></param>
  68. /// <returns></returns>
  69. [Permission(EPermission.CircularEntity)]
  70. [HttpGet("circular/entity/{id}")]
  71. public async Task<CircularDto> CircularEntity(string id)
  72. {
  73. var model = await _circularRepository.Queryable()
  74. .Includes(x => x.CircularReadGroups)
  75. .FirstAsync(x => x.Id == id, HttpContext.RequestAborted);
  76. return _mapper.Map<CircularDto>(model);
  77. }
  78. /// <summary>
  79. /// 新增通知
  80. /// </summary>
  81. /// <param name="dto"></param>
  82. /// <returns></returns>
  83. [Permission(EPermission.AddCircular)]
  84. [HttpPost("circular/add")]
  85. public async Task AddCircular([FromBody] CircularFlowDto dto)
  86. {
  87. var model = _mapper.Map<Circular>(dto.Data);
  88. model.CircularState = ECircularState.InReview;
  89. model.ReadedNum = 0;
  90. model.NeedReadNum = model.CircularReadGroups.Count;
  91. var id = await _circularRepository.AddAsync(model, HttpContext.RequestAborted);
  92. try
  93. {
  94. var startDto = _mapper.Map<StartWorkflowDto>(dto.Workflow);
  95. startDto.DefinitionModuleCode = WorkflowModuleConsts.CircularApply;
  96. startDto.Title = model.Title;
  97. await _workflowApplication.StartWorkflowAsync(startDto, id, HttpContext.RequestAborted);
  98. }
  99. catch (Exception ex)
  100. {
  101. await _circularRepository.RemoveAsync(id, false, HttpContext.RequestAborted);
  102. throw new UserFriendlyException($"新增通知流程失败!,{ex.Message}", "新增通知流程失败");
  103. }
  104. }
  105. /// <summary>
  106. /// 列表页面基础信息
  107. /// </summary>
  108. /// <returns></returns>
  109. [HttpGet("circular/listbasedata")]
  110. public async Task<object> CircularBaseData()
  111. {
  112. var rsp = new
  113. {
  114. CircularType = await _systemDomainService.GetSysDicDataByCodeAsync(SysDicTypeConsts.CircularType)
  115. };
  116. return rsp;
  117. }
  118. /// <summary>
  119. /// 新增页面基础数据
  120. /// </summary>
  121. /// <returns></returns>
  122. [HttpGet("circular/addbasedata")]
  123. public async Task<object> CircularAddBaseData()
  124. {
  125. var rsp = new
  126. {
  127. CircularType = _systemDomainService.GetSysDicDataByCodeAsync(SysDicTypeConsts.CircularType),
  128. OrgsOptions = await _organizeRepository.GetOrgJson(),
  129. };
  130. return rsp;
  131. }
  132. /// <summary>
  133. /// 通知阅读(内部)
  134. /// </summary>
  135. /// <param name="id"></param>
  136. /// <returns></returns>
  137. [HttpGet("circular/read/{id}")]
  138. public async Task<CircularDto> CircularRead(string id)
  139. {
  140. var model = await _circularRepository.Queryable()
  141. .Includes(x => x.CircularReadGroups)
  142. .FirstAsync(x => x.Id == id, HttpContext.RequestAborted);
  143. //更新阅读信息
  144. if (model.CircularType == ECircularType.Person)
  145. {
  146. //个人阅读
  147. var readGroup = model.CircularReadGroups.FirstOrDefault(x => x.UserId == _sessionContext.UserId && !x.IsRead);
  148. if (readGroup!=null)
  149. {
  150. readGroup.IsRead = true;
  151. readGroup.ReadTime = DateTime.Now;
  152. if (DateTime.Now > model.LostEfficacyTime)
  153. readGroup.IsTimeOut = true;
  154. else
  155. readGroup.IsTimeOut = false;
  156. await _circularReadGroupRepository.UpdateAsync(readGroup, HttpContext.RequestAborted);
  157. //处理计数
  158. }
  159. }
  160. else
  161. {
  162. //部门阅读
  163. }
  164. return _mapper.Map<CircularDto>(model);
  165. }
  166. /// <summary>
  167. /// 获取小红点计数
  168. /// </summary>
  169. /// <returns></returns>
  170. [HttpGet("megcount")]
  171. public async Task<CircularRecordDto> QueryMegCount()
  172. {
  173. var list = await _circularRecordRepository.Queryable().Where(x => x.UserId == _sessionContext.UserId || x.OrgId == _sessionContext.OrgId).ToListAsync();
  174. if (list!=null && list.Count>0)
  175. {
  176. var rsp = new CircularRecordDto();
  177. rsp.OrgCount = list.FirstOrDefault(x => x.CircularType == ECircularType.Org)?.RecordCount ?? 0;
  178. rsp.PersonCount = list.FirstOrDefault(x => x.CircularType == ECircularType.Person)?.RecordCount ?? 0;
  179. rsp.SumCount = rsp.OrgCount + rsp.PersonCount;
  180. }
  181. return new CircularRecordDto() { SumCount = 0, OrgCount = 0, PersonCount = 0 };
  182. }
  183. /// <summary>
  184. /// 查询通知流程开启参数
  185. /// </summary>
  186. /// <returns></returns>
  187. [HttpGet("circular/startflow")]
  188. public async Task<DefinedStepDto> GetCircularFlowStartOptions()
  189. {
  190. return await _workflowApplication.GetStartOptionsAsync(WorkflowModuleConsts.CircularApply, HttpContext.RequestAborted);
  191. }
  192. #endregion
  193. #region 公告
  194. /// <summary>
  195. /// 查询公告列表
  196. /// </summary>
  197. /// <param name="dto"></param>
  198. /// <returns></returns>
  199. [Permission(EPermission.QueryBulletinList)]
  200. [HttpGet("bulletin/query")]
  201. public async Task<PagedDto<BulletinDto>> QueryBulletinList([FromQuery]QueryBulletinListRequestDto dto)
  202. {
  203. var (total,items) = await _bulletinRepository.Queryable()
  204. .WhereIF(!string.IsNullOrEmpty(dto.BulletinTypeId), d => d.BulletinTypeId == dto.BulletinTypeId)
  205. .WhereIF(!string.IsNullOrEmpty(dto.Title), d => d.Title.Contains(dto.Title))
  206. .WhereIF(dto.BulletinTimeStart.HasValue, d => d.BulletinTime >= dto.BulletinTimeStart)
  207. .WhereIF(dto.BulletinTimeEnd.HasValue, d => d.BulletinTime <= dto.BulletinTimeEnd)
  208. .OrderByDescending(d => d.CreationTime)
  209. .ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted);
  210. return new PagedDto<BulletinDto>(total, _mapper.Map<IReadOnlyList<BulletinDto>>(items));
  211. }
  212. /// <summary>
  213. /// 公告详情(内部)
  214. /// </summary>
  215. /// <param name="id"></param>
  216. /// <returns></returns>
  217. [Permission(EPermission.BulletinEntity)]
  218. [HttpGet("bulletin/entity/{id}")]
  219. public async Task<BulletinDto> BulletinEntity(string id)
  220. {
  221. var model = await _bulletinRepository.Queryable()
  222. .FirstAsync(x=>x.Id == id, HttpContext.RequestAborted);
  223. return _mapper.Map<BulletinDto>(model);
  224. }
  225. /// <summary>
  226. /// 新增公告
  227. /// </summary>
  228. /// <param name="dto"></param>
  229. /// <returns></returns>
  230. [Permission(EPermission.AddBulletin)]
  231. [HttpPost("bulletin/add")]
  232. public async Task AddBulletin([FromBody]BulletinFlowDto dto)
  233. {
  234. var model = _mapper.Map<Bulletin>(dto.Data);
  235. model.BulletinState = Share.Enums.Article.EBulletinState.InReview;
  236. model.ReadedNum = 0;
  237. var id = await _bulletinRepository.AddAsync(model, HttpContext.RequestAborted);
  238. try
  239. {
  240. var startDto = _mapper.Map<StartWorkflowDto>(dto.Workflow);
  241. startDto.DefinitionModuleCode = WorkflowModuleConsts.BulletinApply;
  242. startDto.Title = model.Title;
  243. await _workflowApplication.StartWorkflowAsync(startDto, id, HttpContext.RequestAborted);
  244. }
  245. catch (Exception ex)
  246. {
  247. await _bulletinRepository.RemoveAsync(id, false, HttpContext.RequestAborted);
  248. throw new UserFriendlyException($"新增公告流程失败!,{ex.Message}", "新增公告流程失败");
  249. }
  250. }
  251. /// <summary>
  252. /// 列表页面基础数据
  253. /// </summary>
  254. /// <returns></returns>
  255. [HttpGet("bulletin/listbasedata")]
  256. public async Task<object> BulletinListBaseData()
  257. {
  258. var rsp = new
  259. {
  260. BulletinType = await _systemDomainService.GetSysDicDataByCodeAsync(SysDicTypeConsts.BulletinType)
  261. };
  262. return rsp;
  263. }
  264. /// <summary>
  265. /// 新增页面基础数据
  266. /// </summary>
  267. /// <returns></returns>
  268. [HttpGet("bulletin/addbasedata")]
  269. public async Task<object> BulletinAddBaseData()
  270. {
  271. var rsp = new
  272. {
  273. BulletinType = await _systemDomainService.GetSysDicDataByCodeAsync(SysDicTypeConsts.BulletinType),
  274. PushRanges = EnumExts.GetDescriptions<EPushRange>(),
  275. OrgsOptions = await _organizeRepository.GetOrgJson(),
  276. };
  277. return rsp;
  278. }
  279. /// <summary>
  280. /// 查询公告流程开启参数
  281. /// </summary>
  282. /// <returns></returns>
  283. [HttpGet("bulletin/startflow")]
  284. public async Task<DefinedStepDto> GetBulletinFlowStartOptions()
  285. {
  286. return await _workflowApplication.GetStartOptionsAsync(WorkflowModuleConsts.BulletinApply, HttpContext.RequestAborted);
  287. }
  288. #endregion
  289. }
  290. }