AidopActionRunLogQueryService.cs 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. using System.Text.Json;
  2. namespace Admin.NET.Plugin.AiDOP.Infrastructure;
  3. /// <summary>
  4. /// 业务动作运行日志查询 API。
  5. ///
  6. /// 【租户安全边界】租户一律经 <see cref="AidopTenantScope.ResolveOrThrow"/> 从认证后 JWT 解析,
  7. /// 无有效租户即拒绝,不读前端 tenantId、无默认回退(原实现:类级 <c>[AllowAnonymous]</c> +
  8. /// <c>_userManager.TenantId &gt; 0</c> 否则回退宽松解析,未认证方可携带 <c>?tenantId=</c> 读任意租户日志)。
  9. /// </summary>
  10. [ApiDescriptionSettings(Order = 120, Description = "业务动作运行日志")]
  11. [Route("api/Aidop")]
  12. [NonUnify]
  13. public class AidopActionRunLogQueryService : IDynamicApiController, ITransient
  14. {
  15. private readonly ISqlSugarClient _db;
  16. private readonly UserManager _userManager;
  17. public AidopActionRunLogQueryService(ISqlSugarClient db, UserManager userManager)
  18. {
  19. _db = db;
  20. _userManager = userManager;
  21. }
  22. [DisplayName("业务动作运行日志列表")]
  23. [HttpGet("action-run-log/list")]
  24. public async Task<object> GetList([FromQuery] AidopActionRunLogListInput input)
  25. {
  26. var tenantId = AidopTenantScope.ResolveOrThrow(_userManager);
  27. var page = input.Page <= 0 ? 1 : input.Page;
  28. var pageSize = input.PageSize <= 0 ? 20 : Math.Min(input.PageSize, 100);
  29. var offset = (page - 1) * pageSize;
  30. var pars = new List<SugarParameter> { new("@TenantId", tenantId) };
  31. var where = new List<string> { "tenant_id = @TenantId" };
  32. if (!string.IsNullOrWhiteSpace(input.ActionCode))
  33. {
  34. where.Add("action_code LIKE @ActionCode");
  35. pars.Add(new SugarParameter("@ActionCode", $"%{input.ActionCode.Trim()}%"));
  36. }
  37. if (!string.IsNullOrWhiteSpace(input.Status))
  38. {
  39. where.Add("status = @Status");
  40. pars.Add(new SugarParameter("@Status", input.Status.Trim().ToUpperInvariant()));
  41. }
  42. if (!string.IsNullOrWhiteSpace(input.BizNo))
  43. {
  44. where.Add("biz_no LIKE @BizNo");
  45. pars.Add(new SugarParameter("@BizNo", $"%{input.BizNo.Trim()}%"));
  46. }
  47. if (!string.IsNullOrWhiteSpace(input.StartTimeFrom))
  48. {
  49. where.Add("start_time >= @StartFrom");
  50. pars.Add(new SugarParameter("@StartFrom", input.StartTimeFrom.Trim()));
  51. }
  52. if (!string.IsNullOrWhiteSpace(input.StartTimeTo))
  53. {
  54. where.Add("start_time <= @StartTo");
  55. pars.Add(new SugarParameter("@StartTo", input.StartTimeTo.Trim()));
  56. }
  57. var whereSql = string.Join(" AND ", where);
  58. var total = await _db.Ado.GetIntAsync(
  59. $"SELECT COUNT(*) FROM aidop_action_run_log WHERE {whereSql}",
  60. pars);
  61. var list = await _db.Ado.SqlQueryAsync<AidopActionRunLogListRow>(
  62. $"""
  63. SELECT
  64. id AS Id,
  65. tenant_id AS TenantId,
  66. action_code AS ActionCode,
  67. biz_type AS BizType,
  68. biz_id AS BizId,
  69. biz_no AS BizNo,
  70. status AS Status,
  71. message AS Message,
  72. detail_json AS DetailJson,
  73. start_time AS StartTime,
  74. end_time AS EndTime,
  75. create_time AS CreateTime
  76. FROM aidop_action_run_log
  77. WHERE {whereSql}
  78. ORDER BY start_time DESC, id DESC
  79. LIMIT {pageSize} OFFSET {offset}
  80. """,
  81. pars);
  82. return new { total, page, pageSize, list };
  83. }
  84. [DisplayName("业务动作运行日志详情")]
  85. [HttpGet("action-run-log/{id:long}")]
  86. public async Task<object> GetDetail(long id)
  87. {
  88. var tenantId = AidopTenantScope.ResolveOrThrow(_userManager);
  89. var row = (await _db.Ado.SqlQueryAsync<AidopActionRunLogListRow>(
  90. """
  91. SELECT
  92. id AS Id,
  93. tenant_id AS TenantId,
  94. action_code AS ActionCode,
  95. biz_type AS BizType,
  96. biz_id AS BizId,
  97. biz_no AS BizNo,
  98. status AS Status,
  99. message AS Message,
  100. detail_json AS DetailJson,
  101. start_time AS StartTime,
  102. end_time AS EndTime,
  103. create_time AS CreateTime
  104. FROM aidop_action_run_log
  105. WHERE id = @Id AND tenant_id = @TenantId
  106. LIMIT 1
  107. """,
  108. new SugarParameter("@Id", id),
  109. new SugarParameter("@TenantId", tenantId))).FirstOrDefault()
  110. ?? throw Oops.Oh("运行日志不存在");
  111. object? detail = null;
  112. if (!string.IsNullOrWhiteSpace(row.DetailJson))
  113. {
  114. try { detail = JsonSerializer.Deserialize<JsonElement>(row.DetailJson); }
  115. catch { detail = row.DetailJson; }
  116. }
  117. return new { row, detail };
  118. }
  119. [DisplayName("业务动作编码选项")]
  120. [HttpGet("action-run-log/action-codes")]
  121. public async Task<object> GetActionCodes()
  122. {
  123. var tenantId = AidopTenantScope.ResolveOrThrow(_userManager);
  124. var codes = await _db.Ado.SqlQueryAsync<string>(
  125. """
  126. SELECT DISTINCT action_code
  127. FROM aidop_action_run_log
  128. WHERE tenant_id = @TenantId
  129. ORDER BY action_code
  130. """,
  131. new SugarParameter("@TenantId", tenantId));
  132. return new { list = codes };
  133. }
  134. }
  135. public class AidopActionRunLogListInput
  136. {
  137. public int Page { get; set; } = 1;
  138. public int PageSize { get; set; } = 20;
  139. public string? ActionCode { get; set; }
  140. public string? Status { get; set; }
  141. public string? BizNo { get; set; }
  142. public string? StartTimeFrom { get; set; }
  143. public string? StartTimeTo { get; set; }
  144. }
  145. public sealed class AidopActionRunLogListRow
  146. {
  147. public long Id { get; set; }
  148. public long? TenantId { get; set; }
  149. public string? ActionCode { get; set; }
  150. public string? BizType { get; set; }
  151. public long? BizId { get; set; }
  152. public string? BizNo { get; set; }
  153. public string? Status { get; set; }
  154. public string? Message { get; set; }
  155. public string? DetailJson { get; set; }
  156. public DateTime? StartTime { get; set; }
  157. public DateTime? EndTime { get; set; }
  158. public DateTime? CreateTime { get; set; }
  159. }