783 lines
31 KiB
C#
783 lines
31 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Web;
|
|
using System.Web.Script.Services;
|
|
using System.Web.Services;
|
|
using System.Data;
|
|
using System.Data.Common;
|
|
using System.IO;
|
|
using WebLib;
|
|
using Newtonsoft.Json;
|
|
using NPOI.SS.UserModel;
|
|
using NPOI.XSSF.UserModel;
|
|
|
|
namespace Education.Services
|
|
{
|
|
[WebService(Namespace = "http://tempuri.org/")]
|
|
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
|
|
[System.ComponentModel.ToolboxItem(false)]
|
|
[ScriptService]
|
|
public class 火車票價維護 : ServiceBase
|
|
{
|
|
[WebMethod(EnableSession = true)]
|
|
[ScriptMethod(ResponseFormat = ResponseFormat.Json)]
|
|
public ServiceResponse GetVersions()
|
|
{
|
|
try
|
|
{
|
|
DAC_火車票價 dac = new DAC_火車票價();
|
|
var versions = dac.查詢版本號List();
|
|
return ServiceResponse.CreateSuccess("取得版本清單成功", versions);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
return ServiceResponse.CreateError($"取得版本清單失敗:{ex.Message}");
|
|
}
|
|
}
|
|
|
|
[WebMethod(EnableSession = true)]
|
|
[ScriptMethod(ResponseFormat = ResponseFormat.Json)]
|
|
public ServiceResponse GetFareTable(int versionId)
|
|
{
|
|
try
|
|
{
|
|
DAC_火車票價 dac = new DAC_火車票價();
|
|
var data = dac.查詢票價表(versionId);
|
|
|
|
if (data.Count == 0)
|
|
{
|
|
return ServiceResponse.CreateSuccess("無資料", new
|
|
{
|
|
originStations = new List<string>(),
|
|
destStations = new List<string>(),
|
|
fares = new Dictionary<string, int>()
|
|
});
|
|
}
|
|
|
|
// 取得所有起站和訖站
|
|
var originStations = data.OrderBy(x => x.起站站碼).Select(x => x.起站).Distinct().ToList();
|
|
var destStations = data.OrderBy(x => x.迄站站碼).Select(x => x.迄站).Distinct().ToList();
|
|
|
|
// 起訖站由北至南排序
|
|
|
|
|
|
|
|
|
|
// 建立票價字典
|
|
var fares = new Dictionary<string, int>();
|
|
foreach (var item in data)
|
|
{
|
|
var key = $"{item.起站}_{item.迄站}";
|
|
fares[key] = item.票價;
|
|
}
|
|
|
|
return ServiceResponse.CreateSuccess("取得票價表成功", new
|
|
{
|
|
originStations = originStations,
|
|
destStations = destStations,
|
|
fares = fares
|
|
});
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
return ServiceResponse.CreateError($"取得票價表失敗:{ex.Message}");
|
|
}
|
|
}
|
|
|
|
[WebMethod(EnableSession = true)]
|
|
[ScriptMethod(ResponseFormat = ResponseFormat.Json)]
|
|
public ServiceResponse SaveFareTable(int versionId, string fares)
|
|
{
|
|
try
|
|
{
|
|
Dictionary<string, int> faresDict = JsonConvert.DeserializeObject<Dictionary<string, int>>(fares);
|
|
|
|
using (var ts = DAC.NewTransactionScope())
|
|
{
|
|
using (var conn = DAC.NewConnection())
|
|
{
|
|
DAC_火車票價 dac = new DAC_火車票價(conn);
|
|
|
|
// 刪除原有的版本資料
|
|
var existingData = dac.Select(noInputReturnAll: true, 版本號: versionId, 起站: null, 迄站: null);
|
|
|
|
// 保存原有的生效日期(應該所有同版本的記錄生效日期都一樣)
|
|
DateTime effectiveDate = existingData.Count > 0 ? existingData[0].生效日期 : DateTime.Today;
|
|
|
|
foreach (var item in existingData)
|
|
{
|
|
dac.DeleteOne(item.編號, item.DB_APPNO);
|
|
}
|
|
|
|
// 新增更新後的資料,使用保存的生效日期
|
|
foreach (var kvp in faresDict)
|
|
{
|
|
var parts = kvp.Key.Split('_');
|
|
if (parts.Length != 2) continue;
|
|
|
|
var origin = parts[0];
|
|
var destination = parts[1];
|
|
|
|
if (origin == destination) continue; // 跳過同站
|
|
|
|
var newItem = new 火車票價Item
|
|
{
|
|
版本號 = versionId,
|
|
生效日期 = effectiveDate,
|
|
起站 = origin,
|
|
迄站 = destination,
|
|
票價 = kvp.Value
|
|
};
|
|
|
|
dac.InsertOne(newItem);
|
|
}
|
|
|
|
ts.Complete();
|
|
}
|
|
}
|
|
|
|
return ServiceResponse.CreateSuccess("儲存成功");
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
return ServiceResponse.CreateError($"儲存失敗:{ex.Message}");
|
|
}
|
|
}
|
|
|
|
[WebMethod(EnableSession = true)]
|
|
[ScriptMethod(ResponseFormat = ResponseFormat.Json)]
|
|
public ServiceResponse CreateNewVersion(int versionId)
|
|
{
|
|
try
|
|
{
|
|
// 只保留年月日,不要時間
|
|
DateTime effectiveDate = PublicVariable.TaiwanNow.Date;
|
|
|
|
using (var ts = DAC.NewTransactionScope())
|
|
{
|
|
using (var conn = DAC.NewConnection())
|
|
{
|
|
DAC_火車票價 dac = new DAC_火車票價(conn);
|
|
|
|
// 檢查版本是否已存在
|
|
var existingData = dac.Select(noInputReturnAll: true, 版本號: versionId, 起站: null, 迄站: null);
|
|
if (existingData.Count > 0)
|
|
{
|
|
return ServiceResponse.CreateError($"版本 {versionId} 已存在");
|
|
}
|
|
|
|
// 建立預設車站清單(使用現有最新版本的車站)
|
|
var latestVersion = dac.SelectAll().GroupBy(x => x.版本號).OrderByDescending(x => x.Key).FirstOrDefault();
|
|
if (latestVersion != null)
|
|
{
|
|
// 複製最新版本的結構(但票價為零)
|
|
var stations = latestVersion.Select(x => x.起站).Distinct().ToList();
|
|
foreach (var origin in stations)
|
|
{
|
|
foreach (var dest in stations)
|
|
{
|
|
if (origin != dest)
|
|
{
|
|
var newItem = new 火車票價Item
|
|
{
|
|
版本號 = versionId,
|
|
生效日期 = effectiveDate,
|
|
起站 = origin,
|
|
迄站 = dest,
|
|
票價 = 0
|
|
};
|
|
dac.InsertOne(newItem);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
ts.Complete();
|
|
}
|
|
}
|
|
|
|
return ServiceResponse.CreateSuccess("新版本建立成功");
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
return ServiceResponse.CreateError($"建立新版本失敗:{ex.Message}");
|
|
}
|
|
}
|
|
|
|
[WebMethod(EnableSession = true)]
|
|
[ScriptMethod(ResponseFormat = ResponseFormat.Json)]
|
|
public ServiceResponse DeleteVersion(int versionId)
|
|
{
|
|
try
|
|
{
|
|
using (var ts = DAC.NewTransactionScope())
|
|
{
|
|
using (var conn = DAC.NewConnection())
|
|
{
|
|
DAC_火車票價 dac = new DAC_火車票價(conn);
|
|
|
|
// 刪除該版本的所有資料
|
|
var existingData = dac.Select(noInputReturnAll: true, 版本號: versionId, 起站: null, 迄站: null);
|
|
foreach (var item in existingData)
|
|
{
|
|
dac.DeleteOne(item.編號, item.DB_APPNO);
|
|
}
|
|
|
|
ts.Complete();
|
|
}
|
|
}
|
|
|
|
return ServiceResponse.CreateSuccess("版本刪除成功");
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
return ServiceResponse.CreateError($"版本刪除失敗:{ex.Message}");
|
|
}
|
|
}
|
|
|
|
[WebMethod(EnableSession = true)]
|
|
[ScriptMethod(ResponseFormat = ResponseFormat.Json)]
|
|
public ServiceResponse ExportFareData(int versionId)
|
|
{
|
|
try
|
|
{
|
|
DAC_火車票價 dac = new DAC_火車票價();
|
|
var data = dac.Select(noInputReturnAll: true, 版本號: versionId, 起站: null, 迄站: null);
|
|
|
|
List<string> originStations;
|
|
List<string> destStations;
|
|
var fares = new Dictionary<string, int>();
|
|
|
|
if (data.Count == 0)
|
|
{
|
|
// 指定版本沒有資料,嘗試從其他版本取得車站清單
|
|
var allData = dac.SelectAll();
|
|
if (allData.Count == 0)
|
|
{
|
|
// 完全沒有任何資料,使用預設車站清單
|
|
originStations = GetDefaultOriginStations();
|
|
destStations = GetDefaultDestStations();
|
|
}
|
|
else
|
|
{
|
|
// 使用現有版本的車站清單(會包含所有現有版本出現過的車站)
|
|
originStations = allData.Select(x => x.起站).Distinct().ToList();
|
|
destStations = allData.Select(x => x.迄站).Distinct().ToList();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// 取得該版本的起站和訖站
|
|
originStations = data.Select(x => x.起站).Distinct().ToList();
|
|
destStations = data.Select(x => x.迄站).Distinct().ToList();
|
|
|
|
// 建立票價字典
|
|
foreach (var item in data)
|
|
{
|
|
var key = $"{item.起站}_{item.迄站}";
|
|
fares[key] = item.票價;
|
|
}
|
|
}
|
|
|
|
// 建立 Excel 檔案
|
|
var excelData = CreateFareExcel(originStations, destStations, fares, versionId);
|
|
|
|
var response = new
|
|
{
|
|
Data = new
|
|
{
|
|
originStations = originStations,
|
|
destStations = destStations,
|
|
fares = fares
|
|
},
|
|
ExcelData = excelData,
|
|
Success = true,
|
|
Message = "匯出成功"
|
|
};
|
|
|
|
return ServiceResponse.CreateSuccess("匯出成功", response);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
return ServiceResponse.CreateError($"匯出失敗:{ex.Message}");
|
|
}
|
|
}
|
|
|
|
[WebMethod(EnableSession = true)]
|
|
[ScriptMethod(ResponseFormat = ResponseFormat.Json)]
|
|
public ServiceResponse GetExcelTemplate()
|
|
{
|
|
try
|
|
{
|
|
// 建立預設車站清單
|
|
var originStations = GetDefaultOriginStations();
|
|
var destStations = GetDefaultDestStations();
|
|
|
|
// 建立空的 Excel 範本
|
|
var excelData = CreateFareExcel(originStations, destStations, new Dictionary<string, int>(), 0, isTemplate: true);
|
|
|
|
return ServiceResponse.CreateSuccess("取得範本成功", excelData);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
return ServiceResponse.CreateError($"取得範本失敗:{ex.Message}");
|
|
}
|
|
}
|
|
|
|
private List<string> GetDefaultOriginStations()
|
|
{
|
|
return new List<string>
|
|
{
|
|
"台北", "桃園", "中壢", "埔心", "楊梅", "竹北", "新竹", "竹南", "苗栗",
|
|
"花蓮", "豐原", "清水", "台中"
|
|
};
|
|
}
|
|
|
|
private List<string> GetDefaultDestStations()
|
|
{
|
|
return new List<string>
|
|
{
|
|
"基隆", "八堵", "七堵", "汐止", "南港", "松山", "台北", "板橋", "樹林",
|
|
"鶯歌", "桃園", "中壢", "楊梅", "竹北", "新竹", "竹東", "竹南", "苗栗",
|
|
"豐原", "大甲", "清水", "台中", "沙鹿", "彰化", "員林", "田中", "二水",
|
|
"斗六", "斗南", "嘉義", "新營", "善化", "台南", "岡山", "高雄", "屏東"
|
|
};
|
|
}
|
|
|
|
private string CreateFareExcel(List<string> originStations, List<string> destStations,
|
|
Dictionary<string, int> fares, int versionId, bool isTemplate = false)
|
|
{
|
|
XSSFWorkbook workbook = new XSSFWorkbook();
|
|
try
|
|
{
|
|
var sheet = workbook.CreateSheet("火車票價");
|
|
|
|
// 設定列寬
|
|
sheet.SetColumnWidth(0, 3500);
|
|
for (int i = 1; i <= originStations.Count; i++)
|
|
{
|
|
sheet.SetColumnWidth(i, 2500);
|
|
}
|
|
|
|
// 設定標題列(橫軸為起站)
|
|
var headerRow = sheet.CreateRow(0);
|
|
headerRow.CreateCell(0).SetCellValue("訖站\\起站");
|
|
for (int i = 0; i < originStations.Count; i++)
|
|
{
|
|
headerRow.CreateCell(i + 1).SetCellValue(originStations[i]);
|
|
}
|
|
|
|
// 設定資料列(縱軸為訖站)
|
|
for (int i = 0; i < destStations.Count; i++)
|
|
{
|
|
var row = sheet.CreateRow(i + 1);
|
|
row.CreateCell(0).SetCellValue(destStations[i]);
|
|
|
|
for (int j = 0; j < originStations.Count; j++)
|
|
{
|
|
var cell = row.CreateCell(j + 1);
|
|
|
|
if (originStations[j] == destStations[i])
|
|
{
|
|
// 同站,不填票價
|
|
cell.SetCellValue("");
|
|
}
|
|
else
|
|
{
|
|
var key = $"{originStations[j]}_{destStations[i]}";
|
|
if (fares.ContainsKey(key))
|
|
{
|
|
cell.SetCellValue(fares[key]);
|
|
}
|
|
else if (!isTemplate)
|
|
{
|
|
cell.SetCellValue("");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// 轉換為 Base64
|
|
using (var ms = new MemoryStream())
|
|
{
|
|
workbook.Write(ms);
|
|
return Convert.ToBase64String(ms.ToArray());
|
|
}
|
|
}
|
|
finally
|
|
{
|
|
workbook.Close();
|
|
}
|
|
}
|
|
|
|
[WebMethod(EnableSession = true)]
|
|
[ScriptMethod(ResponseFormat = ResponseFormat.Json)]
|
|
public ServiceResponse ImportFareData(string filePath)
|
|
{
|
|
try
|
|
{
|
|
// 驗證檔案路徑
|
|
if (string.IsNullOrEmpty(filePath) || !File.Exists(filePath))
|
|
{
|
|
return ServiceResponse.CreateError("檔案不存在或已過期");
|
|
}
|
|
|
|
// 在迴圈外取得當前日期,只保留年月日
|
|
DateTime effectiveDate = PublicVariable.TaiwanNow.Date;
|
|
|
|
// 從檔案讀取並驗證資料
|
|
var fares = new Dictionary<string, int>();
|
|
var originStations = new List<string>();
|
|
var destStations = new List<string>();
|
|
|
|
using (var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read))
|
|
{
|
|
IWorkbook workbook = null;
|
|
|
|
try
|
|
{
|
|
fileStream.Position = 0;
|
|
workbook = new XSSFWorkbook(fileStream);
|
|
}
|
|
catch
|
|
{
|
|
DeleteUploadedFile(filePath);
|
|
return ServiceResponse.CreateError("檔案格式錯誤");
|
|
}
|
|
|
|
if (workbook == null || workbook.NumberOfSheets == 0)
|
|
{
|
|
DeleteUploadedFile(filePath);
|
|
return ServiceResponse.CreateError("Excel 檔案格式錯誤");
|
|
}
|
|
|
|
var sheet = workbook.GetSheetAt(0);
|
|
if (sheet == null || sheet.PhysicalNumberOfRows == 0)
|
|
{
|
|
DeleteUploadedFile(filePath);
|
|
return ServiceResponse.CreateError("Excel 工作表為空");
|
|
}
|
|
|
|
// 讀取標題列
|
|
var headerRow = sheet.GetRow(0);
|
|
if (headerRow == null)
|
|
{
|
|
DeleteUploadedFile(filePath);
|
|
return ServiceResponse.CreateError("Excel 缺少標題列");
|
|
}
|
|
|
|
// 取得起站列表(橫軸為起站,從第二欄開始)
|
|
for (int i = 1; i < headerRow.PhysicalNumberOfCells; i++)
|
|
{
|
|
var cell = headerRow.GetCell(i);
|
|
if (cell != null && !string.IsNullOrEmpty(cell.StringCellValue))
|
|
{
|
|
originStations.Add(cell.StringCellValue);
|
|
}
|
|
}
|
|
|
|
// 讀取資料列(縱軸為訖站,第一欄為訖站)
|
|
for (int rowIdx = 1; rowIdx <= sheet.LastRowNum; rowIdx++)
|
|
{
|
|
var row = sheet.GetRow(rowIdx);
|
|
if (row == null) continue;
|
|
|
|
// 第一欄是訖站
|
|
var destCell = row.GetCell(0);
|
|
if (destCell == null || string.IsNullOrEmpty(destCell.StringCellValue))
|
|
continue;
|
|
|
|
string dest = destCell.StringCellValue;
|
|
destStations.Add(dest);
|
|
|
|
// 從第二欄開始是票價,對應起站(橫軸)
|
|
for (int colIdx = 1; colIdx <= originStations.Count; colIdx++)
|
|
{
|
|
var fareCell = row.GetCell(colIdx);
|
|
string origin = originStations[colIdx - 1];
|
|
|
|
if (origin == dest)
|
|
continue; // 跳過同站
|
|
|
|
if (fareCell != null && fareCell.CellType != CellType.Blank)
|
|
{
|
|
try
|
|
{
|
|
int fare = (int)fareCell.NumericCellValue;
|
|
if (fare >= 0)
|
|
{
|
|
var key = $"{origin}_{dest}";
|
|
fares[key] = fare;
|
|
}
|
|
}
|
|
catch
|
|
{
|
|
// 忽略格式錯誤的單元格
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// 執行匯入 - 只有新增模式,自動產生新版本號
|
|
using (var ts = DAC.NewTransactionScope())
|
|
{
|
|
using (var conn = DAC.NewConnection())
|
|
{
|
|
DAC_火車票價 dac = new DAC_火車票價(conn);
|
|
|
|
// 取得下一個版本號
|
|
int targetVersionId = 1;
|
|
var allVersions = dac.SelectAll();
|
|
if (allVersions.Count > 0)
|
|
{
|
|
targetVersionId = allVersions.Max(x => x.版本號) + 1;
|
|
}
|
|
|
|
// 新增資料(使用迴圈外取得的 effectiveDate,只保留年月日)
|
|
foreach (var kvp in fares)
|
|
{
|
|
var parts = kvp.Key.Split('_');
|
|
if (parts.Length != 2) continue;
|
|
|
|
var origin = parts[0];
|
|
var destination = parts[1];
|
|
|
|
if (origin == destination) continue; // 跳過同站
|
|
|
|
var newItem = new 火車票價Item
|
|
{
|
|
版本號 = targetVersionId,
|
|
生效日期 = effectiveDate, // 使用迴圈外的年月日
|
|
起站 = origin,
|
|
迄站 = destination,
|
|
票價 = kvp.Value
|
|
};
|
|
|
|
dac.InsertOne(newItem);
|
|
}
|
|
|
|
ts.Complete();
|
|
}
|
|
}
|
|
|
|
// 匯入成功後刪除上傳的臨時檔案
|
|
DeleteUploadedFile(filePath);
|
|
|
|
return ServiceResponse.CreateSuccess("匯入成功");
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
// 匯入失敗也刪除上傳的檔案
|
|
if (!string.IsNullOrEmpty(filePath))
|
|
{
|
|
DeleteUploadedFile(filePath);
|
|
}
|
|
return ServiceResponse.CreateError($"匯入失敗:{ex.Message}");
|
|
}
|
|
}
|
|
|
|
[WebMethod(EnableSession = true)]
|
|
[ScriptMethod(ResponseFormat = ResponseFormat.Json)]
|
|
public ServiceResponse ValidateImportFile(string filePath)
|
|
{
|
|
try
|
|
{
|
|
if (string.IsNullOrEmpty(filePath) || !File.Exists(filePath))
|
|
{
|
|
return ServiceResponse.CreateError("檔案不存在");
|
|
}
|
|
|
|
var fares = new Dictionary<string, int>();
|
|
var originStations = new List<string>();
|
|
var destStations = new List<string>();
|
|
var errors = new List<string>();
|
|
int rowCount = 0;
|
|
|
|
using (var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read))
|
|
{
|
|
IWorkbook workbook = null;
|
|
|
|
// 嘗試讀取為 XLSX
|
|
try
|
|
{
|
|
fileStream.Position = 0;
|
|
workbook = new XSSFWorkbook(fileStream);
|
|
}
|
|
catch
|
|
{
|
|
// 檔案格式錯誤,刪除上傳的檔案
|
|
DeleteUploadedFile(filePath);
|
|
return ServiceResponse.CreateError("只支援 .xlsx 格式的 Excel 檔案");
|
|
}
|
|
|
|
if (workbook == null || workbook.NumberOfSheets == 0)
|
|
{
|
|
// 檔案格式錯誤,刪除上傳的檔案
|
|
DeleteUploadedFile(filePath);
|
|
return ServiceResponse.CreateError("Excel 檔案格式錯誤");
|
|
}
|
|
|
|
var sheet = workbook.GetSheetAt(0);
|
|
if (sheet == null || sheet.PhysicalNumberOfRows == 0)
|
|
{
|
|
// 工作表為空,刪除上傳的檔案
|
|
DeleteUploadedFile(filePath);
|
|
return ServiceResponse.CreateError("Excel 工作表為空");
|
|
}
|
|
|
|
// 讀取標題列
|
|
var headerRow = sheet.GetRow(0);
|
|
if (headerRow == null)
|
|
{
|
|
// 標題列缺失,刪除上傳的檔案
|
|
DeleteUploadedFile(filePath);
|
|
return ServiceResponse.CreateError("Excel 缺少標題列");
|
|
}
|
|
|
|
// 取得起站列表(橫軸為起站,從第二欄開始)
|
|
for (int i = 1; i < headerRow.PhysicalNumberOfCells; i++)
|
|
{
|
|
var cell = headerRow.GetCell(i);
|
|
if (cell != null && !string.IsNullOrEmpty(cell.StringCellValue))
|
|
{
|
|
originStations.Add(cell.StringCellValue);
|
|
}
|
|
}
|
|
|
|
// 讀取資料列(縱軸為訖站,第一欄為訖站)
|
|
for (int rowIdx = 1; rowIdx <= sheet.LastRowNum; rowIdx++)
|
|
{
|
|
var row = sheet.GetRow(rowIdx);
|
|
if (row == null) continue;
|
|
|
|
// 第一欄是訖站
|
|
var destCell = row.GetCell(0);
|
|
if (destCell == null || string.IsNullOrEmpty(destCell.StringCellValue))
|
|
continue;
|
|
|
|
string dest = destCell.StringCellValue;
|
|
destStations.Add(dest);
|
|
|
|
// 從第二欄開始是票價,對應起站(橫軸)
|
|
for (int colIdx = 1; colIdx <= originStations.Count; colIdx++)
|
|
{
|
|
var fareCell = row.GetCell(colIdx);
|
|
string origin = originStations[colIdx - 1];
|
|
|
|
if (origin == dest)
|
|
continue; // 跳過同站
|
|
|
|
if (fareCell != null && fareCell.CellType != CellType.Blank)
|
|
{
|
|
try
|
|
{
|
|
int fare = (int)fareCell.NumericCellValue;
|
|
if (fare < 0)
|
|
{
|
|
errors.Add($"第 {rowIdx + 1} 列,{origin} 到 {dest} 的票價不能為負數");
|
|
}
|
|
else
|
|
{
|
|
var key = $"{origin}_{dest}";
|
|
fares[key] = fare;
|
|
}
|
|
}
|
|
catch
|
|
{
|
|
errors.Add($"第 {rowIdx + 1} 列,{origin} 到 {dest} 的票價格式不正確");
|
|
}
|
|
}
|
|
}
|
|
|
|
rowCount++;
|
|
}
|
|
}
|
|
|
|
if (errors.Count > 0)
|
|
{
|
|
// 驗證失敗,刪除上傳的檔案
|
|
DeleteUploadedFile(filePath);
|
|
return ServiceResponse.CreateSuccess("檔案驗證失敗", new
|
|
{
|
|
Errors = errors,
|
|
RowCount = 0
|
|
});
|
|
}
|
|
|
|
return ServiceResponse.CreateSuccess("檔案驗證成功", new
|
|
{
|
|
Fares = fares,
|
|
OriginStations = originStations.Distinct().ToList(),
|
|
DestStations = destStations.Distinct().ToList(),
|
|
Errors = new List<string>()
|
|
});
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
// 驗證異常,刪除上傳的檔案
|
|
if (!string.IsNullOrEmpty(filePath))
|
|
{
|
|
DeleteUploadedFile(filePath);
|
|
}
|
|
return ServiceResponse.CreateError($"驗證檔案失敗:{ex.Message}");
|
|
}
|
|
}
|
|
|
|
private void DeleteUploadedFile(string filePath)
|
|
{
|
|
if (string.IsNullOrEmpty(filePath))
|
|
{
|
|
return;
|
|
}
|
|
|
|
try
|
|
{
|
|
// 刪除指定的檔案
|
|
if (File.Exists(filePath))
|
|
{
|
|
File.Delete(filePath);
|
|
}
|
|
|
|
// 清理所有 TrainFareImport_*.xlsx 格式的檔案
|
|
string uploadDir = Path.Combine(HttpContext.Current.Server.MapPath("~/"), "DocUpload");
|
|
if (Directory.Exists(uploadDir))
|
|
{
|
|
try
|
|
{
|
|
var searchPattern = "TrainFareImport_*.xlsx";
|
|
var oldFiles = Directory.GetFiles(uploadDir, searchPattern);
|
|
|
|
foreach (var oldFile in oldFiles)
|
|
{
|
|
try
|
|
{
|
|
// 刪除30分鐘以前的檔案
|
|
var fileInfo = new FileInfo(oldFile);
|
|
if (DateTime.Now - fileInfo.LastWriteTime > TimeSpan.FromMinutes(30))
|
|
{
|
|
File.Delete(oldFile);
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
System.Diagnostics.Debug.WriteLine($"清理舊檔案失敗:{oldFile} - {ex.Message}");
|
|
}
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
System.Diagnostics.Debug.WriteLine($"掃描清理檔案失敗:{ex.Message}");
|
|
}
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
// 記錄刪除失敗但不拋出例外
|
|
System.Diagnostics.Debug.WriteLine($"刪除上傳檔案失敗:{filePath} - {ex.Message}");
|
|
}
|
|
}
|
|
}
|
|
}
|