HKC_Blazor/MasaBlazorApp3/Pages/DrawerTake.razor

605 lines
27 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

@page "/take/drawer"
@using MasaBlazorApp3.Pojo.Config;
@using MasaBlazorApp3.Util;
@using Microsoft.Extensions.Options;
@using Newtonsoft.Json;
@using log4net;
<style>
.rz-custom-header {
width: 100%;
}
</style>
<RadzenStack Orientation="Orientation.Horizontal">
<div class="row justify-content-center">
@if (DrawerNos.Count() > 8)
{
<div class="col-12 row justify-content-center align-items-center text-center" style="background: url('/images/box-16.jpg') no-repeat; background-size: 100% 100%; width: 380px; height:650px">
<div class="row justify-content-around align-items-center" style="margin-top: 220px; height: 430px;">
@foreach (int i in DrawerNos)
{
<RadzenButton class="col-5" Click="@(() => SelectDrawer(i))" Text="@i.ToString()" Disabled="@(status > 0)" Shade="Shade.Light" Variant="@(drawerNo !=i ? Variant.Outlined : Variant.Flat)" />
}
</div>
</div>
}
else
{
<div class="col-12 row justify-content-center align-items-center text-center" style="background: url('/images/box.png') no-repeat; background-size: 100% 100%; width: 380px; height:650px">
<div class="row justify-content-around align-items-center" style="margin-top: 220px; height: 430px;">
@foreach (int i in DrawerNos)
{
<RadzenButton class="col-12" Click="@(() => SelectDrawer(i))" Text="@i.ToString()" Disabled="@(status > 0)" Shade="Shade.Light" Variant="@(drawerNo !=i ? Variant.Outlined : Variant.Flat)" />
}
</div>
</div>
}
</div>
<RadzenDataGrid @ref="grid" Style="width:66vw; overflow:auto"
LoadData="@LoadData"
IsLoading="@isLoading"
Count="@count"
EmptyText="无数据"
Data="@channels"
AllowColumnResize="true" AllowAlternatingRows="false"
CellClick="@((DataGridCellMouseEventArgs<ChannelStock> args) => OnCellClick(args))"
AllowPaging="true" PageSize="10" PagerHorizontalAlign="HorizontalAlign.Left" ShowPagingSummary="true" PagingSummaryFormat="{0}/{1} 共{2}条数据">
<HeaderTemplate>
<RadzenRow JustifyContent="JustifyContent.End">
@if (status < 3)
{
if (setting.Value.returnDrawer != null && setting.Value.returnDrawer.Contains(drawerNo))
{
<RadzenButton IsBusy="@(status>0)" BusyText="取空瓶中。。。" ButtonStyle="ButtonStyle.Warning" Variant="Variant.Flat" Shade="Shade.Light" Text="取空瓶" Click="@OpenDrawer" />
}
else
{
<RadzenButton IsBusy="@(status>0)" BusyText="取药中。。。" ButtonStyle="ButtonStyle.Warning" Variant="Variant.Flat" Shade="Shade.Light" Text="取药" Click="@OpenDrawer" />
}
}
@if (status == 3)
{
if (setting.Value.returnDrawer != null && setting.Value.returnDrawer.Contains(drawerNo))
{ }
else
{
<RadzenLabel Text="入库药箱" Component="BoxList" />
<RadzenDropDownDataGrid AllowVirtualization="true" Name="BoxColorList" TValue="BoxModel" Data="@BoxColorList" Value="BoxColor" Style="width: 7vw;"
ValueChanged="@((args) => OnColorChanged(args))" AllowFiltering="false"
AllowFilteringByAllStringColumns="true" TextProperty="药箱号">
<Template>
@((context as BoxModel).BoxNo == 1 ? "白" : (context as BoxModel).BoxNo == 3 ? "非常规" : "绿")
</Template>
<Columns>
<RadzenDropDownDataGridColumn Property="BoxNo" Title="药箱颜色" Sortable="false" />
</Columns>
</RadzenDropDownDataGrid>
<RadzenDropDownDataGrid AllowVirtualization="true" Name="BoxList" TValue="BoxModel" Data="@BoxList" Value="BoxNum" Style="width: 15vw;"
ValueChanged="@((args) => OnBoxChanged(args))" AllowFilteringByAllStringColumns="true" TextProperty="药箱号">
<Template>
@(
(context as BoxModel).BoxName == 99 ? "急诊药盒" : (context as BoxModel).BoxName == 111 ? "恢复室药盒" :
(context as BoxModel).BoxName == 31 ? "胃镜药盒" :
(context as BoxModel).BoxName == 32 ? "导管药盒" :
(context as BoxModel).BoxName == 33 ? "生殖药盒" :
(context as BoxModel).BoxName == 34 ? "妇门药盒" : (context as BoxModel).BoxName + "-" + ((context as BoxModel).BoxNo == 1 ? "白" : "绿")
)
</Template>
<Columns>
<RadzenDropDownDataGridColumn Property="BoxName" Title="药箱号" Sortable="false" />
</Columns>
</RadzenDropDownDataGrid>
}
<RadzenButton Visible="@CompleteIsEnable" ButtonStyle="ButtonStyle.Warning" Variant="Variant.Flat" Shade="Shade.Light" Text="完成" Click="@TakeFinish" />
}
@if (status > 0 && status <= 3)
{
<RadzenButton Visible="@CancleIsEnable" Variant="Variant.Flat" Text="取消" Click="@Cancel" Style="width: 120px" />
}
</RadzenRow>
</HeaderTemplate>
<Columns>
<RadzenDataGridColumn Width="4vw" Title="库位" Property="ColNo"></RadzenDataGridColumn>
<RadzenDataGridColumn Width="15vw" Title="药品名称" Property="Drug.DrugName">
<Template Context="channel">
<RadzenText TextStyle="TextStyle.Subtitle2" class="mb-0">@channel.Drug?.DrugName</RadzenText>
<RadzenText TextStyle="TextStyle.Caption">@channel.Drug?.DrugSpec</RadzenText>
</Template>
</RadzenDataGridColumn>
<RadzenDataGridColumn Width="15vw" Title="批次" Property="ManuNo">
<Template Context="channel">
<RadzenText TextStyle="TextStyle.Subtitle2" class="mb-0">@channel.ManuNo</RadzenText>
<RadzenText TextStyle="TextStyle.Caption">@channel.EffDate</RadzenText>
</Template>
</RadzenDataGridColumn>
<RadzenDataGridColumn Title="库存" Width="10vw" Property="Quantity">
<Template Context="channel">
<RadzenButton ButtonStyle="ButtonStyle.Info" Size="ButtonSize.Medium" Variant="Variant.Flat" Shade="Shade.Lighter" class="m-1" Text="@channel.Quantity.ToString()" />
</Template>
</RadzenDataGridColumn>
<RadzenDataGridColumn MinWidth="15vw" Title="取药数量" Property="TakeQuantity">
<HeaderTemplate>
<div style="text-align: center;">
取药<br>数量
</div>
</HeaderTemplate>
<EditTemplate Context="channel">
@if (channel.BoardType.ToString().Contains("2") || channel.BoardType.ToString().Contains("3"))
{
@channel.TakeQuantity
}
else
{
<RadzenNumeric Style="display: block" Min="0" Max="@channel.Quantity" Name="Quantity" @bind-Value=@channel.TakeQuantity />
@* <RadzenNumericRangeValidator Style="position: absolute;z-index: 9999;" Min="0" Max="@cs.Quantity" Text="请填写正确的取出数量" Component="Quantity" Popup="true" /> *@
}
</EditTemplate>
</RadzenDataGridColumn>
</Columns>
</RadzenDataGrid>
</RadzenStack>
@code {
@inject IChannelListDao channelListDao;
@inject NavigationManager na;
@inject PortUtil PortUtil;
@inject NotificationService _message
@inject IOptions<DrawerConfig> setting;
@inject IOptions<PortConfig> portSetting;
@inject IOrderInfoDao orderInfoDao;
int status = 0;
int drawerNo = 1;
RadzenDataGrid<ChannelStock> grid;
private List<ChannelStock>? channels;
bool isLoading;
int count;
int[] DrawerNos = new int[] { 1, 2, 3, 4, 5, 6, 7, 8 };
int[] BeforeQuantity = new int[9];
int[] AfterQuantity = new int[9];
// 当前操作的库位号列表
public List<int> ColNos { get; set; } = new List<int>();
int currentCol = 0;
bool CompleteIsEnable = true;
bool CancleIsEnable = true;
BoxModel BoxNum;
BoxModel BoxColor;
//全部药盒集合
List<BoxModel> AllBoxList = new List<BoxModel>();
//药盒集合
List<BoxModel> BoxList = new List<BoxModel>();
//药盒颜色集合
List<BoxModel> BoxColorList = new List<BoxModel>()
{
new BoxModel{BoxNo=1,BoxName=1 },
new BoxModel{BoxNo=2 ,BoxName=1},
new BoxModel{BoxNo=3 ,BoxName=1}
};
private readonly ILog logger = LogManager.GetLogger(typeof(DrawerTake));
protected override async Task OnInitializedAsync()
{
BoxColor = BoxColorList.FirstOrDefault();
AllBoxList = await orderInfoDao.GetOperationNum(0);
BoxList = AllBoxList.Where(bl => bl.BoxNo == BoxColor.BoxNo && bl.BoxName <= 30).ToList();
BoxNum = AllBoxList.FirstOrDefault();
await base.OnInitializedAsync();
}
async Task LoadData(LoadDataArgs args)
{
isLoading = true;
// var result = await channelListDao.GetChannelStockByDrawerNo(drawerNo, 1);
var result = await channelListDao.GetChannelStockByDrawerNoWithDrawers(drawerNo, 1);
DrawerNos = result.DrawerArray;
// Update the Data property
channels = result.ChannelStocks;
// Update the count
count = result.ChannelStocks.Count;
isLoading = false;
}
private async Task OnColorChanged(object value)
{
if ((((BoxModel)value).BoxNo) == 3)
{
BoxList = AllBoxList.Where(bl => bl.BoxName > 30).ToList();
BoxNum = BoxList.FirstOrDefault();
await InvokeAsync(StateHasChanged);
}
else
{
BoxList = AllBoxList.Where(bl => bl.BoxNo == ((BoxModel)value).BoxNo && bl.BoxName <= 30).ToList();
BoxNum = BoxList.FirstOrDefault();
}
}
//药箱选中修改
private async Task OnBoxChanged(object value)
{
// BoxList = BoxList.Where(bl => bl.BoxNo == ((BoxModel)value).BoxNo && bl.BoxName == ((BoxModel)value).BoxName).ToList();
BoxNum = (BoxModel)value;
}
async Task OpenDrawer()
{
this.status = 1;
PortUtil.PowerOn(this.drawerNo);
await Task.Delay(portSetting.Value.delayTime);
PortUtil.DrawerNo = this.drawerNo;
// 根据抽屉类型来决定打开前是否需要查询数量
var promiseUtil = new PromiseUtil<object>();
await promiseUtil.taskAsyncLoop(500, null, async (data, next, stop) =>
{
try
{
if (this.status == 0)
{
stop();
}
// 开启抽屉
else if (this.status == 1)
{
// 判断是否为单支抽屉
if (setting.Value.single != null && setting.Value.single.Contains(this.drawerNo))
{
byte[] quantity = await PortUtil.CheckQuantityByDrawer(this.drawerNo);
BeforeQuantity = quantity.Select(it => Convert.ToInt32(it)).ToArray().Skip(3).Take(9).ToArray();
logger.Info($"单支抽屉,开抽屉前检测数量【{string.Join(",", BeforeQuantity)}】");
}
var b = await PortUtil.OpenDrawerStatus(this.drawerNo);
if (b)
{
PortUtil.speechSynthesizer.SpeakAsyncCancelAll();
if (setting.Value.returnDrawer != null && setting.Value.returnDrawer.Contains(drawerNo))
{
PortUtil.SpeakAsync($"{drawerNo}号抽屉已经打开,请,取空瓶");
}
else
{
PortUtil.SpeakAsync($"{drawerNo}号抽屉已经打开,请,取药");
}
PortUtil.Operate = true;
this.status = 2;
next();
}
else
{
_message.Notify(
new NotificationMessage { Severity = NotificationSeverity.Error, Summary = "提示", Detail = $"抽屉【{drawerNo}】打开失败,请检测硬件", Duration = 4000 }
);
logger.Info($"抽屉打开失败");
RestData();
stop();
}
}
// 检测状态
else if (this.status == 2)
{
// 查询抽屉是否为关闭状态
var b = await PortUtil.CheckDrawerStatus2(drawerNo);
// 关闭则改变状态并终止循环
if (b)
{
PortUtil.speechSynthesizer.SpeakAsyncCancelAll();
if (setting.Value.returnDrawer != null && setting.Value.returnDrawer.Contains(drawerNo))
{
PortUtil.SpeakAsync($"取空瓶完成,请核对或录入正确的取出数量");
}
else
{
PortUtil.SpeakAsync($"取药完成,请核对或录入正确的取出数量");
}
// 判断是否为称重抽屉
if (setting.Value.weigh != null && setting.Value.weigh.Contains(this.drawerNo))
{
//关闭抽屉后获取称重稳定数量
await GetWeightQuantity();
}
logger.Info($"关闭抽屉,称重抽屉获取稳定数量后日志");
this.status = 3;
PortUtil.Operate = false;
stop();
}
else
{
if (setting.Value.box != null && setting.Value.box.Contains(this.drawerNo))
{
// 判断是否为称重抽屉
if (setting.Value.weigh != null && setting.Value.weigh.Contains(this.drawerNo))
{
//开抽屉前先查数
if (currentCol > 0)
{
int beforeQuantity = await PortUtil.CheckQuantityForSingle(currentCol);
BeforeQuantity[currentCol - 1] = beforeQuantity;
logger.Info($"BeforeQuantity:{currentCol}-{beforeQuantity}数量{string.Join(",", BeforeQuantity)}");
await Task.Delay(200);
ColNos.Add(currentCol);
}
}
//药盒抽屉,开药盒
if (currentCol > 0)
{
await PortUtil.OpenBoxByColNo(currentCol);
}
currentCol = 0;
}
if (setting.Value.single != null && setting.Value.single.Contains(this.drawerNo))
{
byte[] quantity = await PortUtil.CheckQuantityByDrawer(this.drawerNo);
AfterQuantity = quantity.Select(it => Convert.ToInt32(it)).ToArray().Skip(3).Take(9).ToArray();
logger.Info($"单支抽屉,抽屉未关检测数量【{string.Join(",", AfterQuantity)}】");
if (!BeforeQuantity.SequenceEqual(AfterQuantity))
{
channels.ForEach(cl =>
{
cl.TakeQuantity = this.BeforeQuantity[cl.ColNo - 1] - this.AfterQuantity[cl.ColNo - 1];
});
await InvokeAsync(StateHasChanged);
}
}
// 判断是否为称重抽屉
if (setting.Value.weigh != null && setting.Value.weigh.Contains(this.drawerNo))
{
//开抽屉后查数
for (int i = 0; i < ColNos.Count; i++)
{
int afterQuantity = await PortUtil.CheckQuantityForSingle(ColNos[i]);
AfterQuantity[ColNos[i] - 1] = afterQuantity;
logger.Info($"AfterQuantity:{ColNos[i]}-{afterQuantity}数量{string.Join(",", AfterQuantity)}");
}
if (!BeforeQuantity.SequenceEqual(AfterQuantity))
{
channels.Where(cl => ColNos.Contains(cl.ColNo)).ToList().ForEach(cl =>
{
cl.TakeQuantity = this.BeforeQuantity[cl.ColNo - 1] - this.AfterQuantity[cl.ColNo - 1];
});
await InvokeAsync(StateHasChanged);
}
}
next(); // continue iteration
}
}
}
catch (Exception e)
{
logger.Info($"抽屉取药发生错误,{e.Message}");
_message.Notify(
new NotificationMessage { Severity = NotificationSeverity.Error, Summary = "提示", Detail = $"发生错误,{e.Message}", Duration = 4000 }
);
if (setting.Value.single.Contains(this.drawerNo))
{
PortUtil.PowerOff(this.drawerNo);
}
RestData();
stop();
}
});
PortUtil.PowerOff(this.drawerNo);
}
//关闭抽屉后获取称重稳定数量
public async Task GetWeightQuantity()
{
List<int[]> finallyQuantity = new List<int[]>();
await new PromiseUtil<int>().taskAsyncLoop(200, 0, async (options, next, stop) =>
{
if (!PortUtil.Operate || this.status == 0)
{
stop();
CancleIsEnable = true;
CompleteIsEnable = true;
logger.Info($"停止循环{!PortUtil.Operate}-{this.status}");
}
else
{
try
{
logger.Info("关闭抽屉后获取称重稳定数量");
if (finallyQuantity.Count >= 10)
{
for (int i = 0; i < finallyQuantity.Count; i++)
{
logger.Info($"finallyQuantity{i} {string.Join(",", finallyQuantity[i])}");
}
if (AreAllArraysEqual(finallyQuantity))
{
stop();
CancleIsEnable = true;
CompleteIsEnable = true;
logger.Info("对比成功停止循环");
channels.ForEach(cl =>
{
cl.TakeQuantity = this.BeforeQuantity[cl.ColNo - 1] - this.AfterQuantity[cl.ColNo - 1];
});
await InvokeAsync(StateHasChanged);
}
else
{
finallyQuantity.RemoveAt(0);
CancleIsEnable = true;
next();
}
}
else
{
if (finallyQuantity.Count >= 9)
{
CancleIsEnable = true;
}
else
{
CancleIsEnable = false;
}
CompleteIsEnable = false;
PortUtil.DrawerNo = drawerNo;
PortUtil.ColNoLst = ColNos;
int[] quantity = await PortUtil.CheckQuantityByAddrForMulti();
AfterQuantity = quantity;
int[] Quantitys = new int[BeforeQuantity.Length];
for (int i = 0; i < BeforeQuantity.Length; i++)
{
Quantitys[i] = BeforeQuantity[i] - AfterQuantity[i];
}
finallyQuantity.Add(Quantitys);
logger.Info($"Quantity{string.Join(",", Quantitys)}");
if (!BeforeQuantity.SequenceEqual(AfterQuantity))
{
channels.ForEach(cl =>
{
cl.TakeQuantity = this.BeforeQuantity[cl.ColNo - 1] - this.AfterQuantity[cl.ColNo - 1];
});
await InvokeAsync(StateHasChanged);
}
next();
}
}
catch (Exception ex)
{
logger.Info($"关闭抽屉后获取称重稳定数量异常{ex.Message}");
next();
}
}
});
}
public bool AreAllArraysEqual(List<int[]> arrays)
{
if (arrays == null || arrays.Count == 0) return false;
// 取第一个数组作为参照进行比较
var referenceArray = arrays[0];
// 检查列表中除了第一个数组外的所有数组是否与第一个数组相等
return arrays.Skip(1).All(array => array.SequenceEqual(referenceArray));
}
void RestData()
{
PortUtil.PowerOff(this.drawerNo);
PortUtil.speechSynthesizer.SpeakAsyncCancelAll();
this.status = 0;
this.BeforeQuantity = new int[9];
this.AfterQuantity = new int[9];
ColNos.Clear();
currentCol = 0;
// InvokeAsync(StateHasChanged);
}
async Task TakeFinish()
{
if (channels.Any(cl => cl.TakeQuantity != 0))
{
CheckInfo<ChannelList> checkInfo = null;
// if(BoxNum!=null&&BoxNum.BoxNo!=0)
// {
// //查询本次加药的药盒里是否有绑该药,有则正常入库,无则提示无绑定不可添加
// checkInfo = await channelListDao.CheckBoxDrugInfo(BoxNum, channels.Where(cl => cl.TakeQuantity != 0).ToList());
// if (!string.IsNullOrEmpty(checkInfo.StrInfo))
// {
// _message.Notify(new NotificationMessage { Severity = NotificationSeverity.Error, Summary = "提示", Detail = $"该药盒中未绑定该批次药品无法添加", Duration = 4000 });
// logger.Error($"该药盒中未绑定该批次药品无法添加,数据{JsonConvert.SerializeObject(channels)}");
// return;
// }
// }
if (setting.Value.returnDrawer != null && setting.Value.returnDrawer.Contains(drawerNo))
{
BoxNum = null;
}
// 保存账册、操作记录
var b = await channelListDao.DrawerOperationFinish(channels.Where(cl => cl.TakeQuantity != 0).ToList(), 2, BoxNum, null);
if (!b)
{
_message.Notify(new NotificationMessage { Severity = NotificationSeverity.Error, Summary = "提示", Detail = $"数据保存失败", Duration = 4000 });
logger.Error($"抽屉取药保存数据库失败,数据{JsonConvert.SerializeObject(channels)}");
}
else
{
// 判断是否为标签抽屉
if (setting.Value.label != null && setting.Value.label.Contains(this.drawerNo))
{
//写标签数量
channels.Where(it => it.TakeQuantity > 0).ToList().ForEach(async it =>
{
await PortUtil.WriteQuantityMethod(it.Quantity - it.TakeQuantity, it.DrawerNo, it.ColNo);
});
}
}
}
//重置状态
this.RestData();
// 重新查询库存
await grid.Reload();
}
void Cancel()
{
RestData();
}
void SelectDrawer(int drawerNo)
{
this.drawerNo = drawerNo;
grid.Reload();
}
void OnCellClick(DataGridCellMouseEventArgs<ChannelStock> args)
{
// if (args.Data.BoardType.ToString().Contains("3"))
// {
// //是药盒抽屉则点击行,打开对应行的药盒
// if (!ColNos.Contains(args.Data.ColNo))
// {
// ColNos.Add(args.Data.ColNo);
// }
// }
// else
// {
// grid.EditRow(args.Data);
// }
if (setting.Value.box.Contains(args.Data.DrawerNo) && status != 2)
{
PortUtil.speechSynthesizer.SpeakAsyncCancelAll();
PortUtil.SpeakAsync("请先点取药按钮打开抽屉");
}
currentCol = args.Data.ColNo;
grid.EditRow(args.Data);
}
private IDisposable? registration;
protected override void OnAfterRender(bool firstRender)
{
if (firstRender)
{
registration = na.RegisterLocationChangingHandler(OnLocationChanging);
}
}
private ValueTask OnLocationChanging(LocationChangingContext context)
{
// 操作中不可跳转页面
if (status > 0)
{
context.PreventNavigation(); //阻止导航
}
return ValueTask.CompletedTask;
}
//在生命周期函数Dispose中移除订阅的事件并销毁非托管资源registration===========================================
public void Dispose()
{
registration?.Dispose();
}
}