This commit is contained in:
wanghu
2026-09-02 10:23:24 +08:00
parent 5a414b14d2
commit ce436cbb32
117 changed files with 13768 additions and 0 deletions
@@ -0,0 +1,51 @@
using Microsoft.AspNetCore.Mvc;
using YhCore.Common;
using YhCore.Common.UserContext;
using YhCore.Entity;
using YhCore.Model.Vo;
using YhCore.Service.Interfaces;
namespace YhCore.WebApi.Controllers.Api
{
/// <summary>
/// 日志查询接口(对应 Java 版 controller/api/LogController,路由 /api/log/)。
/// </summary>
[ApiController]
[Route(ApiRoutes.ApiPath + "/log")]
public class LogController : ControllerBase
{
private readonly ILogService _logService;
public LogController(ILogService logService)
{
_logService = logService;
}
/// <summary>
/// 系统操作日志搜索(对应 Java GET /api/log/systemSearch)。
/// </summary>
/// <param name="keyword">关键字(可空)</param>
/// <param name="page">页码,从 0 开始(对应 Spring Pageable.page)</param>
/// <param name="size">每页大小(对应 Spring Pageable.size)</param>
[HttpGet("systemSearch")]
public PageVO<SysOperationLog> SystemSearch(
[FromQuery] string keyword,
[FromQuery] int page = 0,
[FromQuery] int size = 20)
{
return _logService.Search(UserContextHolder.GetSchId(), keyword, true, page, size);
}
/// <summary>
/// 操作日志搜索(对应 Java GET /api/log/search)。
/// </summary>
[HttpGet("search")]
public PageVO<SysOperationLog> Search(
[FromQuery] string keyword,
[FromQuery] int page = 0,
[FromQuery] int size = 20)
{
return _logService.Search(UserContextHolder.GetSchId(), keyword, false, page, size);
}
}
}
@@ -0,0 +1,116 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.Json;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Yh.SchClass.OpenApi;
using Yh.SchClass.OpenApi.Model;
using YhCore.Common;
namespace YhCore.WebApi.Controllers.Api
{
/// <summary>
/// 教务(SchClass)开放接口演示控制器:引用 Yh.SchClass.OpenApi.dll(Library),
/// 对应 Java 教务 bschclassmanage 的 /oapi 端点(配置节 yh:schclass:open)。
/// <para>SDK 门面 <see cref="SchClassOpenApi"/> 聚合 10 个客户端,本控制器演示其中 5 个。</para>
/// </summary>
[ApiController]
[Route(ApiRoutes.ApiPath + "/com/schClass")]
public class SchClassController : ControllerBase
{
private readonly SchClassOpenApi _sch;
public SchClassController(SchClassOpenApi sch)
{
_sch = sch ?? throw new ArgumentNullException(nameof(sch));
}
/// <summary>
/// 全部学校列表(GET /oapi/SchInfo/AllList)。
/// </summary>
[HttpGet("schools")]
public async Task<List<SchInfoVo>> Schools()
{
return await _sch.SchInfo.AllListAsync();
}
/// <summary>
/// 按学校外部序列号查询学校(GET /oapi/SchInfo/GetSchFirst)。
/// </summary>
/// <param name="schId">学校外部序列号</param>
[HttpGet("school")]
public async Task<SchInfoVo> School([FromQuery] string schId)
{
return await _sch.SchInfo.GetSchFirstAsync(schId);
}
/// <summary>
/// 按学校查询教师列表(GET /oapi/OATea/GetSchTeainfo)。
/// </summary>
/// <param name="schSerId">学校外部序列号</param>
/// <param name="schId">学校内部 ID(优先使用)</param>
[HttpGet("teachers")]
public async Task<List<TeaInfoVo>> Teachers(
[FromQuery] string schSerId,
[FromQuery] int? schId)
{
return await _sch.TeaInfo.GetSchTeaInfoAsync(schSerId, schId);
}
/// <summary>
/// 按学校查询班级列表(GET /oapi/VSchClass/GetVClassList)。
/// </summary>
/// <param name="schSerId">学校外部序列号</param>
[HttpGet("classes")]
public async Task<List<Dictionary<string, object>>> Classes([FromQuery] string schSerId)
{
var rows = await _sch.VClass.GetVClassListAsync(schSerId);
return rows.Select(ToPlainRow).ToList();
}
/// <summary>
/// 按学校查询学生列表(GET /oapi/OAStu/GetSchStuList)。
/// </summary>
/// <param name="schserid">学校外部序列号</param>
/// <param name="schgroupid">学校分组 ID(可空)</param>
[HttpGet("students")]
public async Task<List<Dictionary<string, object>>> Students(
[FromQuery] string schserid,
[FromQuery] string schgroupid)
{
var rows = await _sch.StuInfo.GetSchStuListAsync(schserid, schgroupid);
return rows.Select(ToPlainRow).ToList();
}
// ===================== JsonElement → 普通对象 =====================
// SDK 行类型 SchClassRow = Dictionary<string, JsonElement>(Java Map<String,Object> 兼容);
// 直接返回会被 Newtonsoft 序列化成 JsonElement 内部结构,这里转成原生对象。
private static Dictionary<string, object> ToPlainRow(Dictionary<string, JsonElement> row)
=> row.ToDictionary(kv => kv.Key, kv => ToPlain(kv.Value));
private static object ToPlain(JsonElement el)
{
switch (el.ValueKind)
{
case JsonValueKind.String:
return el.GetString();
case JsonValueKind.Number:
return el.TryGetInt32(out var i) ? (object)i : el.GetDouble();
case JsonValueKind.True:
return true;
case JsonValueKind.False:
return false;
case JsonValueKind.Null:
return null;
case JsonValueKind.Array:
return el.EnumerateArray().Select(ToPlain).ToList();
case JsonValueKind.Object:
return el.EnumerateObject().ToDictionary(p => p.Name, p => ToPlain(p.Value));
default:
return el.ToString();
}
}
}
}
@@ -0,0 +1,67 @@
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Features;
using Microsoft.AspNetCore.Mvc;
using System.Collections.Generic;
using System.Threading.Tasks;
using Yh.Platform.Abstractions;
using Yh.Platform.Auth;
using Yh.Platform.OpenApi;
using YhCore.Common;
namespace YhCore.WebApi.Controllers.Api
{
/// <summary>
/// 用户基础接口(对应 Java 版 controller/api/UserController,路由 /api/base/)。
/// </summary>
[ApiController]
[Route(ApiRoutes.ApiPath + "/base")]
public class UserController : ControllerBase
{
private readonly IOpenApiUserClient _openApiUserClient;
public UserController(IOpenApiUserClient openApiUserClient)
{
_openApiUserClient = openApiUserClient;
}
/// <summary>
/// 获取当前用户可见的应用模块(对应 Java GET /api/base/getUserMod,
/// 内部调用 YschBaseOpenApi.getUserModule)。
/// </summary>
[HttpGet("getUserMod")]
public async Task<List<BoaModule>> GetUserMod()
{
var boa = BoaUserContext.Get();
return await _openApiUserClient.GetUserModuleAsync(boa?.Id ?? 0, boa?.School?.Id);
}
/// <summary>
/// 获取当前登录用户信息(对应 Java GET /api/base/getUserInfo,
/// Java 版直接返回认证切面注入的 authUserWithDept)。
/// </summary>
[HttpGet("getUserInfo")]
public BoaUser GetUserInfo()
{
return BoaUserContext.Get();
}
/// <summary>
/// 登出(对应 Java GET /api/base/logout:session.invalidate())。
/// </summary>
[HttpGet("logout")]
public async Task<IActionResult> Logout()
{
// 清除本地 Cookie 登录态
await HttpContext.SignOutAsync(YhAuthDefaults.CookieScheme);
if (HttpContext.Features.Get<ISessionFeature>() != null)
{
HttpContext.Session.Clear();
}
return Ok();
}
}
}
@@ -0,0 +1,306 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Yh.Platform.Abstractions;
using YhCore.Common;
using YhCore.Common.Config;
using YhCore.Common.UserContext;
using YhCore.Entity;
using YhCore.Model.Dto;
using YhCore.Service.Interfaces;
namespace YhCore.WebApi.Controllers.Api.Common
{
/// <summary>
/// 公共字典 / 文件(对应旧 Areas/Common/CommonController,路由 api/base)。
/// 字典部分 8 接口 + 文件部分 4 接口(FileDown / FilePreview / FileUpload / FileUploadImage)已落地;
/// 旧 [NoAuth] 语义:无需用户上下文,schId 由前端传入或取当前用户。
/// </summary>
[ApiController]
[Route(ApiRoutes.ApiPath + "/base")]
public class CommonController : ControllerBase
{
private readonly IDictionaryService _dict;
private readonly IFileService _file;
public CommonController(IDictionaryService dict, IFileService file)
{
_dict = dict;
_file = file;
}
/// <summary>获取指定字典数据(Type 1~10)。</summary>
[HttpGet("GetSysDic")]
public async Task<List<DicOption>> GetSysDic([FromQuery] int type = 0)
{
var typeId = DictionaryTypeHelper.FromSysDicType(type);
if (typeId == null)
{
throw new DException("参数错误");
}
return await _dict.GetDictListAsync(typeId, SchSerID());
}
/// <summary>字典类别列表([NoAuth],排除部门)。</summary>
[HttpGet("GetDicTypeList")]
public async Task<List<DicOption>> GetDicTypeList() => await _dict.GetDicTypeListAsync();
/// <summary>字典列表管理(Type=0/DEPT 取全校;其他仅超管 bestsch)。</summary>
[HttpGet("GetDictMangeList")]
public async Task<List<DicManageItem>> GetDictMangeList([FromQuery] string type)
{
var typeId = DictionaryTypeHelper.ResolveTypeId(type);
if (typeId == null)
{
throw new DException("参数错误");
}
if (DictionaryTypeHelper.IsDept(typeId))
{
return await _dict.GetDictMangeListAsync("DEPT", SchSerID());
}
//if (UserContextHolder.Current.() =1 )
//{
// throw new DException("非超管不得操作!");
//}
return await _dict.GetDictMangeListAsync(typeId, "");
}
/// <summary>添加字典。</summary>
[HttpPost("AddDic")]
public async Task AddDic([FromBody] Common_Dictionary model)
{
if (model == null) throw new DException("参数错误!");
var info = new Common_Dictionary
{
typeID = model.typeID,
typeName = DictionaryTypeHelper.GetTypeName(model.typeID),
Name = model.Name,
Schserid = SchSerID()
};
await _dict.AddDicAsync(info);
}
/// <summary>更新字典。</summary>
[HttpPost("UpdateDic")]
public async Task UpdateDic([FromBody] Common_Dictionary model)
{
if (model == null) throw new DException("参数有误!");
model.Schserid = SchSerID();
await _dict.UpdateDicAsync(model);
}
/// <summary>编辑字典名称。</summary>
[HttpPost("EditDic")]
public async Task EditDic([FromBody] Common_Dictionary model)
{
if (model == null) throw new DException("参数有误!");
model.Schserid = SchSerID();
await _dict.EditDicAsync(model);
}
/// <summary>添加发文部门。</summary>
[HttpPost("AddDeptDic")]
public async Task AddDeptDic([FromBody] Common_Dictionary model)
{
if (model == null) throw new DException("参数有误!");
var info = new Common_Dictionary
{
typeID = "DEPT",
typeName = "部门类别",
Name = model.Name,
Schserid = SchSerID()
};
await _dict.AddDicAsync(info);
}
/// <summary>更新发文部门。</summary>
[HttpPost("UpdateDeptDic")]
public async Task UpdateDeptDic([FromBody] Common_Dictionary model)
{
if (model == null) throw new DException("参数有误!");
model.Schserid = SchSerID();
await _dict.UpdateDicAsync(model);
}
#region 文件:下载 / 预览 / 上传
/// <summary>
/// 公用下载文件(旧 FileDown,[NoAuth])。yl=true 且为图片/PDF 时重定向到文件 URL(webapp 预览),
/// 否则物理文件下载。
/// </summary>
[HttpGet("FileDown")]
public async Task<IActionResult> FileDown([FromQuery] int id, [FromQuery] bool yl = false)
{
if (id == 0)
return Ok();
var file = await _file.GetEnclosureAsync(id);
string[] previewArry = { ".jpg", ".gif", ".png", ".pdf", ".jpeg", ".bmp" };
if (yl)
{
// 旧 sch_weboa_url.Replace("notice/api", AppType + "/") + fileurl → 新 FileWebPath + fileurl
string fileUrl = (Config.FileWebPath ?? "") + file.fileurl;
string suffName = Path.GetExtension(fileUrl);
if (previewArry.Any(x => x == suffName.ToLower()))
return Redirect(fileUrl);
}
// WebHelper.DownFile:物理文件下载
string filePath = _file.MapPhysicalPath(file.fileurl);
if (!System.IO.File.Exists(filePath))
return Content("请求的文件不存在!");
string contentType = GetContentType(filePath);
string outputFileName = file.filename ?? "file";
return PhysicalFile(filePath, contentType, outputFileName);
}
/// <summary>
/// 公用预览 office 文件(旧 FilePreview / CommonPreview,[NoAuth])。
/// type=1 → 返回可用预览 url(本地 .pdf 存在优先);type=2 → 重定向本地 pdf 或 officeapps.live.com;
/// 其余 → 重定向替换后缀为 .pdf 的地址。跳转返回 RedirectResult(全局包装过滤器不拦截)。
/// </summary>
[HttpGet("FilePreview")]
public async Task<object> FilePreview([FromQuery] int id, [FromQuery] string type = null)
{
if (id == 0)
throw new DException("文件ID错误!");
var file = await _file.GetEnclosureAsync(id);
// 公文另做处理
if (file.fileurl != null && file.fileurl.IndexOf("gw.") > -1)
{
string fileUrl = "http://" + file.fileurl;
string suffName = Path.GetExtension(fileUrl);
string newName = fileUrl.Remove(fileUrl.LastIndexOf(suffName, StringComparison.Ordinal), suffName.Length) + ".pdf";
return Redirect(newName);
}
string fileUrl2 = (Config.FileWebPath ?? "") + file.fileurl;
string suffName2 = Path.GetExtension(fileUrl2);
if (!string.IsNullOrEmpty(type))
{
// 单独读取文件是否存在
string newFile = file.fileurl;
string pdfFile = newFile.Remove(newFile.LastIndexOf(suffName2, StringComparison.Ordinal), suffName2.Length) + ".pdf";
string outFile = _file.MapPhysicalPath(pdfFile);
if (type == "1")
{
if (System.IO.File.Exists(outFile)) return (Config.FileWebPath ?? "") + pdfFile;
return fileUrl2;
}
if (type == "2")
{
string pdfUrl = string.Empty;
if (System.IO.File.Exists(outFile)) pdfUrl = (Config.FileWebPath ?? "") + pdfFile;
else pdfUrl = "https://view.officeapps.live.com/op/view.aspx?src=" + fileUrl2;
return Redirect(pdfUrl);
}
return "";
}
string newName2 = fileUrl2.Remove(fileUrl2.LastIndexOf(suffName2, StringComparison.Ordinal), suffName2.Length) + ".pdf";
return Redirect(newName2);
}
/// <summary>
/// 公用附件上传(旧 FileUpload,[NoAuth])。
/// chunk 参数 → 分片保存返回 {code:1,type:"chunk",msg};fileName 参数 → 合并分片;否则单文件上传。
/// 落库 Common_UpFiles(TopicType=AppCode),返回 {fileurl,host,fileid,name,type}。
/// </summary>
[HttpPost("FileUpload")]
public async Task<object> Upload()
{
string apptype = "docprint"; // 旧 WebHelper.AppType 固定 docprint
string guid = Request.Form["guid"];
string chunk = Request.Form["chunk"];
string fileName = Request.Form["fileName"];
if (!string.IsNullOrEmpty(chunk))
{
var chunkFile = Request.Form.Files.FirstOrDefault(f => f.Name == "file") ?? Request.Form.Files.FirstOrDefault();
await _file.SaveChunkAsync(guid, chunk, chunkFile);
return new { code = 1, type = "chunk", msg = "分片上传成功!" };
}
FileObj url;
string errMsg = "上传失败!";
if (string.IsNullOrEmpty(fileName))
{
url = await _file.SaveFileAsync(apptype, Request.Form.Files.FirstOrDefault());
}
else
{
url = await _file.MergeSaveAsync(apptype, guid, fileName);
}
if (url == null)
throw new DException(errMsg);
// 旧 WebHelper.AppCode == "1102" ? "1002" : AppCode → docprint 固定 1003
int serid = await _file.SaveEnclosureAsync(url, DocPrintConstants.AppCode.ToString());
return new { fileurl = url.fileurl, host = url.host, fileid = serid, name = url.filename, type = url.filetype };
}
/// <summary>公用图片上传(旧 FileUploadImage,[NoAuth];多图,返回数组)。</summary>
[HttpPost("FileUploadImage")]
public async Task<object> UploadImg()
{
string apptype = "docprint";
var urlList = await _file.SaveFileImageAsync(apptype, Request.Form.Files);
if (urlList.Count == 0)
throw new DException("上传失败!");
var result = new List<object>();
foreach (var item in urlList)
{
int serid = await _file.SaveEnclosureAsync(item, DocPrintConstants.AppCode.ToString());
result.Add(new { fileurl = item.fileurl, host = item.host, fileid = serid, name = item.filename, type = item.filetype });
}
return result;
}
/// <summary>按扩展名取 ContentType(替代旧 MimeMapping.GetMimeMapping)。</summary>
private static string GetContentType(string filePath)
{
string ext = Path.GetExtension(filePath).ToLower();
return ext switch
{
".jpg" or ".jpeg" => "image/jpeg",
".gif" => "image/gif",
".png" => "image/png",
".bmp" => "image/bmp",
".pdf" => "application/pdf",
".txt" => "text/plain",
".doc" => "application/msword",
".docx" => "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
".xls" => "application/vnd.ms-excel",
".xlsx" => "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
".ppt" => "application/vnd.ms-powerpoint",
".pptx" => "application/vnd.openxmlformats-officedocument.presentationml.presentation",
".zip" => "application/zip",
".rar" => "application/x-rar-compressed",
".mp4" => "video/mp4",
_ => "application/octet-stream",
};
}
#endregion
private static string SchSerID() => UserContextHolder.Current.SchSerID;
}
}
@@ -0,0 +1,64 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using YhCore.Common;
using YhCore.Common.UserContext;
using YhCore.Model.Dto;
using YhCore.Service.Interfaces;
namespace YhCore.WebApi.Controllers.Api.Common
{
/// <summary>
/// 自由审批流控制器(对应旧 Areas/Common/FreeApproveController,路由 api/common/freeapprove)。
/// 7 接口:自由流程节点查询/保存、审核意见、审核回显、抄送人。
/// </summary>
[ApiController]
[Route(ApiRoutes.ApiPath + "/common/freeapprove")]
public class FreeApproveController : ControllerBase
{
private readonly IFreeApproveService _svc;
public FreeApproveController(IFreeApproveService svc)
{
_svc = svc;
}
/// <summary>获取当前自由流程节点(dataid 为空时取最大 dataid)。</summary>
[HttpGet("GetFleeFlow")]
public Task<List<FreeFlowNode>> GetFleeFlow([FromQuery] int? dataid = null)
=> _svc.GetFleeFlowAsync(UserContextHolder.Current?.Id ?? 0, dataid);
/// <summary>保存自由流程审核人,返回首步骤 SerID。</summary>
[HttpGet("EditFleeFlow")]
public Task<int> EditFleeFlow([FromQuery] string FlowUids, [FromQuery] int? dataid = null, [FromQuery] bool IsFlowNull = false)
=> _svc.EditFleeFlowAsync(UserContextHolder.Current?.Id ?? 0, SchSerID(), dataid, FlowUids, IsFlowNull);
/// <summary>添加审核意见。</summary>
[HttpGet("AddShenheRemark")]
public Task<string> AddShenheRemark([FromQuery] int? dataid, [FromQuery] string remark, [FromQuery] int freestepid)
=> _svc.AddShenheRemarkAsync(UserContextHolder.Current?.Id ?? 0, dataid, remark, freestepid);
/// <summary>获取后续自由流程节点。</summary>
[HttpGet("GetAfterFleeFlow")]
public Task<List<FreeFlowNode>> GetAfterFleeFlow([FromQuery] int? dataid, [FromQuery] int freestepid)
=> _svc.GetAfterFleeFlowAsync(dataid, freestepid);
/// <summary>编辑后续自由流程,返回末步骤 SerID。</summary>
[HttpGet("EditAfterFleeFlow")]
public Task<int> EditAfterFleeFlow([FromQuery] int? dataid, [FromQuery] int freestepid, [FromQuery] string FlowUids)
=> _svc.EditAfterFleeFlowAsync(dataid, freestepid, FlowUids);
/// <summary>自由流程审核回显(发起人 + 审核人步骤)。</summary>
[HttpGet("ShenheFlow")]
public Task<List<FreeShenheInfo>> ShenheFlow([FromQuery] int uid, [FromQuery] string ctime, [FromQuery] int dataid,
[FromQuery] int? freestepid = null, [FromQuery] int? flowid = null)
=> _svc.ShenheFlowAsync(uid, ctime, dataid, freestepid, flowid);
/// <summary>抄送人列表(按 uids 查用户)。</summary>
[HttpGet("ChaoSendList")]
public Task<List<ChaoSendUser>> ChaoSendList([FromQuery] string uids)
=> _svc.ChaoSendListAsync(uids);
private static string SchSerID() => UserContextHolder.Current.SchSerID;
}
}
@@ -0,0 +1,167 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Yh.SchClass.OpenApi.Model;
using YhCore.Common;
using YhCore.Common.UserContext;
using YhCore.Entity;
using YhCore.Model.Dto;
using YhCore.Model.Vo;
using YhCore.Service.Interfaces;
namespace YhCore.WebApi.Controllers.Api.Common
{
/// <summary>
/// 审核流程管理控制器(对应旧 Areas/Common/reviewprocessController,路由 api/common/reviewprocess)。
/// 23 接口:流程/步骤 CRUD、教师查询、流程判断、用户角色。
/// </summary>
[ApiController]
[Route(ApiRoutes.ApiPath + "/common/reviewprocess")]
public class ReviewprocessController : ControllerBase
{
private readonly IReviewProcessService _svc;
public ReviewprocessController(IReviewProcessService svc)
{
_svc = svc;
}
#region 流程与步骤
/// <summary>审核流程列表(分页)。</summary>
[HttpGet("List")]
public Task<PageVO<FlowListItem>> List([FromQuery] string Name, [FromQuery] int PageSize,
[FromQuery] int PageIndex, [FromQuery] int flowType, [FromQuery] bool Edit = false)
=> _svc.ListAsync(Name, PageSize, PageIndex, flowType, Edit, SchSerID());
/// <summary>审核流程列表【局版】(降级为当前学校)。</summary>
[HttpGet("List2")]
public Task<PageVO<FlowListItem>> List2([FromQuery] string Name, [FromQuery] int PageSize,
[FromQuery] int PageIndex, [FromQuery] int flowType, [FromQuery] bool Edit = false)
=> _svc.List2Async(Name, PageSize, PageIndex, flowType, Edit, SchSerID());
/// <summary>步骤流程列表。</summary>
[HttpGet("StepList")]
public Task<PageVO<StepListItem>> StepList([FromQuery] string Name, [FromQuery] int Serid)
=> _svc.StepListAsync(Name, Serid);
/// <summary>添加审核流程。</summary>
[HttpPost("Create")]
public async Task Create([FromBody] Common_flowinfo model)
{
model.schSerID = SchSerID();
await _svc.CreateAsync(model);
}
/// <summary>修改审核流程。</summary>
[HttpPost("Edit")]
public async Task Edit([FromBody] Common_flowinfo model)
{
model.schSerID = SchSerID();
await _svc.EditAsync(model);
}
/// <summary>添加步骤流程。</summary>
[HttpPost("StepCreate")]
public Task StepCreate([FromBody] Common_flowstep model)
=> _svc.StepCreateAsync(model);
/// <summary>修改步骤流程。</summary>
[HttpPost("StepEdit")]
public Task StepEdit([FromBody] Common_flowstep model)
=> _svc.StepEditAsync(model);
/// <summary>删除审核流程(ids 逗号分隔)。</summary>
[HttpGet("Delete")]
public Task Delete([FromQuery] string ids)
=> _svc.DeleteAsync(ids);
/// <summary>删除步骤。</summary>
[HttpPost("StepDelete")]
public Task StepDelete([FromBody] decimal[] ids)
=> _svc.StepDeleteAsync(ids);
/// <summary>流程绑定的步骤列表。</summary>
[HttpGet("BindstepList")]
public Task<List<BindStepItem>> BindstepList([FromQuery] int Serid)
=> _svc.BindstepListAsync(Serid);
/// <summary>绑定步骤的人员。</summary>
[HttpGet("BindGroupuserList")]
public Task<List<BindGroupuserItem>> BindGroupuserList([FromQuery] int flowid, [FromQuery] int prestep)
=> _svc.BindGroupuserListAsync(flowid, prestep);
/// <summary>绑定流程(流程 + 抄送人)。</summary>
[HttpGet("Bindflowinfo")]
public Task<List<BindFlowItem>> Bindflowinfo([FromQuery] int flowType)
=> _svc.BindflowinfoAsync(SchSerID(), flowType);
#endregion
#region 教师 / 人员
/// <summary>当前学校教师列表。</summary>
[HttpGet("GetTeaList")]
public Task<List<TeaOption>> GetTeaList()
=> _svc.GetTeaListAsync(SchSerID());
/// <summary>学校 + 教育局教师列表(降级为当前学校)。</summary>
[HttpGet("GetTeaListSup")]
public Task<List<TeaOption>> GetTeaListSup()
=> _svc.GetTeaListSupAsync(SchSerID());
/// <summary>教师信息分页。</summary>
[HttpGet("GetUserinfo")]
public Task<PageVO<TeaInfoVo>> GetUserinfo([FromQuery] string Name, [FromQuery] int statetype,
[FromQuery] int PageSize, [FromQuery] int PageIndex)
=> _svc.GetUserinfoAsync(SchSerID(), Name, statetype, PageSize, PageIndex);
/// <summary>非中层领导人员。</summary>
[HttpGet("GetNoLeadingMiddleInfo")]
public Task<string[]> GetNoLeadingMiddleInfo()
=> _svc.GetNoLeadingMiddleInfoAsync(SchSerID());
/// <summary>非中层领导人员【局版】(降级为当前学校)。</summary>
[HttpGet("GetNoLeadingMiddleInfoSup")]
public Task<string[]> GetNoLeadingMiddleInfoSup()
=> _svc.GetNoLeadingMiddleInfoSupAsync(SchSerID());
/// <summary>设置/取消中层领导(教务 SDK 未提供,暂不支持)。</summary>
[HttpGet("changeLeadingMiddleStatus")]
public Task ChangeLeadingMiddleStatus([FromQuery] int state, [FromQuery] string UserTeaSerIDstr)
=> _svc.ChangeLeadingMiddleStatusAsync(state, UserTeaSerIDstr);
/// <summary>附件数据源。</summary>
[HttpGet("filelist")]
public Task<List<FileListItem>> Filelist([FromQuery] string ids)
=> _svc.FilelistAsync(ids);
#endregion
#region 流程判断 / 用户
/// <summary>该校审核流程是固定还是自由。</summary>
[HttpGet("IsShenheflow")]
public Task<ShenheFlowResult> IsShenheflow()
=> _svc.IsShenheflowAsync(SchSerID(), UserContextHolder.Current?.Id ?? 0);
/// <summary>绑定抄送默认人。</summary>
[HttpGet("IsSendUser")]
public Task<List<SendUserItem>> IsSendUser()
=> _svc.IsSendUserAsync(SchSerID(), UserContextHolder.Current?.Id ?? 0);
/// <summary>当前用户基础信息。</summary>
[HttpGet("GetUser")]
public Task<CurrentUserInfo> GetUser()
=> _svc.GetUserAsync();
/// <summary>用户流程角色(1 有流程,0 无)。</summary>
[HttpGet("GetUserFlowRole")]
public Task<int> GetUserFlowRole()
=> _svc.GetUserFlowRoleAsync(UserContextHolder.Current?.Id ?? 0);
#endregion
private static string SchSerID() => UserContextHolder.Current.SchSerID;
}
}
@@ -0,0 +1,65 @@
using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Yh.Platform.Abstractions;
using YhCore.Common;
using YhCore.Model.Dto;
using YhCore.Service.Interfaces;
namespace YhCore.WebApi.Controllers.Api.DocPrint
{
/// <summary>
/// 文印统计看板控制器(对应旧 Areas/DocPrint/DocPrintStatisticsController,路由 api/docprint/statistics)。
/// 旧类级 [NoAuth]:schId 由前端传入(非当前用户),新项目 SSO 关闭时匿名放行、开启时按配置保护,
/// 语义一致。ExportRecord(Excel 导出,NPOI)延后迁移。
/// </summary>
[ApiController]
[Route(ApiRoutes.ApiPath + "/docprint/statistics")]
public class DocPrintStatisticsController : ControllerBase
{
private readonly IDocPrintStatisticsService _statistics;
public DocPrintStatisticsController(IDocPrintStatisticsService statistics)
{
_statistics = statistics;
}
/// <summary>打印总数/消耗/最多类型统计(旧 GetDocPrintCount)。</summary>
[HttpGet("GetDocPrintCount")]
public async Task<System.Collections.Generic.List<DocPrintCountItem>> GetDocPrintCount(
[FromQuery] int schId,
[FromQuery] DateTime? startDate = null,
[FromQuery] DateTime? endDate = null)
=> await _statistics.GetDocPrintCountAsync(schId, startDate, endDate);
/// <summary>饼图(按类型,消耗/数量,旧 GetPieChart)。</summary>
[HttpGet("GetPieChart")]
public async Task<System.Collections.Generic.List<PieChartSeries>> GetPieChart(
[FromQuery] int schId,
[FromQuery] DateTime? startDate = null,
[FromQuery] DateTime? endDate = null)
=> await _statistics.GetPieChartAsync(schId, startDate, endDate);
/// <summary>打印类型列表(旧 GetDocPrintType)。</summary>
[HttpGet("GetDocPrintType")]
public async Task<System.Collections.Generic.List<DocPrintTypeItem>> GetDocPrintType([FromQuery] int schId)
=> await _statistics.GetDocPrintTypeAsync(schId);
/// <summary>分页明细(旧 GetDocPrintList;旧 1 基 pageIndex 内部转 0 基)。</summary>
[HttpGet("GetDocPrintList")]
public async Task<DocPrintListResult> GetDocPrintList(
[FromQuery] int schId,
[FromQuery] string docType = "ALL",
[FromQuery] string likeName = null,
[FromQuery] int pageIndex = 1,
[FromQuery] int pageSize = 10,
[FromQuery] DateTime? startDate = null,
[FromQuery] DateTime? endDate = null)
{
if (pageSize <= 0) throw new DException("pageSize 必须大于 0");
return await _statistics.GetDocPrintListAsync(schId, docType, likeName, pageIndex, pageSize, startDate, endDate);
}
// 延后:ExportRecord(Excel 导出,NPOI)
}
}
@@ -0,0 +1,32 @@
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using YhCore.Common;
using YhCore.Entity;
using YhCore.Repository;
namespace YhCore.WebApi.Controllers.Api.DocPrint
{
/// <summary>
/// 启动预热控制器(对应旧 Areas/DocPrint/LoadingController,路由 api/docprint/loading)。
/// 无业务逻辑:执行一次 Base_Log 查询触发数据库连接建立,防止首请求慢。
/// 旧接口 void 无返回体;新项目由 GlobalWrapResultFilter 统一包装为 {code:0,msg:"",data:null}。
/// </summary>
[ApiController]
[Route(ApiRoutes.ApiPath + "/docprint/loading")]
public class LoadingController : ControllerBase
{
private readonly IRepository<Base_Log> _log;
public LoadingController(IRepository<Base_Log> log)
{
_log = log;
}
/// <summary>预热(执行一次 Base_Log 查询)。</summary>
[HttpGet("List")]
public async Task List()
{
await _log.FirstOrDefaultAsync(a => a.Id > 0);
}
}
}
@@ -0,0 +1,334 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Yh.Platform.Abstractions;
using YhCore.Common;
using YhCore.Common.UserContext;
using YhCore.Entity;
using YhCore.Model.Dto;
using YhCore.Model.Vo;
using YhCore.Service.Interfaces;
namespace YhCore.WebApi.Controllers.Api.DocPrint
{
/// <summary>
/// 审核角色 + 流程配置控制器(对应旧 Areas/DocPrint/WYSHRoleController,路由 api/docprint/wyshrole)。
/// 45 action 中本批落地 39 个;Excel 导入导出(ExceltotalListSHRole/WYRDExceldaochu/UpfileExcelSHRole/
/// downMBOfSHRole/downUpfileSHRoleFK)与审批单 PDF(DwonWYSQD)依赖 NPOI/PdfHelper,延后迁移。
/// </summary>
[ApiController]
[Route(ApiRoutes.ApiPath + "/docprint/wyshrole")]
public class WYSHRoleController : ControllerBase
{
private readonly IWYSHRoleService _role;
public WYSHRoleController(IWYSHRoleService role)
{
_role = role;
}
#region 审核角色管理
/// <summary>学校是否启用审核角色(旧 getIsSHRole)。</summary>
[HttpGet("getIsSHRole")]
public async Task<string> GetIsSHRole() => await _role.GetIsSHRoleAsync(SchSerID());
/// <summary>保存启用开关(旧 saveIsSHRole)。</summary>
[HttpGet("saveIsSHRole")]
public async Task<string> SaveIsSHRole([FromQuery] string val) => await _role.SaveIsSHRoleAsync(SchSerID(), val);
/// <summary>审核角色列表(旧 getSHRole)。</summary>
[HttpGet("getSHRole")]
public async Task<List<WYSHRoleExt>> GetSHRole() => await _role.GetSHRoleAsync(SchSerID());
/// <summary>角色改名(旧 UpdateSHRoleName)。</summary>
[HttpGet("UpdateSHRoleName")]
public async Task<string> UpdateSHRoleName([FromQuery] decimal serID, [FromQuery] string sHRoleName)
=> await _role.UpdateSHRoleNameAsync(SchSerID(), UserId(), serID, sHRoleName);
/// <summary>新增/编辑角色(旧 EditSHRole,form: WYSHRole=JSON → [FromBody])。</summary>
[HttpPost("EditSHRole")]
public async Task<string> EditSHRole([FromBody] WYSHRoleExt model)
{
if (model == null) throw new DException("参数错误!");
return await _role.EditSHRoleAsync(SchSerID(), UserId(), model);
}
/// <summary>编辑成员行(旧 editSHTeaRow,form: SHTeaTxt → [FromBody])。</summary>
[HttpPost("editSHTeaRow")]
public async Task<string> EditSHTeaRow([FromBody] WY_SHRole_SHTea model)
{
if (model == null) throw new DException("参数错误!");
return await _role.EditSHTeaRowAsync(SchSerID(), UserId(), model);
}
/// <summary>删除成员行(旧 delSHTeaRow)。</summary>
[HttpGet("delSHTeaRow")]
public async Task<string> DelSHTeaRow([FromQuery] decimal serID)
=> await _role.DelSHTeaRowAsync(SchSerID(), serID);
/// <summary>批量保存审核人(旧 editSHTea,form: SHRoleID + listSHTeaTxt → [FromBody])。</summary>
[HttpPost("editSHTea")]
public async Task<string> EditSHTea([FromBody] EditSHTeaDto model)
{
if (model == null) throw new DException("参数错误!");
return await _role.EditSHTeaAsync(SchSerID(), UserId(), model.SHRoleID, model.listSHTea);
}
/// <summary>批量保存被审核人(旧 editBSHTea,form: SHRoleID + listBSHTeaTxt → [FromBody])。</summary>
[HttpPost("editBSHTea")]
public async Task<string> EditBSHTea([FromBody] EditBSHTeaDto model)
{
if (model == null) throw new DException("参数错误!");
return await _role.EditBSHTeaAsync(SchSerID(), UserId(), model.SHRoleID, model.listBSHTea);
}
/// <summary>删除角色(旧 delSHRole,form: listSHRoleIDTxt → [FromBody])。</summary>
[HttpPost("delSHRole")]
public async Task<string> DelSHRole([FromBody] DelSHRoleDto model)
{
if (model == null) throw new DException("参数错误!");
return await _role.DelSHRoleAsync(SchSerID(), model.listSHRoleID);
}
#endregion
#region 审核角色流程
/// <summary>审核流程列表(旧 ListFlow)。</summary>
[HttpGet("ListFlow")]
public async Task<PageVO<SHRoleFlowListItem>> ListFlow(
[FromQuery] string name = null,
[FromQuery] int pageSize = 10,
[FromQuery] int pageIndex = 0,
[FromQuery] int flowType = 0,
[FromQuery] bool edit = false)
=> await _role.ListFlowAsync(name, pageSize, pageIndex, SchSerID(), flowType, edit);
/// <summary>新增/编辑流程(旧 EditFlow;schSerID 取当前用户)。</summary>
[HttpPost("EditFlow")]
public async Task<string> EditFlow([FromBody] Common_flowinfo model)
{
if (model == null) throw new DException("参数错误!");
model.schSerID = SchSerID();
return await _role.EditFlowAsync(model);
}
/// <summary>新增步骤(旧 StepCreateOfSHRole)。</summary>
[HttpPost("StepCreateOfSHRole")]
public async Task<string> StepCreateOfSHRole([FromBody] Common_flowstep model)
{
if (model == null) throw new DException("参数错误!");
return await _role.StepCreateOfSHRoleAsync(model);
}
/// <summary>步骤详情(旧 getStepInfo)。</summary>
[HttpGet("getStepInfo")]
public async Task<SHRoleStepInfo> GetStepInfo([FromQuery] decimal flowid)
=> await _role.GetStepInfoAsync(SchSerID(), flowid);
/// <summary>删除步骤(旧 StepDelete)。</summary>
[HttpGet("StepDelete")]
public async Task<string> StepDelete([FromQuery] int id)
=> await _role.StepDeleteAsync(new List<int> { id });
/// <summary>改步骤名/条件/金额/按钮显隐(旧 updateStepName)。</summary>
[HttpGet("updateStepName")]
public async Task<string> UpdateStepName(
[FromQuery] int serID,
[FromQuery] int flowid,
[FromQuery] string stepName,
[FromQuery] int cond = 0,
[FromQuery] string isshowJE = "0",
[FromQuery] string isshowBtn = "1")
=> await _role.UpdateStepNameAsync(SchSerID(), serID, flowid, stepName, cond, isshowJE, isshowBtn);
/// <summary>步骤绑定角色(旧 AddStepSHRole)。</summary>
[HttpGet("AddStepSHRole")]
public async Task<string> AddStepSHRole([FromQuery] int flowid, [FromQuery] int stepid, [FromQuery] decimal shRoleid)
=> await _role.AddStepSHRoleAsync(SchSerID(), flowid, stepid, shRoleid);
/// <summary>步骤解绑角色(旧 delStepSHRole)。</summary>
[HttpGet("delStepSHRole")]
public async Task<string> DelStepSHRole([FromQuery] int stepid, [FromQuery] decimal shRoleid)
=> await _role.DelStepSHRoleAsync(SchSerID(), stepid, shRoleid);
/// <summary>按金额取步骤(旧 getStepByJE)。</summary>
[HttpGet("getStepByJE")]
public async Task<SHRoleStepByJEResult> GetStepByJE([FromQuery] int flowid, [FromQuery] int je)
=> await _role.GetStepByJEAsync(SchSerID(), UserId(), flowid, je);
#endregion
#region 文印申请页面
/// <summary>流程发起人列表(旧 getLCOfUser)。</summary>
[HttpGet("getLCOfUser")]
public async Task<List<WYFlowForUser>> GetLCOfUser()
=> await _role.GetLCOfUserAsync(SchSerID(), UserId(), UserName());
/// <summary>当前用户是否发起人(旧 IsSendUserSHRole)。</summary>
[HttpGet("IsSendUserSHRole")]
public async Task<List<SendUserItem>> IsSendUserSHRole([FromQuery] int flowid)
=> await _role.IsSendUserSHRoleAsync(SchSerID(), UserContextHolder.Current?.Id ?? 0, flowid);
/// <summary>字典信息(旧 getDicInfo)。</summary>
[HttpGet("getDicInfo")]
public async Task<List<Common_Dictionary>> GetDicInfo([FromQuery] string typeID)
=> await _role.GetDicInfoAsync(SchSerID(), typeID);
/// <summary>编辑文印(审核角色视角;旧 editDocPrint,form 三段 JSON → [FromBody])。</summary>
[HttpPost("editDocPrint")]
public async Task<int> EditDocPrint([FromBody] WYSHRoleEditDocPrintDto model)
{
if (model == null) throw new DException("参数错误!");
return await _role.EditDocPrintAsync(SchSerID(), UserId(), model);
}
/// <summary>审核流程回显(旧 getshenheFlow)。</summary>
[HttpGet("getshenheFlow")]
public async Task<SHRoleShenheFlowResult> GetshenheFlow([FromQuery] decimal docprintID, [FromQuery] int flowid)
=> await _role.GetshenheFlowAsync(SchSerID(), docprintID, flowid);
/// <summary>文印表格数据(旧 getdocOftable)。</summary>
[HttpGet("getdocOftable")]
public async Task<SHRoleDocOfTableResult> GetDocOftable([FromQuery] decimal docPrintID)
=> await _role.GetDocOftableAsync(SchSerID(), docPrintID);
#endregion
#region 审核角色列表与审批
/// <summary>单条详情(旧 MyListtoOneSHRole)。</summary>
[HttpGet("MyListtoOneSHRole")]
public async Task<List<SHRoleDocPrintListItem>> MyListtoOneSHRole([FromQuery] int serID)
=> await _role.MyListtoOneSHRoleAsync(serID, SchSerID());
/// <summary>我的文印(旧 MyListSHRole)。</summary>
[HttpGet("MyListSHRole")]
public async Task<List<SHRoleDocPrintListItem>> MyListSHRole(
[FromQuery] string name = null,
[FromQuery] string status = null,
[FromQuery] string startDate = null,
[FromQuery] string endDate = null,
[FromQuery] int pageSize = 10,
[FromQuery] int pageIndex = 0)
=> await _role.MyListSHRoleAsync(name, status, startDate, endDate, pageSize, pageIndex, UserId(), SchSerID());
/// <summary>全部文印(旧 totalListSHRole)。</summary>
[HttpGet("totalListSHRole")]
public async Task<List<SHRoleDocPrintListItem>> TotalListSHRole(
[FromQuery] int flowid = 0,
[FromQuery] int dwid = 0,
[FromQuery] string name = null,
[FromQuery] string stateid = null,
[FromQuery] string starttime = null,
[FromQuery] string endtime = null,
[FromQuery] int pageSize = 10,
[FromQuery] int pageIndex = 0)
=> await _role.TotalListSHRoleAsync(flowid, dwid, name, stateid, starttime, endtime, pageSize, pageIndex, SchSerID());
/// <summary>抄送列表(旧 SendRdListSHRole)。</summary>
[HttpGet("SendRdListSHRole")]
public async Task<List<SHRoleDocPrintListItem>> SendRdListSHRole(
[FromQuery] int flowid = 0,
[FromQuery] int dwid = 0,
[FromQuery] string name = null,
[FromQuery] string status = null,
[FromQuery] string startDate = null,
[FromQuery] string endDate = null,
[FromQuery] int pageSize = 10,
[FromQuery] int pageIndex = 0)
=> await _role.SendRdListSHRoleAsync(flowid, dwid, name, status, startDate, endDate, UserId(), SchSerID(), pageSize, pageIndex);
/// <summary>审批列表(旧 SPListSHRole)。</summary>
[HttpGet("SPListSHRole")]
public async Task<List<SHRoleDocPrintListItem>> SPListSHRole(
[FromQuery] int flowid = 0,
[FromQuery] int dwid = 0,
[FromQuery] string name = null,
[FromQuery] string status = null,
[FromQuery] string startDate = null,
[FromQuery] string endDate = null,
[FromQuery] int pageSize = 10,
[FromQuery] int pageIndex = 0)
=> await _role.SPListSHRoleAsync(flowid, dwid, name, status, startDate, endDate, UserId(), UserName(), SchSerID(), pageSize, pageIndex);
/// <summary>审核确认(旧 shenheokSHRole)。</summary>
[HttpPost("shenheokSHRole")]
public async Task<string> ShenheOkSHRole([FromBody] FlowTranctDto model)
{
if (model == null) throw new DException("参数错误!");
model.actionuserid = UserContextHolder.Current?.Id ?? 0;
return await _role.ShenheOkSHRoleAsync(model);
}
// 延后:ExceltotalListSHRole / WYRDExceldaochu / UpfileExcelSHRole / downMBOfSHRole / downUpfileSHRoleFK(Excel,NPOI)
// 延后:DwonWYSQD(审批单 PDF,PdfHelper + Server.MapPath)
#endregion
#region 签名 / 退回 / 金额重提
/// <summary>保存签名(旧 SaveSignature,form: pic → [FromBody])。</summary>
[HttpPost("SaveSignature")]
public async Task<string> SaveSignature([FromBody] SaveSignatureDto model)
{
if (model == null) throw new DException("参数错误!");
return await _role.SaveSignatureAsync(SchSerID(), UserId(), model.pic);
}
/// <summary>获取签名(旧 GetSignature)。</summary>
[HttpGet("GetSignature")]
public async Task<string> GetSignature() => await _role.GetSignatureAsync(SchSerID(), UserId());
/// <summary>删除签名(旧 DelSignature)。</summary>
[HttpGet("DelSignature")]
public async Task<string> DelSignature() => await _role.DelSignatureAsync(SchSerID(), UserId());
/// <summary>退回(旧 TuiHui,form: DocID + cont → [FromBody])。</summary>
[HttpPost("TuiHui")]
public async Task<string> TuiHui([FromBody] TuiHuiDto model)
{
if (model == null) throw new DException("参数错误!");
return await _role.TuiHuiAsync(UserId(), model.cont, model.DocID);
}
/// <summary>撤销退回(旧 unTuiHui)。</summary>
[HttpGet("unTuiHui")]
public async Task<string> UnTuiHui([FromQuery] decimal docID)
=> await _role.UnTuiHuiAsync(UserId(), docID);
/// <summary>金额重提(旧 regetJE,form: DocID 逗号分隔 + type → [FromBody])。</summary>
[HttpPost("regetJE")]
public async Task<string> RegetJE([FromBody] RegetJEDto model)
{
if (model == null) throw new DException("参数错误!");
var ids = (model.DocID ?? "").Split(',')
.Where(a => !string.IsNullOrEmpty(a) && decimal.TryParse(a, out _))
.Select(decimal.Parse).ToList();
return await _role.RegetJEAsync(SchSerID(), UserId(), ids, model.type);
}
/// <summary>重提记录(旧 getRegetJERd)。</summary>
[HttpGet("getRegetJERd")]
public async Task<List<SHRoleRegetJERdItem>> GetRegetJERd(
[FromQuery] int pageSize = 10,
[FromQuery] int pageIndex = 0)
=> await _role.GetRegetJERdAsync(SchSerID(), pageSize, pageIndex);
/// <summary>记录下载次数(旧 setDownFileTimes)。</summary>
[HttpGet("setDownFileTimes")]
public async Task<int> SetDownFileTimes([FromQuery] int serID)
=> await _role.SetDownFileTimesAsync(serID);
#endregion
private static string SchSerID() => UserContextHolder.Current.SchSerID;
private static string UserId() => UserContextHolder.Current?.Id.ToString() ?? "0";
private static string UserName() => UserContextHolder.Current?.UserName ?? "";
}
}
@@ -0,0 +1,335 @@
using System;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Yh.Platform.Abstractions;
using YhCore.Common;
using YhCore.Common.UserContext;
using YhCore.Entity;
using YhCore.Model.Dto;
using YhCore.Service.Interfaces;
namespace YhCore.WebApi.Controllers.Api.DocPrint
{
/// <summary>
/// 文印业务主控制器(对应旧 Areas/DocPrint/WY_listController,路由 api/docprint/wy_list)。
/// 第一批:分类 / 版面 / 字典 14 接口;第三批 D1:文印 CRUD / 列表 / 审核 / 统计 / 指派 24 接口;
/// Excel 导出 4 接口延后批次迁移。
/// </summary>
[ApiController]
[Route(ApiRoutes.ApiPath + "/docprint/wy_list")]
public class WY_listController : ControllerBase
{
private readonly IDocPrintClassifyService _classify;
private readonly IDictionaryService _dict;
private readonly IWYDocPrintService _wy;
public WY_listController(IDocPrintClassifyService classify, IDictionaryService dict, IWYDocPrintService wy)
{
_classify = classify;
_dict = dict;
_wy = wy;
}
#region 分类 / 版面 / 字典
/// <summary>添加文印分类。</summary>
[HttpPost("AddDic")]
public async Task AddDic([FromBody] Common_Dictionary model)
{
if (model == null) throw new DException("参数错误!");
model.Schserid = SchSerID();
await _classify.AddDicAsync(model);
}
/// <summary>文印分类列表。</summary>
[HttpGet("CategoryList")]
public async Task<System.Collections.Generic.List<CategoryItem>> CategoryList([FromQuery] string name = null)
=> await _classify.CategoryListAsync(SchSerID(), name);
/// <summary>添加印制版面。</summary>
[HttpPost("AddYZBM")]
public async Task AddYZBM([FromBody] Common_Dictionary model)
{
if (model == null) throw new DException("参数错误!");
model.Schserid = SchSerID();
await _classify.AddYZBMAsync(model);
}
/// <summary>印制版面列表。</summary>
[HttpGet("YZBMList")]
public async Task<System.Collections.Generic.List<CategoryItem>> YZBMList([FromQuery] string name = null)
=> await _classify.YZBMListAsync(SchSerID(), name);
/// <summary>删除文印分类/版面(ids 逗号分隔)。</summary>
[HttpGet("DeleteDic")]
public async Task DeleteDic([FromQuery] string ids)
{
if (string.IsNullOrWhiteSpace(ids)) throw new DException("ids is not null");
decimal[] idArr = ids.Split(',').Select(a => decimal.Parse(a)).ToArray();
await _classify.DeleteDicAsync(idArr);
}
/// <summary>公共类别列表。</summary>
[HttpGet("DictionaryTypeList")]
public async Task<System.Collections.Generic.List<DictionaryTypeItem>> DictionaryTypeList(
[FromQuery] string typeID,
[FromQuery] string name = "",
[FromQuery] bool showAll = false)
=> await _classify.DictionaryTypeListAsync(SchSerID(), name, showAll, typeID);
/// <summary>添加公共类别(复用字典添加逻辑)。</summary>
[HttpPost("AddDictionaryType")]
public async Task AddDictionaryType([FromBody] Common_Dictionary model)
{
if (model == null) throw new DException("参数错误!");
model.Schserid = SchSerID();
await _dict.AddDicAsync(model);
}
/// <summary>编辑公共类别(旧调 GetSysDict.EditDic)。</summary>
[HttpPost("EditDictionaryType")]
public async Task EditDictionaryType([FromBody] Common_Dictionary model)
{
if (model == null) throw new DException("参数有误!");
model.Schserid = SchSerID();
await _dict.EditDicAsync(model);
}
/// <summary>删除公共类别(软删除)。</summary>
[HttpGet("DeleteDictionaryType")]
public async Task DeleteDictionaryType([FromQuery] string ids)
{
if (string.IsNullOrWhiteSpace(ids)) throw new DException("ids is not null");
string[] idArr = ids.Split(',');
await _classify.DeleteDictionaryTypeAsync(idArr);
}
/// <summary>公共类别显隐。</summary>
[HttpGet("SetDictionaryOrd")]
public async Task SetDictionaryOrd([FromQuery] int dicSerID, [FromQuery] bool show)
=> await _classify.SetDictionaryOrdAsync(SchSerID(), dicSerID, show);
/// <summary>公共类别排序。</summary>
[HttpGet("OrderDic")]
public async Task OrderDic([FromQuery] string ids)
=> await _classify.OrderDicAsync(ids, SchSerID());
/// <summary>结果链接(依赖资源平台,已降级)。</summary>
[HttpGet("GetResultUrl")]
public async Task<object> GetResultUrl([FromQuery] int dataId)
{
var user = UserContextHolder.Current;
return await _classify.GetResultUrlAsync(dataId, user?.Id ?? 0, 0, SchSerID());
}
/// <summary>学校文印资源开关。</summary>
[HttpGet("GetSchZyBit")]
public async Task<bool> GetSchZyBit() => await _classify.GetSchZyBitAsync(SchSerID());
/// <summary>设置学校文印资源开关。</summary>
[HttpGet("SetSchZyBit")]
public async Task SetSchZyBit([FromQuery] bool zyBit) => await _classify.SetSchZyBitAsync(SchSerID(), zyBit);
/// <summary>待审数量角标。</summary>
[HttpGet("GetShnheCount")]
public async Task<int> GetShnheCount()
=> await _classify.GetShnheCountAsync(UserContextHolder.Current?.Id.ToString(), SchSerID());
#endregion
#region 文印核心(第三批 D1:抄送 / 附件 / CRUD / 列表 / 审核 / 统计 / 指派)
/// <summary>抄送列表(旧 SendRdList)。</summary>
[HttpGet("SendRdList")]
public async Task<System.Collections.Generic.List<DocPrintListItem>> SendRdList(
[FromQuery] string name = null,
[FromQuery] string startDate = null,
[FromQuery] string endDate = null,
[FromQuery] int pageSize = 10,
[FromQuery] int pageIndex = 0)
=> await _wy.SendRdListAsync(name, startDate, endDate, UserId(), SchSerID(), pageSize, pageIndex);
/// <summary>查看抄送人员详情(旧 SendDetailsList)。</summary>
[HttpGet("SendDetailsList")]
public async Task<System.Collections.Generic.List<SendDetailItem>> SendDetailsList([FromQuery] int serID)
=> await _wy.SendDetailsListAsync(serID);
/// <summary>修改抄送人(旧 EditSend)。</summary>
[HttpGet("EditSend")]
public async Task<string> EditSend([FromQuery] int serID, [FromQuery] string senduserid, [FromQuery] string mysenduserid)
=> await _wy.EditSendAsync(serID, senduserid, mysenduserid, SchSerID(), UserId());
/// <summary>获取附件数据源(旧 filelist)。</summary>
[HttpGet("filelist")]
public async Task<System.Collections.Generic.List<DocPrintFileItem>> FileList([FromQuery] string ids)
=> await _wy.FileListAsync(ids);
/// <summary>添加文印(旧 Create;短信/待办推送已降级为纯落库)。</summary>
[HttpPost("Create")]
public async Task<int> Create([FromBody] WYDocPrintSaveDto model)
{
if (model == null) throw new DException("参数错误!");
model.UserID = UserId();
model.SchSerID = SchSerID();
return await _wy.CreateAsync(model);
}
/// <summary>修改文印(旧 Edit)。</summary>
[HttpPost("Edit")]
public async Task<int> Edit([FromBody] WYDocPrintSaveDto model)
{
if (model == null) throw new DException("参数错误!");
model.UserID = UserId();
model.SchSerID = SchSerID();
return await _wy.EditAsync(model);
}
/// <summary>撤销(旧 Revoke)。</summary>
[HttpPost("Revoke")]
public async Task<string> Revoke([FromBody] FlowTranctDto model)
{
if (model == null) throw new DException("参数错误!");
model.actionuserid = UserContextHolder.Current?.Id;
return await _wy.RevokeAsync(model);
}
/// <summary>我的文印列表(旧 MyList)。</summary>
[HttpGet("MyList")]
public async Task<System.Collections.Generic.List<DocPrintListItem>> MyList(
[FromQuery] string name = null,
[FromQuery] string status = null,
[FromQuery] string startDate = null,
[FromQuery] string endDate = null,
[FromQuery] int pageSize = 10,
[FromQuery] int pageIndex = 0)
=> await _wy.MyListAsync(name, status, startDate, endDate, UserId(), SchSerID(), pageSize, pageIndex);
/// <summary>全部文印列表(旧 AllList 四分类,返回 ctype)。</summary>
[HttpGet("AllList")]
public async Task<System.Collections.Generic.List<DocPrintListItem>> AllList(
[FromQuery] string name = null,
[FromQuery] int pageSize = 10,
[FromQuery] int pageIndex = 0)
=> await _wy.AllListAsync(name, UserId(), SchSerID(), pageSize, pageIndex);
/// <summary>文印审核列表(旧 ShenheList;旧 Name 过滤为死代码,保持不生效)。</summary>
[HttpGet("ShenheList")]
public async Task<System.Collections.Generic.List<DocPrintListItem>> ShenheList(
[FromQuery] int pageSize = 10,
[FromQuery] int pageIndex = 0)
=> await _wy.ShenheListAsync(UserId(), SchSerID(), pageSize, pageIndex);
/// <summary>审批列表(旧 SPList)。</summary>
[HttpGet("SPList")]
public async Task<System.Collections.Generic.List<DocPrintListItem>> SPList(
[FromQuery] string name = null,
[FromQuery] string status = null,
[FromQuery] string startDate = null,
[FromQuery] string endDate = null,
[FromQuery] int pageSize = 10,
[FromQuery] int pageIndex = 0)
=> await _wy.SPListAsync(name, status, startDate, endDate, UserId(), SchSerID(), pageSize, pageIndex);
/// <summary>文印已审列表(旧 YishenList)。</summary>
[HttpGet("YishenList")]
public async Task<System.Collections.Generic.List<DocPrintListItem>> YishenList(
[FromQuery] string name = null,
[FromQuery] int pageSize = 10,
[FromQuery] int pageIndex = 0)
=> await _wy.YishenListAsync(name, UserId(), SchSerID(), pageSize, pageIndex);
/// <summary>全部文印列表(旧 totalList)。</summary>
[HttpGet("totalList")]
public async Task<System.Collections.Generic.List<DocPrintListItem>> TotalList(
[FromQuery] string name = null,
[FromQuery] string stateid = null,
[FromQuery] string starttime = null,
[FromQuery] string endtime = null,
[FromQuery] int pageSize = 10,
[FromQuery] int pageIndex = 0)
=> await _wy.TotalListAsync(name, stateid, starttime, endtime, SchSerID(), pageSize, pageIndex);
/// <summary>获取当前一条文印详情(旧 MyListtoOne;附件明细并入条目 tempresultfile)。</summary>
[HttpGet("MyListtoOne")]
public async Task<System.Collections.Generic.List<DocPrintDetailItem>> MyListtoOne([FromQuery] int serID)
=> await _wy.MyListtoOneAsync(serID, SchSerID());
/// <summary>审核确认(旧 shenheok)。</summary>
[HttpPost("shenheok")]
public async Task<string> ShenheOk([FromBody] FlowTranctDto model)
{
if (model == null) throw new DException("参数错误!");
model.actionuserid = UserContextHolder.Current?.Id ?? 0;
return await _wy.ShenheOkAsync(model);
}
/// <summary>领取确认(旧 AffirmApplyforOk)。</summary>
[HttpPost("AffirmApplyforOk")]
public async Task<string> AffirmApplyforOk([FromBody] FlowTranctDto model)
{
if (model == null) throw new DException("参数错误!");
model.actionuserid = UserContextHolder.Current?.Id ?? 0;
return await _wy.AffirmApplyforOkAsync(model);
}
/// <summary>删除文印(旧 Delete)。</summary>
[HttpGet("Delete")]
public async Task Delete([FromQuery] string ids)
{
if (string.IsNullOrWhiteSpace(ids)) throw new DException("ids is not null");
await _wy.DeleteAsync(ids);
}
/// <summary>绑定流程(旧 Bindflowinfo)。</summary>
[HttpGet("Bindflowinfo")]
public async Task<System.Collections.Generic.List<BindFlowOption>> Bindflowinfo([FromQuery] int flowType)
=> await _wy.BindflowinfoAsync(SchSerID(), flowType);
/// <summary>查询指派(旧 GetUserZhipai)。</summary>
[HttpGet("GetUserZhipai")]
public async Task<string> GetUserZhipai([FromQuery] int? flowid, [FromQuery] int? flowstepid, [FromQuery] string type)
=> await _wy.GetUserZhipaiAsync(UserContextHolder.Current?.Id ?? 0, SchSerID(), flowid, flowstepid, type);
/// <summary>文印数量按月统计(旧 List1)。</summary>
[HttpGet("List1")]
public async Task<System.Collections.Generic.List<MonthStatItem>> List1([FromQuery] string starttime = null, [FromQuery] string endtime = null)
=> await _wy.List1Async(starttime, endtime, SchSerID());
/// <summary>文印详情统计列表(旧 List2)。</summary>
[HttpGet("List2")]
public async Task<System.Collections.Generic.List<DocDetailStatItem>> List2(
[FromQuery] string starttime = null, [FromQuery] string endtime = null,
[FromQuery] int pageSize = 10, [FromQuery] int pageIndex = 0)
=> await _wy.List2Async(starttime, endtime, SchSerID(), pageSize, pageIndex);
/// <summary>文印数量按用户排名(旧 List3)。</summary>
[HttpGet("List3")]
public async Task<System.Collections.Generic.List<UserRankItem>> List3(
[FromQuery] string starttime = null, [FromQuery] string endtime = null,
[FromQuery] int pageSize = 10, [FromQuery] int pageIndex = 0)
=> await _wy.List3Async(starttime, endtime, SchSerID(), pageSize, pageIndex);
/// <summary>按月份统计明细(旧 List4)。</summary>
[HttpGet("List4")]
public async Task<System.Collections.Generic.List<StatListItem>> List4(
[FromQuery] int year, [FromQuery] int month,
[FromQuery] int pageSize = 10, [FromQuery] int pageIndex = 0)
=> await _wy.List4Async(year, month, SchSerID(), pageSize, pageIndex);
/// <summary>按用户统计明细(旧 List5)。</summary>
[HttpGet("List5")]
public async Task<System.Collections.Generic.List<StatListItem>> List5(
[FromQuery] string userid = null, [FromQuery] string starttime = null, [FromQuery] string endtime = null,
[FromQuery] int pageSize = 10, [FromQuery] int pageIndex = 0)
=> await _wy.List5Async(userid, starttime, endtime, SchSerID(), pageSize, pageIndex);
// 延后批次:ExceltotalList / Exceldaochu1 / Exceldaochu2 / Exceldaochu3(Excel 导出,方案待定)
#endregion
private static string SchSerID() => UserContextHolder.Current.SchSerID;
private static string UserId() => UserContextHolder.Current?.Id.ToString() ?? "0";
}
}
@@ -0,0 +1,94 @@
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Features;
using Microsoft.AspNetCore.Mvc;
using System.Collections.Generic;
using System.Threading.Tasks;
using Yh.Platform.Abstractions;
using Yh.Platform.Auth;
using Yh.Platform.OpenApi;
using YhCore.Common;
namespace YhCore.WebApi.Controllers.Api
{
/// <summary>
/// 登录用户接口(对应 Java 版 controller/api/LoginUserController,路由 /api/GetUserMod 等)。
/// 注意:Java 版路由以大写开头(GetUserMod / GetUserInfo / Logout),此处保持 URL 大小写一致。
/// </summary>
[ApiController]
[Route(ApiRoutes.ApiPath)]
public class LoginUserController : ControllerBase
{
private readonly IOpenApiUserClient _openApiUserClient;
public LoginUserController(IOpenApiUserClient openApiUserClient)
{
_openApiUserClient = openApiUserClient;
}
/// <summary>
/// 获取当前用户可见的应用模块(对应 Java GET /api/GetUserMod,
/// 内部调用 YschBaseOpenApi.getUserModule(id, schoolId))。
/// </summary>
[HttpGet("GetUserMod")]
public async Task<List<BoaModule>> GetUserMod()
{
var boa = BoaUserContext.Get();
return await _openApiUserClient.GetUserModuleAsync(boa?.Id ?? 0, boa?.School?.Id);
}
/// <summary>
/// 获取当前登录用户信息(对应 Java GET /api/GetUserInfo,
/// Java 版直接返回认证切面注入的 authUserWithDept;未登录时为 null)。
/// 返回新框架用户上下文解析的完整 BoaUser(含 School/CurrentRole/RoleIds),与 Java 返回结构一致。
/// </summary>
[HttpGet("GetUserInfo")]
public BoaUser GetUserInfo()
{
return BoaUserContext.Get();
}
/// <summary>
/// 判断是否登录(对应 Java GET /api/checkLogin):
/// 已登录 → 重定向到运维工作台 /work-view.html(兼容 context-path,.NET 用相对路径);
/// 未登录 → 401 + {"code":401,"msg":"未登录"}(通常 CAS 拦截器会先行 302 到 CAS 登录页)。
/// </summary>
[HttpGet("checkLogin")]
public IActionResult CheckLogin()
{
if (BoaUserContext.Get()?.Id > 0)
{
// 对应 Java request.getContextPath() + "/work-view.html"(.NET 无 contextPath,用根相对路径)
return Redirect("/work-view.html");
}
return new ContentResult
{
Content = "{\"code\":401,\"msg\":\"未登录\"}",
ContentType = "application/json;charset=UTF-8",
StatusCode = StatusCodes.Status401Unauthorized
};
}
/// <summary>
/// 登出(对应 Java GET /api/Logout:session.invalidate())。
/// 清除本地 Cookie 认证(新框架 YhCookie 方案)+ 可选跳转到 CAS 单点登出(CasServerUrlPrefix + logout)。
/// TODO:按需启用单点登出(去 yh:sso:cas-server-url-prefix + logout 退出所有 SSO 应用)。
/// </summary>
[HttpGet("Logout")]
public async Task<IActionResult> Logout()
{
// 清除本地 Cookie 登录态(对应 session.invalidate())
await HttpContext.SignOutAsync(YhAuthDefaults.CookieScheme);
// 仅在已启用 Session 中间件时再清一份
if (HttpContext.Features.Get<ISessionFeature>() != null)
{
HttpContext.Session.Clear();
}
return Ok();
}
}
}