[WebApi]操作紀錄改成MSSQL撈取

This commit is contained in:
張家睿 2024-11-26 16:45:53 +08:00
parent b97828ca6a
commit e2f3992b9c
3 changed files with 333 additions and 174 deletions

View File

@ -24,6 +24,8 @@ using System.Threading.Tasks;
using Image = System.Drawing.Image; using Image = System.Drawing.Image;
using System.IdentityModel.Tokens.Jwt; using System.IdentityModel.Tokens.Jwt;
using System.Net; using System.Net;
using NPOI.POIFS.Crypt.Dsig;
using System.Text;
namespace FrontendWebApi.ApiControllers namespace FrontendWebApi.ApiControllers
{ {
@ -32,230 +34,386 @@ namespace FrontendWebApi.ApiControllers
public class OperationLogController : MyBaseApiController<OperationLogController> public class OperationLogController : MyBaseApiController<OperationLogController>
{ {
private readonly IBackendRepository backendRepository; private readonly IBackendRepository backendRepository;
private readonly IBackgroundServiceMsSqlRepository backgroundServiceMsSqlRepository;
private string operationFileSaveAsPath = ""; private string operationFileSaveAsPath = "";
public OperationLogController(IBackendRepository backendRepository) public OperationLogController(IBackendRepository backendRepository, IBackgroundServiceMsSqlRepository backgroundServiceMsSqlRepository)
{ {
this.backendRepository = backendRepository; this.backendRepository = backendRepository;
operationFileSaveAsPath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "upload", "operation"); operationFileSaveAsPath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "upload", "operation");
this.backgroundServiceMsSqlRepository = backgroundServiceMsSqlRepository;
} }
/// <summary>
/// 巨蛋操作紀錄api 1:系統紀錄;2:登入紀錄;3:燈控排程紀錄
/// </summary>
/// <param name="pageResult"></param>
/// <returns></returns>
[HttpPost] [HttpPost]
[Route("api/OperationLog/GetList")] [Route("api/OperationLog/GetLogList")]
public async Task<ActionResult<ApiResult<List<OperationLogOutput>>>> GetList([FromBody] PageResult<OperationLogInput> pageResult) public async Task<ApiResult<PageResult<List<OperationLogOutput>>>> GetLogList([FromBody] PageResult<OperationLogInput> pageResult)
{ {
ApiResult<List<OperationLogOutput>> apiResult = new ApiResult<List<OperationLogOutput>>(jwt_str); ApiResult<PageResult<List<OperationLogOutput>>> apiResult = new ApiResult<PageResult<List<OperationLogOutput>>>();
if (!jwtlife) List<OperationLogOutput> logList = new List<OperationLogOutput>();
{ int total = 0;
apiResult.Code = "5000"; string start_time = DateTime.Parse(pageResult.data?.start_time).ToString("yyyy-MM-dd");
return BadRequest(apiResult); string end_time = DateTime.Parse(pageResult.data?.end_time).ToString("yyyy-MM-dd"); ;
} string mark = pageResult.isEnable ? ";" : "\n";
try try
{ {
string pageQuery = pageResult.isEnable ? " LIMIT @pageSize OFFSET @skip" : ""; if (pageResult.data.type == 1 || pageResult.data.type == 2)
// 取得資料 {
var logList = await backendRepository.GetAllAsync<OperationLogOutput>($@" string building_tag = pageResult.data?.building_tag;
select ui.full_name as 'user_name' ,ol.* from operation_log ol string tableName = (building_tag == "D2" || building_tag == "D3") ? "D2_Pri" : $"{building_tag}";
LEFT JOIN userinfo ui on ui.userinfo_guid COLLATE utf8mb4_unicode_ci = ol.user_guid string sWhere = pageResult.data.type == 1 ? "OPERATION ='Invoked'" : "(OPERATION = 'Login' or OPERATION = 'Logout (Timeout)')";
WHERE ol.operation_type = @operation_type AND ol.building_tag = @building_tag AND string sWhere2 = pageResult.data.type == 1 ? ((building_tag == "D2" || building_tag == "D3") ?
ol.created_at >= @start_time AND ol.created_at <= @end_time "and (TARGET like '/Arena/D2%' or target like '/Arena/D3%')" : $"and TARGET like '/Arena/{building_tag}%'") : "";
{pageQuery}", string pageQuery = pageResult.isEnable ? "" : @"ORDER BY [TIMESTAMP] DESC -- 必須提供 ORDER BY 子句
new { OFFSET @skip ROWS
pageSize = pageResult.pageSize , FETCH NEXT @pageSize ROWS ONLY;";
skip = (pageResult.currentPage - 1) * pageResult.pageSize,
operation_type = pageResult.data?.operation_type,
building_tag = pageResult.data?.building_tag,
start_time = pageResult.data?.start_time,
end_time = pageResult.data?.end_time,
});
// 設定呈現紀錄內容 string sql = $@"SELECT DISTINCT
foreach (var log in logList) { [TIMESTAMP] created_at
if (log.parameter == null) { ,[OPERATION] action_name
continue; ,[TARGET] parameter
} ,[SLOTNAME]
switch (log.operation_type) { ,[OLDVALUE]
case 1: ,[VALUE]
var chaName = JsonConvert.DeserializeObject<ChangeName>(log.parameter); ,[USERNAME] user_name
if (chaName == null) continue; FROM [taipei_dome].[dbo].[ARENA_{tableName}_AUDITHISTORY]
log.content = chaName.TagName + "" + chaName.ChangeN; WHERE {sWhere}
break; AND TIMESTAMP >= @start_time AND TIMESTAMP < DATEADD(day, 1, @end_time)
case 2: {sWhere2}
var schedule = JsonConvert.DeserializeObject<SaveSchedule>(log.parameter); {pageQuery}";
if (schedule == null) continue; // 取得資料
var contentArr = new List<string>() { logList = await backgroundServiceMsSqlRepository.GetAllAsync<OperationLogOutput>(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<int>(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<OperationLogOutput>(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<int>(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<ChangeName>(log.parameter);
if (chaName == null) continue;
log.content = chaName.TagName + "" + chaName.ChangeN;
break;
case 2:
var schedule = JsonConvert.DeserializeObject<SaveSchedule>(log.parameter);
if (schedule == null) continue;
var contentArr = new List<string>() {
"編號:" + schedule.light_schedule_guid, "編號:" + schedule.light_schedule_guid,
"名稱:" + schedule.full_name, "名稱:" + schedule.full_name,
}; };
if (log.action_name == "修改") { if (log.action_name == "修改")
contentArr.Add("修改內容:" + string.Join("、", schedule.changeNames)); {
} contentArr.Add("修改內容:" + string.Join("、", schedule.changeNames));
log.content = string.Join("\n",contentArr); }
break; log.content = string.Join(mark, contentArr);
break;
}
} }
} }
else
{
apiResult.Code = "5000";
apiResult.Msg = "無效參數";
return apiResult;
}
var result = new PageResult<List<OperationLogOutput>>
{
pageSize = pageResult.pageSize,
totalItem = total,
currentPage = pageResult.currentPage,
data = logList.OrderByDescending(log => log.created_at).ToList()
};
apiResult.Code = "0000"; apiResult.Code = "0000";
apiResult.Data = logList; apiResult.Data = result;
} }
catch (Exception exception) catch (Exception exception)
{ {
apiResult.Code = "9999"; apiResult.Code = "9999";
apiResult.Msg = "系統內部錯誤,請聯絡管理者。";
Logger.LogError("【" + controllerName + "/" + actionName + "】" + exception.Message); Logger.LogError("【" + controllerName + "/" + actionName + "】" + exception.Message);
return Ok(apiResult); return apiResult;
} }
return Ok(apiResult); return apiResult;
} }
[HttpPost] [HttpPost]
[Route("api/OperationLog/ExportList")] [Route("api/OperationLog/ExportList")]
public async Task<FileResult> ExportList([FromBody] OperationLogExportInput input) public async Task<IActionResult> ExportList([FromBody] OperationLogExportInput input)
{ {
List<OperationLogOutput> result = new List<OperationLogOutput>(); List<OperationLogOutput> result = new List<OperationLogOutput>();
if (input.isNiagara) //if (input.isNiagara)
//{
// result = input.exportList;
//}
//else
//{
// PageResult<OperationLogInput> pageResult = input.listInput;
// pageResult.isEnable = false;
// result = ((ApiResult<List<OperationLogOutput>>)((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)
{ {
result = input.exportList; 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 else
{ {
PageResult<OperationLogInput> pageResult = input.listInput; var msg = new { Code = "0003", Msg = "無資料可匯出。" };
pageResult.isEnable = false; return StatusCode(400, msg);
result = ((ApiResult<List<OperationLogOutput>>)((OkObjectResult)(await this.GetList(pageResult)).Result).Value).Data.ToList();
} }
var workbook = new XSSFWorkbook(); #region excel寫法 1,048,576
#region excel設定 #region excel設定
IFont font12 = workbook.CreateFont(); //var workbook = new XSSFWorkbook();
font12.FontName = "新細明體"; //IFont font12 = workbook.CreateFont();
font12.FontHeightInPoints = 12; //font12.FontName = "新細明體";
ICellStyle style12 = workbook.CreateCellStyle(); //font12.FontHeightInPoints = 12;
style12.SetFont(font12); //ICellStyle style12 = workbook.CreateCellStyle();
style12.Alignment = HorizontalAlignment.Center; //style12.SetFont(font12);
style12.VerticalAlignment = VerticalAlignment.Center; //style12.Alignment = HorizontalAlignment.Center;
IFont font12Times = workbook.CreateFont(); //style12.VerticalAlignment = VerticalAlignment.Center;
font12Times.FontName = "Times New Roman"; //IFont font12Times = workbook.CreateFont();
font12Times.FontHeightInPoints = 12; //font12Times.FontName = "Times New Roman";
IFont font18 = workbook.CreateFont(); //font12Times.FontHeightInPoints = 12;
font18.FontName = "新細明體"; //IFont font18 = workbook.CreateFont();
font18.FontHeightInPoints = 18; //font18.FontName = "新細明體";
font18.IsBold = true; //font18.FontHeightInPoints = 18;
ICellStyle styleTitle18 = workbook.CreateCellStyle(); //font18.IsBold = true;
styleTitle18.SetFont(font18); //ICellStyle styleTitle18 = workbook.CreateCellStyle();
styleTitle18.Alignment = HorizontalAlignment.Center; //styleTitle18.SetFont(font18);
styleTitle18.VerticalAlignment = VerticalAlignment.Center; //styleTitle18.Alignment = HorizontalAlignment.Center;
ICellStyle styleLeft12 = workbook.CreateCellStyle(); //styleTitle18.VerticalAlignment = VerticalAlignment.Center;
styleLeft12.SetFont(font12); //ICellStyle styleLeft12 = workbook.CreateCellStyle();
styleLeft12.Alignment = HorizontalAlignment.Left; //styleLeft12.SetFont(font12);
styleLeft12.VerticalAlignment = VerticalAlignment.Center; //styleLeft12.Alignment = HorizontalAlignment.Left;
ICellStyle styleLine12 = workbook.CreateCellStyle(); //styleLeft12.VerticalAlignment = VerticalAlignment.Center;
styleLine12.SetFont(font12); //ICellStyle styleLine12 = workbook.CreateCellStyle();
styleLine12.Alignment = NPOI.SS.UserModel.HorizontalAlignment.Center; //styleLine12.SetFont(font12);
styleLine12.VerticalAlignment = VerticalAlignment.Center; //styleLine12.Alignment = NPOI.SS.UserModel.HorizontalAlignment.Center;
styleLine12.BorderTop = NPOI.SS.UserModel.BorderStyle.Thin; //styleLine12.VerticalAlignment = VerticalAlignment.Center;
styleLine12.BorderBottom = NPOI.SS.UserModel.BorderStyle.Thin; //styleLine12.BorderTop = NPOI.SS.UserModel.BorderStyle.Thin;
styleLine12.BorderRight = NPOI.SS.UserModel.BorderStyle.Thin; //styleLine12.BorderBottom = NPOI.SS.UserModel.BorderStyle.Thin;
styleLine12.BorderLeft = NPOI.SS.UserModel.BorderStyle.Thin; //styleLine12.BorderRight = NPOI.SS.UserModel.BorderStyle.Thin;
ICellStyle stylein12 = workbook.CreateCellStyle(); //styleLine12.BorderLeft = NPOI.SS.UserModel.BorderStyle.Thin;
stylein12.SetFont(font12Times); //ICellStyle stylein12 = workbook.CreateCellStyle();
stylein12.Alignment = NPOI.SS.UserModel.HorizontalAlignment.Left; //stylein12.SetFont(font12Times);
stylein12.VerticalAlignment = VerticalAlignment.Center; //stylein12.Alignment = NPOI.SS.UserModel.HorizontalAlignment.Left;
stylein12.BorderTop = NPOI.SS.UserModel.BorderStyle.Thin; //stylein12.VerticalAlignment = VerticalAlignment.Center;
stylein12.BorderBottom = NPOI.SS.UserModel.BorderStyle.Thin; //stylein12.BorderTop = NPOI.SS.UserModel.BorderStyle.Thin;
stylein12.BorderRight = NPOI.SS.UserModel.BorderStyle.Thin; //stylein12.BorderBottom = NPOI.SS.UserModel.BorderStyle.Thin;
stylein12.BorderLeft = NPOI.SS.UserModel.BorderStyle.Thin; //stylein12.BorderRight = NPOI.SS.UserModel.BorderStyle.Thin;
stylein12.WrapText = true; //stylein12.BorderLeft = NPOI.SS.UserModel.BorderStyle.Thin;
//stylein12.WrapText = true;
#endregion #endregion
var sheet = workbook.CreateSheet(input.exportOpeTypeName); //var sheet = workbook.CreateSheet(input.exportOpeTypeName);
int RowPosition = 0; //int RowPosition = 0;
if (result.Count > 0) //if (result.Count > 0)
{ //{
#region set cell // #region set cell
int ri = 0; // int ri = 0;
IRow row = sheet.CreateRow(RowPosition); // IRow row = sheet.CreateRow(RowPosition);
if (!input.isNiagara) { // //if (!input.isNiagara)
sheet.SetColumnWidth(ri++, 1 * 160 * 12); // //{
} // // sheet.SetColumnWidth(ri++, 1 * 160 * 12);
sheet.SetColumnWidth(ri++, 2 * 160 * 12); // //}
sheet.SetColumnWidth(ri++, 2 * 160 * 12); // sheet.SetColumnWidth(ri++, 2 * 160 * 12);
sheet.SetColumnWidth(ri++, 8 * 160 * 12); // sheet.SetColumnWidth(ri++, 2 * 160 * 12);
sheet.SetColumnWidth(ri++, 4 * 160 * 12); // sheet.SetColumnWidth(ri++, 8 * 160 * 12);
// sheet.SetColumnWidth(ri++, 4 * 160 * 12);
int i = 0; // int i = 0;
ICell cell = row.CreateCell(i++); // ICell cell = row.CreateCell(i++);
if (!input.isNiagara) // //if (!input.isNiagara)
{ // //{
cell.SetCellValue("編號"); // // cell.SetCellValue("編號");
cell.CellStyle = styleLine12; // // cell.CellStyle = styleLine12;
cell = row.CreateCell(i++); // // cell = row.CreateCell(i++);
} // //}
cell.SetCellValue("操作人"); // cell.SetCellValue("操作人");
cell.CellStyle = styleLine12; // cell.CellStyle = styleLine12;
cell = row.CreateCell(i++); // cell = row.CreateCell(i++);
cell.SetCellValue("動作"); // cell.SetCellValue("動作");
cell.CellStyle = styleLine12; // cell.CellStyle = styleLine12;
cell = row.CreateCell(i++); // cell = row.CreateCell(i++);
cell.SetCellValue("內容"); // cell.SetCellValue("內容");
cell.CellStyle = styleLine12; // cell.CellStyle = styleLine12;
cell = row.CreateCell(i++); // cell = row.CreateCell(i++);
cell.SetCellValue("紀錄時間"); // cell.SetCellValue("紀錄時間");
cell.CellStyle = styleLine12; // cell.CellStyle = styleLine12;
#endregion // #endregion
foreach (var r in result) // foreach (var r in result)
{ // {
RowPosition += 1; // RowPosition += 1;
int k = 3; // int k = 3;
row = sheet.CreateRow(RowPosition); // row = sheet.CreateRow(RowPosition);
for (int j = 0; j <= i; j++) // for (int j = 0; j <= i; j++)
{ // {
int s = 0; // int s = 0;
cell = row.CreateCell(j); // cell = row.CreateCell(j);
if (!input.isNiagara && j == s++) // //if (!input.isNiagara && j == s++)
{ // //{
cell.SetCellValue(r.id); // // cell.SetCellValue(r.id);
} // //}
if (j == s++) // if (j == s++)
{ // {
cell.SetCellValue(r.user_name); // cell.SetCellValue(r.user_name);
} // }
if (j == s++) // if (j == s++)
{ // {
cell.SetCellValue(r.action_name); // cell.SetCellValue(r.action_name);
} // }
if (j == s++) // if (j == s++)
{ // {
cell.SetCellValue(r.content); // 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; // if (j == s++)
} // {
} // cell.SetCellValue(r.created_at != null ? ((DateTime)r.created_at).ToString("yyyy-MM-dd HH:mm:ss") : null);
} // }
var ms = new NpoiMemoryStream // cell.CellStyle = style12;
{ // }
AllowClose = false // }
}; //}
workbook.Write(ms);
ms.Flush();
ms.Seek(0, SeekOrigin.Begin);
Response.Headers.Add("Access-Control-Expose-Headers", "Content-Disposition"); //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
return File(ms, "application/vnd.ms-excel", $"操作紀錄_{input.exportOpeTypeName}.xlsx");
} }
} }
} }

View File

@ -168,6 +168,7 @@ namespace FrontendWebApi.Models
public string end_time { get; set; } public string end_time { get; set; }
public string building_tag{ get; set; } public string building_tag{ get; set; }
public short operation_type { get; set; } public short operation_type { get; set; }
public int type { get; set; } = 1; // log選項 1:系統紀錄;2:登入紀錄;3:燈控排程紀錄
} }
public class OperationLogExportInput { public class OperationLogExportInput {
public bool isNiagara { get; set; } public bool isNiagara { get; set; }

View File

@ -286,7 +286,7 @@ namespace FrontendWebApi.Models
public class BasePageResult { public class BasePageResult {
public int? pageSize { get; set; } = 10; public int? pageSize { get; set; } = 10;
public int? totalItem { get; set; } = 0;
public int? totalPage { get; set; } = 0; public int? totalPage { get; set; } = 0;
public int? currentPage { get; set; } = 0; public int? currentPage { get; set; } = 0;
} }
@ -295,6 +295,6 @@ namespace FrontendWebApi.Models
{ {
public T data { get; set; } public T data { get; set; }
public bool isEnable { get; set; } public bool isEnable { get; set; }
} }
} }