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; 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) { _bulletinRepository = bulletinRepository; _mapper = mapper; _organizeRepository = organizeRepository; _workflowApplication = workflowApplication; _circularRepository = circularRepository; _sessionContext = sessionContext; _circularRecordRepository = circularRecordRepository; _circularReadGroupRepository = circularReadGroupRepository; _userRepository = userRepository; _circularRecordDomainService = circularRecordDomainService; _systemDicDataCacheManager = systemDicDataCacheManager; _mediator = mediator; } #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.UserId || x.OrgId == _sessionContext.OrgId).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); 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); //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.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; await _bulletinRepository.AddAsync(model, 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), PushRanges = _systemDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.BulletinPushRange), OrgsOptions = await _organizeRepository.GetOrgJson(), }; return rsp; } #endregion } }