using FrontendWebApi.Models; using iTextSharp.text; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Filters; using Microsoft.Extensions.Logging; using Newtonsoft.Json; using NPOI.HPSF; using NPOI.HSSF.UserModel; using NPOI.SS.Formula.Functions; using NPOI.SS.UserModel; using NPOI.XSSF.UserModel; using NPOI.Util; using Org.BouncyCastle.Crypto.Agreement.JPake; using Repository.BackendRepository.Interface; using Repository.FrontendRepository.Interface; using System; using System.Collections.Generic; using System.Drawing.Drawing2D; using System.Drawing.Imaging; using System.IO; using System.Linq; using System.Threading.Tasks; using Image = System.Drawing.Image; using System.IdentityModel.Tokens.Jwt; using System.Net; using NPOI.POIFS.Crypt.Dsig; using System.Text; namespace FrontendWebApi.ApiControllers { //[Route("api/[controller]")] //[ApiController] public class OperationLogController : MyBaseApiController { private readonly IBackendRepository backendRepository; private readonly IBackgroundServiceMsSqlRepository backgroundServiceMsSqlRepository; private string operationFileSaveAsPath = ""; public OperationLogController(IBackendRepository backendRepository, IBackgroundServiceMsSqlRepository backgroundServiceMsSqlRepository) { this.backendRepository = backendRepository; operationFileSaveAsPath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "upload", "operation"); this.backgroundServiceMsSqlRepository = backgroundServiceMsSqlRepository; } /// /// 巨蛋操作紀錄api 1:系統紀錄;2:登入紀錄;3:燈控排程紀錄 /// /// /// [HttpPost] [Route("api/OperationLog/GetLogList")] public async Task>>> GetLogList([FromBody] PageResult pageResult) { ApiResult>> apiResult = new ApiResult>>(); List logList = new List(); int total = 0; string start_time = DateTime.Parse(pageResult.data?.start_time).ToString("yyyy-MM-dd"); string end_time = DateTime.Parse(pageResult.data?.end_time).ToString("yyyy-MM-dd"); ; string mark = pageResult.isEnable ? ";" : "\n"; try { if (pageResult.data.type == 1 || pageResult.data.type == 2) { string building_tag = pageResult.data?.building_tag; string tableName = (building_tag == "D2" || building_tag == "D3") ? "D2_Pri" : $"{building_tag}"; string sWhere = pageResult.data.type == 1 ? "OPERATION ='Invoked'" : "(OPERATION = 'Login' or OPERATION = 'Logout (Timeout)')"; string sWhere2 = pageResult.data.type == 1 ? ((building_tag == "D2" || building_tag == "D3") ? "and (TARGET like '/Arena/D2%' or target like '/Arena/D3%')" : $"and TARGET like '/Arena/{building_tag}%'") : ""; string pageQuery = pageResult.isEnable ? "" : @"ORDER BY [TIMESTAMP] DESC -- 必須提供 ORDER BY 子句 OFFSET @skip ROWS FETCH NEXT @pageSize ROWS ONLY;"; string sql = $@"SELECT DISTINCT [TIMESTAMP] created_at ,[OPERATION] action_name ,[TARGET] parameter ,[SLOTNAME] ,[OLDVALUE] ,[VALUE] ,[USERNAME] user_name FROM [taipei_dome].[dbo].[ARENA_{tableName}_AUDITHISTORY] WHERE {sWhere} AND TIMESTAMP >= @start_time AND TIMESTAMP < DATEADD(day, 1, @end_time) {sWhere2} {pageQuery}"; // 取得資料 logList = await backgroundServiceMsSqlRepository.GetAllAsync(sql, new { pageSize = pageResult.pageSize, skip = (pageResult.currentPage - 1) * pageResult.pageSize, operation_type = pageResult.data?.operation_type, start_time = start_time, end_time = end_time, }); sql = @$"SELECT COUNT(*) AS TotalCount FROM ( SELECT DISTINCT [TIMESTAMP] created_at, [OPERATION] action_name, [TARGET] parameter, [SLOTNAME], [OLDVALUE], [VALUE], [USERNAME] user_name FROM [taipei_dome].[dbo].[ARENA_{tableName}_AUDITHISTORY] WHERE {sWhere} AND TIMESTAMP >= @start_time AND TIMESTAMP < DATEADD(day, 1, @end_time) {sWhere2} ) AS subquery;"; total = await backgroundServiceMsSqlRepository.GetOneAsync(sql, new { start_time = start_time, end_time = end_time, }); logList.ForEach(log => log.content = $"Target:{log.parameter}{mark}Value:{log.value}"); } else if (pageResult.data.type == 3) { string pageQuery = pageResult.isEnable ? "" : "LIMIT @pageSize OFFSET @skip"; var sql = $@"SELECT ui.full_name AS user_name, ol.* FROM operation_log ol LEFT JOIN userinfo ui ON ui.userinfo_guid COLLATE utf8mb4_unicode_ci = ol.user_guid WHERE ol.operation_type = @operation_type AND ol.building_tag = @building_tag AND ol.created_at >= @start_time AND ol.created_at <= @end_time {pageQuery}"; // 取得資料 logList = await backendRepository.GetAllAsync(sql, new { pageSize = pageResult.pageSize, skip = (pageResult.currentPage - 1) * pageResult.pageSize, operation_type = pageResult.data?.operation_type, building_tag = pageResult.data?.building_tag, start_time = start_time, end_time = end_time, }); sql = $@"SELECT COUNT(*) AS total_count FROM ( SELECT ui.full_name AS user_name, ol.* FROM operation_log ol LEFT JOIN userinfo ui ON ui.userinfo_guid COLLATE utf8mb4_unicode_ci = ol.user_guid WHERE ol.operation_type = @operation_type AND ol.building_tag = @building_tag AND ol.created_at >= @start_time AND ol.created_at <= @end_time ) AS subquery;"; total = await backendRepository.GetOneAsync(sql, new { operation_type = pageResult.data?.operation_type, building_tag = pageResult.data?.building_tag, start_time = start_time, end_time = end_time, }); // 設定呈現紀錄內容 foreach (var log in logList) { if (log.parameter == null) { continue; } switch (log.operation_type) { case 1: var chaName = JsonConvert.DeserializeObject(log.parameter); if (chaName == null) continue; log.content = chaName.TagName + ":" + chaName.ChangeN; break; case 2: var schedule = JsonConvert.DeserializeObject(log.parameter); if (schedule == null) continue; var contentArr = new List() { "編號:" + schedule.light_schedule_guid, "名稱:" + schedule.full_name, }; if (log.action_name == "修改") { contentArr.Add("修改內容:" + string.Join("、", schedule.changeNames)); } log.content = string.Join(mark, contentArr); break; } } } else { apiResult.Code = "5000"; apiResult.Msg = "無效參數"; return apiResult; } var result = new PageResult> { pageSize = pageResult.pageSize, totalItem = total, currentPage = pageResult.currentPage, data = logList.OrderByDescending(log => log.created_at).ToList() }; apiResult.Code = "0000"; apiResult.Data = result; } catch (Exception exception) { apiResult.Code = "9999"; apiResult.Msg = "系統內部錯誤,請聯絡管理者。"; Logger.LogError("【" + controllerName + "/" + actionName + "】" + exception.Message); return apiResult; } return apiResult; } [HttpPost] [Route("api/OperationLog/ExportList")] public async Task ExportList([FromBody] OperationLogExportInput input) { List result = new List(); //if (input.isNiagara) //{ // result = input.exportList; //} //else //{ // PageResult pageResult = input.listInput; // pageResult.isEnable = false; // result = ((ApiResult>)((OkObjectResult)(await this.GetList(pageResult)).Result).Value).Data.ToList(); //} input.listInput.isEnable = true; result = GetLogList(input.listInput).Result.Data.data; var FileName = $"{input.exportOpeTypeName}_{DateTime.Now}.csv"; // 生成CSV文件 string Csv; string formatted_created_at = null; if (result.Count > 0) { StringBuilder csv = new StringBuilder(); // 添加CSV標題行 csv.AppendLine("操作人,動作,內容,紀錄時間"); // 添加數據行 foreach (var item in result) { if (item.created_at.HasValue) { formatted_created_at = item.created_at.Value.ToString("yyyy/MM/dd HH:mm:ss"); } csv.AppendLine($"{item.user_name},{item.action_name},{item.content},{formatted_created_at}"); } Csv = csv.ToString(); using (var fileMemoryStream = new MemoryStream()) { using (var streamWriter = new StreamWriter(fileMemoryStream, Encoding.UTF8)) { streamWriter.Write(Csv); } return File(fileMemoryStream.ToArray(), "text/csv", FileName); } } else { var msg = new { Code = "0003", Msg = "無資料可匯出。" }; return StatusCode(400, msg); } #region excel寫法,但有行數上限為 1,048,576 #region excel設定 //var workbook = new XSSFWorkbook(); //IFont font12 = workbook.CreateFont(); //font12.FontName = "新細明體"; //font12.FontHeightInPoints = 12; //ICellStyle style12 = workbook.CreateCellStyle(); //style12.SetFont(font12); //style12.Alignment = HorizontalAlignment.Center; //style12.VerticalAlignment = VerticalAlignment.Center; //IFont font12Times = workbook.CreateFont(); //font12Times.FontName = "Times New Roman"; //font12Times.FontHeightInPoints = 12; //IFont font18 = workbook.CreateFont(); //font18.FontName = "新細明體"; //font18.FontHeightInPoints = 18; //font18.IsBold = true; //ICellStyle styleTitle18 = workbook.CreateCellStyle(); //styleTitle18.SetFont(font18); //styleTitle18.Alignment = HorizontalAlignment.Center; //styleTitle18.VerticalAlignment = VerticalAlignment.Center; //ICellStyle styleLeft12 = workbook.CreateCellStyle(); //styleLeft12.SetFont(font12); //styleLeft12.Alignment = HorizontalAlignment.Left; //styleLeft12.VerticalAlignment = VerticalAlignment.Center; //ICellStyle styleLine12 = workbook.CreateCellStyle(); //styleLine12.SetFont(font12); //styleLine12.Alignment = NPOI.SS.UserModel.HorizontalAlignment.Center; //styleLine12.VerticalAlignment = VerticalAlignment.Center; //styleLine12.BorderTop = NPOI.SS.UserModel.BorderStyle.Thin; //styleLine12.BorderBottom = NPOI.SS.UserModel.BorderStyle.Thin; //styleLine12.BorderRight = NPOI.SS.UserModel.BorderStyle.Thin; //styleLine12.BorderLeft = NPOI.SS.UserModel.BorderStyle.Thin; //ICellStyle stylein12 = workbook.CreateCellStyle(); //stylein12.SetFont(font12Times); //stylein12.Alignment = NPOI.SS.UserModel.HorizontalAlignment.Left; //stylein12.VerticalAlignment = VerticalAlignment.Center; //stylein12.BorderTop = NPOI.SS.UserModel.BorderStyle.Thin; //stylein12.BorderBottom = NPOI.SS.UserModel.BorderStyle.Thin; //stylein12.BorderRight = NPOI.SS.UserModel.BorderStyle.Thin; //stylein12.BorderLeft = NPOI.SS.UserModel.BorderStyle.Thin; //stylein12.WrapText = true; #endregion //var sheet = workbook.CreateSheet(input.exportOpeTypeName); //int RowPosition = 0; //if (result.Count > 0) //{ // #region set cell // int ri = 0; // IRow row = sheet.CreateRow(RowPosition); // //if (!input.isNiagara) // //{ // // sheet.SetColumnWidth(ri++, 1 * 160 * 12); // //} // sheet.SetColumnWidth(ri++, 2 * 160 * 12); // sheet.SetColumnWidth(ri++, 2 * 160 * 12); // sheet.SetColumnWidth(ri++, 8 * 160 * 12); // sheet.SetColumnWidth(ri++, 4 * 160 * 12); // int i = 0; // ICell cell = row.CreateCell(i++); // //if (!input.isNiagara) // //{ // // cell.SetCellValue("編號"); // // cell.CellStyle = styleLine12; // // cell = row.CreateCell(i++); // //} // cell.SetCellValue("操作人"); // cell.CellStyle = styleLine12; // cell = row.CreateCell(i++); // cell.SetCellValue("動作"); // cell.CellStyle = styleLine12; // cell = row.CreateCell(i++); // cell.SetCellValue("內容"); // cell.CellStyle = styleLine12; // cell = row.CreateCell(i++); // cell.SetCellValue("紀錄時間"); // cell.CellStyle = styleLine12; // #endregion // foreach (var r in result) // { // RowPosition += 1; // int k = 3; // row = sheet.CreateRow(RowPosition); // for (int j = 0; j <= i; j++) // { // int s = 0; // cell = row.CreateCell(j); // //if (!input.isNiagara && j == s++) // //{ // // cell.SetCellValue(r.id); // //} // if (j == s++) // { // cell.SetCellValue(r.user_name); // } // if (j == s++) // { // cell.SetCellValue(r.action_name); // } // if (j == s++) // { // cell.SetCellValue(r.content); // } // if (j == s++) // { // cell.SetCellValue(r.created_at != null ? ((DateTime)r.created_at).ToString("yyyy-MM-dd HH:mm:ss") : null); // } // cell.CellStyle = style12; // } // } //} //var ms = new NpoiMemoryStream //{ // AllowClose = false //}; //workbook.Write(ms); //ms.Flush(); //ms.Seek(0, SeekOrigin.Begin); //Response.Headers.Add("Access-Control-Expose-Headers", "Content-Disposition"); //return File(ms, "application/vnd.ms-excel", $"操作紀錄_{input.exportOpeTypeName}.xlsx"); #endregion } } }