电子药箱通讯服务端
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

MainWindowViewModel.cs 59KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992
  1. using Microsoft.AspNetCore.Components;
  2. using Microsoft.EntityFrameworkCore;
  3. using Microsoft.EntityFrameworkCore.Storage.ValueConversion.Internal;
  4. using Microsoft.Extensions.DependencyInjection;
  5. using Prism.Commands;
  6. using Prism.Mvvm;
  7. using Prism.Regions;
  8. using PropertyChanged;
  9. using Rdh.ElectronicMedicineKit.EntityFrameworkCore;
  10. using Rdh.ElectronicMedicineKit.Models;
  11. using Rdh.SocketServer.Client.BLL;
  12. using Rdh.SocketServer.Client.Models;
  13. using Rdh.SocketServer.Client.MQ;
  14. using RDH.Data;
  15. using RDH.Data.BLL;
  16. using RDH.Data.Models;
  17. using Serilog;
  18. using System;
  19. using System.Collections.Generic;
  20. using System.Collections.ObjectModel;
  21. using System.Diagnostics;
  22. using System.Linq;
  23. using System.Text;
  24. using System.Threading;
  25. using System.Threading.Tasks;
  26. using System.Transactions;
  27. using System.Windows;
  28. using System.Windows.Input;
  29. using TouchSocket.Core.ByteManager;
  30. using TouchSocket.Sockets;
  31. namespace Rdh.SocketServer.Client.ViewModels
  32. {
  33. [AddINotifyPropertyChangedInterface]
  34. public class MainWindowViewModel : BindableBase
  35. {
  36. private readonly IRegionManager _regionManager;
  37. private readonly ApplicationDbContext _dbContext;
  38. private readonly ITcpService _tcpService;
  39. private readonly Encoding _encoding;
  40. private List<PortableStorageType> _listStorageTypes;
  41. public const String ViewOfData = "有效数据",
  42. ViewOfInvalid = "无效数据",
  43. ViewOfClient = "客户端",
  44. ViewOfLog = "日志";
  45. #region Constructor
  46. public MainWindowViewModel(IRegionManager regionManager, IServiceProvider serviceProvider, ApplicationDbContext dbContext)
  47. {
  48. ListLogs = new ObservableCollection<LogModel>();
  49. _regionManager = regionManager;
  50. _dbContext = dbContext;
  51. var servers = serviceProvider.GetServices<ITcpService>();
  52. _tcpService = servers?.FirstOrDefault(x => x.ServerName == "ElectronicMedicineKit");
  53. _encoding = Encoding.GetEncoding("gb2312");
  54. if (_tcpService != null)
  55. {
  56. if (_tcpService is TcpService service)
  57. {
  58. service.Connecting += (client, e) =>
  59. {
  60. Log($"{client.IP}:{client.Port.ToString()}正在建立连接");
  61. };//有客户端正在连接
  62. service.Connected += (client, e) =>
  63. {
  64. Log($"已从{client.IP}:{client.Port.ToString()}建立连接");
  65. Application.Current.Dispatcher.Invoke(() =>
  66. {
  67. ListClients.Add(new TimeFlagModel<SocketClient>(client));
  68. });
  69. };//有客户端连接
  70. service.Disconnected += (client, e) =>
  71. {
  72. Log($"已从{client.IP}:{client.Port.ToString()}断开连接");
  73. Application.Current.Dispatcher.Invoke(() =>
  74. {
  75. lock (ListClients)
  76. {
  77. for (Int32 i = 0; i < ListClients.Count; i++)
  78. {
  79. if (ListClients[i].Model.IP == client.IP)
  80. {
  81. ListClients.RemoveAt(i);
  82. i--;
  83. }
  84. }
  85. }
  86. });
  87. };//有客户端断开连接
  88. service.Received += Reveiced;
  89. }
  90. Task.Factory.StartNew(() => DataHandle());
  91. }
  92. _dbContext.Database.EnsureCreated();
  93. DeleteDataCommand = new DelegateCommand(DeleteDataCommandHandler);
  94. ClearCommand = new DelegateCommand<String>(ClearCommandHandler);
  95. }
  96. #endregion
  97. #region Properties
  98. public ObservableCollection<Pocket> Pockets { get; set; } = new ObservableCollection<Pocket>();
  99. public Pocket SelectedData { get; set; }
  100. public ObservableCollection<Pocket> InvalidPockets { get; set; } = new ObservableCollection<Pocket>();
  101. public ObservableCollection<LogModel> ListLogs { get; set; }
  102. public ObservableCollection<TimeFlagModel<SocketClient>> ListClients { get; set; } = new ObservableCollection<TimeFlagModel<SocketClient>>();
  103. public ICommand ClearCommand { get; set; }
  104. public ICommand DeleteDataCommand { get; set; }
  105. public string Title { get; set; }
  106. #endregion
  107. public void Init()
  108. {
  109. Task.Run(() =>
  110. {
  111. try
  112. {
  113. using (ConnectionSessionScope conn = new ConnectionSessionScope())
  114. {
  115. PortableStorageTypeBLL portableStorageTypeBLL = new PortableStorageTypeBLL();
  116. _listStorageTypes = portableStorageTypeBLL.ListModels(100, 0);
  117. }
  118. }
  119. catch (Exception ex)
  120. {
  121. Log($"加载药箱类型出错:{ex.Message}", -1);
  122. Serilog.Log.Warning($"{ex.StackTrace}");
  123. }
  124. });
  125. }
  126. #region Private Methods
  127. #region 页面命令处理
  128. //删除数据按钮
  129. private void DeleteDataCommandHandler()
  130. {
  131. if (SelectedData == null)
  132. {
  133. return;
  134. }
  135. RemovePocket(SelectedData);
  136. Log($"删除数据:{SelectedData.Data}");
  137. }
  138. //清空按钮
  139. private void ClearCommandHandler(String view)
  140. {
  141. switch (view)
  142. {
  143. case ViewOfLog:
  144. this.ListLogs.Clear();
  145. break;
  146. case ViewOfInvalid:
  147. InvalidPockets.Clear();
  148. break;
  149. }
  150. }
  151. #endregion
  152. private void Reveiced(SocketClient client, ByteBlock byteBlock, IRequestInfo requestInfo)
  153. {
  154. Application.Current.Dispatcher.BeginInvoke(new Action(() =>
  155. {
  156. Log($"Received from:{client.IP}:{client.Port.ToString()}");
  157. EleMedKitData? data = requestInfo as EleMedKitData;
  158. if (data == null)
  159. {
  160. InvalidPockets.Add(new Pocket(client, null));
  161. }
  162. else
  163. {
  164. if (data.Message == null)
  165. {
  166. Pockets.Add(new Pocket(client, data));
  167. }
  168. else
  169. {
  170. Log($"解析失败:{data.Message}", -1);
  171. InvalidPockets.Add(new Pocket(client, data));
  172. }
  173. }
  174. }));
  175. }
  176. private void DataHandle()
  177. {
  178. while (true)
  179. {
  180. Pocket? curPocket = PeekData();
  181. if (curPocket != null)
  182. {
  183. EleMedKitProtocol responseData = null;
  184. switch (curPocket.Data.ProtocolDataInfo.Command)
  185. {
  186. case EleMedKitCommand.RequestClock:
  187. ClockResponseProtocol clockResponseProtocol = new ClockResponseProtocol();
  188. responseData = clockResponseProtocol;
  189. break;
  190. case EleMedKitCommand.RequestSupplyList:
  191. try
  192. {
  193. ResponseSupplyDrugProtocol responseSupplyDrugProtocol = new ResponseSupplyDrugProtocol();
  194. responseSupplyDrugProtocol.ListSupplyResult = new List<DrugLotProtocol>();
  195. RequestSupplyDrugProtocol requestSupplyDrugProtocol = (RequestSupplyDrugProtocol)curPocket.Data.ProtocolDataInfo;
  196. responseSupplyDrugProtocol.UserInfo = requestSupplyDrugProtocol.UserInfo;
  197. responseSupplyDrugProtocol.EleMedKitCode = requestSupplyDrugProtocol.EleMedKitCode;
  198. String? state = null;
  199. StorageSpacePortableLink? requestStorageLink = null;
  200. using (ConnectionSessionScope conn = new ConnectionSessionScope())
  201. {
  202. requestStorageLink = GetRequestStorageLink(null, requestSupplyDrugProtocol.EleMedKitCode, out state);
  203. }
  204. if (state != null
  205. || requestStorageLink == null)
  206. {
  207. Log("检查药箱信息不通过", -1);
  208. break;
  209. }
  210. responseSupplyDrugProtocol.MedKitTypeCode = GetPortableTypeCode(requestStorageLink);
  211. if (requestSupplyDrugProtocol.ListBarcode != null
  212. && requestSupplyDrugProtocol.ListBarcode.Count > 0)
  213. {
  214. IEnumerable<ItemBarcodeLibrary> barcodeLibraries = new ShouShuShiBLL()
  215. .ListBarcodeInfo(requestSupplyDrugProtocol.ListBarcode.ToArray());
  216. if (barcodeLibraries != null && barcodeLibraries.Count() > 0)
  217. {
  218. IEnumerable<IGrouping<Guid?, ItemBarcodeLibrary>> itemGroups = barcodeLibraries.GroupBy(x => x.ItemKey);
  219. using (TransactionScope transaction = new TransactionScope())
  220. {
  221. using (ConnectionSessionScope conn = new ConnectionSessionScope())
  222. {
  223. UserInfo? requestUser = GetRequestUserInfo(new UserInfoBLL(), requestSupplyDrugProtocol.UserInfo, out state);
  224. if (state != null || requestUser == null)
  225. {
  226. Log("检查用户信息不通过:" + state, -1);
  227. break;
  228. }
  229. foreach (IGrouping<Guid?, ItemBarcodeLibrary> barcodeLibrary in itemGroups)
  230. {
  231. PortableStorageItemBLL portableStorageItemBLL = new PortableStorageItemBLL();
  232. PortableStorageItem? requestPortableStorageItem = GetRequestPortableItem(portableStorageItemBLL,
  233. requestStorageLink, barcodeLibrary.Key.GetValueOrDefault());
  234. if (requestPortableStorageItem == null)
  235. {
  236. //在药箱的配药列表未找到指定药品时,将返回的条码信息标记为“多”
  237. responseSupplyDrugProtocol.ListSupplyResult.AddRange(barcodeLibrary.Select(x => new DrugLotProtocol
  238. {
  239. Barcode = x.Barcode,
  240. SupplyState = SupplyStateCodes.Add,
  241. }));
  242. continue;
  243. }
  244. #region 更新药品库存及记录
  245. //增加药品操作记录
  246. ItemTransactionBLL itemTransactionBLL = new ItemTransactionBLL();
  247. ItemTransaction itemTransaction = new ItemTransaction
  248. {
  249. Key = Guid.NewGuid(),
  250. CreateTime = DateTime.Now,
  251. //DeviceKey = requestStorageLink.StorageSpace.DeviceKey,
  252. ItemKey = barcodeLibrary.Key,
  253. CreateBy = requestUser.Key,
  254. TransactionType = TransactionTypeCodes.MedKitSupplyPlan.ToString(),
  255. Quantity = barcodeLibrary.Count(),
  256. Ext02 = requestStorageLink.PortableStorage?.Code,
  257. };
  258. //增加库存更新记录
  259. StorageSpaceItemTransactionBLL storageSpaceItemTransactionBLL = new StorageSpaceItemTransactionBLL();
  260. StorageSpaceItemTransaction ssiTransaction = new StorageSpaceItemTransaction
  261. {
  262. Key = Guid.NewGuid(),
  263. CreateBy = requestUser.Key,
  264. CreateTime = DateTime.Now,
  265. StorageSpaceItemKey = requestPortableStorageItem.Key,
  266. ItemTransactionKey = itemTransaction.Key,
  267. };
  268. #endregion
  269. PortableStorageItemLotBLL portableStorageItemLotBLL = new PortableStorageItemLotBLL();
  270. SPILItemTransactionBLL sPILItemTransactionBLL = new SPILItemTransactionBLL();
  271. #region 更新批号库存和记录
  272. Int32 totalIncrease = 0;
  273. foreach (ItemBarcodeLibrary b in barcodeLibrary)
  274. {
  275. PortableStorageItemLot portableStorageItemLot = portableStorageItemLotBLL.GetByItemBarcode(b.Barcode);
  276. if (portableStorageItemLot == null)
  277. {
  278. portableStorageItemLot = new PortableStorageItemLot
  279. {
  280. Key = Guid.NewGuid(),
  281. CreateTime = DateTime.Now,
  282. PortableStorageItemkey = requestPortableStorageItem.Key,
  283. Quantity = 1,
  284. ItemKey = requestPortableStorageItem.ItemKey,
  285. LotKey = b.ItemLotKey,
  286. Ext01 = b.Barcode,
  287. };
  288. totalIncrease += 1;
  289. portableStorageItemLotBLL.Save(portableStorageItemLot);
  290. SPILItemTransaction spilTransaction = new SPILItemTransaction
  291. {
  292. Key = Guid.NewGuid(),
  293. CreateTime = DateTime.Now,
  294. Quantity = 1,
  295. ItemLotKey = b.ItemLotKey,
  296. ItemTransactionKey = itemTransaction.Key,
  297. StorageSpaceItemLotKey = portableStorageItemLot.Key,
  298. Ext01 = b.Barcode,
  299. };
  300. sPILItemTransactionBLL.Save(spilTransaction);
  301. }
  302. //生成返回数据
  303. responseSupplyDrugProtocol.ListSupplyResult.Add(new DrugLotProtocol
  304. {
  305. Barcode = b.Barcode,
  306. SupplyState = SupplyStateCodes.Success,
  307. DrugKey = barcodeLibrary.Key.GetValueOrDefault().ToString(),
  308. DrugLotCode = b.ItemLotInfo.LotNo,
  309. });
  310. }
  311. #endregion
  312. if (totalIncrease > 0)
  313. {
  314. itemTransactionBLL.Save(itemTransaction);
  315. //增加药箱药品库存
  316. requestPortableStorageItem.CurrentQuantity = requestPortableStorageItem.CurrentQuantity.GetValueOrDefault() + barcodeLibrary.Count();
  317. portableStorageItemBLL.Update(requestPortableStorageItem);
  318. storageSpaceItemTransactionBLL.Save(ssiTransaction);
  319. }
  320. }
  321. transaction.Complete();
  322. }
  323. }
  324. }
  325. }
  326. responseData = responseSupplyDrugProtocol;
  327. }
  328. catch (Exception ex)
  329. {
  330. Log("查询药品条码信息出错:" + ex.Message, -1);
  331. }
  332. break;
  333. case EleMedKitCommand.RequestLocation:
  334. try
  335. {
  336. LocationResponseProtocol locationResponse = new LocationResponseProtocol();
  337. LocationRequestProtocol locationRequest = (LocationRequestProtocol)curPocket.Data.ProtocolDataInfo;
  338. #region 获取基站绑定的手术间
  339. IEnumerable<RDH.Data.Models.OperationRoom> rooms = new ShouShuShiBLL().ListOperationRoomByStation(locationRequest.StationCode);
  340. if (rooms != null && rooms.Count() > 0)
  341. {
  342. //以3位字符显示手术间号(左侧补0)
  343. locationResponse.SectionCode = rooms.First().RoomId.PadLeft(3, '0');
  344. locationResponse.EleMedKitCode = locationRequest.EleMedKitCode;
  345. responseData = locationResponse;
  346. #region 记录定位
  347. //记录时,使用纯编号(没有左侧的补0)
  348. String simpleMedkitCode = locationRequest.EleMedKitCode.TrimStart('0');
  349. String simpleStationCode = locationRequest.StationCode.TrimStart('0');
  350. PortableStorageTrackBLL portableStorageTrackBLL = new PortableStorageTrackBLL();
  351. PortableStorageTrack lastTrack = portableStorageTrackBLL.GetLastTrackByItem(simpleMedkitCode);
  352. if (lastTrack == null
  353. || lastTrack.CreateTime.GetValueOrDefault().Date < DateTime.Now.Date
  354. || lastTrack.TrackCode != simpleStationCode)
  355. {
  356. using (ConnectionSessionScope scope = new ConnectionSessionScope())
  357. {
  358. PortableStorageTrack curTrack = new PortableStorageTrack();
  359. curTrack.CreateTime = DateTime.Now;
  360. curTrack.ItemCode = simpleMedkitCode;
  361. curTrack.TrackCode = simpleStationCode;
  362. portableStorageTrackBLL.Save(curTrack);
  363. }
  364. }
  365. #endregion
  366. }
  367. else
  368. {
  369. Log($"基站编号[{locationRequest.StationCode}]未配置手术间");
  370. }
  371. #endregion
  372. }
  373. catch (Exception ex)
  374. {
  375. Log("处理定位信息出错:" + ex.Message, -1);
  376. }
  377. break;
  378. case EleMedKitCommand.RequestPatientOperation:
  379. try
  380. {
  381. RequestPatientOperationProtocol requestProtocol = (RequestPatientOperationProtocol)curPocket.Data.ProtocolDataInfo;
  382. if (requestProtocol.RoomCode == null)
  383. {
  384. Log("请求手术信息时,手术间编号为空", -1);
  385. }
  386. else
  387. {
  388. ResponsePatientOperationProtocol responseProtocol = new ResponsePatientOperationProtocol();
  389. responseProtocol.EleMedKitCode = requestProtocol.EleMedKitCode;
  390. responseProtocol.ListOperations = new List<PatientOperationProtocol>();
  391. IEnumerable<RDH.Data.Models.PatientOperationInfo> operationInfos = new ShouShuShiBLL()
  392. .ListOperattionInfoByRoom(requestProtocol.RoomCode.TrimStart('0'));
  393. if (operationInfos != null)
  394. {
  395. responseProtocol.ListOperations.AddRange(operationInfos.Select(x => new PatientOperationProtocol
  396. {
  397. Key = x.Key.GetValueOrDefault().ToString(),
  398. OperationName = SubString(x.OperationName, 10),
  399. PatientCode = x.PatientInfo.PatientId,
  400. Age = GetAge(x.PatientInfo.Birthday),
  401. Gender = GetGender(x.PatientInfo.Gender),
  402. OperationPart = "-",
  403. PatientName = x.PatientInfo.Name,
  404. }));
  405. }
  406. responseData = responseProtocol;
  407. }
  408. }
  409. catch (Exception ex)
  410. {
  411. Log("查询手术排班信息出错:" + ex.Message, -1);
  412. }
  413. break;
  414. case EleMedKitCommand.RequestPatientOperationUsage:
  415. try
  416. {
  417. ResponseOperationUsageProtocol responseUsageData = new ResponseOperationUsageProtocol();
  418. RequestOperationUsageProtocol requestUsageProtocol = (RequestOperationUsageProtocol)curPocket.Data.ProtocolDataInfo;
  419. using (TransactionScope transaction = new TransactionScope())
  420. {
  421. using (ConnectionSessionScope conn = new ConnectionSessionScope())
  422. {
  423. #region 数据验证
  424. responseUsageData.EleMedKitCode = requestUsageProtocol.EleMedKitCode;
  425. //检查药品列表
  426. if (requestUsageProtocol.ListDrugs == null
  427. || requestUsageProtocol.ListDrugs.Count == 0)
  428. {
  429. Log("用药信息为空", -1);
  430. break;
  431. }
  432. //检查用户信息
  433. String state;
  434. UserInfoBLL userInfoBLL = new UserInfoBLL();
  435. UserInfo? requestUser = GetRequestUserInfo(userInfoBLL, requestUsageProtocol.UserInfo, out state);
  436. if (state != null)
  437. {
  438. Log("检查用户信息不通过:" + state, -1);
  439. break;
  440. }
  441. //检查手术排班信息
  442. if (requestUsageProtocol.OperationInfo == null)
  443. {
  444. Log("手术排班信息为空", -1);
  445. break;
  446. }
  447. Guid operationKey;
  448. if (!Guid.TryParse(requestUsageProtocol.OperationInfo.Key, out operationKey))
  449. {
  450. Log("手术排班ID无效:" + requestUsageProtocol.OperationInfo.Key, -1);
  451. break;
  452. }
  453. PatientOperationInfoBLL patientOperationInfoBLL = new PatientOperationInfoBLL();
  454. PatientOperationInfo requestOperation = patientOperationInfoBLL.Get(new PatientOperationInfo
  455. {
  456. Key = operationKey
  457. });
  458. if (requestOperation == null)
  459. {
  460. Log("未找到请求的手术排班:" + requestUsageProtocol.OperationInfo.Key, -1);
  461. break;
  462. }
  463. #endregion
  464. OperationTakeItemBagBLL operationTakeItemBagBLL = new OperationTakeItemBagBLL();
  465. OperationTakeItemBag curTakeBag = operationTakeItemBagBLL.GetByOperation(requestOperation);
  466. #region 保存OperationTakeItemBag
  467. if (curTakeBag == null)
  468. {
  469. curTakeBag = new OperationTakeItemBag();
  470. curTakeBag.CreateTime = DateTime.Now;
  471. curTakeBag.CreateBy = requestUser.Key;
  472. curTakeBag.Key = Guid.NewGuid();
  473. curTakeBag.OperationKey = requestOperation.Key;
  474. curTakeBag.SnapshotKey = Guid.NewGuid();
  475. curTakeBag.Ext02 = requestUsageProtocol.RoomCode;
  476. curTakeBag.Ext05 = requestUsageProtocol.EleMedKitCode;
  477. operationTakeItemBagBLL.Save(curTakeBag);
  478. }
  479. //else
  480. //{
  481. // Log("重复接收到用药信息:" + requestOperation.OperationId, -1);
  482. // break;
  483. //}
  484. #endregion
  485. PortableStorageItemBLL portableStorageItemBLL = new PortableStorageItemBLL();
  486. PortableStorageItemLotBLL portableStorageItemLotBLL = new PortableStorageItemLotBLL();
  487. StorageSpaceItemTransactionBLL storageSpaceItemTransactionBLL = new StorageSpaceItemTransactionBLL();
  488. SPILItemTransactionBLL sPILItemTransactionBLL = new SPILItemTransactionBLL();
  489. OperationTakeItemBLL operationTakeItemBLL = new OperationTakeItemBLL();
  490. IEnumerable<OperationTakeItem> takeHistory = operationTakeItemBLL.ListTakeItemsByTakeBag(curTakeBag);
  491. Boolean drugHandleFlag = true;
  492. #region 根据请求的标签获取对应库存
  493. List<Tuple<PortableStorageItemLot, Int32>> usageWithInventory = new List<Tuple<PortableStorageItemLot, Int32>>();
  494. foreach (DrugUsageProtocol d in requestUsageProtocol.ListDrugs)
  495. {
  496. OperationTakeItem? historyItem = takeHistory == null
  497. ? null
  498. : takeHistory.FirstOrDefault(x => x.ItemKey.GetValueOrDefault().ToString() == d.DrugKey);
  499. if (historyItem != null)
  500. {
  501. Log($"重复接收到药品用药信息,药品:{historyItem.Item.ItemCommonName}");
  502. }
  503. else
  504. {
  505. if (d.UsageCode == DrugUsageCodes.Used
  506. || d.UsageCode == DrugUsageCodes.Lost
  507. || d.UsageCode == DrugUsageCodes.LastUsed)
  508. {
  509. PortableStorageItemLot inventoryLot = portableStorageItemLotBLL.GetByItemBarcode(d.Barcode);
  510. //if (inventoryLot.PortableStorageItem.Item.Key.ToString() != d.DrugKey)
  511. //{
  512. // Log("上传的药品ID与数据库不符:" + d.DrugKey, -1);
  513. // drugHandleFlag = false;
  514. // break;
  515. //}
  516. if (inventoryLot != null)
  517. {
  518. EleMedKitDrugUsageStates usageState = EleMedKitDrugUsageStates.Normal;
  519. switch (d.UsageCode)
  520. {
  521. case DrugUsageCodes.Lost:
  522. usageState = EleMedKitDrugUsageStates.Lost;
  523. break;
  524. case DrugUsageCodes.LastUsed:
  525. usageState = EleMedKitDrugUsageStates.LastUsed;
  526. break;
  527. }
  528. usageWithInventory.Add(new Tuple<PortableStorageItemLot, int>(inventoryLot, (Int32)usageState));
  529. }
  530. else
  531. {
  532. Log("未找到药品条码标签:" + d.Barcode, -1);
  533. //drugHandleFlag = false;
  534. // break;
  535. }
  536. }
  537. }
  538. }
  539. if (!drugHandleFlag)
  540. {
  541. break;
  542. }
  543. #endregion
  544. #region 更新库存和业务记录
  545. IEnumerable<IGrouping<Guid, Tuple<PortableStorageItemLot, Int32>>> inventoryLogGroup = usageWithInventory
  546. .GroupBy(x => x.Item1.LotKey.GetValueOrDefault());
  547. //保存OperationTakeItem
  548. foreach (IGrouping<Guid, Tuple<PortableStorageItemLot, Int32>> g in inventoryLogGroup)
  549. {
  550. OperationTakeItem operationTakeItem = new OperationTakeItem
  551. {
  552. Key = Guid.NewGuid(),
  553. SnapshotKey = Guid.NewGuid(),
  554. ItemKey = g.First().Item1.ItemKey,
  555. Ext01 = g.First().Item1.LotKey.GetValueOrDefault().ToString(),
  556. TakeBagKey = curTakeBag.Key,
  557. TakeQuantity = g.Count(),
  558. };
  559. operationTakeItemBLL.Save(operationTakeItem);
  560. //更新PortableStorageItem
  561. PortableStorageItem psi = g.First().Item1.PortableStorageItem;
  562. psi.CurrentQuantity = psi.CurrentQuantity.GetValueOrDefault() - g.Count();
  563. portableStorageItemBLL.Update(psi);
  564. //保存StorageSpaceItemTransaction
  565. StorageSpaceItemTransaction ssiTransaction = new StorageSpaceItemTransaction()
  566. {
  567. Key = Guid.NewGuid(),
  568. CreateBy = requestUser.Key,
  569. CreateTime = DateTime.Now,
  570. StorageSpaceItemKey = psi.Key,
  571. ItemTransactionKey = curTakeBag.Key,
  572. Ext01 = g.Count().ToString(),
  573. };
  574. storageSpaceItemTransactionBLL.Save(ssiTransaction);
  575. }
  576. //更新批号库存
  577. foreach (Tuple<PortableStorageItemLot, Int32> psil in usageWithInventory)
  578. {
  579. SPILItemTransaction sPILItemTransaction = new SPILItemTransaction()
  580. {
  581. Key = Guid.NewGuid(),
  582. StorageSpaceItemLotKey = psil.Item1.Key,
  583. Quantity = 1,
  584. ItemTransactionKey = curTakeBag.Key.GetValueOrDefault(),
  585. ItemLotKey = psil.Item1.LotKey,
  586. Ext01 = psil.Item1.Ext01,
  587. Ext09 = psil.Item2.ToString(),
  588. };
  589. sPILItemTransactionBLL.Save(sPILItemTransaction);
  590. portableStorageItemLotBLL.Delete(psil.Item1);
  591. }
  592. #endregion
  593. #region 更新手术状态
  594. //完成时间
  595. requestOperation.OperationOverTime = DateTime.Now;
  596. patientOperationInfoBLL.UpdateCurrent(requestOperation);
  597. #endregion
  598. transaction.Complete();
  599. }
  600. }
  601. responseData = responseUsageData;
  602. }
  603. catch (Exception ex)
  604. {
  605. Log(ex.Message, -1);
  606. }
  607. break;
  608. case EleMedKitCommand.RequestReturnMedKit:
  609. try
  610. {
  611. Log("请求归还");
  612. ResponseMedKitReturnProtocol responseReturnProtocol = new ResponseMedKitReturnProtocol();
  613. RequestMedKitReturnProtocol requestReturnProtocol = (RequestMedKitReturnProtocol)curPocket.Data.ProtocolDataInfo;
  614. responseReturnProtocol.EleMedKitCode = requestReturnProtocol.EleMedKitCode;
  615. String? state = null;
  616. StorageSpacePortableLink? requestStorageLink = null;
  617. UserInfo? requestUser = null;
  618. using (ConnectionSessionScope conn = new ConnectionSessionScope())
  619. {
  620. requestStorageLink = GetRequestStorageLink(null, requestReturnProtocol.EleMedKitCode, out state);
  621. if (state != null
  622. || requestStorageLink == null)
  623. {
  624. Log("检查药箱信息不通过", -1);
  625. break;
  626. }
  627. UserInfoBLL userInfoBLL = new UserInfoBLL();
  628. requestUser = GetRequestUserInfo(userInfoBLL, requestReturnProtocol.UserInfo, out state);
  629. if (state != null || requestUser == null)
  630. {
  631. Log("检查用户信息不通过:" + state, -1);
  632. break;
  633. }
  634. }
  635. responseReturnProtocol.State = new StateProtocol()
  636. {
  637. IsSuccess = true
  638. };
  639. responseData = responseReturnProtocol;
  640. state = MQService.Singleton.RequestReturnMedKit(requestUser, requestStorageLink);
  641. if (state != null)
  642. {
  643. Log("向药箱柜发送退药请求失败:" + state, -1);
  644. }
  645. }
  646. catch (Exception ex)
  647. {
  648. Log("归还出错:" + ex.Message, -1);
  649. }
  650. break;
  651. case EleMedKitCommand.RequestDrugLend:
  652. try
  653. {
  654. Log("请求借药");
  655. RequestDrugLendProtocol requestLendProtocol = (RequestDrugLendProtocol)curPocket.Data.ProtocolDataInfo;
  656. StorageSpacePortableLink? requestStorageLink = null;
  657. String? state = null;
  658. using (ConnectionSessionScope conn = new ConnectionSessionScope())
  659. {
  660. requestStorageLink = GetRequestStorageLink(null, requestLendProtocol.EleMedKitCode, out state);
  661. if (state != null
  662. || requestStorageLink == null)
  663. {
  664. Log("检查药箱信息不通过", -1);
  665. break;
  666. }
  667. //根据药箱定位,获取最近的手术间
  668. PortableStorageTrackBLL portableStorageTrackBLL = new PortableStorageTrackBLL();
  669. PortableStorageTrack lastTrack = portableStorageTrackBLL.GetLastTrackByItem(requestLendProtocol.EleMedKitCode.TrimStart('0'));
  670. if (lastTrack == null)
  671. {
  672. Log($"未找到药箱[{requestLendProtocol.EleMedKitCode}]最近的定位信息");
  673. break;
  674. }
  675. OperationRoomBLL operationRoomBLL = new OperationRoomBLL();
  676. RDH.Data.Models.OperationRoom currentRoom = operationRoomBLL.GetOperationRoomBySignalStation(lastTrack.TrackCode.PadLeft(3, '0'));
  677. if (currentRoom == null)
  678. {
  679. Log($"未找到基站[{lastTrack.TrackCode}]配置的手术间");
  680. break;
  681. }
  682. //根据手术间,获取最近的借药信息
  683. SPILItemTransactionBLL sPILItemTransactionBLL = new SPILItemTransactionBLL();
  684. IEnumerable<SPILItemTransaction> transactions = sPILItemTransactionBLL.ListMekKitDrugLendTransactionByRoom(currentRoom.RoomName.TrimStart('0'));
  685. if (transactions == null || transactions.Count() == 0)
  686. {
  687. Log($"未找到手术间[{currentRoom.RoomName}]的借药记录");
  688. break;
  689. }
  690. //生成返回信息
  691. ResponseLendDrugProtocol response = new ResponseLendDrugProtocol();
  692. response.EleMedKitCode = requestLendProtocol.EleMedKitCode;
  693. response.ListLendResult = new List<SimpleDrugLotProtocol>();
  694. foreach (SPILItemTransaction t in transactions)
  695. {
  696. response.ListLendResult.Add(new SimpleDrugLotProtocol
  697. {
  698. DrugKey = t.ItemTransaction.ItemKey.ToString(),
  699. DrugLotCode = t.ItemLotInfo.LotNo,
  700. Barcode = t.Ext06
  701. });
  702. }
  703. responseData = response;
  704. //更新借药成功的状态
  705. ItemTransactionBLL itemTransactionBLL = new ItemTransactionBLL();
  706. ItemTransaction itemTransaction = transactions.First().ItemTransaction;
  707. itemTransaction.Ext10 = "1";
  708. itemTransactionBLL.Update(itemTransaction);
  709. #region 更新药箱库存
  710. PortableStorageItemBLL portableStorageItemBLL = new PortableStorageItemBLL();
  711. PortableStorageItemLotBLL portableStorageItemLotBLL = new PortableStorageItemLotBLL();
  712. foreach (SPILItemTransaction t in transactions)
  713. {
  714. PortableStorageItem inventoryItem = portableStorageItemBLL.GetByStorageAndItem(
  715. requestStorageLink.PortableStorage.Code,
  716. t.ItemTransaction.ItemKey.GetValueOrDefault());
  717. if (inventoryItem != null)
  718. {
  719. inventoryItem.CurrentQuantity = inventoryItem.CurrentQuantity.GetValueOrDefault() + 1;
  720. portableStorageItemBLL.Update(inventoryItem);
  721. PortableStorageItemLot inventoryItemLot = new PortableStorageItemLot();
  722. inventoryItemLot.Quantity = 1;
  723. inventoryItemLot.Key = Guid.NewGuid();
  724. inventoryItemLot.ItemKey = t.ItemTransaction.ItemKey;
  725. inventoryItemLot.LotKey = t.ItemLotKey;
  726. inventoryItemLot.CreateTime = DateTime.Now;
  727. inventoryItemLot.PortableStorageItemkey = inventoryItem.Key;
  728. inventoryItemLot.Ext01 = t.Ext06;
  729. portableStorageItemLotBLL.Save(inventoryItemLot);
  730. }
  731. }
  732. #endregion
  733. #region 测试
  734. //ResponseLendDrugProtocol response = new ResponseLendDrugProtocol();
  735. //response.EleMedKitCode = requestLendProtocol.EleMedKitCode;
  736. //response.ListLendResult = new List<SimpleDrugLotProtocol>();
  737. //response.ListLendResult.Add(new SimpleDrugLotProtocol()
  738. //{
  739. // Barcode = "E00000000000000000000011",
  740. // DrugKey = "81992454-f7a9-4385-aae5-78a3ce7af412",
  741. // DrugLotCode = "20230807",
  742. //});
  743. //response.ListLendResult.Add(new SimpleDrugLotProtocol()
  744. //{
  745. // Barcode = "E00000000000000000000002",
  746. // DrugKey = "39383086-f0aa-4ed0-bbe8-e1bf7fba719f",
  747. // DrugLotCode = "20230817",
  748. //});
  749. //responseData = response;
  750. #endregion
  751. }
  752. }
  753. catch (Exception ex)
  754. {
  755. Log("借药出错:" + ex.Message, -1);
  756. }
  757. break;
  758. case EleMedKitCommand.RequestStartPatientOperation:
  759. try
  760. {
  761. Log("开启手术");
  762. RequestStartPatientOperationProtocol requestLendProtocol = (RequestStartPatientOperationProtocol)curPocket.Data.ProtocolDataInfo;
  763. StorageSpacePortableLink? requestStorageLink = null;
  764. String? state = null;
  765. using (ConnectionSessionScope conn = new ConnectionSessionScope())
  766. {
  767. requestStorageLink = GetRequestStorageLink(null, requestLendProtocol.EleMedKitCode, out state);
  768. if (state != null
  769. || requestStorageLink == null)
  770. {
  771. Log("检查药箱信息不通过", -1);
  772. break;
  773. }
  774. #region 检查手术ID
  775. Guid operationKey;
  776. if (!Guid.TryParse(requestLendProtocol.PatientOperationID, out operationKey))
  777. {
  778. Log("手术排班ID无效:" + requestLendProtocol.PatientOperationID, -1);
  779. break;
  780. }
  781. PatientOperationInfoBLL patientOperationInfoBLL = new PatientOperationInfoBLL();
  782. PatientOperationInfo requestOperation = patientOperationInfoBLL.Get(new PatientOperationInfo
  783. {
  784. Key = operationKey
  785. });
  786. if (requestOperation == null)
  787. {
  788. Log("未找到请求的手术排班:" + requestLendProtocol.PatientOperationID, -1);
  789. break;
  790. }
  791. #endregion
  792. requestOperation.ClientTime = DateTime.Now;
  793. patientOperationInfoBLL.Update(requestOperation);
  794. }
  795. }
  796. catch (Exception ex)
  797. {
  798. Log("开启手术出错:" + ex.Message, -1);
  799. }
  800. break;
  801. }
  802. if (responseData != null)
  803. {
  804. Log("服务器反馈:" + responseData.ToString());
  805. Byte[] responseBytes = _encoding.GetBytes(responseData.ToString());
  806. try
  807. {
  808. _tcpService.SendAsync(curPocket.ClientId, responseBytes, 0, responseBytes.Length);
  809. curPocket.IsHandled = true;
  810. DebugHelper.Log("已处理消息");
  811. RemovePocket(curPocket);
  812. }
  813. catch (Exception ex)
  814. {
  815. RemovePocket(curPocket);
  816. Log("服务器反馈出错:" + ex.Message, -1);
  817. }
  818. }
  819. else
  820. {
  821. DebugHelper.Log("未处理的消息");
  822. RemovePocket(curPocket);
  823. }
  824. Thread.Sleep(1);
  825. }
  826. else
  827. {
  828. Thread.Sleep(1000);
  829. }
  830. }
  831. }
  832. private Pocket? PeekData()
  833. {
  834. lock (Pockets)
  835. {
  836. return Pockets.FirstOrDefault();
  837. }
  838. }
  839. private void RemovePocket(Pocket pocket)
  840. {
  841. lock (Pockets)
  842. {
  843. Application.Current.Dispatcher.Invoke(() =>
  844. {
  845. try
  846. {
  847. Pockets.Remove(pocket);
  848. DebugHelper.Log("删除消息");
  849. }
  850. catch (Exception ex)
  851. {
  852. DebugHelper.Log("删除消息失败:" + ex.Message);
  853. }
  854. });
  855. }
  856. }
  857. private void Log(String content, Int32 logLevel = 0)
  858. {
  859. if (Thread.CurrentThread.ManagedThreadId != Application.Current.Dispatcher.Thread.ManagedThreadId)
  860. {
  861. Application.Current.Dispatcher.Invoke(() =>
  862. {
  863. Log(content, logLevel);
  864. });
  865. }
  866. else
  867. {
  868. Serilog.Log.Debug(content, logLevel);
  869. this.ListLogs.Add(new LogModel()
  870. {
  871. Content = content,
  872. LogLevel = logLevel
  873. });
  874. if (this.ListLogs.Count > 100)
  875. {
  876. this.ListLogs.RemoveAt(0);
  877. }
  878. }
  879. }
  880. #region 业务处理
  881. private String GetAge(DateTime birth)
  882. {
  883. Int32 year = DateTime.Now.Year - birth.Year,
  884. month = DateTime.Now.Month - birth.Month,
  885. day = DateTime.Now.Day - birth.Day;
  886. if (year > 0)
  887. {
  888. if (month >= 0)
  889. {
  890. if (day >= 0)
  891. {
  892. return year.ToString() + "岁";
  893. }
  894. }
  895. if (year - 1 > 0)
  896. {
  897. return (year - 1).ToString() + "岁";
  898. }
  899. month += 12;
  900. }
  901. if (month > 0)
  902. {
  903. return month.ToString() + "月";
  904. }
  905. return day.ToString() + "天";
  906. }
  907. private String GetGender(Boolean flag)
  908. {
  909. return flag ? "女" : "男";
  910. }
  911. private String SubString(String source, Int32 maxLength)
  912. {
  913. return source == null
  914. ? String.Empty
  915. : source.Length > maxLength
  916. ? source.Substring(0, maxLength) + ".."
  917. : source;
  918. }
  919. //获取指定药箱的类型代码
  920. private String GetPortableTypeCode(StorageSpacePortableLink link)
  921. {
  922. if (_listStorageTypes != null)
  923. {
  924. PortableStorageType? storageType = _listStorageTypes.FirstOrDefault(x => x.TypeName == link.Ext02);
  925. if (storageType != null)
  926. {
  927. return storageType.TypeCode;
  928. }
  929. }
  930. return "X";
  931. }
  932. //根据请求的用户信息,获取用户数据
  933. private UserInfo? GetRequestUserInfo(UserInfoBLL userInfoBLL, UserInfoProtocol? requestUserData, out String? state)
  934. {
  935. if (requestUserData == null)
  936. {
  937. state = "传入的用户信息无效";
  938. return null;
  939. }
  940. //避免药箱bug,当传入的usercode为空时,使用默认的管理员账号
  941. if (String.IsNullOrEmpty(requestUserData.UserCode))
  942. {
  943. requestUserData.UserCode = "admin";
  944. }
  945. UserInfo? rlt = userInfoBLL.GetByUserId(requestUserData.UserCode);
  946. if (rlt == null)
  947. {
  948. state = "未找到用户信息:" + requestUserData.UserCode;
  949. return null;
  950. }
  951. state = null;
  952. return rlt;
  953. }
  954. private StorageSpacePortableLink? GetRequestStorageLink(StorageSpacePortableLinkBLL? storageSpacePortableLinkBLL, String? medKitCode, out String? state)
  955. {
  956. Int32 codeNumber;
  957. if (!Int32.TryParse(medKitCode, out codeNumber))
  958. {
  959. state = "请求的药箱号为空";
  960. return null;
  961. }
  962. if (storageSpacePortableLinkBLL == null)
  963. {
  964. storageSpacePortableLinkBLL = new StorageSpacePortableLinkBLL();
  965. }
  966. StorageSpacePortableLink? rlt = storageSpacePortableLinkBLL.GetByStorageCode(null, codeNumber.ToString());
  967. if (rlt == null)
  968. {
  969. state = "未找到设备信息";
  970. return null;
  971. }
  972. state = null;
  973. return rlt;
  974. }
  975. private PortableStorageItem? GetRequestPortableItem(PortableStorageItemBLL? portableStorageItemBLL, StorageSpacePortableLink storageLink, Guid itemKey)
  976. {
  977. if (portableStorageItemBLL == null)
  978. {
  979. portableStorageItemBLL = new PortableStorageItemBLL();
  980. }
  981. PortableStorageItem? rlt = portableStorageItemBLL.GetByStorageAndItem(storageLink.PortableStorageKey.GetValueOrDefault(), itemKey);
  982. return rlt;
  983. }
  984. #endregion
  985. #endregion
  986. }
  987. }