56 lines
3.0 KiB
C#
56 lines
3.0 KiB
C#
using Evergreen.Health.Application.Health.Entities;
|
|
using SqlSugar;
|
|
|
|
namespace Evergreen.Health.Application.Health.Integrations.Ib43;
|
|
|
|
// 仅由本地维护程序调用;不是 Controller,也不注册 HTTP 路由。
|
|
public sealed class Ib43LocalBinding(ISqlSugarClient db, TimeProvider clock)
|
|
{
|
|
public async Task<HealthIb43Binding> Run(string phone, Ib43Options options, string actor, bool apply)
|
|
{
|
|
var device = options.Devices.SingleOrDefault(d => d.ProductKey == "evergreen-test" && d.SerialNumber == "IB43SIM001");
|
|
if (device?.Simulation != true) throw new InvalidOperationException("模拟设备白名单不匹配,已停止。");
|
|
var users = await db.Queryable<HealthUser>().Where(u => u.Phone == phone && !u.IsDelete &&
|
|
u.Status == HealthUserStatus.Enabled).Select(u => new { u.Id }).ToListAsync();
|
|
if (users.Count != 1) throw new InvalidOperationException("未找到唯一且已启用的健康账号,已停止。");
|
|
var key = Ib43DataRepository.DeviceKey(device.ProductKey, device.SerialNumber);
|
|
var slot = key + ".left";
|
|
var existing = await db.Queryable<HealthIb43Binding>().Where(b => b.ActiveSlot == slot).FirstAsync();
|
|
if (existing != null)
|
|
{
|
|
if (existing.UserId != users[0].Id || !existing.Simulation || existing.EndedAtMs != null)
|
|
throw new InvalidOperationException("左侧已被其他用户或非模拟绑定占用,未覆盖或解绑。");
|
|
return existing;
|
|
}
|
|
var binding = new HealthIb43Binding
|
|
{
|
|
DeviceKey = key, ProductKey = device.ProductKey, SerialNumber = device.SerialNumber,
|
|
Side = "left", ActiveSlot = slot, UserId = users[0].Id, BedName = "IB43模拟床垫左侧",
|
|
Simulation = true, StartedAtMs = clock.GetUtcNow().ToUnixTimeMilliseconds(), AssignedBy = 0
|
|
};
|
|
if (!apply) return binding;
|
|
if (string.IsNullOrWhiteSpace(actor) || actor.Length > 200) throw new InvalidOperationException("维护操作者信息不合法。");
|
|
var stage = "binding";
|
|
await db.Ado.BeginTranAsync();
|
|
try
|
|
{
|
|
await db.Insertable(binding).ExecuteCommandAsync();
|
|
stage = "audit";
|
|
await db.Insertable(new HealthIb43MaintenanceAudit
|
|
{
|
|
Id = Guid.NewGuid().ToString("N"), BindingId = binding.Id, UserId = binding.UserId,
|
|
Actor = actor, OccurredAtMs = binding.StartedAtMs, Operation = "local-bind-simulator-left"
|
|
}).ExecuteCommandAsync();
|
|
stage = "commit";
|
|
await db.Ado.CommitTranAsync();
|
|
}
|
|
catch (Exception error)
|
|
{
|
|
await db.Ado.RollbackTranAsync();
|
|
var code = error is MySqlConnector.MySqlException mysql ? $" MySQL {mysql.Number}" : "";
|
|
throw new InvalidOperationException($"绑定事务失败 ({stage}, {error.GetType().Name}{code}),请重新预检确认数据库状态。", error);
|
|
}
|
|
return binding;
|
|
}
|
|
}
|