382 lines
12 KiB
C#
382 lines
12 KiB
C#
|
|
using System;
|
|||
|
|
using System.Collections.Generic;
|
|||
|
|
using UnityEngine;
|
|||
|
|
using System.IO;
|
|||
|
|
using System.Text;
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 患者会话服务
|
|||
|
|
/// 管理从登录管理员账号 -> 输入患者信息 -> 启动测量 -> 显示患者数据的完整流程
|
|||
|
|
/// </summary>
|
|||
|
|
public class PatientSessionService : IService
|
|||
|
|
{
|
|||
|
|
public event Action<PatientSession> OnSessionStarted;
|
|||
|
|
public event Action<PatientSession> OnSessionEnded;
|
|||
|
|
public event Action<PatientMeasurementData> OnMeasurementAdded;
|
|||
|
|
public event Action<PatientSession> OnSessionDataUpdated;
|
|||
|
|
|
|||
|
|
private PatientSession _currentSession;
|
|||
|
|
private List<PatientMeasurementData> _sessionMeasurements = new List<PatientMeasurementData>();
|
|||
|
|
// private IDataService _dataService;
|
|||
|
|
private IPatientInfoService _patientInfoService;
|
|||
|
|
|
|||
|
|
// 测量数据收集
|
|||
|
|
private bool _isRecording = false;
|
|||
|
|
|
|||
|
|
public PatientSession CurrentSession => _currentSession;
|
|||
|
|
public bool IsSessionActive => _currentSession != null;
|
|||
|
|
public bool IsRecording => _isRecording;
|
|||
|
|
public IReadOnlyList<PatientMeasurementData> SessionMeasurements => _sessionMeasurements.AsReadOnly();
|
|||
|
|
|
|||
|
|
public PatientSessionService()
|
|||
|
|
{
|
|||
|
|
// _dataService = ServiceLocator.Get<IDataService>();
|
|||
|
|
_patientInfoService = ServiceLocator.Get<IPatientInfoService>();
|
|||
|
|
|
|||
|
|
// 监听数据服务的实时数据更新
|
|||
|
|
// if (_dataService != null)
|
|||
|
|
// {
|
|||
|
|
// _dataService.OnBFIValueUpdated += OnBFIUpdated;
|
|||
|
|
// _dataService.OnBloodFlowValueUpdated += OnBloodFlowUpdated;
|
|||
|
|
// _dataService.OnBatteryLevelUpdated += OnBatteryUpdated;
|
|||
|
|
// }
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 启动患者会话
|
|||
|
|
/// </summary>
|
|||
|
|
public bool StartSession(PatientInfo patient, string adminUserId)
|
|||
|
|
{
|
|||
|
|
if (_currentSession != null)
|
|||
|
|
{
|
|||
|
|
Debug.LogWarning("已有活动会话,请先结束当前会话");
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
_currentSession = new PatientSession
|
|||
|
|
{
|
|||
|
|
SessionId = System.Guid.NewGuid().ToString(),
|
|||
|
|
PatientInfo = patient,
|
|||
|
|
AdminUserId = adminUserId,
|
|||
|
|
StartTime = DateTime.Now,
|
|||
|
|
Status = SessionStatus.Started
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
// 清空之前的测量数据
|
|||
|
|
_sessionMeasurements.Clear();
|
|||
|
|
|
|||
|
|
// 保存患者信息到服务
|
|||
|
|
if (_patientInfoService != null)
|
|||
|
|
{
|
|||
|
|
_patientInfoService.SetCurrentPatient(patient);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
Debug.Log($"患者会话已启动: {patient.Name} (会话ID: {_currentSession.SessionId})");
|
|||
|
|
OnSessionStarted?.Invoke(_currentSession);
|
|||
|
|
|
|||
|
|
return true;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 开始测量数据记录
|
|||
|
|
/// </summary>
|
|||
|
|
public bool StartMeasurement()
|
|||
|
|
{
|
|||
|
|
if (_currentSession == null)
|
|||
|
|
{
|
|||
|
|
Debug.LogError("无活动会话,无法开始测量");
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (_isRecording)
|
|||
|
|
{
|
|||
|
|
Debug.LogWarning("测量已在进行中");
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
_isRecording = true;
|
|||
|
|
_currentSession.MeasurementStartTime = DateTime.Now;
|
|||
|
|
_currentSession.Status = SessionStatus.Measuring;
|
|||
|
|
|
|||
|
|
// 启动数据采集
|
|||
|
|
// if (_dataService != null)
|
|||
|
|
// {
|
|||
|
|
// _dataService.StartDataCollection();
|
|||
|
|
// }
|
|||
|
|
|
|||
|
|
Debug.Log("开始测量数据记录");
|
|||
|
|
OnSessionDataUpdated?.Invoke(_currentSession);
|
|||
|
|
|
|||
|
|
return true;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 停止测量数据记录
|
|||
|
|
/// </summary>
|
|||
|
|
public bool StopMeasurement()
|
|||
|
|
{
|
|||
|
|
if (!_isRecording)
|
|||
|
|
{
|
|||
|
|
Debug.LogWarning("当前没有进行测量");
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
_isRecording = false;
|
|||
|
|
|
|||
|
|
if (_currentSession != null)
|
|||
|
|
{
|
|||
|
|
_currentSession.MeasurementEndTime = DateTime.Now;
|
|||
|
|
_currentSession.Status = SessionStatus.MeasurementComplete;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
Debug.Log("测量数据记录已停止");
|
|||
|
|
OnSessionDataUpdated?.Invoke(_currentSession);
|
|||
|
|
|
|||
|
|
return true;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 结束患者会话
|
|||
|
|
/// </summary>
|
|||
|
|
public bool EndSession()
|
|||
|
|
{
|
|||
|
|
if (_currentSession == null)
|
|||
|
|
{
|
|||
|
|
Debug.LogWarning("没有活动会话可结束");
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 停止测量(如果正在进行)
|
|||
|
|
if (_isRecording)
|
|||
|
|
{
|
|||
|
|
StopMeasurement();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
_currentSession.EndTime = DateTime.Now;
|
|||
|
|
_currentSession.Status = SessionStatus.Completed;
|
|||
|
|
_currentSession.TotalMeasurements = _sessionMeasurements.Count;
|
|||
|
|
|
|||
|
|
Debug.Log($"患者会话已结束: {_currentSession.PatientInfo.Name}");
|
|||
|
|
OnSessionEnded?.Invoke(_currentSession);
|
|||
|
|
|
|||
|
|
_currentSession = null;
|
|||
|
|
|
|||
|
|
return true;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 导出会话数据(包含患者信息和所有测量数据)
|
|||
|
|
/// </summary>
|
|||
|
|
public bool ExportSessionData(string filePath)
|
|||
|
|
{
|
|||
|
|
if (_currentSession == null)
|
|||
|
|
{
|
|||
|
|
Debug.LogError("没有会话数据可导出");
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
try
|
|||
|
|
{
|
|||
|
|
var exportData = new PatientSessionExportData
|
|||
|
|
{
|
|||
|
|
Session = _currentSession,
|
|||
|
|
Measurements = _sessionMeasurements.ToArray(),
|
|||
|
|
ExportTime = DateTime.Now
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
string extension = Path.GetExtension(filePath).ToLower();
|
|||
|
|
|
|||
|
|
switch (extension)
|
|||
|
|
{
|
|||
|
|
case ".json":
|
|||
|
|
return ExportToJSON(exportData, filePath);
|
|||
|
|
case ".csv":
|
|||
|
|
return ExportToCSV(exportData, filePath);
|
|||
|
|
default:
|
|||
|
|
Debug.LogError($"不支持的导出格式: {extension}");
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
catch (Exception ex)
|
|||
|
|
{
|
|||
|
|
Debug.LogError($"导出会话数据失败: {ex.Message}");
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private bool ExportToJSON(PatientSessionExportData data, string filePath)
|
|||
|
|
{
|
|||
|
|
string json = JsonUtility.ToJson(data, true);
|
|||
|
|
File.WriteAllText(filePath, json, Encoding.UTF8);
|
|||
|
|
Debug.Log($"会话数据已导出到: {filePath}");
|
|||
|
|
return true;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private bool ExportToCSV(PatientSessionExportData data, string filePath)
|
|||
|
|
{
|
|||
|
|
var csv = new StringBuilder();
|
|||
|
|
|
|||
|
|
// 患者信息
|
|||
|
|
csv.AppendLine("=== 患者信息 ===");
|
|||
|
|
csv.AppendLine($"姓名,{data.Session.PatientInfo.Name}");
|
|||
|
|
csv.AppendLine($"住院号,{data.Session.PatientInfo.HospitalId}");
|
|||
|
|
csv.AppendLine($"性别,{data.Session.PatientInfo.Gender}");
|
|||
|
|
csv.AppendLine($"年龄,{data.Session.PatientInfo.Age}");
|
|||
|
|
csv.AppendLine($"身高,{data.Session.PatientInfo.Height}");
|
|||
|
|
csv.AppendLine($"体重,{data.Session.PatientInfo.Weight}");
|
|||
|
|
// csv.AppendLine($"身份证号,{data.Session.PatientInfo.IdNumber}");
|
|||
|
|
csv.AppendLine();
|
|||
|
|
|
|||
|
|
// 会话信息
|
|||
|
|
csv.AppendLine("=== 会话信息 ===");
|
|||
|
|
csv.AppendLine($"会话ID,{data.Session.SessionId}");
|
|||
|
|
csv.AppendLine($"管理员,{data.Session.AdminUserId}");
|
|||
|
|
csv.AppendLine($"开始时间,{data.Session.StartTime}");
|
|||
|
|
csv.AppendLine($"结束时间,{data.Session.EndTime}");
|
|||
|
|
csv.AppendLine($"测量开始,{data.Session.MeasurementStartTime}");
|
|||
|
|
csv.AppendLine($"测量结束,{data.Session.MeasurementEndTime}");
|
|||
|
|
csv.AppendLine($"总测量数,{data.Session.TotalMeasurements}");
|
|||
|
|
csv.AppendLine();
|
|||
|
|
|
|||
|
|
// 测量数据
|
|||
|
|
csv.AppendLine("=== 测量数据 ===");
|
|||
|
|
csv.AppendLine("时间,BFI值,血流指数,电池电量,状态");
|
|||
|
|
|
|||
|
|
foreach (var measurement in data.Measurements)
|
|||
|
|
{
|
|||
|
|
csv.AppendLine($"{measurement.Timestamp},{measurement.BFIValue:F2},{measurement.BloodFlowValue:F2},{measurement.BatteryLevel:F1},{measurement.Status}");
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
File.WriteAllText(filePath, csv.ToString(), Encoding.UTF8);
|
|||
|
|
Debug.Log($"会话数据已导出到: {filePath}");
|
|||
|
|
return true;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 加载会话数据
|
|||
|
|
/// </summary>
|
|||
|
|
public PatientSessionExportData LoadSessionData(string filePath)
|
|||
|
|
{
|
|||
|
|
try
|
|||
|
|
{
|
|||
|
|
if (!File.Exists(filePath))
|
|||
|
|
{
|
|||
|
|
Debug.LogError($"文件不存在: {filePath}");
|
|||
|
|
return null;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
string extension = Path.GetExtension(filePath).ToLower();
|
|||
|
|
|
|||
|
|
if (extension == ".json")
|
|||
|
|
{
|
|||
|
|
string json = File.ReadAllText(filePath, Encoding.UTF8);
|
|||
|
|
return JsonUtility.FromJson<PatientSessionExportData>(json);
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
Debug.LogError($"暂不支持加载 {extension} 格式的会话数据");
|
|||
|
|
return null;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
catch (Exception ex)
|
|||
|
|
{
|
|||
|
|
Debug.LogError($"加载会话数据失败: {ex.Message}");
|
|||
|
|
return null;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
#region 数据服务事件处理
|
|||
|
|
|
|||
|
|
private void OnBFIUpdated(float value)
|
|||
|
|
{
|
|||
|
|
// if (_isRecording && _currentSession != null)
|
|||
|
|
// {
|
|||
|
|
// RecordMeasurement(value, _dataService.CurrentBloodFlow, _dataService.CurrentBatteryLevel);
|
|||
|
|
// }
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private void RecordMeasurement(float bfi, float bloodFlow, float battery)
|
|||
|
|
{
|
|||
|
|
var measurement = new PatientMeasurementData
|
|||
|
|
{
|
|||
|
|
Timestamp = DateTime.Now,
|
|||
|
|
BFIValue = bfi,
|
|||
|
|
BloodFlowValue = bloodFlow,
|
|||
|
|
BatteryLevel = battery,
|
|||
|
|
Status = GetMeasurementStatus(bfi, bloodFlow)
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
_sessionMeasurements.Add(measurement);
|
|||
|
|
OnMeasurementAdded?.Invoke(measurement);
|
|||
|
|
|
|||
|
|
// 限制内存中的测量数据数量(保留最近1000条)
|
|||
|
|
if (_sessionMeasurements.Count > 1000)
|
|||
|
|
{
|
|||
|
|
_sessionMeasurements.RemoveAt(0);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private string GetMeasurementStatus(float bfi, float bloodFlow)
|
|||
|
|
{
|
|||
|
|
// if (bfi < 30f || bfi > 70f)
|
|||
|
|
// return "BFI异常";
|
|||
|
|
// if (bloodFlow < 80f || bloodFlow > 120f)
|
|||
|
|
// return "血流异常";
|
|||
|
|
return "正常";
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
#endregion
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 患者会话数据
|
|||
|
|
/// </summary>
|
|||
|
|
[System.Serializable]
|
|||
|
|
public class PatientSession
|
|||
|
|
{
|
|||
|
|
public string SessionId;
|
|||
|
|
public PatientInfo PatientInfo;
|
|||
|
|
public string AdminUserId;
|
|||
|
|
public DateTime StartTime;
|
|||
|
|
public DateTime EndTime;
|
|||
|
|
public DateTime? MeasurementStartTime;
|
|||
|
|
public DateTime? MeasurementEndTime;
|
|||
|
|
public SessionStatus Status;
|
|||
|
|
public int TotalMeasurements;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 会话状态
|
|||
|
|
/// </summary>
|
|||
|
|
public enum SessionStatus
|
|||
|
|
{
|
|||
|
|
Started, // 已开始
|
|||
|
|
Measuring, // 测量中
|
|||
|
|
MeasurementComplete, // 测量完成
|
|||
|
|
Completed // 会话完成
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 患者测量数据
|
|||
|
|
/// </summary>
|
|||
|
|
[System.Serializable]
|
|||
|
|
public class PatientMeasurementData
|
|||
|
|
{
|
|||
|
|
public DateTime Timestamp;
|
|||
|
|
public float BFIValue;
|
|||
|
|
public float BloodFlowValue;
|
|||
|
|
public float BatteryLevel;
|
|||
|
|
public string Status; // 正常、异常等状态
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 患者会话导出数据
|
|||
|
|
/// </summary>
|
|||
|
|
[System.Serializable]
|
|||
|
|
public class PatientSessionExportData
|
|||
|
|
{
|
|||
|
|
public PatientSession Session;
|
|||
|
|
public PatientMeasurementData[] Measurements;
|
|||
|
|
public DateTime ExportTime;
|
|||
|
|
}
|