265 lines
6.9 KiB
C#
265 lines
6.9 KiB
C#
using System;
|
||
using UnityEngine;
|
||
using UnityEngine.UI;
|
||
using TMPro;
|
||
|
||
/// <summary>
|
||
/// BFI历史记录列表项UI组件
|
||
/// 用于在BFIHistoryExportPanel中显示单个历史记录
|
||
/// </summary>
|
||
public class BFIHistoryItem : MonoBehaviour
|
||
{
|
||
[Header("UI组件")]
|
||
[SerializeField] private Toggle selectionToggle;
|
||
[SerializeField] private TextMeshProUGUI testNameText;
|
||
[SerializeField] private TextMeshProUGUI patientNameText;
|
||
[SerializeField] private TextMeshProUGUI testTimeText;
|
||
[SerializeField] private TextMeshProUGUI durationText;
|
||
[SerializeField] private TextMeshProUGUI bfiRangeText;
|
||
[SerializeField] private Image statusImage;
|
||
|
||
[Header("状态颜色")]
|
||
[SerializeField] private Color normalColor = Color.green;
|
||
[SerializeField] private Color warningColor = Color.yellow;
|
||
[SerializeField] private Color errorColor = Color.red;
|
||
|
||
// 事件
|
||
public event System.Action<string, bool> OnSelectionChanged;
|
||
|
||
private BFITestRecord _record;
|
||
|
||
private void Awake()
|
||
{
|
||
InitializeUI();
|
||
}
|
||
|
||
private void InitializeUI()
|
||
{
|
||
// 选择框事件
|
||
if (selectionToggle != null)
|
||
{
|
||
selectionToggle.onValueChanged.AddListener(OnToggleChanged);
|
||
}
|
||
|
||
}
|
||
|
||
/// <summary>
|
||
/// 初始化历史记录项
|
||
/// </summary>
|
||
public void Initialize(BFITestRecord record)
|
||
{
|
||
_record = record;
|
||
UpdateDisplay();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 更新显示内容
|
||
/// </summary>
|
||
private void UpdateDisplay()
|
||
{
|
||
if (_record == null) return;
|
||
|
||
// 测试名称
|
||
if (testNameText != null)
|
||
{
|
||
testNameText.text = _record.TestName;
|
||
}
|
||
|
||
// 患者姓名
|
||
if (patientNameText != null)
|
||
{
|
||
string patientInfo = !string.IsNullOrEmpty(_record.PatientName) ?
|
||
_record.PatientName : "未知患者";
|
||
if (!string.IsNullOrEmpty(_record.PatientId))
|
||
{
|
||
patientInfo += $" ({_record.PatientId})";
|
||
}
|
||
patientNameText.text = patientInfo;
|
||
}
|
||
|
||
// 测试时间
|
||
if (testTimeText != null)
|
||
{
|
||
testTimeText.text = _record.StartTime.ToString("MM-dd HH:mm");
|
||
}
|
||
|
||
// 持续时间
|
||
if (durationText != null)
|
||
{
|
||
var duration = _record.GetDurationMinutes();
|
||
durationText.text = $"{duration:F1}分钟";
|
||
}
|
||
|
||
// BFI范围
|
||
if (bfiRangeText != null && _record.Statistics != null)
|
||
{
|
||
bfiRangeText.text = GetBfiRangeDisplayText();
|
||
}
|
||
|
||
// 状态指示器
|
||
UpdateStatusIndicator();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 更新状态指示器
|
||
/// </summary>
|
||
private void UpdateStatusIndicator()
|
||
{
|
||
if (statusImage == null || _record?.Statistics == null) return;
|
||
|
||
// 根据BFI统计信息确定状态
|
||
var stats = _record.Statistics;
|
||
Color statusColor = normalColor;
|
||
|
||
if (stats.Count <= 0)
|
||
{
|
||
statusImage.color = statusColor;
|
||
return;
|
||
}
|
||
|
||
// 检查是否有异常值(简单规则:超出30-70范围)
|
||
if (stats.MinValue < 30f || stats.MaxValue > 70f)
|
||
{
|
||
statusColor = warningColor;
|
||
}
|
||
|
||
// 检查是否有严重异常(超出20-80范围)
|
||
if (stats.MinValue < 20f || stats.MaxValue > 80f)
|
||
{
|
||
statusColor = errorColor;
|
||
}
|
||
|
||
statusImage.color = statusColor;
|
||
}
|
||
|
||
private string GetBfiRangeDisplayText()
|
||
{
|
||
var stats = _record?.Statistics;
|
||
if (stats == null || stats.Count <= 0)
|
||
{
|
||
return "无数据";
|
||
}
|
||
|
||
if (IsInvalidRange(stats.MinValue, stats.MaxValue) && TryGetRangeFromDataPoints(out float minValue, out float maxValue))
|
||
{
|
||
return $"{minValue:F1}-{maxValue:F1}";
|
||
}
|
||
|
||
return $"{stats.MinValue:F1}-{stats.MaxValue:F1}";
|
||
}
|
||
|
||
private bool IsInvalidRange(float minValue, float maxValue)
|
||
{
|
||
return float.IsNaN(minValue) ||
|
||
float.IsInfinity(minValue) ||
|
||
float.IsNaN(maxValue) ||
|
||
float.IsInfinity(maxValue) ||
|
||
maxValue < minValue;
|
||
}
|
||
|
||
private bool TryGetRangeFromDataPoints(out float minValue, out float maxValue)
|
||
{
|
||
minValue = float.MaxValue;
|
||
maxValue = float.MinValue;
|
||
|
||
if (_record?.DataPoints == null || _record.DataPoints.Count == 0)
|
||
{
|
||
return false;
|
||
}
|
||
|
||
bool hasValidPoint = false;
|
||
foreach (var point in _record.DataPoints)
|
||
{
|
||
if (point == null || float.IsNaN(point.BFI) || float.IsInfinity(point.BFI))
|
||
{
|
||
continue;
|
||
}
|
||
|
||
minValue = Mathf.Min(minValue, point.BFI);
|
||
maxValue = Mathf.Max(maxValue, point.BFI);
|
||
hasValidPoint = true;
|
||
}
|
||
|
||
return hasValidPoint;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 设置选择状态
|
||
/// </summary>
|
||
public void SetSelected(bool selected)
|
||
{
|
||
if (selectionToggle != null)
|
||
{
|
||
selectionToggle.SetIsOnWithoutNotify(selected);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取当前选择状态
|
||
/// </summary>
|
||
public bool IsSelected()
|
||
{
|
||
return selectionToggle != null ? selectionToggle.isOn : false;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取关联的记录
|
||
/// </summary>
|
||
public BFITestRecord GetRecord()
|
||
{
|
||
return _record;
|
||
}
|
||
|
||
#region 事件处理
|
||
|
||
private void OnToggleChanged(bool isOn)
|
||
{
|
||
if (_record != null)
|
||
{
|
||
OnSelectionChanged?.Invoke(_record.TestId, isOn);
|
||
}
|
||
}
|
||
|
||
|
||
#endregion
|
||
|
||
/// <summary>
|
||
/// 高亮显示(用于搜索结果)
|
||
/// </summary>
|
||
public void SetHighlight(bool highlight)
|
||
{
|
||
var bg = GetComponent<Image>();
|
||
if (bg != null)
|
||
{
|
||
bg.color = highlight ? new Color(1f, 1f, 0f, 0.3f) : Color.white;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 更新时间显示格式
|
||
/// </summary>
|
||
public void SetTimeDisplayFormat(bool showFullDate)
|
||
{
|
||
if (testTimeText != null && _record != null)
|
||
{
|
||
if (showFullDate)
|
||
{
|
||
testTimeText.text = _record.StartTime.ToString("yyyy-MM-dd HH:mm");
|
||
}
|
||
else
|
||
{
|
||
// 如果是今天,只显示时间;如果是其他天,显示月-日
|
||
var today = DateTime.Today;
|
||
if (_record.StartTime.Date == today)
|
||
{
|
||
testTimeText.text = _record.StartTime.ToString("HH:mm");
|
||
}
|
||
else
|
||
{
|
||
testTimeText.text = _record.StartTime.ToString("MM-dd HH:mm");
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|