using DotNetCore.CAP; using Hotline.Application.Bulletin; using Hotline.Application.FlowEngine; using Hotline.Article; using Hotline.Caching.Interfaces; using Hotline.Permissions; using Hotline.Repository.SqlSugar.Extensions; using Hotline.Settings; using Hotline.Share.Dtos; using Hotline.Share.Dtos.Article; using Hotline.Share.Dtos.Users; using Hotline.Share.Enums.Article; using Hotline.Users; using MapsterMapper; using MediatR; using Microsoft.AspNetCore.Mvc; using XF.Domain.Authentications; using XF.Domain.Exceptions; using XF.Domain.Repository; using XF.Utility.EnumExtensions; namespace Hotline.Api.Controllers { public class ArticleController : BaseController { private readonly IRepository _bulletinRepository; private readonly IMapper _mapper; private readonly ISystemOrganizeRepository _organizeRepository; private readonly IWorkflowApplication _workflowApplication; private readonly IRepository _circularRepository; private readonly ISessionContext _sessionContext; private readonly IRepository _circularRecordRepository; private readonly IRepository _circularReadGroupRepository; private readonly IRepository _userRepository; private readonly ICircularRecordDomainService _circularRecordDomainService; private readonly ISystemDicDataCacheManager _systemDicDataCacheManager; private readonly IMediator _mediator; private readonly ICapPublisher _capPublisher; private readonly IBulletinApplication _bulletinApplication; public ArticleController(IRepository bulletinRepository, IMapper mapper, ISystemDomainService systemDomainService, ISystemOrganizeRepository organizeRepository, IWorkflowApplication workflowApplication, IRepository circularRepository, ISessionContext sessionContext, IRepository circularRecordRepository, IRepository circularReadGroupRepository, IRepository userRepository, ICircularRecordDomainService circularRecordDomainService, ISystemDicDataCacheManager systemDicDataCacheManager, IMediator mediator, ICapPublisher capPublisher, IBulletinApplication bulletinApplication) { _bulletinRepository = bulletinRepository; _mapper = mapper; _organizeRepository = organizeRepository; _workflowApplication = workflowApplication; _circularRepository = circularRepository; _sessionContext = sessionContext; _circularRecordRepository = circularRecordRepository; _circularReadGroupRepository = circularReadGroupRepository; _userRepository = userRepository; _circularRecordDomainService = circularRecordDomainService; _systemDicDataCacheManager = systemDicDataCacheManager; _mediator = mediator; _capPublisher = capPublisher; _bulletinApplication = bulletinApplication; } #region 通知 /// /// 获取所有用户不分页 /// /// [HttpGet("alluser")] public async Task> GetAllUser() { var list = await _userRepository.Queryable(includeDeleted: false) .Includes(d => d.Account) .Includes(d => d.Organization) .OrderByDescending(x => x.CreationTime) .ToListAsync(); return new List(_mapper.Map>(list)); } /// /// 我的通知列表 /// /// /// [HttpGet("circular/muquery")] public async Task> GetMyCircularList([FromQuery] QueryCircularListRequestDto dto) { var (total, items) = await _circularRepository.Queryable() .Includes(x => x.CircularReadGroups) .Includes(x => x.ExaminMan) .WhereIF(!string.IsNullOrEmpty(dto.CircularTypeId), d => d.CircularTypeId == dto.CircularTypeId) .WhereIF(!string.IsNullOrEmpty(dto.Title), d => d.Title.Contains(dto.Title)) .WhereIF(dto.CircularTimeStart.HasValue, d => d.CircularTime >= dto.CircularTimeStart) .WhereIF(dto.CircularTimeEnd.HasValue, d => d.CircularTime <= dto.CircularTimeEnd) .WhereIF(dto.CircularState != null, d => d.CircularState == dto.CircularState) //.WhereIF(dto.IsRead!=null,d=>d.CircularReadGroups.Any(x=>x.IsRead == dto.IsRead) && (d.CircularReadGroups.Any(x => x.UserId == _sessionContext.RequiredUserId) || d.CircularReadGroups.Any(x => x.OrgId == _sessionContext.RequiredOrgId))) .WhereIF(dto.IsRead != null, d => (d.CircularReadGroups.Any(x => x.IsRead == dto.IsRead && x.UserId == _sessionContext.UserId)) || (d.CircularReadGroups.Any(x => x.IsRead == dto.IsRead && x.OrgId == _sessionContext.OrgId))) //.Where(d=>d.CircularReadGroups.Any(x=> x.UserId == _sessionContext.RequiredUserId) || d.CircularReadGroups.Any(x=>x.OrgId == _sessionContext.RequiredOrgId)) .OrderByDescending(d => d.CreationTime) .ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted); return new PagedDto(total, _mapper.Map>(items)); } /// /// 查询通知列表 /// /// /// [Permission(EPermission.QueryCircularList)] [HttpGet("circular/query")] public async Task> QueryCircularList([FromQuery] QueryCircularListRequestDto dto) { var (total, items) = await _circularRepository.Queryable() .Includes(x => x.CircularReadGroups) .Includes(x => x.ExaminMan) .WhereIF(!string.IsNullOrEmpty(dto.CircularTypeId), d => d.CircularTypeId == dto.CircularTypeId) .WhereIF(!string.IsNullOrEmpty(dto.Title), d => d.Title.Contains(dto.Title)) .WhereIF(dto.CircularTimeStart.HasValue, d => d.CircularTime >= dto.CircularTimeStart) .WhereIF(dto.CircularTimeEnd.HasValue, d => d.CircularTime <= dto.CircularTimeEnd) .WhereIF(dto.CircularState != null, d => d.CircularState == dto.CircularState) .OrderByDescending(d => d.CreationTime) .ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted); return new PagedDto(total, _mapper.Map>(items)); } /// /// 通知详情(内部) /// /// /// [HttpGet("circular/entity/{id}")] public async Task CircularEntity(string id) { var model = await _circularRepository.Queryable() .Includes(x => x.CircularReadGroups) .Includes(x => x.ExaminMan) .FirstAsync(x => x.Id == id, HttpContext.RequestAborted); return _mapper.Map(model); } /// /// 通知审核 /// /// /// [Permission(EPermission.ExamineCircular)] [HttpPost("circular/examine")] public async Task ExamineCircular([FromBody] ExamineCircularDto dto) { var circular = await _circularRepository.GetAsync(dto.Id, HttpContext.RequestAborted); if (circular == null) throw UserFriendlyException.SameMessage("无效数据"); if (circular.CircularState != ECircularState.InReview) throw UserFriendlyException.SameMessage("当前状态不能审核"); if (dto.IsPass) { //更新审核状态 circular.CircularState = Share.Enums.Article.ECircularState.ReviewPass; circular.CircularTime = DateTime.Now; circular.ExaminOpinion = dto.Reason; circular.ExaminTime = DateTime.Now; circular.ExaminManId = _sessionContext.RequiredUserId; await _circularRepository.UpdateAsync(circular, HttpContext.RequestAborted); //更新阅读数量 if (circular.CircularType == Share.Enums.Article.ECircularType.Person) { //个人 var userlist = await _circularReadGroupRepository.Queryable() .Where(x => x.CircularId == circular.Id) .Select(x => x.UserId) .ToListAsync(HttpContext.RequestAborted); if (userlist != null && userlist.Count > 0) { await _circularRecordDomainService.RecordUserHandle(userlist, true); } } else { //部门 var orglist = await _circularReadGroupRepository.Queryable() .Where(x => x.CircularId == circular.Id) .Select(x => x.OrgId) .ToListAsync(HttpContext.RequestAborted); if (orglist != null && orglist.Count > 0) { await _circularRecordDomainService.RecordOrgHandle(orglist, true); } } } else { //驳回 circular.CircularState = Share.Enums.Article.ECircularState.ReviewNoPass; circular.ExaminOpinion = dto.Reason; circular.ExaminTime = DateTime.Now; circular.ExaminManId = _sessionContext.RequiredUserId; await _circularRepository.UpdateAsync(circular, HttpContext.RequestAborted); } } /// /// 提交通知 /// /// /// [Permission(EPermission.CommitCircular)] [HttpGet("circular/commit/{id}")] public async Task CommitCircular(string id) { var circular = await _circularRepository.GetAsync(id, HttpContext.RequestAborted); if (circular == null) throw UserFriendlyException.SameMessage("无效数据"); if (circular.CircularState != ECircularState.Draft && circular.CircularState != ECircularState.ReviewNoPass) throw UserFriendlyException.SameMessage("当前状态不能提交"); circular.CircularState = ECircularState.InReview; circular.CommitTime = DateTime.Now; await _circularRepository.UpdateAsync(circular, HttpContext.RequestAborted); } /// /// 修改通知 /// /// /// [Permission(EPermission.UpdateCircular)] [HttpPost("circular/update")] public async Task UpdateCircular([FromBody] UpdateCircularDto dto) { var circular = await _circularRepository.GetAsync(dto.Id, HttpContext.RequestAborted); if (circular == null) throw UserFriendlyException.SameMessage("无效数据"); if (circular.CircularState != ECircularState.Draft && circular.CircularState != ECircularState.ReviewNoPass) throw UserFriendlyException.SameMessage("当前状态不能修改"); //处理主表 circular.Title = dto.Title; circular.Content = dto.Content; circular.CircularTypeId = dto.CircularTypeId; circular.CircularTypeName = dto.CircularTypeName; circular.CircularType = dto.CircularType; circular.IsMustRead = dto.IsMustRead; circular.SourceOrgId = dto.SourceOrgId; circular.SourceOrgName = dto.SourceOrgName; circular.NeedReadNum = dto.CircularReadGroups.Count; await _circularRepository.UpdateAsync(circular, HttpContext.RequestAborted); //移除子表重新添加 await _circularReadGroupRepository.RemoveAsync(x => x.CircularId == dto.Id, false, HttpContext.RequestAborted); var list = dto.CircularReadGroups; var readGroupList = new List(); foreach (var item in list) { var readGroup = _mapper.Map(item); readGroup.CircularId = dto.Id; readGroup.IsRead = false; readGroupList.Add(readGroup); } await _circularReadGroupRepository.AddRangeAsync(readGroupList); } /// /// 删除通知 /// /// /// [Permission(EPermission.DelCircular)] [HttpGet("circular/del/{id}")] public async Task DelCircular(string id) { var circular = await _circularRepository.GetAsync(id, HttpContext.RequestAborted); if (circular == null) throw UserFriendlyException.SameMessage("无效数据"); if (circular.CircularState != ECircularState.Draft) throw UserFriendlyException.SameMessage("当前状态不能删除"); await _circularReadGroupRepository.RemoveAsync(x => x.CircularId == id, false, HttpContext.RequestAborted); await _circularRepository.RemoveAsync(x => x.Id == id, false, HttpContext.RequestAborted); } /// /// 新增通知 /// /// /// [Permission(EPermission.AddCircular)] [HttpPost("circular/add")] public async Task AddCircular([FromBody] AddCircularDto dto) { var model = _mapper.Map(dto); model.CircularState = ECircularState.Draft; model.ReadedNum = 0; model.NeedReadNum = model.CircularReadGroups.Count; var id = await _circularRepository.AddAsync(model, HttpContext.RequestAborted); //子表 var list = dto.CircularReadGroups; var readGroupList = new List(); foreach (var item in list) { var readGroup = _mapper.Map(item); readGroup.CircularId = id; readGroup.IsRead = false; readGroupList.Add(readGroup); } await _circularReadGroupRepository.AddRangeAsync(readGroupList); } /// /// 列表页面基础信息 /// /// [HttpGet("circular/listbasedata")] public async Task CircularBaseData() { var rsp = new { CircularType = _systemDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.CircularType) }; return rsp; } /// /// 新增页面基础数据 /// /// [HttpGet("circular/addbasedata")] public async Task CircularAddBaseData() { var rsp = new { CircularType = _systemDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.CircularType), OrgsOptions = await _organizeRepository.GetOrgJson(), CircularTypeEnum = EnumExts.GetDescriptions() }; return rsp; } /// /// 通知阅读(内部) /// /// /// [HttpGet("circular/read/{id}")] public async Task CircularRead(string id) { var model = await _circularRepository.Queryable() .Includes(x => x.CircularReadGroups) .FirstAsync(x => x.Id == id, HttpContext.RequestAborted); //更新阅读信息 if (model.CircularType == ECircularType.Person) { //个人阅读 var readGroup = model.CircularReadGroups.FirstOrDefault(x => x.UserId == _sessionContext.RequiredUserId && !x.IsRead); if (readGroup != null) { readGroup.IsRead = true; readGroup.ReadTime = DateTime.Now; if (DateTime.Now > model.LostEfficacyTime) readGroup.IsTimeOut = true; else readGroup.IsTimeOut = false; await _circularReadGroupRepository.UpdateAsync(readGroup, HttpContext.RequestAborted); model.ReadedNum++; await _circularRepository.UpdateAsync(model, HttpContext.RequestAborted); //处理计数 await _circularRecordDomainService.RecordUserHandle(new List { _sessionContext.RequiredUserId }, false, cancellationToken: HttpContext.RequestAborted); } } else { //部门阅读 var readGroup = model.CircularReadGroups.FirstOrDefault(x => x.OrgId == _sessionContext.RequiredOrgId && !x.IsRead); if (readGroup != null) { readGroup.IsRead = true; readGroup.ReadTime = DateTime.Now; if (DateTime.Now > model.LostEfficacyTime) readGroup.IsTimeOut = true; else readGroup.IsTimeOut = false; await _circularReadGroupRepository.UpdateAsync(readGroup, HttpContext.RequestAborted); model.ReadedNum++; await _circularRepository.UpdateAsync(model, HttpContext.RequestAborted); //处理部门计数 await _circularRecordDomainService.RecordOrgHandle(new List { _sessionContext.RequiredOrgId }, false, cancellationToken: HttpContext.RequestAborted); } } return _mapper.Map(model); } /// /// 获取小红点计数 /// /// [HttpGet("megcount")] public async Task QueryMegCount() { var list = await _circularRecordRepository.Queryable().Where(x => x.UserId == _sessionContext.RequiredUserId || x.OrgId == _sessionContext.RequiredOrgId).ToListAsync(); if (list != null && list.Count > 0) { var rsp = new CircularRecordDto(); rsp.OrgCount = list.FirstOrDefault(x => x.CircularType == ECircularType.Org)?.RecordCount ?? 0; rsp.PersonCount = list.FirstOrDefault(x => x.CircularType == ECircularType.Person)?.RecordCount ?? 0; return rsp; } return new CircularRecordDto() { OrgCount = 0, PersonCount = 0 }; } #endregion #region 公告 /// /// 查询公告列表 /// /// /// [HttpGet("bulletin/query")] public async Task> QueryBulletinList([FromQuery] QueryBulletinListRequestDto dto) { var (total, items) = await _bulletinRepository.Queryable() .Includes(x => x.ExaminMan) .WhereIF(!string.IsNullOrEmpty(dto.BulletinTypeId), d => d.BulletinTypeId == dto.BulletinTypeId) .WhereIF(!string.IsNullOrEmpty(dto.Title), d => d.Title.Contains(dto.Title)) .WhereIF(dto.BulletinTimeStart.HasValue, d => d.BulletinTime >= dto.BulletinTimeStart) .WhereIF(dto.BulletinTimeEnd.HasValue, d => d.BulletinTime <= dto.BulletinTimeEnd) .WhereIF(dto.BulletinState != null, d => d.BulletinState == dto.BulletinState) .WhereIF(dto.IsLoseEfficacy != null && dto.IsLoseEfficacy == false, d => d.LoseEfficacyTime > DateTime.Now) .OrderByDescending(d => d.CreationTime) .ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted); return new PagedDto(total, _mapper.Map>(items)); } /// /// 公告详情(内部) /// /// /// [HttpGet("bulletin/entity/{id}")] public async Task BulletinEntity(string id) { var model = await _bulletinRepository.Queryable() .Includes(x => x.ExaminMan) .FirstAsync(x => x.Id == id, HttpContext.RequestAborted); if (model != null && !string.IsNullOrEmpty(model.Content)) model.Content = _bulletinApplication.GetSiteUrls(model.Content); return _mapper.Map(model); } /// /// 公告审核 /// /// /// [Permission(EPermission.ExamineBulletin)] [HttpPost("bulletin/examine")] public async Task ExamineBulletin([FromBody] ExamineBulletinDto dto) { var bulletin = await _bulletinRepository.GetAsync(dto.Id, HttpContext.RequestAborted); if (bulletin == null) throw UserFriendlyException.SameMessage("无效数据"); if (bulletin.BulletinState != EBulletinState.InReview) throw UserFriendlyException.SameMessage("当前状态不能审核"); if (dto.IsPass) { bulletin.BulletinState = Share.Enums.Article.EBulletinState.ReviewPass; bulletin.BulletinTime = DateTime.Now; bulletin.ExaminOpinion = dto.Reason; bulletin.ExaminTime = DateTime.Now; bulletin.ExaminManId = _sessionContext.RequiredUserId; await _bulletinRepository.UpdateAsync(bulletin, HttpContext.RequestAborted); var publishBulletin = _mapper.Map(bulletin); await _capPublisher.PublishAsync(Hotline.Share.Mq.EventNames.HotlinePushBulletin, publishBulletin, cancellationToken: HttpContext.RequestAborted); //todo await _bulletinService.PushBulletin(publishBulletin, HttpContext.RequestAborted); } else { bulletin.ExaminOpinion = dto.Reason; bulletin.ExaminTime = DateTime.Now; bulletin.ExaminManId = _sessionContext.RequiredUserId; bulletin.BulletinState = Share.Enums.Article.EBulletinState.ReviewNoPass; await _bulletinRepository.UpdateAsync(bulletin, HttpContext.RequestAborted); } } /// /// 提交公告 /// /// /// [Permission(EPermission.CommitBulletin)] [HttpGet("bulletin/commit")] public async Task CommitBulletin(string id) { var bulletin = await _bulletinRepository.GetAsync(id, HttpContext.RequestAborted); if (bulletin == null) throw UserFriendlyException.SameMessage("无效数据"); if (bulletin.BulletinState != EBulletinState.Draft && bulletin.BulletinState != EBulletinState.ReviewNoPass) throw UserFriendlyException.SameMessage("当前状态不能提交"); bulletin.BulletinState = EBulletinState.InReview; bulletin.CommitTime = DateTime.Now; await _bulletinRepository.UpdateAsync(bulletin, HttpContext.RequestAborted); } /// /// 修改公告 /// /// /// [Permission(EPermission.UpdateBulletin)] [HttpPost("bulletin/update")] public async Task UpdateBulletin([FromBody] UpdateBulletinDto dto) { var bulletin = await _bulletinRepository.GetAsync(dto.Id, HttpContext.RequestAborted); if (bulletin == null) throw UserFriendlyException.SameMessage("无效数据"); if (bulletin.BulletinState != EBulletinState.Draft && bulletin.BulletinState != EBulletinState.ReviewNoPass) throw UserFriendlyException.SameMessage("当前状态不能修改"); bulletin.Title = dto.Title; bulletin.Content = dto.Content; bulletin.BulletinTypeId = dto.BulletinTypeId; bulletin.BulletinTypeName = dto.BulletinTypeName; bulletin.LoseEfficacyTime = dto.LoseEfficacyTime; bulletin.PushRanges = dto.PushRanges; bulletin.DisplayLocation = dto.DisplayLocation; bulletin.SourceOrgId = dto.SourceOrgId; bulletin.SourceOrgName = dto.SourceOrgName; await _bulletinRepository.UpdateAsync(bulletin, HttpContext.RequestAborted); } /// /// 删除公告 /// /// /// [Permission(EPermission.DelBulletin)] [HttpGet("bulletin/del/{id}")] public async Task DelBulletin(string id) { var bulletin = await _bulletinRepository.GetAsync(id, HttpContext.RequestAborted); if (bulletin == null) throw UserFriendlyException.SameMessage("无效数据"); if (bulletin.BulletinState != EBulletinState.Draft) throw UserFriendlyException.SameMessage("当前状态不能删除"); await _bulletinRepository.RemoveAsync(x => x.Id == id, false, HttpContext.RequestAborted); } /// /// 新增公告 /// /// /// [Permission(EPermission.AddBulletin)] [HttpPost("bulletin/add")] public async Task AddBulletin([FromBody] AddBulletinDto dto) { var model = _mapper.Map(dto); model.BulletinState = Share.Enums.Article.EBulletinState.Draft; model.ReadedNum = 0; model.IsArrive = false; await _bulletinRepository.AddAsync(model, HttpContext.RequestAborted); } /// /// 公告上架或者下架 /// /// /// [HttpPost("bulletin-arrive")] public async Task BulletinArrive([FromBody] BulletinArriveDto dto) { var bulletin = await _bulletinRepository.GetAsync(dto.Id, HttpContext.RequestAborted); if (bulletin == null) throw UserFriendlyException.SameMessage("无效数据"); if (bulletin.BulletinState != EBulletinState.ReviewPass) throw UserFriendlyException.SameMessage("当前状态不能操作上架或下架"); bulletin.IsArrive = dto.IsArrive; if (bulletin.IsArrive == false) { bulletin.ExaminTime = null; bulletin.ExaminManId = null; bulletin.ExaminOpinion = null; bulletin.CommitTime = null; bulletin.BulletinState = EBulletinState.Draft; } await _bulletinRepository.UpdateAsync(bulletin, HttpContext.RequestAborted); } /// /// 列表页面基础数据 /// /// [HttpGet("bulletin/listbasedata")] public async Task BulletinListBaseData() { var rsp = new { BulletinType = _systemDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.BulletinType) }; return rsp; } /// /// 新增页面基础数据 /// /// [HttpGet("bulletin/addbasedata")] public async Task BulletinAddBaseData() { var rsp = new { BulletinType = _systemDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.BulletinType), BulletinDisplayLocation = _systemDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.BulletinDisplayLocation), PushRanges = _systemDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.BulletinPushRange), OrgsOptions = await _organizeRepository.GetOrgJson(), }; return rsp; } #endregion } }