PlanController.cs 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561
  1. using MapsterMapper;
  2. using Microsoft.AspNetCore.Mvc;
  3. using XF.Domain.Authentications;
  4. using XF.Domain.Repository;
  5. using Hotline.Application.Planlibrary;
  6. using Hotline.Share.Dtos.Planlibrary;
  7. using SqlSugar;
  8. using Hotline.Planlibrary;
  9. using XF.Domain.Exceptions;
  10. using Hotline.Share.Dtos;
  11. using Hotline.Share.Tools;
  12. using Hotline.Share.Enums.Planlibrary;
  13. using Hotline.Application.ExportWord;
  14. using Hotline.Application.Tools;
  15. using Hotline.Share.Enums.Article;
  16. using XF.Utility.EnumExtensions;
  17. using Hotline.Share.Dtos.Order;
  18. using Hotline.Application.ExportExcel;
  19. namespace Hotline.Api.Controllers
  20. {
  21. /// <summary>
  22. /// 预案库
  23. /// </summary>
  24. public class PlanController : BaseController
  25. {
  26. #region 注入
  27. private readonly IMapper _mapper;
  28. private readonly ISessionContext _sessionContext;
  29. private readonly IPlanApplication _planApplication;
  30. private readonly IRepository<PlanType> _planTypeRepository;
  31. private readonly IRepository<PlanList> _planListRepository;
  32. private readonly IRepository<PlanCollect> _planCollectRepository;
  33. private readonly IWordHelperService _wordHelperService;
  34. private readonly IExportApplication _exportApplication;
  35. public PlanController(
  36. IMapper mapper,
  37. ISessionContext sessionContext,
  38. IPlanApplication planApplication,
  39. IRepository<PlanType> planTypeRepository,
  40. IRepository<PlanList> planListRepository,
  41. IRepository<PlanCollect> planCollectRepository,
  42. IWordHelperService wordHelperService,
  43. IExportApplication exportApplication)
  44. {
  45. _mapper = mapper;
  46. _sessionContext = sessionContext;
  47. _planApplication = planApplication;
  48. _planTypeRepository = planTypeRepository;
  49. _planListRepository = planListRepository;
  50. _planCollectRepository = planCollectRepository;
  51. _wordHelperService = wordHelperService;
  52. _exportApplication = exportApplication;
  53. }
  54. #endregion
  55. #region 预案库类型管理
  56. /// <summary>
  57. /// 获取列表层级分类
  58. /// </summary>
  59. /// <param name="IsEnable">是否启用</param>
  60. /// <returns></returns>
  61. [HttpGet("type/treelist")]
  62. public async Task<List<PlanTypeDto>> QueryAllTreeList(bool? IsEnable)
  63. {
  64. return await _planTypeRepository.Queryable()
  65. .WhereIF(IsEnable.HasValue, x => x.IsEnable == IsEnable)
  66. .Where(x => SqlFunc.Subqueryable<PlanTypeOrg>().Where(to => to.TypeId == x.Id).Any() ||
  67. SqlFunc.Subqueryable<PlanTypeOrg>().Where(to => to.TypeId == x.Id).NotAny()
  68. )
  69. .Select(x => new PlanTypeDto()
  70. {
  71. Id = x.Id.SelectAll()
  72. }
  73. )
  74. .OrderBy(x => x.Sort).ToTreeAsync(it => it.children, it => it.ParentId, null, it => it.Id);
  75. }
  76. /// <summary>
  77. /// 新增
  78. /// </summary>
  79. /// <param name="dto"></param>
  80. /// <returns></returns>
  81. [HttpPost("type/add")]
  82. public async Task<string> AddType([FromBody] AddPlanTypeDto dto)
  83. {
  84. return await _planApplication.AddTypeAsync(dto, HttpContext.RequestAborted);
  85. }
  86. /// <summary>
  87. /// 编辑
  88. /// </summary>
  89. /// <param name="dto"></param>
  90. /// <returns></returns>
  91. [HttpPut("type/update")]
  92. public async Task UpdateType([FromBody] UpdatePlanTypeDto dto)
  93. {
  94. await _planApplication.UpdateTypeAsync(dto, HttpContext.RequestAborted);
  95. }
  96. /// <summary>
  97. /// 查询详情
  98. /// </summary>
  99. /// <param name="Id"></param>
  100. /// <returns></returns>
  101. [HttpGet("type/info/{Id}")]
  102. public async Task<PlanType> GetType(string Id)
  103. {
  104. var types = await _planTypeRepository.Queryable()
  105. .Includes(x => x.PlanTypeOrgs) // 填充子对象
  106. .Where(x => x.Id == Id)
  107. .FirstAsync(HttpContext.RequestAborted);
  108. if (types is null)
  109. throw UserFriendlyException.SameMessage("查询失败!");
  110. return types;
  111. }
  112. /// <summary>
  113. /// 删除
  114. /// </summary>
  115. /// <param name="Id"></param>
  116. /// <returns></returns>
  117. [HttpDelete("type/remove/{Id}")]
  118. public async Task RemoveType(string Id)
  119. {
  120. await _planApplication.RemoveTypeAsync(Id, HttpContext.RequestAborted);
  121. }
  122. #endregion
  123. #region 预案库管理
  124. /// <summary>
  125. /// 预案库分类列表
  126. /// </summary>
  127. /// <param name="IsEnable"></param>
  128. /// <returns></returns>
  129. [HttpGet("list/treelist")]
  130. public async Task<List<PlanTypeDto>> QueryAllPlanTypeTreeList(bool? IsEnable)
  131. {
  132. return await _planTypeRepository.Queryable()
  133. .WhereIF(IsEnable.HasValue, x => x.IsEnable == IsEnable)
  134. .Where(x => SqlFunc.Subqueryable<PlanTypeOrg>().Where(to => to.TypeId == x.Id).Any() ||
  135. SqlFunc.Subqueryable<PlanTypeOrg>().Where(to => to.TypeId == x.Id).NotAny()
  136. )
  137. .Select(x => new PlanTypeDto()
  138. {
  139. Id = x.Id.SelectAll(),
  140. PlanNum = SqlFunc.Subqueryable<PlanRelationType>().LeftJoin<PlanList>((kr, k) => kr.PlanId == k.Id)
  141. .Where((kr, k) => kr.PlanTypeId == x.Id)
  142. .DistinctCount(kr => kr.PlanId)
  143. }
  144. )
  145. .OrderBy(x => x.Sort).ToTreeAsync(it => it.children, it => it.ParentId, null, it => it.Id);
  146. }
  147. /// <summary>
  148. /// 预案库列表
  149. /// </summary>
  150. /// <param name="pagedDto"></param>
  151. /// <returns></returns>
  152. [HttpGet("list")]
  153. public async Task<PagedDto<PlanDataDto>> QueryAllPlanList([FromQuery] PlanListDto pagedDto)
  154. {
  155. return (await _planApplication.QueryAllPlanListAsync(pagedDto, HttpContext.RequestAborted)).ToPaged();
  156. }
  157. /// <summary>
  158. /// 预案库草稿
  159. /// </summary>
  160. /// <param name="dto"></param>
  161. /// <returns></returns>
  162. [HttpPost("list/draft")]
  163. public async Task<string> PlanDraft([FromBody] AddPlanListDto dto)
  164. {
  165. dto.Status = EPlanStatus.NewDrafts;
  166. return await _planApplication.AddPlanAsync(dto, HttpContext.RequestAborted);
  167. }
  168. /// <summary>
  169. /// 预案库草稿修改
  170. /// </summary>
  171. /// <param name="dto"></param>
  172. /// <returns></returns>
  173. [HttpPut("list/draftupdate")]
  174. public async Task UpdatePlanDraft([FromBody] UpdatePlanListDto dto)
  175. {
  176. dto.Status = EPlanStatus.NewDrafts;
  177. await _planApplication.UpdatePlanAsync(dto, HttpContext.RequestAborted);
  178. }
  179. /// <summary>
  180. /// 预案库草稿到审核
  181. /// </summary>
  182. /// <param name="dto"></param>
  183. /// <returns></returns>
  184. [HttpPut("list/draftadd")]
  185. public async Task AddPlanDraft([FromBody] UpdatePlanListDto dto)
  186. {
  187. dto.ApplyStatus = EPlanApplyStatus.Add;
  188. dto.Status = EPlanStatus.OnShelf;
  189. await _planApplication.UpdatePlanAsync(dto, HttpContext.RequestAborted);
  190. }
  191. /// <summary>
  192. /// 预案库草稿删除
  193. /// </summary>
  194. /// <param name="Id"></param>
  195. /// <returns></returns>
  196. [HttpDelete("list/draftremove/{Id}")]
  197. public async Task RemovePlanDraft(string Id)
  198. {
  199. UpdatePlanListDto dto = new UpdatePlanListDto();
  200. dto.ApplyStatus = EPlanApplyStatus.Delete;
  201. dto.Status = EPlanStatus.Auditing;
  202. dto.Id = Id;
  203. await _planApplication.RemovePlanAsync(dto, HttpContext.RequestAborted);
  204. }
  205. /// <summary>
  206. /// 预案库删除到审核
  207. /// </summary>
  208. /// <param name="dtoDel"></param>
  209. /// <returns></returns>
  210. [HttpDelete("list/remove")]
  211. public async Task RemovePlan([FromBody] DelPlanListDto dtoDel)
  212. {
  213. UpdatePlanListDto dto = new UpdatePlanListDto();
  214. dto.ApplyStatus = EPlanApplyStatus.Delete;
  215. dto.Status = EPlanStatus.Auditing;
  216. dto.Id = dtoDel.Id;
  217. dto.ApplyReason = dtoDel.ApplyReason;
  218. await _planApplication.UpdatePlanAsync(dto, HttpContext.RequestAborted);
  219. }
  220. /// <summary>
  221. /// 预案库新增到审核
  222. /// </summary>
  223. /// <param name="dto"></param>
  224. /// <returns></returns>
  225. [HttpPost("list/add")]
  226. public async Task<string> AddPlan([FromBody] AddPlanListDto dto)
  227. {
  228. dto.ApplyStatus = EPlanApplyStatus.Add;
  229. dto.Status = EPlanStatus.Auditing;
  230. return await _planApplication.AddPlanAsync(dto, HttpContext.RequestAborted);
  231. }
  232. /// <summary>
  233. /// 预案库编辑提交到审核
  234. /// </summary>
  235. /// <param name="dto"></param>
  236. /// <returns></returns>
  237. [HttpPut("list/update")]
  238. public async Task UpdatePlan([FromBody] UpdatePlanListDto dto)
  239. {
  240. dto.ApplyStatus = EPlanApplyStatus.Update;
  241. dto.Status = EPlanStatus.Auditing;
  242. await _planApplication.UpdatePlanAsync(dto, HttpContext.RequestAborted);
  243. }
  244. /// <summary>
  245. /// 预案库上架
  246. /// </summary>
  247. /// <param name="Id">预案库ID</param>
  248. /// <returns></returns>
  249. [HttpGet("list/onshelf/{Id}")]
  250. public async Task OnshelfPlan(string Id)
  251. {
  252. UpdatePlanListDto dto = new UpdatePlanListDto();
  253. dto.Id = Id;
  254. dto.ApplyStatus = EPlanApplyStatus.Add;
  255. dto.Status = EPlanStatus.OnShelf;
  256. dto.OnShelfTime = DateTime.Now;
  257. await _planApplication.AuditPlanAsync(dto, HttpContext.RequestAborted);
  258. }
  259. /// <summary>
  260. /// 预案库下架
  261. /// </summary>
  262. /// <param name="Id">预案库ID</param>
  263. /// <returns></returns>
  264. [HttpGet("list/offshelf/{Id}")]
  265. public async Task OffshelfPlan(string Id)
  266. {
  267. UpdatePlanListDto dto = new UpdatePlanListDto();
  268. dto.Id = Id;
  269. dto.ApplyStatus = EPlanApplyStatus.Offshelf;
  270. dto.Status = EPlanStatus.OffShelf;
  271. dto.OffShelfTime = DateTime.Now;
  272. await _planApplication.AuditPlanAsync(dto, HttpContext.RequestAborted);
  273. }
  274. /// <summary>
  275. /// 预案库审核(新增、修改、删除)
  276. /// </summary>
  277. /// <param name="dto"></param>
  278. /// <returns></returns>
  279. [HttpPut("list/examin")]
  280. public async Task ExaminPlan([FromBody] AuditPlanListDto dto)
  281. {
  282. var plan = await _planListRepository.GetAsync(dto.Id);
  283. if (plan == null)
  284. throw UserFriendlyException.SameMessage("预案库查询失败");
  285. var planDto = _mapper.Map<UpdatePlanListDto>(plan);
  286. if (dto.State == 0)
  287. {//不同意
  288. planDto.Status = EPlanStatus.Revert;
  289. }
  290. else if (dto.State == 1)
  291. {//同意
  292. if (planDto.ApplyStatus == EPlanApplyStatus.Add)
  293. {
  294. planDto.Status = EPlanStatus.OnShelf;
  295. planDto.OnShelfTime = DateTime.Now;
  296. }
  297. if (planDto.ApplyStatus == EPlanApplyStatus.Update)
  298. {
  299. planDto.Status = EPlanStatus.OnShelf;
  300. planDto.OnShelfTime = DateTime.Now;
  301. planDto.UpdateTime = DateTime.Now;
  302. }
  303. if (planDto.ApplyStatus == EPlanApplyStatus.Offshelf)
  304. {
  305. planDto.Status = EPlanStatus.OffShelf;
  306. planDto.OffShelfTime = DateTime.Now;
  307. }
  308. if (planDto.ApplyStatus == EPlanApplyStatus.Delete)
  309. {
  310. planDto.Status = EPlanStatus.Drafts;
  311. }
  312. }
  313. planDto.Id = dto.Id;
  314. planDto.ExaminTime = DateTime.Now;
  315. planDto.ExaminManId = _sessionContext.UserId;
  316. planDto.ExaminOrganizeId = _sessionContext.OrgId;
  317. planDto.ExaminOpinion = dto.ExaminOpinion;
  318. await _planApplication.AuditPlanAsync(planDto, HttpContext.RequestAborted);
  319. }
  320. /// <summary>
  321. /// 预案库详情
  322. /// </summary>
  323. /// <param name="Id"></param>
  324. /// <param name="IsAddPv"></param>
  325. /// <returns></returns>
  326. [HttpGet("list/info")]
  327. public async Task<PlanInfoDto> GetPlan(string Id, bool IsAddPv)
  328. {
  329. return await _planApplication.GetPlanAsync(Id, IsAddPv, HttpContext.RequestAborted);
  330. }
  331. /// <summary>
  332. /// 预案库申请理由
  333. /// </summary>
  334. /// <param name="Id">预案库ID</param>
  335. /// <returns></returns>
  336. [HttpGet("list/reason/{Id}")]
  337. public async Task<PlanApplyReasonDto> ReasonPlan(string Id)
  338. {
  339. var reason = await _planListRepository.GetAsync(x => x.Id == Id);
  340. return _mapper.Map<PlanApplyReasonDto>(reason);
  341. }
  342. /// <summary>
  343. /// 预案库评分
  344. /// </summary>
  345. /// <param name="dto"></param>
  346. /// <returns></returns>
  347. [HttpPut("list/score")]
  348. public async Task ScorePlan([FromBody] PvPlanListDto dto)
  349. {
  350. var collect = await _planCollectRepository.GetAsync(x => x.PlanId == dto.Id && x.CreatorId == _sessionContext.UserId);
  351. if (collect != null)
  352. {
  353. if (collect.Score > 0)
  354. throw UserFriendlyException.SameMessage("当前知识已经评分");
  355. collect.Score = dto.Score;
  356. await _planCollectRepository.UpdateAsync(collect, HttpContext.RequestAborted);
  357. }
  358. else
  359. {
  360. collect = new PlanCollect();
  361. collect.PlanId = dto.Id;
  362. collect.Score = dto.Score;
  363. await _planCollectRepository.AddAsync(collect, HttpContext.RequestAborted);
  364. }
  365. //计算总分
  366. var sugar = _planCollectRepository.Queryable().Where(x => x.PlanId == dto.Id);
  367. var count = await sugar.CountAsync();
  368. var collects = await sugar.SumAsync(x => x.Score);
  369. var scoreTemp = collects / count;
  370. var plan = await _planListRepository.GetAsync(x => x.Id == dto.Id);
  371. if (plan != null)
  372. {
  373. plan.Score = decimal.Round(scoreTemp.Value, 1);
  374. await _planListRepository.UpdateAsync(plan, HttpContext.RequestAborted);
  375. }
  376. }
  377. /// <summary>
  378. /// 预案库查重
  379. /// </summary>
  380. /// <param name="dto"></param>
  381. /// <returns></returns>
  382. [HttpPost("list/exist")]
  383. public async Task<bool> ExistPlan([FromBody] PlanExistDto dto)
  384. {
  385. var any = await _planListRepository.Queryable()
  386. .Where(x => x.Status == EPlanStatus.Auditing || x.Status >= EPlanStatus.OnShelf)
  387. .WhereIF(!string.IsNullOrEmpty(dto.Title), x => x.Title.Equals(dto.Title))
  388. .WhereIF(!string.IsNullOrEmpty(dto.Content), x => x.Content.Equals(dto.Content))
  389. .WhereIF(!string.IsNullOrEmpty(dto.Id), x => x.Id != dto.Id)
  390. .AnyAsync();
  391. return any;
  392. }
  393. /// <summary>
  394. /// 预案库详情导出
  395. /// </summary>
  396. /// <param name="dto"></param>
  397. /// <returns></returns>
  398. [HttpPost("list/info/export")]
  399. public async Task<IActionResult> PlanInfoExport([FromBody] PlanInfoExportDto dto)
  400. {
  401. if (dto.Ids.Length > 1)
  402. {
  403. var streams = await _planApplication.PlanInfoListExportAsync(dto, HttpContext.RequestAborted);
  404. byte[] fileBytes = _wordHelperService.ConvertZipStream(streams);
  405. var name = DateTime.Now.ToString("yyyyMMddHHmmss");
  406. return File(fileBytes, "application/octet-stream", $"{name}.zip");
  407. }
  408. var info = await _planListRepository.GetAsync(dto.Ids[0]) ?? throw UserFriendlyException.SameMessage("预案不存在");
  409. return info.Content.HtmlToStream(dto.FileType).GetFileStreamResult(dto.FileType, info.Title, false);
  410. }
  411. /// <summary>
  412. /// 预案库列表导出
  413. /// </summary>
  414. /// <param name="dto"></param>
  415. /// <returns></returns>
  416. [HttpPost("export")]
  417. public async Task<IActionResult> GetPlanListExportAsync([FromBody] ExportExcelDto<PlanListDto> dto)
  418. {
  419. var items = (await _planApplication.QueryAllPlanListAsync(dto.QueryDto, HttpContext.RequestAborted)).Item2;
  420. return _exportApplication.GetExcelFile(dto, items, "预案明细导出");
  421. }
  422. /// <summary>
  423. /// 预案库列表页面枚举值
  424. /// </summary>
  425. /// <returns></returns>
  426. [HttpGet("list/status-data")]
  427. public Dictionary<string, dynamic> PlanStatus()
  428. {
  429. var tabStatusName = new List<KeyValuePair<int, string>>
  430. {
  431. new KeyValuePair<int, string>(3, "已上架"),
  432. new KeyValuePair<int, string>(4, "已下架"),
  433. new KeyValuePair<int, string>(1, "审核中"),
  434. new KeyValuePair<int, string>(7, "草稿"),
  435. new KeyValuePair<int, string>(-1, "全部")
  436. };
  437. var tabExamineName = new List<KeyValuePair<int, string>>
  438. {
  439. new KeyValuePair<int, string>(-1, "全部"),
  440. new KeyValuePair<int, string>(0, "新增审核"),
  441. new KeyValuePair<int, string>(1, "修改审核"),
  442. new KeyValuePair<int, string>(2, "删除审核")
  443. };
  444. var StatusName = new List<KeyValuePair<int, string>>
  445. {
  446. new KeyValuePair<int, string>(-1, "全部"),
  447. new KeyValuePair<int, string>(0, "待提交"),
  448. new KeyValuePair<int, string>(1, "审核中"),
  449. new KeyValuePair<int, string>(3, "已上架"),
  450. new KeyValuePair<int, string>(4, "已下架"),
  451. new KeyValuePair<int, string>(5, "审核不通过"),
  452. new KeyValuePair<int, string>(6, "已过期"),
  453. new KeyValuePair<int, string>(7, "草稿")
  454. };
  455. var ApplyStatusName = new List<KeyValuePair<int, string>>
  456. {
  457. new KeyValuePair<int, string>(-1, "全部"),
  458. new KeyValuePair<int, string>(0, "新增审核"),
  459. new KeyValuePair<int, string>(1, "修改审核"),
  460. new KeyValuePair<int, string>(2, "删除审核")
  461. };
  462. var ignoreFileType = EFileType.excel | EFileType.pdf;
  463. var items = EnumExts.GetDescriptions<EFileType>();
  464. var filteredDictionary = items
  465. .Where(kvp => (ignoreFileType & (EFileType)kvp.Key) == 0)
  466. .ToDictionary(kvp => kvp.Key, kvp => kvp.Value)
  467. .ToList();
  468. return new Dictionary<string, dynamic>
  469. {
  470. { "fileType", filteredDictionary},
  471. { "tabStatusName", tabStatusName },
  472. { "tabExamineName", tabExamineName },
  473. { "StatusName", StatusName },
  474. { "ApplyStatusName", ApplyStatusName }
  475. };
  476. }
  477. #endregion
  478. #region 预案库检索
  479. /// <summary>
  480. /// 检索列表
  481. /// </summary>
  482. /// <param name="pagedDto"></param>
  483. /// <returns></returns>
  484. [HttpGet("search")]
  485. public async Task<PagedDto<PlanDataDto>> QueryOnShelfPlanList([FromQuery] PlanListDto pagedDto)
  486. {
  487. pagedDto.Status = EPlanStatus.OnShelf;
  488. return (await _planApplication.QueryAllPlanListAsync(pagedDto, HttpContext.RequestAborted)).ToPaged();
  489. }
  490. /// <summary>
  491. /// 检索列表前10
  492. /// </summary>
  493. /// <returns></returns>
  494. [HttpGet("search/top10")]
  495. public async Task<List<PlanPageViewDto>> QueryTop10PlanList()
  496. {
  497. return await _planListRepository.Queryable()
  498. .Take(10)
  499. .Where(x => x.Status == EPlanStatus.OnShelf)
  500. .Select(x => new PlanPageViewDto
  501. {
  502. Id = x.Id,
  503. Title = x.Title,
  504. PageView = x.PageView
  505. })
  506. .OrderBy(x => x.PageView, OrderByType.Desc)
  507. .ToListAsync();
  508. }
  509. #endregion
  510. }
  511. }