From aa9d3b332957fc324ce787b8b213919ca549fb75 Mon Sep 17 00:00:00 2001 From: "MSI\\User" Date: Mon, 22 Dec 2025 11:32:24 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A0=B1=E8=A1=A8=E8=AA=BF=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Controllers/HomeController.cs | 6 ++ Controllers/ReportController.cs | 221 ++++++++++++++++++++++++++-------------- Program.cs | 4 +- Views/Report/Index.cshtml | 29 ++++-- Views/Shared/_Layout.cshtml | 13 ++- 5 files changed, 183 insertions(+), 90 deletions(-) diff --git a/Controllers/HomeController.cs b/Controllers/HomeController.cs index 0e25e94..6ac0374 100644 --- a/Controllers/HomeController.cs +++ b/Controllers/HomeController.cs @@ -27,6 +27,12 @@ public class HomeController : Controller } public IActionResult Index() { + //如果已經登入,直接導向報表頁面 + if (User.Identity?.IsAuthenticated == true) + { + return RedirectToAction("Index", "Report"); + } + ViewBag.OauthUrl = _oauthOption.Value.ParkingOAuthUrl; return View(new LoginViewModel()); } diff --git a/Controllers/ReportController.cs b/Controllers/ReportController.cs index 9bcc2cd..1ca3892 100644 --- a/Controllers/ReportController.cs +++ b/Controllers/ReportController.cs @@ -52,11 +52,11 @@ public class ReportController : Controller private async Task LoadReportData(DateTime? startDate, DateTime? endDate) { - var query = _couponContext.Logs.AsQueryable().Where(x => x.LogType == "Consume" && x.LogInfo.Contains("耗用成功")); - var serialNo = query.GroupBy(x => x.SerialNo).Select(g => g.Key).ToList(); - var carEnter = _parkingEyesContext.CarEnters.Where(x => serialNo.Contains(x.SerialNo)).ToList(); + // 建立包含日期篩選的查詢 + var query = _couponContext.Logs.AsQueryable() + .Where(x => x.LogType == "Consume" && x.LogInfo.Contains("耗用成功")); - if (startDate.HasValue) + if (startDate.HasValue) { query = query.Where(x => x.LogTime >= startDate.Value); } @@ -66,21 +66,30 @@ public class ReportController : Controller query = query.Where(x => x.LogTime <= endDate.Value.AddDays(1).AddSeconds(-1)); } - var logs = await query.OrderBy(x => x.LogTime).ToListAsync(); + var consumeLogs = await query.OrderBy(x => x.LogTime).ToListAsync(); + var serialNo = consumeLogs.Select(x => x.SerialNo).Distinct().ToList(); + + var evaluateLogsQuery = await _couponContext.Logs + .Where(x => serialNo.Contains(x.SerialNo) && x.LogType == "Evaluate" && x.LogInfo.Contains("評估成功")) + .ToListAsync(); + + // 建立 SerialNo 到 Evaluate Log 的映射 + var evaluateLogDict = evaluateLogsQuery + .GroupBy(x => x.SerialNo) + .ToDictionary(g => g.Key, g => g.FirstOrDefault()); + + //var carEnter = _parkingEyesContext.CarEnters.Where(x => serialNo.Contains(x.SerialNo)).ToList(); + //var carEnter = _mySqlContext.Cario.Where(x => serialNo.Contains(x.SerialNo)).ToList(); // 建立 SerialNo 到編號的映射 var serialNoToRowNumber = new Dictionary(); int currentRowNumber = 1; // 建立 SerialNo 到 CarEnter 的映射,方便快速查找 - var carEnterDict = carEnter.GroupBy(x => x.SerialNo) - .ToDictionary(g => g.Key, g => g.FirstOrDefault()); + //var carEnterDict = carEnter.GroupBy(x => x.SerialNo) + // .ToDictionary(g => g.Key, g => g.FirstOrDefault()); - var viewModel = new CouponReportViewModel - { - StartDate = startDate, - EndDate = endDate, - ReportItems = logs.Select(log => + var reportItems = consumeLogs.Select(log => { // 如果這個 SerialNo 還沒出現過,給它一個新編號 if (!string.IsNullOrEmpty(log.SerialNo) && !serialNoToRowNumber.ContainsKey(log.SerialNo)) @@ -88,17 +97,22 @@ public class ReportController : Controller serialNoToRowNumber[log.SerialNo] = currentRowNumber++; } - // 從 CarEnter 取得出場時間 + // 從 evaluateLogDict 取得出場時間 DateTime? exitTime = null; + if (!string.IsNullOrEmpty(log.SerialNo) && evaluateLogDict.ContainsKey(log.SerialNo)) + { + exitTime = evaluateLogDict[log.SerialNo]?.LogTime; + } + var tenantCode = string.Empty; DateTime? invoiceDate = null; var invoiceNo = string.Empty; var invoiceAmount = 0m; - if (!string.IsNullOrEmpty(log.SerialNo) && carEnterDict.ContainsKey(log.SerialNo)) - { - exitTime = carEnterDict[log.SerialNo]?.DepartureDateTime; - } + //if (!string.IsNullOrEmpty(log.SerialNo) && carEnterDict.ContainsKey(log.SerialNo)) + // { + // exitTime = carEnterDict[log.SerialNo]?.OutTime; + // } invoiceDate = _reportService.GetInvoiceDateTime(log.ExternalSystemKey); invoiceNo = _reportService.GetInvoiceNo(log.ExternalSystemKey); @@ -113,7 +127,7 @@ public class ReportController : Controller InvoiceDate = invoiceDate, InvoiceNumber = invoiceNo, InvoiceAmount = invoiceAmount, - DiscountUnit = "新台幣", + DiscountUnit = "金額", DiscountAmount = log.DiscountAmount, DiscountTime = log.LogTime, EnterTime = log.EnterTime, @@ -121,7 +135,13 @@ public class ReportController : Controller ParkingAmount = log.TotalAmount, ClaimAmount = log.DiscountAmount }; - }).ToList() + }).OrderBy(x => x.RowNumber).ThenBy(x => x.DiscountTime).ToList(); + + var viewModel = new CouponReportViewModel + { + StartDate = startDate, + EndDate = endDate, + ReportItems = reportItems }; return View(viewModel); @@ -129,9 +149,8 @@ public class ReportController : Controller public async Task ExportToExcel(DateTime? startDate, DateTime? endDate) { - var query = _couponContext.Logs.AsQueryable().Where(x => x.LogType == "Consume" && x.LogInfo.Contains("耗用成功")); - var serialNo = query.GroupBy(x => x.SerialNo).Select(g => g.Key).ToList(); - var carEnter = _parkingEyesContext.CarEnters.Where(x => serialNo.Contains(x.SerialNo)).ToList(); + var query = _couponContext.Logs.AsQueryable() + .Where(x => x.LogType == "Consume" && x.LogInfo.Contains("耗用成功")); if (startDate.HasValue) { @@ -143,23 +162,29 @@ public class ReportController : Controller query = query.Where(x => x.LogTime <= endDate.Value.AddDays(1).AddSeconds(-1)); } - var logs = await query.OrderBy(x => x.LogTime).ToListAsync(); + var consumeLogs = await query.OrderBy(x => x.LogTime).ToListAsync(); + var serialNo = consumeLogs.Select(x => x.SerialNo).Distinct().ToList(); + + var evaluateLogsQuery = await _couponContext.Logs + .Where(x => serialNo.Contains(x.SerialNo) && x.LogType == "Evaluate" && x.LogInfo.Contains("評估成功")) + .ToListAsync(); + + // 建立 SerialNo 到 Evaluate Log 的映射 + var evaluateLogDict = evaluateLogsQuery + .GroupBy(x => x.SerialNo) + .ToDictionary(g => g.Key, g => g.FirstOrDefault()); // 建立 SerialNo 到編號的映射 var serialNoToRowNumber = new Dictionary(); int currentRowNumber = 1; - // 建立 SerialNo 到 CarEnter 的映射,方便快速查找 - var carEnterDict = carEnter.GroupBy(x => x.SerialNo) - .ToDictionary(g => g.Key, g => g.FirstOrDefault()); - // 建立報表資料列表 var reportItems = new List<(int rowNumber, string tenantCode, string carNumber, DateTime? invoiceDate, string invoiceNo, decimal invoiceAmount, string discountUnit, decimal? discountAmount, DateTime discountTime, DateTime? enterTime, DateTime? exitTime, decimal? parkingAmount, decimal? claimAmount)>(); - foreach (var log in logs) + foreach (var log in consumeLogs) { if (!string.IsNullOrEmpty(log.SerialNo) && !serialNoToRowNumber.ContainsKey(log.SerialNo)) { @@ -167,9 +192,9 @@ public class ReportController : Controller } DateTime? exitTime = null; - if (!string.IsNullOrEmpty(log.SerialNo) && carEnterDict.ContainsKey(log.SerialNo)) + if (!string.IsNullOrEmpty(log.SerialNo) && evaluateLogDict.ContainsKey(log.SerialNo)) { - exitTime = carEnterDict[log.SerialNo]?.DepartureDateTime; + exitTime = evaluateLogDict[log.SerialNo]?.LogTime; } var invoiceDate = _reportService.GetInvoiceDateTime(log.ExternalSystemKey); @@ -180,37 +205,47 @@ public class ReportController : Controller int rowNumber = !string.IsNullOrEmpty(log.SerialNo) ? serialNoToRowNumber[log.SerialNo] : 0; reportItems.Add((rowNumber, tenantCode, log.PlateNo, invoiceDate, invoiceNo, invoiceAmount, - "新台幣", log.DiscountAmount, log.LogTime, log.EnterTime, exitTime, + "金額", log.DiscountAmount, log.LogTime, log.EnterTime, exitTime, log.TotalAmount, log.DiscountAmount)); } + // 按 RowNumber 排序,確保相同編號的資料連續,避免合併儲存格錯誤 + reportItems = reportItems.OrderBy(x => x.rowNumber).ThenBy(x => x.discountTime).ToList(); + using var workbook = new XLWorkbook(); var worksheet = workbook.Worksheets.Add("折扣報表"); + // 匯出資訊(合併儲存格以避免影響欄寬) + worksheet.Range(1, 1, 1, 13).Merge(); + worksheet.Cell(1, 1).Value = $"匯出時間:{DateTime.Now:yyyy-MM-dd HH:mm:ss}"; + + worksheet.Range(2, 1, 2, 13).Merge(); + worksheet.Cell(2, 1).Value = $"篩選條件:{startDate?.ToString("yyyy-MM-dd")} ~ {endDate?.ToString("yyyy-MM-dd")}"; + // 標題列 - worksheet.Cell(1, 1).Value = "編號"; - worksheet.Cell(1, 2).Value = "店別(統編)"; - worksheet.Cell(1, 3).Value = "車號"; - worksheet.Cell(1, 4).Value = "發票日期"; - worksheet.Cell(1, 5).Value = "發票號碼"; - worksheet.Cell(1, 6).Value = "發票金額"; - worksheet.Cell(1, 7).Value = "折扣單位"; - worksheet.Cell(1, 8).Value = "折扣金額"; - worksheet.Cell(1, 9).Value = "折扣時間"; - worksheet.Cell(1, 10).Value = "入場時間"; - worksheet.Cell(1, 11).Value = "出場時間"; - worksheet.Cell(1, 12).Value = "停車金額"; - worksheet.Cell(1, 13).Value = "請款金額"; + worksheet.Cell(4, 1).Value = "編號"; + worksheet.Cell(4, 2).Value = "店別(統編)"; + worksheet.Cell(4, 3).Value = "車號"; + worksheet.Cell(4, 4).Value = "發票日期"; + worksheet.Cell(4, 5).Value = "發票號碼"; + worksheet.Cell(4, 6).Value = "發票金額"; + worksheet.Cell(4, 7).Value = "折扣單位"; + worksheet.Cell(4, 8).Value = "折扣金額"; + worksheet.Cell(4, 9).Value = "折扣時間"; + worksheet.Cell(4, 10).Value = "入場時間"; + worksheet.Cell(4, 11).Value = "出場時間"; + worksheet.Cell(4, 12).Value = "停車金額"; + worksheet.Cell(4, 13).Value = "請款金額"; // 設定標題列樣式 - var headerRange = worksheet.Range(1, 1, 1, 13); + var headerRange = worksheet.Range(4, 1, 4, 13); headerRange.Style.Font.Bold = true; headerRange.Style.Fill.BackgroundColor = XLColor.LightGray; headerRange.Style.Alignment.Horizontal = XLAlignmentHorizontalValues.Center; headerRange.Style.Alignment.Vertical = XLAlignmentVerticalValues.Center; // 填入資料並記錄合併範圍 - int row = 2; + int row = 5; var mergedCells = new Dictionary(); foreach (var item in reportItems) @@ -219,16 +254,16 @@ public class ReportController : Controller worksheet.Cell(row, 1).Value = item.rowNumber; worksheet.Cell(row, 2).Value = item.tenantCode; worksheet.Cell(row, 3).Value = item.carNumber; - worksheet.Cell(row, 4).Value = item.invoiceDate?.ToString("yyyy-MM-dd HH:mm:ss"); + worksheet.Cell(row, 4).Value = item.invoiceDate?.ToString("yyyy-MM-dd"); worksheet.Cell(row, 5).Value = item.invoiceNo; - worksheet.Cell(row, 6).Value = item.invoiceAmount; + worksheet.Cell(row, 6).Value = $"NT$ {item.invoiceAmount:N0}"; worksheet.Cell(row, 7).Value = item.discountUnit; - worksheet.Cell(row, 8).Value = item.discountAmount; + worksheet.Cell(row, 8).Value = $"NT$ {item.discountAmount:N0}"; worksheet.Cell(row, 9).Value = item.discountTime.ToString("yyyy-MM-dd HH:mm:ss"); worksheet.Cell(row, 10).Value = item.enterTime?.ToString("yyyy-MM-dd HH:mm:ss"); worksheet.Cell(row, 11).Value = item.exitTime?.ToString("yyyy-MM-dd HH:mm:ss"); - worksheet.Cell(row, 12).Value = item.parkingAmount; - worksheet.Cell(row, 13).Value = item.claimAmount; + worksheet.Cell(row, 12).Value = $"NT$ {item.parkingAmount:N0}"; + worksheet.Cell(row, 13).Value = $"NT$ {item.claimAmount:N0}"; // 記錄需要合併的儲存格範圍(按 rowNumber 分組) if (item.rowNumber > 0) @@ -274,7 +309,7 @@ public class ReportController : Controller } // 將所有資料儲存格置中 - var dataRange = worksheet.Range(2, 1, row - 1, 13); + var dataRange = worksheet.Range(5, 1, row - 1, 13); dataRange.Style.Alignment.Horizontal = XLAlignmentHorizontalValues.Center; dataRange.Style.Alignment.Vertical = XLAlignmentVerticalValues.Center; @@ -288,9 +323,8 @@ public class ReportController : Controller public async Task ExportToPdf(DateTime? startDate, DateTime? endDate) { - var query = _couponContext.Logs.AsQueryable().Where(x => x.LogType == "Consume" && x.LogInfo.Contains("耗用成功")); - var serialNo = query.GroupBy(x => x.SerialNo).Select(g => g.Key).ToList(); - var carEnter = _parkingEyesContext.CarEnters.Where(x => serialNo.Contains(x.SerialNo)).ToList(); + var query = _couponContext.Logs.AsQueryable() + .Where(x => x.LogType == "Consume" && x.LogInfo.Contains("耗用成功")); if (startDate.HasValue) { @@ -302,23 +336,29 @@ public class ReportController : Controller query = query.Where(x => x.LogTime <= endDate.Value.AddDays(1).AddSeconds(-1)); } - var logs = await query.OrderBy(x => x.LogTime).ToListAsync(); + var consumeLogs = await query.OrderBy(x => x.LogTime).ToListAsync(); + var serialNo = consumeLogs.Select(x => x.SerialNo).Distinct().ToList(); + + var evaluateLogsQuery = await _couponContext.Logs + .Where(x => serialNo.Contains(x.SerialNo) && x.LogType == "Evaluate" && x.LogInfo.Contains("評估成功")) + .ToListAsync(); + + // 建立 SerialNo 到 Evaluate Log 的映射 + var evaluateLogDict = evaluateLogsQuery + .GroupBy(x => x.SerialNo) + .ToDictionary(g => g.Key, g => g.FirstOrDefault()); // 建立 SerialNo 到編號的映射 var serialNoToRowNumber = new Dictionary(); int currentRowNumber = 1; - // 建立 SerialNo 到 CarEnter 的映射,方便快速查找 - var carEnterDict = carEnter.GroupBy(x => x.SerialNo) - .ToDictionary(g => g.Key, g => g.FirstOrDefault()); + // 建立臨時資料列表以便排序 + var tempReportItems = new List<(int rowNumber, string tenantCode, string carNumber, DateTime? invoiceDate, + string invoiceNo, decimal invoiceAmount, string discountUnit, decimal? discountAmount, + DateTime discountTime, DateTime? enterTime, DateTime? exitTime, + decimal? parkingAmount, decimal? claimAmount)>(); - // 建立報表資料並分組 - var reportGroups = new Dictionary>(); - var groupData = new Dictionary(); - - foreach (var log in logs) + foreach (var log in consumeLogs) { if (!string.IsNullOrEmpty(log.SerialNo) && !serialNoToRowNumber.ContainsKey(log.SerialNo)) { @@ -326,9 +366,9 @@ public class ReportController : Controller } DateTime? exitTime = null; - if (!string.IsNullOrEmpty(log.SerialNo) && carEnterDict.ContainsKey(log.SerialNo)) + if (!string.IsNullOrEmpty(log.SerialNo) && evaluateLogDict.ContainsKey(log.SerialNo)) { - exitTime = carEnterDict[log.SerialNo]?.DepartureDateTime; + exitTime = evaluateLogDict[log.SerialNo]?.LogTime; } var invoiceDate = _reportService.GetInvoiceDateTime(log.ExternalSystemKey); @@ -338,15 +378,31 @@ public class ReportController : Controller int rowNumber = !string.IsNullOrEmpty(log.SerialNo) ? serialNoToRowNumber[log.SerialNo] : 0; + tempReportItems.Add((rowNumber, tenantCode, log.PlateNo, invoiceDate, invoiceNo, invoiceAmount, + "金額", log.DiscountAmount, log.LogTime, log.EnterTime, exitTime, + log.TotalAmount, log.DiscountAmount)); + } + + // 按 RowNumber 排序,確保相同編號的資料連續,避免合併儲存格錯誤 + tempReportItems = tempReportItems.OrderBy(x => x.rowNumber).ThenBy(x => x.discountTime).ToList(); + + // 建立報表資料並分組 + var reportGroups = new Dictionary>(); + var groupData = new Dictionary(); + + foreach (var item in tempReportItems) + { // 記錄群組資料 - if (!groupData.ContainsKey(rowNumber)) + if (!groupData.ContainsKey(item.rowNumber)) { - groupData[rowNumber] = (rowNumber, log.PlateNo, "新台幣", log.DiscountAmount, log.LogTime, - log.EnterTime, exitTime, log.TotalAmount, log.DiscountAmount); - reportGroups[rowNumber] = new List<(string, DateTime?, string, decimal)>(); + groupData[item.rowNumber] = (item.rowNumber, item.carNumber, item.discountUnit, item.discountAmount, item.discountTime, + item.enterTime, item.exitTime, item.parkingAmount, item.claimAmount); + reportGroups[item.rowNumber] = new List<(string, DateTime?, string, decimal)>(); } - reportGroups[rowNumber].Add((tenantCode, invoiceDate, invoiceNo, invoiceAmount)); + reportGroups[item.rowNumber].Add((item.tenantCode, item.invoiceDate, item.invoiceNo, item.invoiceAmount)); } var stream = new MemoryStream(); @@ -380,6 +436,17 @@ public class ReportController : Controller .SetFontSize(18); document.Add(title); + // 匯出資訊 + var exportInfo = new Paragraph($"匯出時間:{DateTime.Now:yyyy-MM-dd HH:mm:ss}") + .SetFontSize(10) + .SetMarginTop(10); + document.Add(exportInfo); + + var filterInfo = new Paragraph($"篩選條件:{startDate?.ToString("yyyy-MM-dd")} ~ {endDate?.ToString("yyyy-MM-dd")}") + .SetFontSize(10) + .SetMarginBottom(10); + document.Add(filterInfo); + // 建立表格 var table = new Table(13).UseAllAvailableWidth(); table.SetFontSize(8); @@ -428,18 +495,18 @@ public class ReportController : Controller // 每一行:發票日期、發票號碼、發票金額 table.AddCell(new Cell().Add(new Paragraph(invoice.invoiceDate?.ToString("yyyy-MM-dd") ?? "")).SetTextAlignment(TextAlignment.CENTER)); table.AddCell(new Cell().Add(new Paragraph(invoice.invoiceNo ?? "")).SetTextAlignment(TextAlignment.CENTER)); - table.AddCell(new Cell().Add(new Paragraph(invoice.invoiceAmount.ToString("N0"))).SetTextAlignment(TextAlignment.CENTER)); + table.AddCell(new Cell().Add(new Paragraph($"NT$ {invoice.invoiceAmount:N0}")).SetTextAlignment(TextAlignment.CENTER)); if (isFirstRow) { // 合併欄位:折扣單位、折扣金額、折扣時間、入場時間、出場時間、停車金額、請款金額 table.AddCell(new Cell(rowSpan, 1).Add(new Paragraph(group.discountUnit ?? "")).SetTextAlignment(TextAlignment.CENTER).SetVerticalAlignment(VerticalAlignment.MIDDLE)); - table.AddCell(new Cell(rowSpan, 1).Add(new Paragraph(group.discountAmount?.ToString("N0") ?? "")).SetTextAlignment(TextAlignment.CENTER).SetVerticalAlignment(VerticalAlignment.MIDDLE)); + table.AddCell(new Cell(rowSpan, 1).Add(new Paragraph($"NT$ {group.discountAmount:N0}")).SetTextAlignment(TextAlignment.CENTER).SetVerticalAlignment(VerticalAlignment.MIDDLE)); table.AddCell(new Cell(rowSpan, 1).Add(new Paragraph(group.discountTime.ToString("yyyy-MM-dd HH:mm"))).SetTextAlignment(TextAlignment.CENTER).SetVerticalAlignment(VerticalAlignment.MIDDLE)); table.AddCell(new Cell(rowSpan, 1).Add(new Paragraph(group.enterTime?.ToString("yyyy-MM-dd HH:mm") ?? "")).SetTextAlignment(TextAlignment.CENTER).SetVerticalAlignment(VerticalAlignment.MIDDLE)); table.AddCell(new Cell(rowSpan, 1).Add(new Paragraph(group.exitTime?.ToString("yyyy-MM-dd HH:mm") ?? "")).SetTextAlignment(TextAlignment.CENTER).SetVerticalAlignment(VerticalAlignment.MIDDLE)); - table.AddCell(new Cell(rowSpan, 1).Add(new Paragraph(group.parkingAmount?.ToString("N0") ?? "")).SetTextAlignment(TextAlignment.CENTER).SetVerticalAlignment(VerticalAlignment.MIDDLE)); - table.AddCell(new Cell(rowSpan, 1).Add(new Paragraph(group.claimAmount?.ToString("N0") ?? "")).SetTextAlignment(TextAlignment.CENTER).SetVerticalAlignment(VerticalAlignment.MIDDLE)); + table.AddCell(new Cell(rowSpan, 1).Add(new Paragraph($"NT$ {group.parkingAmount:N0}")).SetTextAlignment(TextAlignment.CENTER).SetVerticalAlignment(VerticalAlignment.MIDDLE)); + table.AddCell(new Cell(rowSpan, 1).Add(new Paragraph($"NT$ {group.claimAmount:N0}")).SetTextAlignment(TextAlignment.CENTER).SetVerticalAlignment(VerticalAlignment.MIDDLE)); } } } diff --git a/Program.cs b/Program.cs index e724ad9..4e837da 100644 --- a/Program.cs +++ b/Program.cs @@ -24,11 +24,12 @@ builder.Services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationSc { options.LoginPath = "/Home/Index"; options.AccessDeniedPath = "/Home/Index"; + options.Cookie.Name = "CouponReport.Auth"; // 設定 Cookie 名稱 options.Cookie.HttpOnly = true; options.Cookie.IsEssential = true; options.Cookie.SameSite = SameSiteMode.Strict; options.SlidingExpiration = true; - options.Cookie.Expiration = null; + options.ExpireTimeSpan = TimeSpan.FromMinutes(15); // 設定15分鐘後過期 }); // Add services to the container. @@ -37,6 +38,7 @@ builder.Services.AddSession(options => { options.Cookie.HttpOnly = true; options.Cookie.IsEssential = true; + options.IdleTimeout = TimeSpan.FromMinutes(15); // Session 15分鐘後過期 }); var app = builder.Build(); diff --git a/Views/Report/Index.cshtml b/Views/Report/Index.cshtml index 9c85580..5528f53 100644 --- a/Views/Report/Index.cshtml +++ b/Views/Report/Index.cshtml @@ -56,6 +56,13 @@ .group-row-odd { background-color: #ffffff; } + .table th, .table td { + text-align: center; + vertical-align: middle; + } + .text-right { + text-align: right !important; + }
@@ -100,25 +107,25 @@ @if (isNewGroup) { - @item.RowNumber + @item.RowNumber } @item.TenantCode @if (isNewGroup) { - @item.CarNumber + @item.CarNumber } - @item.InvoiceDate?.ToString("yyyy-MM-dd HH:mm:ss") + @item.InvoiceDate?.ToString("yyyy-MM-dd") @item.InvoiceNumber - @item.InvoiceAmount?.ToString("N0") + NT$ @item.InvoiceAmount?.ToString("N0") @if (isNewGroup) { - @item.DiscountUnit - @item.DiscountAmount?.ToString("N0") - @item.DiscountTime?.ToString("yyyy-MM-dd HH:mm:ss") - @item.EnterTime?.ToString("yyyy-MM-dd HH:mm:ss") - @item.ExitTime?.ToString("yyyy-MM-dd HH:mm:ss") - @item.ParkingAmount?.ToString("N0") - @item.ClaimAmount?.ToString("N0") + @item.DiscountUnit + NT$ @item.DiscountAmount?.ToString("N0") + @item.DiscountTime?.ToString("yyyy-MM-dd HH:mm:ss") + @item.EnterTime?.ToString("yyyy-MM-dd HH:mm:ss") + @item.ExitTime?.ToString("yyyy-MM-dd HH:mm:ss") + NT$ @item.ParkingAmount?.ToString("N0") + NT$ @item.ClaimAmount?.ToString("N0") } } diff --git a/Views/Shared/_Layout.cshtml b/Views/Shared/_Layout.cshtml index ced9d98..27f883b 100644 --- a/Views/Shared/_Layout.cshtml +++ b/Views/Shared/_Layout.cshtml @@ -12,7 +12,18 @@