HotSpotController.cs 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371
  1. using Hotline.Caching.Interfaces;
  2. using Hotline.FlowEngine;
  3. using Hotline.Repository.SqlSugar.Extensions;
  4. using Hotline.Settings;
  5. using Hotline.Settings.Hotspots;
  6. using Hotline.Settings.TimeLimits;
  7. using Hotline.Share.Dtos;
  8. using Hotline.Share.Dtos.Hotspots;
  9. using Hotline.Share.Dtos.Settings;
  10. using Hotline.Share.Enums.Order;
  11. using Hotline.Share.Enums.Settings;
  12. using MapsterMapper;
  13. using Microsoft.AspNetCore.Mvc;
  14. using SqlSugar;
  15. using StackExchange.Redis;
  16. using XF.Domain.Exceptions;
  17. using XF.Domain.Repository;
  18. using XF.Utility.EnumExtensions;
  19. namespace Hotline.Api.Controllers
  20. {
  21. /// <summary>
  22. /// 热点
  23. /// </summary>
  24. public class HotspotController : BaseController
  25. {
  26. private readonly IRepository<Hotspot> _hotspotTypeRepository;
  27. private readonly IMapper _mapper;
  28. private readonly ITimeLimitDomainService _timeLimitDomainService;
  29. private readonly ITimeLimitRepository _timeLimitRepository;
  30. private readonly ISystemDicDataCacheManager _sysDicDataCacheManager;
  31. private readonly IEventCategoryRepository _eventCategoryRepository;
  32. public HotspotController(IRepository<Hotspot> hotspotTypeRepository,
  33. IMapper mapper, ITimeLimitDomainService timeLimitDomainService, ITimeLimitRepository timeLimitRepository, ISystemDicDataCacheManager sysDicDataCacheManager, IEventCategoryRepository eventCategoryRepository)
  34. {
  35. _hotspotTypeRepository = hotspotTypeRepository;
  36. _mapper = mapper;
  37. _timeLimitDomainService = timeLimitDomainService;
  38. _timeLimitRepository = timeLimitRepository;
  39. _sysDicDataCacheManager = sysDicDataCacheManager;
  40. _eventCategoryRepository = eventCategoryRepository;
  41. }
  42. #region 热点
  43. /// <summary>
  44. /// 查询子项
  45. /// </summary>
  46. [HttpGet("children")]
  47. public async Task<IReadOnlyList<Hotspot>> GetChildren([FromQuery] string? id)
  48. {
  49. var list = await _hotspotTypeRepository.Queryable()
  50. .WhereIF(!string.IsNullOrEmpty(id), x => x.ParentId == id)
  51. .WhereIF(string.IsNullOrEmpty(id), x => x.ParentId == null || x.ParentId == "")
  52. .OrderBy(d => d.HotSpotName)
  53. .Select(x=> new Hotspot
  54. {
  55. Id = x.Id,
  56. HotSpotName = x.HotSpotName,
  57. ParentId = x.ParentId,
  58. HotSpotFullName = x.HotSpotFullName,
  59. ProvinceCode = x.ProvinceCode,
  60. HasChild = SqlFunc.Subqueryable<Hotspot>().Where(d=>d.ParentId == x.Id).NotAny(),
  61. }).ToListAsync();
  62. return list;
  63. }
  64. /// <summary>
  65. /// 名称检索热点树形
  66. /// </summary>
  67. /// <param name="name"></param>
  68. /// <returns></returns>
  69. [HttpGet("children-hasname")]
  70. public async Task<IReadOnlyList<Hotspot>> GetChildrenHasName([FromQuery]string name)
  71. {
  72. var arr = _hotspotTypeRepository.Queryable()
  73. .WhereIF(!string.IsNullOrEmpty(name), x => x.HotSpotName.Contains(name)).Select(x=>x.Id).ToList().Cast<object>().ToArray();
  74. //.ToTreeAsync(x => x.Children, it => it.ParentId, null);
  75. return await _hotspotTypeRepository.Queryable().Select(x => new Hotspot
  76. {
  77. Id = x.Id,
  78. HotSpotName = x.HotSpotName,
  79. ParentId = x.ParentId,
  80. HotSpotFullName = x.HotSpotFullName,
  81. ProvinceCode = x.ProvinceCode,
  82. HasChild = SqlFunc.Subqueryable<Hotspot>().Where(d => d.ParentId == x.Id).NotAny(),
  83. }).ToTreeAsync(x => x.Children, it => it.ParentId,"", arr);
  84. }
  85. /// <summary>
  86. /// 查询热点数据(包含所有根目录及所查热点的所有上级对象)
  87. /// <remarks>
  88. /// 编辑页面使用
  89. /// </remarks>
  90. /// </summary>
  91. /// <param name="id"></param>
  92. /// <returns></returns>
  93. [HttpGet("{id}/with-parents")]
  94. public async Task<IReadOnlyList<Hotspot>> GetWithParents(string id)
  95. {
  96. var targetList = await _hotspotTypeRepository.Queryable()
  97. .ToTreeAsync(d => d.Children, d => d.ParentId, null, new[] { id });
  98. var topIds = targetList.Select(d => d.Id);
  99. var hotspots = await _hotspotTypeRepository.Queryable()
  100. .Where(d => string.IsNullOrEmpty(d.ParentId) && !topIds.Contains(d.Id))
  101. .ToListAsync();
  102. hotspots.AddRange(targetList);
  103. return hotspots.OrderBy(d => d.HotSpotName).ToList();
  104. }
  105. #endregion
  106. #region 事件分类管理
  107. /// <summary>
  108. /// 事件全部树形
  109. /// </summary>
  110. /// <returns></returns>
  111. [HttpGet("event/tree")]
  112. public async Task<IReadOnlyList<EventCategory>> GetEventAllTree()
  113. {
  114. return await _eventCategoryRepository.Queryable()
  115. .OrderBy(d => d.OrderBy)
  116. .ToTreeAsync(x => x.Children, it => it.ParentId,null);
  117. }
  118. /// <summary>
  119. /// 查询子项
  120. /// </summary>
  121. /// <param name="id"></param>
  122. /// <returns></returns>
  123. [HttpGet("event/children")]
  124. public async Task<IReadOnlyList<EventCategory>> GetEventChildren([FromQuery]string? id)
  125. {
  126. var list = await _eventCategoryRepository.Queryable()
  127. .WhereIF(!string.IsNullOrEmpty(id),x => x.ParentId == id)
  128. .WhereIF(string.IsNullOrEmpty(id),x=>x.ParentId == null || x.ParentId=="")
  129. .OrderBy(d => d.EventName)
  130. .Select(x => new EventCategory
  131. {
  132. Id = x.Id,
  133. EventName = x.EventName,
  134. ParentId = x.ParentId,
  135. EventFullName = x.EventFullName,
  136. HasChild = SqlFunc.Subqueryable<EventCategory>().Where(d => d.ParentId == x.Id).NotAny()
  137. }).ToListAsync();
  138. return list;
  139. }
  140. /// <summary>
  141. /// 名称检索事件树形
  142. /// </summary>
  143. /// <param name="name"></param>
  144. /// <returns></returns>
  145. [HttpGet("event/children-hasname")]
  146. public async Task<IReadOnlyList<EventCategory>> GetEventChildrenHasName([FromQuery]string name)
  147. {
  148. var arr = _eventCategoryRepository.Queryable()
  149. .WhereIF(!string.IsNullOrEmpty(name), x => x.EventName.Contains(name)).Select(x => x.Id).ToList().Cast<object>().ToArray();
  150. return await _eventCategoryRepository.Queryable().Select(
  151. x=> new EventCategory {
  152. Id = x.Id,
  153. EventName = x.EventName,
  154. ParentId = x.ParentId,
  155. EventFullName = x.EventFullName,
  156. HasChild = SqlFunc.Subqueryable<EventCategory>().Where(d => d.ParentId == x.Id).NotAny()
  157. }).ToTreeAsync(x => x.Children, it => it.ParentId, "", arr);
  158. }
  159. #region 管理接口
  160. /// <summary>
  161. /// 新增事件
  162. /// </summary>
  163. /// <param name="dto"></param>
  164. /// <returns></returns>
  165. [HttpPost("event/add-event")]
  166. public async Task AddEventCategory([FromBody]AddEventCategoryDto dto)
  167. {
  168. //验证重复
  169. var ishas = await _eventCategoryRepository.AnyAsync(x => x.ParentId == dto.ParentId && x.EventName == dto.EventName);
  170. if (ishas)
  171. {
  172. throw UserFriendlyException.SameMessage("同级别下存在相同名字的事件,不能添加");
  173. }
  174. var model = _mapper.Map<EventCategory>(dto);
  175. (model.Id,model.EventFullName) = await _eventCategoryRepository.GetNewEventCodeAsync(dto.ParentId,model.EventName);
  176. await _eventCategoryRepository.AddAsync(model, HttpContext.RequestAborted);
  177. }
  178. /// <summary>
  179. /// 删除事件
  180. /// </summary>
  181. /// <param name="id"></param>
  182. /// <returns></returns>
  183. [HttpDelete("event/del-event")]
  184. public async Task DelEventCategory(string[] id)
  185. {
  186. var list = await _eventCategoryRepository.Queryable().In(id).ToListAsync(HttpContext.RequestAborted);
  187. await _eventCategoryRepository.RemoveRangeAsync(list, HttpContext.RequestAborted);
  188. }
  189. #endregion
  190. #endregion
  191. #region 时限管理
  192. /// <summary>
  193. /// 获取时限配置页面基础数据
  194. /// </summary>
  195. /// <returns></returns>
  196. [HttpGet("timelimit-basedata")]
  197. public async Task<object> GetTimeLimitBaseData()
  198. {
  199. return new
  200. {
  201. //ModuleOptions = WorkflowModule.Modules.ToList(),//todo
  202. TimeType = EnumExts.GetDescriptions<ETimeType>(),
  203. BaseData = TimeLimitBaseData.GetBaseData(),
  204. //AcceptType = EnumExts.GetDescriptions<EAcceptType>(),
  205. AcceptType = _sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.AcceptType),
  206. //PushType = _sysDicDataCacheManager.GetSysDicDataCache(TimeLimitBaseDataConsts.PushType),
  207. SourceChannel = _sysDicDataCacheManager.GetSysDicDataCache(TimeLimitBaseDataConsts.SourceChannel),
  208. IdentityType = EnumExts.GetDescriptions<EIdentityType>(),
  209. OrderType = _sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.OrderType),
  210. CertType = _sysDicDataCacheManager.GetSysDicDataCache(TimeLimitBaseDataConsts.LicenceType),
  211. EmergencyLevel = EnumExts.GetDescriptions<EEmergencyLevel>()
  212. };
  213. }
  214. /// <summary>
  215. /// 新增时限管理
  216. /// </summary>
  217. /// <param name="dto"></param>
  218. /// <returns>数据主键</returns>
  219. [HttpPost("add-timelimit")]
  220. public async Task<string> AddTimeLimit([FromBody] AddTimeLimitDto dto)
  221. {
  222. var model = _mapper.Map<TimeLimit>(dto);
  223. model.TimeLimitState = ETimeLimitState.Draft;
  224. return await _timeLimitDomainService.AddAsync(model, HttpContext.RequestAborted);
  225. }
  226. /// <summary>
  227. /// 修改时限管理
  228. /// </summary>
  229. /// <param name="dto"></param>
  230. /// <returns></returns>
  231. [HttpPost("update-timelimit")]
  232. public async Task UpdateTimeLimit([FromBody] UpdateTimeLimitDto dto)
  233. {
  234. var model = _mapper.Map<TimeLimit>(dto);
  235. await _timeLimitDomainService.UpdateAsync(model, HttpContext.RequestAborted);
  236. }
  237. /// <summary>
  238. /// 获取对象
  239. /// </summary>
  240. /// <param name="id"></param>
  241. /// <returns></returns>
  242. [HttpGet("timelimit/{id}")]
  243. public async Task<TimeLimit?> GetTimeLimit(string id)
  244. {
  245. return await _timeLimitRepository.GetAsync(id, HttpContext.RequestAborted);
  246. }
  247. /// <summary>
  248. /// 获取时限管理列表
  249. /// </summary>
  250. /// <param name="dto"></param>
  251. /// <returns></returns>
  252. [HttpGet("paged-timelimit")]
  253. public async Task<PagedDto<TimeLimit>> QueryPagedTimeLimit([FromQuery] QueryPagedTimeLimitPagedDto dto)
  254. {
  255. var (total, items) = await _timeLimitRepository.Queryable()
  256. .WhereIF(!string.IsNullOrEmpty(dto.Keyword), d => d.TimeLimitName.Contains(dto.Keyword!))
  257. .OrderByDescending(d => d.CreationTime)
  258. .ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted);
  259. return new PagedDto<TimeLimit>(total, _mapper.Map<IReadOnlyList<TimeLimit>>(items));
  260. }
  261. /// <summary>
  262. /// 删除时限(草稿)
  263. /// </summary>
  264. /// <param name="id"></param>
  265. /// <returns></returns>
  266. [HttpDelete("deltimelimit")]
  267. public async Task DelTimeLimit(string id)
  268. {
  269. var model = await _timeLimitRepository.GetAsync(id, HttpContext.RequestAborted);
  270. if (model == null)
  271. {
  272. throw UserFriendlyException.SameMessage("无效数据");
  273. }
  274. if (model.TimeLimitState != ETimeLimitState.Draft)
  275. {
  276. throw UserFriendlyException.SameMessage("无法删除,请刷新页面");
  277. }
  278. await _timeLimitRepository.RemoveAsync(id, true, HttpContext.RequestAborted);
  279. }
  280. /// <summary>
  281. /// 启用时限
  282. /// </summary>
  283. /// <param name="id"></param>
  284. /// <returns></returns>
  285. [HttpGet("enable-timelimit/{id}")]
  286. public async Task EnableTimeLimit(string id)
  287. {
  288. var model = await _timeLimitRepository.GetAsync(id, HttpContext.RequestAborted);
  289. if (model == null)
  290. {
  291. throw UserFriendlyException.SameMessage("无效数据");
  292. }
  293. if (model.TimeLimitState == ETimeLimitState.Enable)
  294. {
  295. throw UserFriendlyException.SameMessage("该配置已生效");
  296. }
  297. var list = await _timeLimitRepository.QueryAsync(x => x.WorkflowCode == model.WorkflowCode && x.TimeLimitState == ETimeLimitState.Enable);
  298. list.ForEach(x => x.TimeLimitState = ETimeLimitState.Disable);
  299. model.TimeLimitState = ETimeLimitState.Enable;
  300. list.Add(model);
  301. await _timeLimitRepository.UpdateRangeAsync(list, HttpContext.RequestAborted);
  302. }
  303. /// <summary>
  304. /// 禁用时限
  305. /// </summary>
  306. /// <param name="id"></param>
  307. /// <returns></returns>
  308. [HttpGet("disable-timelimit/{id}")]
  309. public async Task DisableTimeLimit(string id)
  310. {
  311. var model = await _timeLimitRepository.GetAsync(id, HttpContext.RequestAborted);
  312. if (model == null)
  313. {
  314. throw UserFriendlyException.SameMessage("无效数据");
  315. }
  316. if (model.TimeLimitState == ETimeLimitState.Draft)
  317. {
  318. throw UserFriendlyException.SameMessage("该配置未生效,无法禁用");
  319. }
  320. if (model.TimeLimitState == ETimeLimitState.Disable)
  321. {
  322. throw UserFriendlyException.SameMessage("该配置已禁用");
  323. }
  324. model.TimeLimitState = ETimeLimitState.Disable;
  325. await _timeLimitRepository.UpdateAsync(model, HttpContext.RequestAborted);
  326. }
  327. #endregion
  328. #region 工作日设定
  329. #endregion
  330. }
  331. }