平安校园
Du kannst nicht mehr als 25 Themen auswählen Themen müssen entweder mit einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.
 
 
 
 
 
 

345 Zeilen
15 KiB

  1. using NPOI.Util;
  2. using NPOI.XWPF.UserModel;
  3. using SafeCampus.Application.Services.Business.Warn.Dto;
  4. using SafeCampus.Application.Services.Business.Warn.Service;
  5. using System.Diagnostics;
  6. using MoYu.FriendlyException;
  7. using SafeCampus.Core.Extension;
  8. namespace SafeCampus.Web.Core.Controllers.Application.Violation;
  9. /// <summary>
  10. /// 预警分析控制器
  11. /// </summary>
  12. [ApiDescriptionSettings(ApiGroupConsts.SYSTEM_Business, Tag = "预警分析", Order = 86)]
  13. [Route("violation/analysis")]
  14. [RolePermission]
  15. public class VioAnalysisController
  16. {
  17. private readonly ISimpleCacheService _simpleCacheService;
  18. private readonly IWarnInfoService _warnInfoService;
  19. public VioAnalysisController(ISimpleCacheService simpleCacheService, IWarnInfoService warnInfoService)
  20. {
  21. _simpleCacheService = simpleCacheService;
  22. _warnInfoService = warnInfoService;
  23. }
  24. //场景报告导出
  25. //导出查询条件
  26. //生成word
  27. [DisplayName("场景报告导出")]
  28. public async Task<IActionResult> ReportExport(ReportExportInput input)
  29. {
  30. //var categories = new List<string>() { "Category A", "Category B", "Category C", "Category D" };
  31. //var values = new List<int>() { 215, 130, 245, 210 };
  32. //GenBar("XXX场景告警统计", categories, values, Path.Combine(Directory.GetCurrentDirectory(), "Template", $"{Guid.NewGuid():N}.png"));
  33. //GenPie("XXX场景告警统计", categories, values, Path.Combine(Directory.GetCurrentDirectory(), "Template", $"{Guid.NewGuid():N}.png"));
  34. //switch (input.GroupCode)
  35. //{
  36. // case "MCLZ":
  37. // return await GetMCLZ(input);
  38. // case "ZHKT":
  39. // return await GetZHKT(input);
  40. // case "XSGQ":
  41. // return await GetXSGQ(input);
  42. // case "XYFBL":
  43. // return await GetXYFBL(input);
  44. // case "XYAQ":
  45. // return await GetXYAQ(input);
  46. // case "QYGK":
  47. // return await GetQYGK(input);
  48. // case "ABXL":
  49. // return await GetABXL(input);
  50. // default:
  51. // throw Oops.Oh("请选择正确的场景");
  52. //}
  53. //PythonEngine.BeginAllowThreads();
  54. var result = await GetMCLZ(input);
  55. //PythonEngine.Shutdown();
  56. return result;
  57. }
  58. #region 图表生成
  59. private bool GenCharts(string title, List<string> label, List<int> value, string name,string pyName)
  60. {
  61. try
  62. {
  63. var script = Path.Combine(Directory.GetCurrentDirectory(), "Template", pyName);
  64. string args = $"\"{script}\" \"{name}\" \"{title}\" \"{string.Join(",", label)}\" \"{string.Join(",", value)}\"";
  65. ProcessStartInfo start = new ProcessStartInfo();
  66. start.FileName = App.Configuration["AppInfo:Python"]; // Python 解释器路径
  67. start.Arguments = args; // 参数列表
  68. start.UseShellExecute = false;
  69. start.RedirectStandardOutput = true;
  70. start.RedirectStandardError = true;
  71. // 启动进程
  72. using (Process process = Process.Start(start))
  73. {
  74. using (StreamReader reader = process.StandardOutput)
  75. {
  76. string result = reader.ReadToEnd();
  77. Console.Write(result);
  78. }
  79. using (StreamReader reader = process.StandardError)
  80. {
  81. string error = reader.ReadToEnd();
  82. LogHelper.WriteToLog("python执行错误", error);
  83. }
  84. }
  85. }
  86. catch (global::System.Exception)
  87. {
  88. return false;
  89. }
  90. return true;
  91. }
  92. /// <summary>
  93. /// 生成柱状图
  94. /// </summary>
  95. /// <param name="label"></param>
  96. /// <param name="value"></param>
  97. /// <param name="name"></param>
  98. /// <returns></returns>
  99. private bool GenBar(string title, List<string> label, List<int> value, string name)
  100. {
  101. try
  102. {
  103. //var m_threadState = PythonEngine.BeginAllowThreads();
  104. //using (Py.GIL())
  105. //{
  106. // dynamic plt = Py.Import("matplotlib.pyplot");
  107. // dynamic fm = Py.Import("matplotlib.font_manager");
  108. // dynamic prop = fm.FontProperties(fname: "C:\\Windows\\Fonts\\msyh.ttc");
  109. // plt.rcParams["font.family"] = prop.get_name();
  110. // //var categories = new List<string>() { "Category A", "Category B", "Category C", "Category D" };
  111. // //var values = new List<int>() { 215, 130, 245, 210 };
  112. // var bars = plt.bar(ToPythonList(label), ToPythonList(value));
  113. // foreach (var bar in bars)
  114. // {
  115. // double yval = bar.get_height();
  116. // plt.text(bar.get_x() + bar.get_width() / 2.5, yval, Math.Round(yval, 1), va: "bottom");
  117. // }
  118. // // 设置图表标题并显示图表
  119. // plt.title(title);
  120. // plt.savefig(name);
  121. // //plt.show();
  122. // plt.close();
  123. //}
  124. //PythonEngine.EndAllowThreads(m_threadState);
  125. }
  126. catch (global::System.Exception)
  127. {
  128. return false;
  129. }
  130. return true;
  131. }
  132. /// <summary>
  133. /// 生成饼图
  134. /// </summary>
  135. /// <param name="label"></param>
  136. /// <param name="value"></param>
  137. /// <param name="name"></param>
  138. /// <returns></returns>
  139. private bool GenPie(string title, List<string> label, List<int> value, string name)
  140. {
  141. try
  142. {
  143. //var m_threadState = PythonEngine.BeginAllowThreads();
  144. //using (Py.GIL())
  145. //{
  146. // dynamic plt = Py.Import("matplotlib.pyplot");
  147. // dynamic fm = Py.Import("matplotlib.font_manager");
  148. // dynamic prop = fm.FontProperties(fname: "C:\\Windows\\Fonts\\msyh.ttc");
  149. // plt.rcParams["font.family"] = prop.get_name();
  150. // //var categories = new List<string>() { "Category A", "Category B", "Category C", "Category D" };
  151. // //var values = new List<int>() { 215, 130, 245, 210 };
  152. // var color = new List<string>() { "gold", "yellowgreen", "lightcoral", "lightskyblue" };
  153. // var pie = plt.pie(ToPythonList(value), labels: ToPythonList(label), colors: ToPythonList(color), autopct: "%1.1f%%");
  154. // plt.axis("equal");
  155. // // 设置图表标题并显示图表
  156. // plt.title(title);
  157. // plt.savefig(name);
  158. // //plt.show();
  159. // plt.close();
  160. //}
  161. //PythonEngine.EndAllowThreads(m_threadState);
  162. }
  163. catch (global::System.Exception)
  164. {
  165. return false;
  166. }
  167. return true;
  168. }
  169. #endregion
  170. /// <summary>
  171. /// 获取明厨亮灶报告
  172. /// </summary>
  173. /// <returns></returns>
  174. private async Task<FileContentResult> GetMCLZ(ReportExportInput input)
  175. {
  176. var warnGroup = _simpleCacheService
  177. .Get<List<WarnGroupInfo>>(SafeCampusConst.WarnGroup)
  178. .Where(x => x.Code == input.GroupCode).FirstOrDefault();
  179. var warnList = await _warnInfoService.GetListNoPage(new WarnInfoSearch
  180. {
  181. StartTick = input.StartTime,
  182. EndTick = input.EndTime.AddDays(1).AddSeconds(-1),
  183. AlarmTypes = warnGroup.Subset.Where(x=>x.State).Select(x => x.Code).ToArray(),
  184. PersonSetIds = input.PersonSetIds,
  185. CameraIds = warnGroup.CameraId
  186. });
  187. var templatePath = Path.Combine(Directory.GetCurrentDirectory(), "Template", $"WordTemplate.docx");
  188. await using var fs = new FileStream(templatePath, FileMode.Open, FileAccess.ReadWrite);
  189. XWPFDocument doc = new XWPFDocument(fs);
  190. var content = warnList.GroupBy(x => x.AlarmTypeDesc).ToList();
  191. if (!content.Any())
  192. {
  193. throw Oops.Oh("该时间段无数据,无法生成报告!");
  194. }
  195. Dictionary<string, string> replacements = new Dictionary<string, string>()
  196. {
  197. //图片
  198. { "{{ImagePie}}","" },
  199. { "{{ImageBar}}","" },
  200. //场景名称
  201. { "{{GroupName}}", warnGroup.Name},
  202. //摄 像 头
  203. { "{{CameraName}}",string.Join("、",warnGroup.CameraName)},
  204. //统计时间
  205. { "{{StatitionTime}}", $"{input.StartTime:yyyy-MM-dd} 至 {input.EndTime:yyyy-MM-dd}"},
  206. //累计告警
  207. { "{{Count}}",warnList.Count.ToString()},
  208. //内容详情
  209. { "{{Content}}", $"按类型统计如下:{string.Join("、",content.Select(x=>$"{x.Key}:{x.Count()}条"))}"}
  210. };
  211. // 遍历文档中的所有段落
  212. foreach (XWPFParagraph para in doc.Paragraphs)
  213. {
  214. foreach (var kvp in replacements)
  215. {
  216. if (para.Text.Contains(kvp.Key)) // 检查是否为图片文件名
  217. {
  218. if (kvp.Key == "{{ImageBar}}")
  219. {
  220. var categories = content.Select(x => x.Key).ToList();//new List<string>() { "Category A", "Category B", "Category C", "Category D" });
  221. var values = content.Select(x => x.Count()).ToList();// new List<int>() { 215, 130, 245, 210 };
  222. var filePath = Path.Combine(Directory.GetCurrentDirectory(), "Template",
  223. $"{Guid.NewGuid():N}.png");
  224. GenCharts($"{warnGroup.Name}场景告警统计", categories, values, filePath,"GenBar.py");
  225. await using var file = new FileStream(filePath, FileMode.Open, FileAccess.Read);
  226. XWPFRun run = para.CreateRun();
  227. using MemoryStream imgStream = new MemoryStream();
  228. await file.CopyToAsync(imgStream);
  229. imgStream.Seek(0, SeekOrigin.Begin);
  230. run.AddPicture(imgStream,
  231. (int)PictureType.JPEG, "image.jpg", Units.ToEMU(403.2), Units.ToEMU(300.8));
  232. para.RemoveRun(0); // 移除原来的占位符文本
  233. await file.DisposeAsync();
  234. File.Delete(filePath);
  235. }else if (kvp.Key == "{{ImagePie}}")
  236. {
  237. var categories = content.Select(x => x.Key).ToList();//new List<string>() { "Category A", "Category B", "Category C", "Category D" });
  238. var values = content.Select(x => x.Count()).ToList();// new List<int>() { 215, 130, 245, 210 };
  239. var filePath = Path.Combine(Directory.GetCurrentDirectory(), "Template",
  240. $"{Guid.NewGuid():N}.png");
  241. GenCharts($"{warnGroup.Name}场景告警统计", categories, values, filePath,"GenPie.py");
  242. await using var file = new FileStream(filePath, FileMode.Open, FileAccess.Read);
  243. XWPFRun run = para.CreateRun();
  244. using MemoryStream imgStream = new MemoryStream();
  245. await file.CopyToAsync(imgStream);
  246. imgStream.Seek(0, SeekOrigin.Begin);
  247. run.AddPicture(imgStream,
  248. (int)PictureType.JPEG, "image.jpg", Units.ToEMU(403.2), Units.ToEMU(300.8));
  249. para.RemoveRun(0); // 移除原来的占位符文本
  250. await file.DisposeAsync();
  251. File.Delete(filePath);
  252. }
  253. else
  254. {
  255. para.ReplaceText(kvp.Key, kvp.Value);
  256. }
  257. }
  258. }
  259. }
  260. await using MemoryStream wordStream = new MemoryStream();
  261. doc.Write(wordStream);
  262. var bytes = wordStream.ToArray();
  263. doc.Close();
  264. var wordFile = new FileContentResult(bytes, "application/octet-stream") { FileDownloadName = $"{warnGroup.Name}场景分析报告.docx" };
  265. return await Task.FromResult(wordFile);
  266. }
  267. /// <summary>
  268. /// 获取智慧课堂报告
  269. /// </summary>
  270. /// <returns></returns>
  271. private async Task<FileContentResult> GetZHKT(ReportExportInput input)
  272. {
  273. var warnGroup = _simpleCacheService
  274. .Get<List<WarnGroupInfo>>(SafeCampusConst.WarnGroup)
  275. .Where(x => x.Code == input.GroupCode).FirstOrDefault();
  276. var wordFile = new FileContentResult(new byte[] { }, "application/octet-stream") { FileDownloadName = $"{warnGroup.Name}场景分析报告.docx" };
  277. return await Task.FromResult(wordFile);
  278. }
  279. /// <summary>
  280. /// 获取学生归寝报告
  281. /// </summary>
  282. /// <returns></returns>
  283. private async Task<FileContentResult> GetXSGQ(ReportExportInput input)
  284. {
  285. var warnGroup = _simpleCacheService
  286. .Get<List<WarnGroupInfo>>(SafeCampusConst.WarnGroup)
  287. .Where(x => x.Code == input.GroupCode).FirstOrDefault();
  288. var wordFile = new FileContentResult(new byte[] { }, "application/octet-stream") { FileDownloadName = $"{warnGroup.Name}场景分析报告.docx" };
  289. return await Task.FromResult(wordFile);
  290. }
  291. /// <summary>
  292. /// 获取校园防霸凌报告
  293. /// </summary>
  294. /// <returns></returns>
  295. private async Task<FileContentResult> GetXYFBL(ReportExportInput input)
  296. {
  297. var warnGroup = _simpleCacheService
  298. .Get<List<WarnGroupInfo>>(SafeCampusConst.WarnGroup)
  299. .Where(x => x.Code == input.GroupCode).FirstOrDefault();
  300. var wordFile = new FileContentResult(new byte[] { }, "application/octet-stream") { FileDownloadName = $"{warnGroup.Name}场景分析报告.docx" };
  301. return await Task.FromResult(wordFile);
  302. }
  303. /// <summary>
  304. /// 获取校园安全报告
  305. /// </summary>
  306. /// <returns></returns>
  307. private async Task<FileContentResult> GetXYAQ(ReportExportInput input)
  308. {
  309. var warnGroup = _simpleCacheService
  310. .Get<List<WarnGroupInfo>>(SafeCampusConst.WarnGroup)
  311. .Where(x => x.Code == input.GroupCode).FirstOrDefault();
  312. var wordFile = new FileContentResult(new byte[] { }, "application/octet-stream") { FileDownloadName = $"{warnGroup.Name}场景分析报告.docx" };
  313. return await Task.FromResult(wordFile);
  314. }
  315. /// <summary>
  316. /// 获取区域管控报告
  317. /// </summary>
  318. /// <returns></returns>
  319. private async Task<FileContentResult> GetQYGK(ReportExportInput input)
  320. {
  321. var warnGroup = _simpleCacheService
  322. .Get<List<WarnGroupInfo>>(SafeCampusConst.WarnGroup)
  323. .Where(x => x.Code == input.GroupCode).FirstOrDefault();
  324. var wordFile = new FileContentResult(new byte[] { }, "application/octet-stream") { FileDownloadName = $"{warnGroup.Name}场景分析报告.docx" };
  325. return await Task.FromResult(wordFile);
  326. }
  327. /// <summary>
  328. /// 获取安保巡逻报告
  329. /// </summary>
  330. /// <returns></returns>
  331. private async Task<FileContentResult> GetABXL(ReportExportInput input)
  332. {
  333. var warnGroup = _simpleCacheService
  334. .Get<List<WarnGroupInfo>>(SafeCampusConst.WarnGroup)
  335. .Where(x => x.Code == input.GroupCode).FirstOrDefault();
  336. var wordFile = new FileContentResult(new byte[] { }, "application/octet-stream") { FileDownloadName = $"{warnGroup.Name}场景分析报告.docx" };
  337. return await Task.FromResult(wordFile);
  338. }
  339. }