DCS/ruiyiweiUX/Assets/Scripts/Views/BFIHistoryExportPanel.cs

1090 lines
35 KiB
C#
Raw Normal View History

2026-06-09 13:59:11 +08:00
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEngine.UI;
using TMPro;
/// <summary>
/// BFI历史记录和数据导出UI面板
/// 提供历史记录查看、搜索、选择和导出功能
/// </summary>
public class BFIHistoryExportPanel : BasePanel
{
[Header("UI引用")]
[SerializeField] private Transform historyListParent;
[SerializeField] private GameObject historyItemPrefab;
[SerializeField] private ScrollRect historyScrollRect;
[SerializeField] private TMP_InputField searchInputField;
[SerializeField] private KeyboardLayout searchKeyboardLayout = KeyboardLayout.Pinyin;
[SerializeField] private Button searchButton;
[SerializeField] private Button clearRecordButton;
[Header("过滤器")]
[SerializeField] private TMP_Dropdown dateFilterDropdown;
[SerializeField] private TMP_InputField startDateInput;
[SerializeField] private TMP_InputField endDateInput;
[SerializeField] private Button applyDateFilterButton;
[Header("选择控制")]
[SerializeField] private Toggle selectAllToggle;
// [SerializeField] private Button selectTodayButton;
// [SerializeField] private Button selectWeekButton;
// [SerializeField] private Button clearSelectionButton;
[SerializeField] private TextMeshProUGUI selectionCountText;
[Header("导出控制")]
[SerializeField] private TMP_Dropdown exportFormatDropdown;
[SerializeField] private Button exportSelectedButton;
[SerializeField] private Button exportAllButton;
[SerializeField] private Button previewButton;
[Header("通用按钮")]
public Button HomeButton;
public Button BackButton;
[Header("统计信息")]
[SerializeField] private TextMeshProUGUI totalRecordsText;
[SerializeField] private TextMeshProUGUI totalTestTimeText;
[SerializeField] private TextMeshProUGUI todayRecordsText;
[SerializeField] private TextMeshProUGUI weekRecordsText;
[SerializeField] private TextMeshProUGUI monthRecordsText;
[Header("状态显示")]
[SerializeField] private TextMeshProUGUI statusText;
// [SerializeField] private Slider progressSlider;
// [SerializeField] private GameObject loadingPanel;
private List<BFITestRecord> allRecords;
private List<BFITestRecord> filteredRecords;
private List<BFIHistoryItem> historyItems;
private Dictionary<string, BFIHistoryItem> historyItemsByRecordId;
private HashSet<string> selectedRecordIds;
private string lastExportedFilePath;
private string lastExportFailureMessage;
private Coroutine historyListBuildCoroutine;
private const int HISTORY_ITEMS_PER_FRAME = 20;
public override void Init()
{
allRecords = new List<BFITestRecord>();
filteredRecords = new List<BFITestRecord>();
historyItems = new List<BFIHistoryItem>();
historyItemsByRecordId = new Dictionary<string, BFIHistoryItem>();
selectedRecordIds = new HashSet<string>();
InitializeUI();
LoadHistoryRecords();
UpdateStatistics();
// 订阅历史管理器事件
if (BFIHistoryManager.Instance != null)
{
BFIHistoryManager.Instance.OnRecordAdded += OnRecordAdded;
BFIHistoryManager.Instance.OnRecordUpdated += OnRecordUpdated;
BFIHistoryManager.Instance.OnRecordRemoved += OnRecordRemoved;
BFIHistoryManager.Instance.OnHistoryLoaded += OnHistoryLoaded;
}
}
private void OnDestroy()
{
StopHistoryListBuildCoroutine();
HideCustomKeyboardIfNeeded();
// 取消订阅事件
if (BFIHistoryManager.Instance != null)
{
BFIHistoryManager.Instance.OnRecordAdded -= OnRecordAdded;
BFIHistoryManager.Instance.OnRecordUpdated -= OnRecordUpdated;
BFIHistoryManager.Instance.OnRecordRemoved -= OnRecordRemoved;
BFIHistoryManager.Instance.OnHistoryLoaded -= OnHistoryLoaded;
}
}
private void InitializeUI()
{
// 搜索功能
if (searchButton != null)
searchButton.onClick.AddListener(OnSearchClicked);
if (searchInputField != null)
{
searchInputField.onEndEdit.AddListener(OnSearchInputChanged);
SetupSearchCustomKeyboard();
}
// 日期过滤
if (applyDateFilterButton != null)
applyDateFilterButton.onClick.AddListener(OnApplyDateFilter);
// 选择控制
if (selectAllToggle != null){
selectAllToggle.onValueChanged.AddListener(OnSelectAllToggled);
selectAllToggle.isOn = false;
}
// 清空记录
if (clearRecordButton != null)
clearRecordButton.onClick.AddListener(OnClearClicked);
// 导出控制
if (exportSelectedButton != null)
exportSelectedButton.onClick.AddListener(OnExportSelectedClicked);
if (exportAllButton != null)
exportAllButton.onClick.AddListener(OnExportAllClicked);
if (previewButton != null)
previewButton.onClick.AddListener(OnPreviewClicked);
// 通用按钮
if (HomeButton != null)
HomeButton.onClick.AddListener(() =>
{
HideCustomKeyboardIfNeeded();
ReturnToHome();
});
if (BackButton != null)
BackButton.onClick.AddListener(() =>
{
HideCustomKeyboardIfNeeded();
ClosePanel();
});
// 初始化下拉菜单
InitializeDropdowns();
// 设置默认日期
if (startDateInput != null)
startDateInput.text = DateTime.Today.AddDays(-7).ToString("yyyy-MM-dd");
if (endDateInput != null)
endDateInput.text = DateTime.Today.ToString("yyyy-MM-dd");
}
private void InitializeDropdowns()
{
// 日期过滤下拉菜单
if (dateFilterDropdown != null)
{
dateFilterDropdown.ClearOptions();
dateFilterDropdown.AddOptions(new List<string>
{
"全部时间",
"今天",
"本周",
"本月",
// "自定义日期范围"
});
dateFilterDropdown.SetValueWithoutNotify(0);
dateFilterDropdown.RefreshShownValue();
}
// 导出格式下拉菜单
if (exportFormatDropdown != null)
{
exportFormatDropdown.ClearOptions();
exportFormatDropdown.AddOptions(new List<string>
{
"文本报告",
"CSV数据",
"PDF报告",
});
}
}
private void SetupSearchCustomKeyboard()
{
if (searchInputField == null)
{
return;
}
if (CustomKeyboardManager.Instance == null)
{
Debug.LogWarning("BFI导出搜索框未找到CustomKeyboardManager保留默认输入方式");
return;
}
CustomKeyboardManager.SetupInputField(searchInputField, searchKeyboardLayout,
(newValue) =>
{
searchInputField.text = newValue;
ApplySearch();
},
clearOnFirstInput: false);
}
private void HideCustomKeyboardIfNeeded()
{
if (CustomKeyboardManager.Instance != null && CustomKeyboardManager.Instance.IsKeyboardShowing())
{
CustomKeyboardManager.Instance.HideKeyboard();
}
}
private List<BFITestRecord> SortRecordsByRecentFirst(IEnumerable<BFITestRecord> records)
{
return (records ?? Enumerable.Empty<BFITestRecord>())
.Where(record => record != null)
.OrderByDescending(record => record.StartTime)
.ThenByDescending(record => record.EndTime)
.ToList();
}
private void LoadHistoryRecords()
{
try
{
UpdateStatus("正在加载历史记录...");
RecoverPendingRecordingJournal();
FlushCurrentRecordingSnapshot();
if (BFIHistoryManager.Instance != null)
{
allRecords = BFIHistoryManager.Instance.LoadHistoryRecordSummaries(false);
filteredRecords = SortRecordsByRecentFirst(allRecords);
RefreshHistoryList();
UpdateSelectionCount();
string historyPath = BFIHistoryManager.Instance.GetHistoryFilePath();
UpdateStatus(allRecords.Count > 0
? $"已加载 {allRecords.Count} 条历史记录"
: $"未找到已保存的BFI历史记录");
Debug.Log($"BFI历史索引路径: {historyPath}");
UpdateStatistics();
}
else
{
UpdateStatus("历史管理器未初始化");
}
}
catch (Exception ex)
{
Debug.LogError($"加载历史记录失败: {ex.Message}");
UpdateStatus($"加载失败: {ex.Message}");
}
}
private void FlushCurrentRecordingSnapshot()
{
try
{
var dataService = ServiceLocator.IsRegistered<IDataService>() ? ServiceLocator.Get<IDataService>() as DataService : null;
if (dataService != null)
{
dataService.FlushCurrentBFIRecordingSnapshot("打开BFI数据导出界面");
return;
}
DataService.Instance?.FlushCurrentBFIRecordingSnapshot("打开BFI数据导出界面");
}
catch (Exception ex)
{
Debug.LogWarning($"刷新当前BFI记录快照失败: {ex.Message}");
}
}
private void RecoverPendingRecordingJournal()
{
try
{
var dataService = ServiceLocator.IsRegistered<IDataService>() ? ServiceLocator.Get<IDataService>() as DataService : null;
if (dataService != null)
{
dataService.RecoverPendingBFIRecordingJournal("打开BFI数据导出界面");
return;
}
DataService.Instance?.RecoverPendingBFIRecordingJournal("打开BFI数据导出界面");
}
catch (Exception ex)
{
Debug.LogWarning($"恢复待保存BFI实时日志失败: {ex.Message}");
}
}
private void RefreshHistoryList()
{
StopHistoryListBuildCoroutine();
filteredRecords = SortRecordsByRecentFirst(filteredRecords);
if (historyItemsByRecordId == null)
{
historyItemsByRecordId = new Dictionary<string, BFIHistoryItem>();
}
if (historyScrollRect == null && historyListParent != null)
{
historyScrollRect = historyListParent.GetComponentInParent<ScrollRect>();
}
// 清空现有项目
foreach (var item in historyItems)
{
if (item != null && item.gameObject != null)
Destroy(item.gameObject);
}
historyItems.Clear();
historyItemsByRecordId.Clear();
MoveHistoryScrollToNewest();
UpdateSelectionCount();
historyListBuildCoroutine = StartCoroutine(BuildHistoryListGradually(filteredRecords));
}
private IEnumerator BuildHistoryListGradually(List<BFITestRecord> records)
{
var recordsToBuild = records != null ? new List<BFITestRecord>(records) : new List<BFITestRecord>();
for (int i = 0; i < recordsToBuild.Count; i++)
{
CreateHistoryItem(recordsToBuild[i]);
if ((i + 1) % HISTORY_ITEMS_PER_FRAME == 0)
{
UpdateSelectionCount();
yield return null;
}
}
historyListBuildCoroutine = null;
UpdateSelectionCount();
UpdateSelectAllToggle();
MoveHistoryScrollToNewest();
}
private void StopHistoryListBuildCoroutine()
{
if (historyListBuildCoroutine != null)
{
StopCoroutine(historyListBuildCoroutine);
historyListBuildCoroutine = null;
}
}
private void MoveHistoryScrollToNewest()
{
if (historyScrollRect == null)
{
return;
}
Canvas.ForceUpdateCanvases();
historyScrollRect.verticalNormalizedPosition = 1f;
}
private void CreateHistoryItem(BFITestRecord record)
{
if (historyItemPrefab == null || historyListParent == null)
return;
GameObject itemObj = Instantiate(historyItemPrefab, historyListParent);
BFIHistoryItem historyItem = itemObj.GetComponent<BFIHistoryItem>();
if (historyItem == null)
historyItem = itemObj.AddComponent<BFIHistoryItem>();
historyItem.Initialize(record);
historyItem.OnSelectionChanged += OnItemSelectionChanged;
historyItem.SetSelected(selectedRecordIds.Contains(record.TestId));
historyItems.Add(historyItem);
if (historyItemsByRecordId == null)
{
historyItemsByRecordId = new Dictionary<string, BFIHistoryItem>();
}
if (!string.IsNullOrEmpty(record.TestId))
{
historyItemsByRecordId[record.TestId] = historyItem;
}
}
private bool TryUpdateVisibleHistoryItem(BFITestRecord record)
{
if (record == null || string.IsNullOrEmpty(record.TestId))
{
return false;
}
int filteredIndex = filteredRecords.FindIndex(r => r != null && r.TestId == record.TestId);
if (filteredIndex < 0)
{
return false;
}
filteredRecords[filteredIndex] = record;
if (historyItemsByRecordId == null)
{
historyItemsByRecordId = new Dictionary<string, BFIHistoryItem>();
}
if (!historyItemsByRecordId.TryGetValue(record.TestId, out var historyItem) || historyItem == null)
{
historyItem = historyItems.FirstOrDefault(item => item != null && item.GetRecord()?.TestId == record.TestId);
if (historyItem == null)
{
return true;
}
historyItemsByRecordId[record.TestId] = historyItem;
}
historyItem.Initialize(record);
historyItem.SetSelected(selectedRecordIds.Contains(record.TestId));
UpdateSelectionCount();
UpdateSelectAllToggle();
return true;
}
private void OnItemSelectionChanged(string recordId, bool isSelected)
{
if (isSelected)
{
selectedRecordIds.Add(recordId);
}
else
{
selectedRecordIds.Remove(recordId);
}
UpdateSelectionCount();
UpdateSelectAllToggle();
}
private void UpdateSelectionCount()
{
if (selectionCountText != null)
{
int totalCount = filteredRecords?.Count ?? 0;
int visibleCount = historyItems?.Count ?? 0;
selectionCountText.text = visibleCount < totalCount
? $"已选择: {selectedRecordIds.Count} / {totalCount}(已显示 {visibleCount}"
: $"已选择: {selectedRecordIds.Count} / {totalCount}";
}
// 更新导出按钮状态
if (exportSelectedButton != null)
exportSelectedButton.interactable = selectedRecordIds.Count > 0;
}
private void UpdateSelectAllToggle()
{
if (selectAllToggle != null)
{
int filteredCount = filteredRecords?.Count ?? 0;
bool allSelected = filteredCount > 0 &&
filteredRecords.All(record => record != null && selectedRecordIds.Contains(record.TestId));
selectAllToggle.SetIsOnWithoutNotify(allSelected);
}
}
private void UpdateStatistics()
{
try
{
if (BFIHistoryManager.Instance != null)
{
var stats = BFIHistoryManager.Instance.GetHistoryStatistics();
if (totalRecordsText != null)
totalRecordsText.text = $"总记录数: {stats.TotalRecords}";
if (totalTestTimeText != null)
totalTestTimeText.text = $"总测试时间: {stats.TotalTestTime:F1} 分钟";
if (todayRecordsText != null)
todayRecordsText.text = $"今日: {stats.TodayRecords}";
if (weekRecordsText != null)
weekRecordsText.text = $"本周: {stats.WeekRecords}";
if (monthRecordsText != null)
monthRecordsText.text = $"本月: {stats.MonthRecords}";
}
}
catch (Exception ex)
{
Debug.LogError($"更新统计信息失败: {ex.Message}");
}
}
#region
private void OnSearchClicked()
{
ApplySearch();
}
private void OnClearSearchClicked()
{
if (searchInputField != null)
searchInputField.text = "";
ApplySearch();
}
// 清空所有测试数据
private void OnClearClicked()
{
// 显示确认对话框
ConfirmDialog.ShowDeleteConfirm(
"所有BFI历史记录",
() => ClearBFIRecordData(),
() => Debug.Log("取消清空记录")
);
}
public void ClearBFIRecordData()
{
try
{
if (BFIHistoryManager.Instance != null)
{
ResetCurrentRecordingAfterClear();
BFIHistoryManager.Instance.ClearHistory();
Debug.Log("BFIHistoryTestHelper: 测试数据已清空");
LoadHistoryRecords();
}
else
{
Debug.LogWarning("BFIHistoryTestHelper: BFIHistoryManager.Instance 为空");
}
}
catch (Exception ex)
{
Debug.LogError($"BFIHistoryTestHelper: 清空测试数据失败: {ex.Message}");
}
}
private void ResetCurrentRecordingAfterClear()
{
try
{
var dataService = ServiceLocator.IsRegistered<IDataService>() ? ServiceLocator.Get<IDataService>() as DataService : null;
if (dataService != null)
{
dataService.ResetCurrentBFIRecordingAfterHistoryClear("清空BFI历史记录");
return;
}
DataService.Instance?.ResetCurrentBFIRecordingAfterHistoryClear("清空BFI历史记录");
}
catch (Exception ex)
{
Debug.LogWarning($"清空后重置当前BFI记录失败: {ex.Message}");
}
}
private void OnSearchInputChanged(string searchText)
{
ApplySearch();
}
private void ApplySearch()
{
try
{
string searchText = searchInputField?.text ?? "";
if (string.IsNullOrEmpty(searchText))
{
filteredRecords = SortRecordsByRecentFirst(allRecords);
}
else if (BFIHistoryManager.Instance != null)
{
filteredRecords = SortRecordsByRecentFirst(BFIHistoryManager.Instance.SearchRecords(searchText));
}
RefreshHistoryList();
UpdateStatus($"搜索结果: {filteredRecords.Count} 条记录");
}
catch (Exception ex)
{
Debug.LogError($"搜索失败: {ex.Message}");
UpdateStatus($"搜索失败: {ex.Message}");
}
}
private void OnApplyDateFilter()
{
try
{
int filterIndex = dateFilterDropdown?.value ?? 0;
DateTime startDate, endDate;
switch (filterIndex)
{
case 0: // 全部时间
filteredRecords = SortRecordsByRecentFirst(allRecords);
break;
case 1: // 今天
startDate = DateTime.Today;
endDate = DateTime.Today.AddDays(1);
ApplyDateRangeFilter(startDate, endDate);
break;
case 2: // 本周
startDate = DateTime.Today.AddDays(-(int)DateTime.Today.DayOfWeek);
endDate = startDate.AddDays(7);
ApplyDateRangeFilter(startDate, endDate);
break;
case 3: // 本月
startDate = new DateTime(DateTime.Today.Year, DateTime.Today.Month, 1);
endDate = startDate.AddMonths(1);
ApplyDateRangeFilter(startDate, endDate);
break;
case 4: // 自定义日期范围
if (DateTime.TryParse(startDateInput?.text, out startDate) &&
DateTime.TryParse(endDateInput?.text, out endDate))
{
ApplyDateRangeFilter(startDate, endDate.AddDays(1));
}
else
{
UpdateStatus("日期格式错误");
return;
}
break;
}
RefreshHistoryList();
UpdateStatus($"过滤结果: {filteredRecords.Count} 条记录");
}
catch (Exception ex)
{
Debug.LogError($"日期过滤失败: {ex.Message}");
UpdateStatus($"过滤失败: {ex.Message}");
}
}
private void ApplyDateRangeFilter(DateTime startDate, DateTime endDate)
{
if (BFIHistoryManager.Instance != null)
{
filteredRecords = SortRecordsByRecentFirst(BFIHistoryManager.Instance.GetRecordsByDateRange(startDate, endDate));
}
}
private void OnSelectAllToggled(bool isOn)
{
selectedRecordIds.Clear();
if (isOn)
{
foreach (var record in filteredRecords)
{
if (record != null && !string.IsNullOrEmpty(record.TestId))
{
selectedRecordIds.Add(record.TestId);
}
}
}
// 更新所有项目的选择状态
foreach (var item in historyItems)
{
if (item != null)
{
item.SetSelected(isOn);
}
}
UpdateSelectionCount();
}
private void OnSelectTodayClicked()
{
selectedRecordIds.Clear();
var today = DateTime.Today;
foreach (var record in filteredRecords)
{
if (record.StartTime.Date == today)
{
selectedRecordIds.Add(record.TestId);
}
}
UpdateItemSelections();
UpdateSelectionCount();
}
private void OnSelectWeekClicked()
{
selectedRecordIds.Clear();
var weekStart = DateTime.Today.AddDays(-(int)DateTime.Today.DayOfWeek);
foreach (var record in filteredRecords)
{
if (record.StartTime >= weekStart)
{
selectedRecordIds.Add(record.TestId);
}
}
UpdateItemSelections();
UpdateSelectionCount();
}
private void OnClearSelectionClicked()
{
selectedRecordIds.Clear();
foreach (var item in historyItems)
{
item.SetSelected(false);
}
UpdateSelectionCount();
if (selectAllToggle != null)
selectAllToggle.SetIsOnWithoutNotify(false);
}
private void UpdateItemSelections()
{
foreach (var item in historyItems)
{
if (item == null || item.GetRecord() == null)
{
continue;
}
bool isSelected = selectedRecordIds.Contains(item.GetRecord().TestId);
item.SetSelected(isSelected);
}
UpdateSelectAllToggle();
}
private void OnExportSelectedClicked()
{
if (selectedRecordIds.Count == 0)
{
UpdateStatus("请先选择要导出的记录");
return;
}
ExportRecords(selectedRecordIds.ToList());
}
private void OnExportAllClicked()
{
var allIds = filteredRecords.Select(r => r.TestId).ToList();
ExportRecords(allIds);
}
private void OnPreviewClicked()
{
// 显示导出预览
if (selectedRecordIds.Count > 0)
{
ShowExportPreview(selectedRecordIds.ToList());
}
else
{
UpdateStatus("请先选择要预览的记录");
}
}
#endregion
#region
private async void ExportRecords(List<string> recordIds)
{
try
{
UpdateStatus("正在准备导出...");
lastExportedFilePath = null;
lastExportFailureMessage = null;
var selectedRecords = new List<BFITestRecord>();
foreach (var id in recordIds)
{
var record = BFIHistoryManager.Instance != null
? BFIHistoryManager.Instance.GetFullRecord(id)
: allRecords.FirstOrDefault(r => r.TestId == id);
if (record != null)
{
selectedRecords.Add(record);
}
}
if (selectedRecords.Count == 0)
{
UpdateStatus("没有找到可导出的记录");
return;
}
// 获取导出格式
ExportFormat format = GetSelectedExportFormat();
UpdateStatus($"正在导出 {selectedRecords.Count} 条记录...");
// 执行导出
bool success = await ExportRecordsAsync(selectedRecords, format);
if (success)
{
UpdateStatus($"导出成功!已导出 {selectedRecords.Count} 条记录");
ShowExportSuccessDialog(selectedRecords.Count, format, lastExportedFilePath);
}
else
{
string failureMessage = string.IsNullOrEmpty(lastExportFailureMessage)
? "导出失败请检查U盘、存储空间和权限"
: lastExportFailureMessage;
UpdateStatus(failureMessage);
ShowExportFailureDialog(failureMessage);
}
}
catch (Exception ex)
{
Debug.LogError($"导出失败: {ex.Message}");
UpdateStatus("导出失败");
ShowExportFailureDialog($"导出失败: {ex.Message}");
}
}
private ExportFormat GetSelectedExportFormat()
{
int formatIndex = exportFormatDropdown?.value ?? 0;
return (ExportFormat)formatIndex;
}
private async System.Threading.Tasks.Task<bool> ExportRecordsAsync(List<BFITestRecord> records, ExportFormat format)
{
await System.Threading.Tasks.Task.Yield();
try
{
records = EnsureFullRecordsForExport(records);
if (records == null || records.Count == 0)
{
if (string.IsNullOrEmpty(lastExportFailureMessage))
{
lastExportFailureMessage = "没有找到可导出的完整BFI记录";
}
return false;
}
var exportService = new DataExportService();
int totalPointCount = records.Sum(record => record?.DataPoints?.Count ?? 0);
Debug.Log($"BFI导出完整记录准备完成: 记录数={records.Count}, 数据点={totalPointCount}, 格式={format}");
Debug.Log("BFI导出开始检查U盘目录授权");
// 先做权限和目录可用性检查,避免仅返回通用失败文案
if (!exportService.CheckExportPermissions())
{
string errorMessage = exportService.GetLastErrorMessage();
Debug.LogWarning($"导出权限检查未通过,原因: {errorMessage}");
if (!string.IsNullOrEmpty(errorMessage))
{
lastExportFailureMessage = errorMessage;
UpdateStatus(errorMessage);
}
lastExportedFilePath = null;
return false;
}
bool success = exportService.ExportHistoryRecords(records, format);
lastExportedFilePath = success ? exportService.GetLastExportedFilePath() : null;
if (!success)
{
string errorMessage = exportService.GetLastErrorMessage();
Debug.LogWarning($"导出服务返回失败,格式: {format},原因: {errorMessage}");
if (!string.IsNullOrEmpty(errorMessage))
{
lastExportFailureMessage = errorMessage;
UpdateStatus(errorMessage);
}
}
// 记录导出操作日志
if (success)
{
var authService = ServiceLocator.Get<IAuthenticationService>();
var logService = ServiceLocator.Get<UserLogService>();
// 统计导出信息
string patientNames = string.Join(", ", records.Select(r => r.PatientName).Distinct().Take(3));
if (records.Select(r => r.PatientName).Distinct().Count() > 3)
patientNames += "等";
logService?.LogUserOperation(
authService?.CurrentUsername ?? "system",
"导出BFI历史记录",
$"导出{records.Count}条记录, 格式: {format}, 患者: {patientNames}",
true);
}
return success;
}
catch (Exception ex)
{
Debug.LogError($"异步导出失败: {ex.Message}");
lastExportFailureMessage = $"导出失败: {ex.Message}";
// 记录导出失败日志
var authService = ServiceLocator.Get<IAuthenticationService>();
var logService = ServiceLocator.Get<UserLogService>();
logService?.LogUserOperation(
authService?.CurrentUsername ?? "system",
"导出BFI历史记录",
$"失败: {ex.Message}",
false);
return false;
}
}
private List<BFITestRecord> EnsureFullRecordsForExport(List<BFITestRecord> records)
{
var fullRecords = new List<BFITestRecord>();
var missingDetailRecords = new List<string>();
if (records == null)
{
return fullRecords;
}
foreach (var record in records)
{
if (record == null)
{
continue;
}
BFITestRecord fullRecord = record;
bool needsFullRecord = record.DataPoints == null || record.DataPoints.Count == 0;
if (needsFullRecord && BFIHistoryManager.Instance != null)
{
fullRecord = BFIHistoryManager.Instance.GetFullRecord(record.TestId) ?? record;
}
if (fullRecord.DataPoints == null || fullRecord.DataPoints.Count == 0)
{
string displayName = string.IsNullOrEmpty(fullRecord.TestName) ? fullRecord.TestId : fullRecord.TestName;
missingDetailRecords.Add(displayName);
Debug.LogWarning($"BFI导出记录缺少明细数据: {fullRecord.TestName}, ID: {fullRecord.TestId}, 文件: {fullRecord.FilePath}");
continue;
}
fullRecords.Add(fullRecord);
}
if (missingDetailRecords.Count > 0)
{
string names = string.Join("、", missingDetailRecords.Take(3));
if (missingDetailRecords.Count > 3)
{
names += "等";
}
lastExportFailureMessage = $"所选记录中有 {missingDetailRecords.Count} 条缺少BFI明细数据无法导出{names}";
fullRecords.Clear();
}
return fullRecords;
}
private void ShowExportPreview(List<string> recordIds)
{
// 实现导出预览功能
// 这里可以显示一个预览窗口,显示将要导出的数据
UpdateStatus($"预览 {recordIds.Count} 条记录的导出内容");
}
private void ShowExportSuccessDialog(int recordCount, ExportFormat format, string filePath)
{
string message = $"已成功导出 {recordCount} 条BFI历史记录\n导出格式: {GetExportFormatDisplayName(format)}";
if (!string.IsNullOrEmpty(filePath))
{
message += $"\n文件路径: {filePath}";
}
ConfirmDialog.Show("导出成功", message, () => { }, null, "确认", "取消", false, false);
}
private void ShowExportFailureDialog(string message)
{
ConfirmDialog.Show("导出失败", message, () => { }, null, "确认", "取消", true, false);
}
private string GetExportFormatDisplayName(ExportFormat format)
{
switch (format)
{
case ExportFormat.CSV:
return "CSV数据";
case ExportFormat.PDF:
return "PDF报告";
case ExportFormat.TXT:
default:
return "文本报告";
}
}
#endregion
#region
private void OnRecordAdded(BFITestRecord record)
{
allRecords.Add(record);
ApplyCurrentFilter();
UpdateStatistics();
}
private void OnRecordUpdated(BFITestRecord record)
{
var existingRecord = allRecords.FirstOrDefault(r => r.TestId == record.TestId);
if (existingRecord != null)
{
int index = allRecords.IndexOf(existingRecord);
allRecords[index] = record;
if (!TryUpdateVisibleHistoryItem(record))
{
// 记录当前不可见时不重建列表;搜索/筛选操作会重新计算可见集合。
UpdateSelectionCount();
UpdateSelectAllToggle();
}
}
}
private void OnRecordRemoved(string recordId)
{
allRecords.RemoveAll(r => r.TestId == recordId);
selectedRecordIds.Remove(recordId);
ApplyCurrentFilter();
UpdateStatistics();
}
private void OnHistoryLoaded()
{
LoadHistoryRecords();
}
private void ApplyCurrentFilter()
{
// 重新应用当前的搜索和过滤条件
ApplySearch();
OnApplyDateFilter();
}
#endregion
#region UI辅助方法
private void UpdateStatus(string message)
{
if (statusText != null)
{
statusText.text = message;
Debug.Log($"状态更新: {message}");
}
}
#endregion
}