添加项目文件。

This commit is contained in:
maqiao 2025-04-18 11:01:56 +08:00
parent 0682ae842d
commit 1a0aced391
123 changed files with 27251 additions and 0 deletions

25
MasaBlazorApp3.sln Normal file
View File

@ -0,0 +1,25 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.7.34024.191
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MasaBlazorApp3", "MasaBlazorApp3\MasaBlazorApp3.csproj", "{B589889C-FAEB-4394-A21D-DDCADF39382D}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{B589889C-FAEB-4394-A21D-DDCADF39382D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B589889C-FAEB-4394-A21D-DDCADF39382D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B589889C-FAEB-4394-A21D-DDCADF39382D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B589889C-FAEB-4394-A21D-DDCADF39382D}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {304B4C57-445A-464F-829B-444D21AFE355}
EndGlobalSection
EndGlobal

15
MasaBlazorApp3/App.razor Normal file
View File

@ -0,0 +1,15 @@
@namespace MasaBlazorApp3
<Router AppAssembly="@typeof(App).Assembly">
<Found Context="routeData">
<RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" />
<FocusOnNavigate RouteData="@routeData" Selector="h1" />
</Found>
<NotFound>
<LayoutView Layout="@typeof(MainLayout)">
<p role="alert">Sorry, there's nothing at this address.</p>
</LayoutView>
</NotFound>
</Router>

View File

@ -0,0 +1,35 @@
using Google.Protobuf.Compiler;
using LinqToDB;
using LinqToDB.Data;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using MasaBlazorApp3.Pojo;
namespace MasaBlazorApp3.DataAccess
{
public class AppDataConnection : DataConnection
{
public AppDataConnection(DataOptions<AppDataConnection> options)
: base(options.Options)
{
}
public ITable<User> User => this.GetTable<User>();
public ITable<Role> Role => this.GetTable<Role>();
public ITable<ChannelList> ChannelList => this.GetTable<ChannelList>();
public ITable<ChannelStock> ChannelStock => this.GetTable<ChannelStock>();
public ITable<DrugInfo> DrugInfo => this.GetTable<DrugInfo>();
public ITable<DrugManuNo> DrugManuNo => this.GetTable<DrugManuNo>();
public ITable<OrderInfo> OrderInfo => this.GetTable<OrderInfo>();
public ITable<OrderDetail> OrderDetail => this.GetTable<OrderDetail>();
public ITable<MachineRecord> MachineRecord => this.GetTable<MachineRecord>();
public ITable<InOutInvoice> InOutInvoice => this.GetTable<InOutInvoice>();
public ITable<AccountBook> AccountBook => this.GetTable<AccountBook>();
}
}

View File

@ -0,0 +1,14 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MasaBlazorApp3.DataAccess
{
public class ChannelStockWithDrawerCount<ChannelStock>
{
public int[] DrawerArray { get; set; }
public List<ChannelStock> ChannelStocks { get; set; } = new List<ChannelStock>();
}
}

View File

@ -0,0 +1,33 @@
using System;
using MasaBlazorApp3.Pojo;
namespace MasaBlazorApp3.DataAccess.Dao
{
public interface IChannelListDao
{
public Task<PageData<ChannelStock>> GetAllChannelList(int DrawerType, string drugName, int? take, int? skip);
public Task<List<ChannelStock>> GetChannelStockByDrugId(string DrugId);
public Task<List<ChannelList>> GetChannelListByDrawerNo(int DrawerNo);
public Task<List<ChannelStock>> GetChannelStockByDrawerNo(int DrawerNo, int Quantity = 0);
public Task<List<ChannelStock>> GetAllDrugChannelStock();
public Task<List<ChannelList>> GetAllDrugChannelList();
public Task<bool> DrawerOperationFinish(List<ChannelStock> Stocks, int type);
public Task<bool> UnBind(string id);
public Task<bool> Bind(ChannelStock Stock);
Task<PageMultiData<ChannelStock,DrugInfo>> GetAllChannelListWithDrug(int DrawerType, string drugName, int? take, int? skip);
Task<ChannelStockWithDrawerCount<ChannelStock>> GetChannelStockByDrawerNoWithDrawers(int DrawerNo, int Quantity = 0);
//盘点
public Task<bool> DrawerCheckFinish(List<ChannelStock> Stocks);
}
}

View File

@ -0,0 +1,34 @@
using MasaBlazorApp3.Pojo;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MasaBlazorApp3.DataAccess.Dao
{
public interface IDrugInfoDao
{
Task<List<DrugInfo>> GetAllDrugAndStock();
Task<List<DrugInfo>> GetAllDrug();
Task<PageData<DrugInfo>> GetAllDrug(string drugId, string drugName, int? take, int? skip);
//Task<List<DrugInfo>> GetAllDrugAndStockList();
Task<DrugManuNo> GetDrugManuNo(string drugId, string manuNo);
//添加药品信息
int AddDrugInfo(DrugInfo drugInfo);
//删除药品信息
Task<bool> DeleteDrugInfo(string drugId);
//修改药品信息
Task<bool> UpdateDrugInfo(DrugInfo drugInfo);
}
}

View File

@ -0,0 +1,19 @@
using MasaBlazorApp3.Pojo;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MasaBlazorApp3.DataAccess.Dao
{
public interface IDrugManuNoDao
{
//添加批次
int AddDrugManuNo(DrugManuNo drugManuNo);
//修改批次
bool UpdateDrugManuNo(DrugManuNo drugManuNo);
//删除批次
bool DeleteDrugManuNo(string id);
}
}

View File

@ -0,0 +1,23 @@
using MasaBlazorApp3.Pojo;
using MasaBlazorApp3.Pojo.Vo;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MasaBlazorApp3.DataAccess.Dao
{
public interface IInOutInvoiceDao
{
Task<PageData<InOutInvoice>> GetAllInvoiceByType(string invoiceNo, DateTime invoiceDate, int? take, int? skip, int type);
Task<List<InvoiceVo>> getTakeInfoByInvoiceNo(string invoiceNo);
Task<List<InvoiceVo>> getAddInfoByInvoiceNo(string invoiceNo);
Task<bool> InvoiceOutFinish(List<InvoiceVo> data);
Task<bool> InvoiceAddFinish(List<InvoiceVo> data);
}
}

View File

@ -0,0 +1,30 @@
using MasaBlazorApp3.Pojo;
using MasaBlazorApp3.Pojo.Vo;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MasaBlazorApp3.DataAccess.Dao
{
public interface IMachineRecordDao
{
int InsertMachineRecord(MachineRecord record);
Task<PageData<MachineRecord>> GetMachineRecordAsync(DateTime start, DateTime end, int operatorId, string drugId, int type, int? take, int? skip);
Task<PageData<MachineRecord>> GetCanReturnRecords(DateTime start, DateTime end, int operatorId, string drugId, int? take, int? skip);
Task<List<OperationVo<List<MachineRecord>>>> getReturnDrugInfoByRecords(List<MachineRecord> records);
Task<bool> ReturnDrugFinish(List<OperationVo<List<MachineRecord>>> datas);
Task<List<ChannelStock>> GetReturnEmpty();
Task<PageData<MachineRecord>> getReturnEmptyInfoByRecords(ChannelStock records);
Task<bool> ReturnEmptyFinish(List<MachineRecord> datas,ChannelStock channelStock);
Task<List<ChannelStock>> GetReturnEmptyWithCanReturnQuantiy();
}
}

View File

@ -0,0 +1,30 @@
using MasaBlazorApp3.Pojo;
using MasaBlazorApp3.Pojo.Vo;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MasaBlazorApp3.DataAccess.Dao
{
public interface IOrderInfoDao
{
public Task<PageData<OrderInfo>> GetAllOrderInfo(string OrderrNo, DateTime OrderDate, int? take, int? skip);
public Task<PageData<OrderInfo>> GetAllCanReturnOrderInfo(string OrderrNo, DateTime OrderDate, int? take, int? skip);
public Task<List<OrderDetail>> getDetailByOrderNo(string OrderrNo);
public Task<List<OrderTakeVo>> getTakeInfoByOrderNo(string OrderrNo);
public Task<bool> OrderTakeFinish(List<OrderTakeVo> datas);
public Task<bool> OrderReturnFinish(List<OperationVo<MachineRecord>> datas, string OrderrNo);
public Task<List<OperationVo<MachineRecord>>> getReturnInfoByOrderNo(string OrderrNo);
}
}

View File

@ -0,0 +1,18 @@
using MasaBlazorApp3.Pojo;
namespace MasaBlazorApp3.DataAccess.Dao
{
public interface IRoleDao
{
int InsertRole(Role role);
Task<Role> GetRoleById(int id);
bool UpdateRole(Role role);
bool DeleteRole(int id);
Task<PageData<Role>> GetRolesByName(string name, int? take, int? skip);
Task<List<Role>> GetAllRoles();
}
}

View File

@ -0,0 +1,17 @@
using MasaBlazorApp3.Pojo;
using MasaBlazorApp3.Pojo.Vo;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MasaBlazorApp3.DataAccess.Dao
{
interface ISelfTakeDao
{
Task<List<ChannelStock>> GetChannelStocksByDrug(List<DrugInfo> drugInfos);
Task<List<OrderTakeVo>> getTakeInfoByOrderNo(List<OrderDetail> orderDetails);
Task<bool> OrderTakeFinish(List<OrderTakeVo> datas,OrderInfo order);
}
}

View File

@ -0,0 +1,23 @@
using MasaBlazorApp3.Pojo;
namespace MasaBlazorApp3.DataAccess.Dao
{
public interface IUserDao
{
int InsertUser(User user);
Task<PageData<User>> GetAllByNickname(string nickname, int? take, int? skip);
User GetById(int id);
User GetByUsername(string username);
bool UpdateUser(User user);
bool DeleteeUser(int id);
//重置用户密码
bool ResetPassword(int id);
Task<bool> UpdateSign(int id, string sign);
}
}

View File

@ -0,0 +1,456 @@

using LinqToDB;
using log4net;
using MasaBlazorApp3.DataAccess.Dao;
using MasaBlazorApp3.Pojo;
using MasaBlazorApp3.Pojo.Config;
using MasaBlazorApp3.Pojo.Vo;
using MasaBlazorApp3.Port;
using Microsoft.Extensions.Options;
using Mysqlx.Crud;
using System.Data;
namespace MasaBlazorApp3.DataAccess.Impl
{
public class ChannelListDao : IChannelListDao
{
private AppDataConnection _connection;
private readonly SettingConfig _setting;
private GlobalStateService _globalStateService;
private readonly PortUtil _portUtil;
private readonly ILog logger = LogManager.GetLogger(typeof(ChannelListDao));
public ChannelListDao(AppDataConnection connection, IOptions<SettingConfig> setting, GlobalStateService globalStateService, PortUtil portUtil)
{
_globalStateService = globalStateService;
_connection = connection;
_setting = setting.Value;
_portUtil = portUtil;
}
public async Task<PageData<ChannelStock>> GetAllChannelList(int DrawerType, string drugName, int? take, int? skip)
{
var query = _connection.ChannelStock.AsQueryable();
if (DrawerType != 0)
{
query = query.Where(cl => cl.DrawerType == DrawerType);
}
if (!String.IsNullOrEmpty(drugName))
{
query = query.Where(cl => cl.Drug.DrugName.Equals(drugName));
}
//query = query.Where(cl => !String.IsNullOrEmpty(cl.DrugId));
query = query.Where(cl => cl.MachineId == _setting.machineId);
int pagedData = await query.CountAsync();
List<ChannelStock> list = await query
.LoadWith(cl => cl.Drug)
.LoadWith(cl => cl.Drug.Manus)
.LoadWith(cl => cl.drugManuNo)
.OrderBy((cl) => cl.DrawerNo)
.ThenBy((cl) => cl.ColNo)
.Skip((int)skip)
.Take((int)take)
.ToListAsync();
return new PageData<ChannelStock>()
{
TotalDesserts = pagedData,
Desserts = list
};
}
public async Task<List<ChannelStock>> GetChannelStockByDrugId(string DrugId)
{
var query = _connection.ChannelStock.AsQueryable();
return await query
.LoadWith(cs => cs.Drug)
.InnerJoin(
_connection.ChannelList.Where(cl => cl.MachineId.Equals(_setting.machineId)).Where(cl => cl.DrawerType == 1),
(cs, cl) => cs.ListId == cl.Id,
(cs, cl) => cs
)
.Where(cs => cs.DrugId == DrugId)
.Where(cs => cs.MachineId == _setting.machineId)
//.Where(cs => cs.Quantity > 0)
.OrderBy((cs) => cs.EffDate)
.ThenBy((cs) => cs.DrawerNo)
.ThenBy((cs) => cs.ColNo)
.ToListAsync();
}
public async Task<List<ChannelStock>> GetChannelStockByDrawerNo(int DrawerNo, int Quantity = 0)
{
var query = _connection.ChannelStock.AsQueryable()
.LoadWith(cs => cs.Drug)
.LoadWith(cs => cs.drugManuNo)
.LoadWith(cs => cs.Drug.Manus)
.Where(cs => cs.DrawerNo == DrawerNo)
.Where(cs => cs.DrugId != String.Empty )
.Where(cs => cs.DrawerType == 1)
.Where(cs => cs.MachineId == _setting.machineId);
if(Quantity > 0)
{
query = query.Where(cs => cs.Quantity > 0);
}
return await query
.OrderBy((cs) => cs.DrawerNo)
.ThenBy((cs) => cs.ColNo)
.ToListAsync();
}
public async Task<List<ChannelList>> GetChannelListByDrawerNo(int DrawerNo)
{
var query = _connection.ChannelList.AsQueryable();
return await query
.LoadWith(cl => cl.Drug)
.LoadWith(cl => cl.ChannelStocks.Where(cs => cs.Quantity > 0))
.Where(cl => cl.DrawerNo == DrawerNo)
.Where(cl => cl.DrawerType == 1)
.Where(cl => cl.MachineId == _setting.machineId)
.OrderBy((cl) => cl.DrawerNo)
.ThenBy((cl) => cl.ColNo)
.ToListAsync();
}
public async Task<List<ChannelStock>> GetAllDrugChannelStock()
{
var query = _connection.ChannelStock.AsQueryable();
return await query
.LoadWith(cs => cs.Drug)
.Where(cs => !String.IsNullOrEmpty(cs.DrugId))
.Where(cs => cs.DrawerType == 1)
.Where(cs => cs.MachineId == _setting.machineId)
.OrderBy((cs) => cs.DrugId)
.ThenBy((cs) => cs.EffDate)
.ThenBy((cs) => cs.DrawerNo)
.ThenBy((cs) => cs.ColNo)
.ToListAsync();
}
public async Task<List<ChannelList>> GetAllDrugChannelList()
{
var query = _connection.ChannelList.AsQueryable();
return await query
.LoadWith(cl => cl.Drug)
.LoadWith(cl => cl.ChannelStocks)
.Where(cl => !String.IsNullOrEmpty(cl.DrugId))
.Where(cl => cl.DrawerType == 1)
.Where(cl => cl.MachineId == _setting.machineId)
.OrderBy((cl) => cl.DrugId)
.ThenBy((cl) => cl.DrawerNo)
.ThenBy((cl) => cl.ColNo)
.ToListAsync();
}
public async Task<bool> DrawerOperationFinish(List<ChannelStock> Stocks, int type = 1)
{
try
{
_connection.BeginTransaction();
string InvoiceId = "DRAWER_" + CurrentTimeMillis();
var flag = true;
for (var i = 0; i < Stocks.Count; i++)
{
var stock = Stocks[i];
//var ManuNo = !stock.drugManuNo.ManuNo.Equals(stock.ManuNo) ? stock.drugManuNo.ManuNo : stock.ManuNo;
//var EffDate = !stock.drugManuNo.ManuNo.Equals(stock.ManuNo) ? stock.drugManuNo.EffDate : stock.EffDate;
var ManuNo = stock.ManuNo;
var EffDate = stock.EffDate;
// 出入库记录
int mid = _connection.InsertWithInt32Identity(new MachineRecord()
{
MachineId = _setting.machineId,
DrawerNo = stock.DrawerNo,
ColNo = stock.ColNo,
DrugId = stock.DrugId,
ManuNo = ManuNo,
EffDate = !String.IsNullOrEmpty(EffDate) ? DateTime.ParseExact(EffDate, "yyyy-MM-dd", System.Globalization.CultureInfo.CurrentCulture) : null,
OperationTime = DateTime.Now,
Type = type,
Quantity = type == 1? stock.AddQuantity : stock.TakeQuantity,
Operator = _globalStateService.Operator.Id,
Reviewer = _globalStateService.Reviewer?.Id ?? _globalStateService.Operator.Id,
InvoiceId = InvoiceId
});
// 更新库存
var stockQ = _connection.ChannelStock.Where(cs => cs.Id == stock.Id)
.Set(cs => cs.Quantity, type == 1 ? stock.Quantity + stock.AddQuantity : stock.Quantity - stock.TakeQuantity);
// 入库时如果库存为0则有可能会修改批次效期进行保存
if(type == 1 && stock.Quantity == 0 && !stock.drugManuNo.ManuNo.Equals(stock.ManuNo))
{
stockQ = stockQ.Set(cs => cs.ManuNo, stock.drugManuNo.ManuNo).Set(cs => cs.EffDate, stock.drugManuNo.EffDate.ToString()).Set(cs => cs.Dmnguid, stock.drugManuNo.Id);
}
int r = stockQ.Update();
// 获取更新完库存之后的药品库存
List<ChannelStock> list = await _connection.ChannelStock.AsQueryable()
.InnerJoin(
_connection.ChannelList.Where(cl => cl.MachineId.Equals(_setting.machineId)).Where(cl => cl.DrawerType == 1),
(cs, cl) => cs.ListId == cl.Id,
(cs, cl) => cs
)
.Where(cs => cs.DrugId.Equals(stock.DrugId))
.ToListAsync();
// 保存账册
int acid = _connection.InsertWithInt32Identity(new AccountBook()
{
MachineId = _setting.machineId,
DrugId = stock.DrugId,
ManuNo = ManuNo,
EffDate = !String.IsNullOrEmpty(EffDate) ? DateTime.ParseExact(EffDate, "yyyy-MM-dd", System.Globalization.CultureInfo.CurrentCulture) : null,
OperationTime = DateTime.Now,
Type = type,
OutQuantity = stock.TakeQuantity,
AddQuantity = stock.AddQuantity,
Operator = _globalStateService.Operator.Id,
Reviewer = _globalStateService.Reviewer?.Id ?? _globalStateService.Operator.Id,
ManuStock = list.Where(it => it.ManuNo == stock.ManuNo).Sum(it => it.Quantity),
TotalStock = list.Sum(it => it.Quantity),
InvoiceId = InvoiceId
});
if (mid > 0 && r > 0 && acid > 0)
{
} else
{
flag = false;
break;
}
}
if (flag)
{
_connection.CommitTransaction();
}
else
{
_connection.RollbackTransaction();
}
return flag;
} catch (Exception ex)
{
logger.Error($"抽屉{(type == 1 ? "" : "")}操作完成保存数据库失败,错误:" + ex.Message);
_connection.RollbackTransaction();
return false;
}
}
public long CurrentTimeMillis()
{
return (long)(DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalMilliseconds;
}
public async Task<bool> UnBind(string id)
{
var r = await _connection.ChannelStock
.Where(cs => cs.Id == id)
.Set(cs => cs.DrugId, String.Empty)
.Set(cs => cs.Dmnguid, String.Empty)
.Set(cs => cs.EffDate, String.Empty)
.Set(cs => cs.ManuNo, String.Empty)
.UpdateAsync();
return r > 0;
}
public async Task<bool> Bind(ChannelStock Stock)
{
var q = _connection.ChannelStock
.Where(cs => cs.Id == Stock.Id)
.Set(cs => cs.Dmnguid, Stock.drugManuNo?.Id??String.Empty)
.Set(cs => cs.EffDate, Stock.drugManuNo?.EffDate.ToString() ?? String.Empty)
.Set(cs => cs.ManuNo, Stock.drugManuNo?.ManuNo ?? String.Empty);
if (Stock.Drug != null && !Stock.Drug.DrugId.Equals(Stock.DrugId)) {
q = q.Set(cs => cs.DrugId, Stock.Drug?.DrugId);
}
var r = await q.UpdateAsync();
return r > 0;
}
public async Task<PageMultiData<ChannelStock,DrugInfo>> GetAllChannelListWithDrug(int DrawerType, string drugName, int? take, int? skip)
{
var query = _connection.ChannelStock.AsQueryable();
if (DrawerType != 0)
{
query = query.Where(cl => cl.DrawerType == DrawerType);
}
if (!String.IsNullOrEmpty(drugName))
{
query = query.Where(cl => cl.Drug.DrugName.Equals(drugName));
}
//query = query.Where(cl => !String.IsNullOrEmpty(cl.DrugId));
query = query.Where(cl => cl.MachineId == _setting.machineId);
int pagedData = await query.CountAsync();
List<ChannelStock> list = await query
.LoadWith(cl => cl.Drug)
.LoadWith(cl => cl.Drug.Manus)
.LoadWith(cl => cl.drugManuNo)
.OrderBy((cl) => cl.DrawerNo)
.ThenBy((cl) => cl.ColNo)
.Skip((int)skip)
.Take((int)take)
.ToListAsync();
var other= _connection.DrugInfo.AsQueryable();
List<DrugInfo> drugInfos= await other
.LoadWith(di => di.Manus)
.OrderBy((di) => di.DrugId)
.ToListAsync();
return new PageMultiData<ChannelStock,DrugInfo>()
{
TotalDesserts = pagedData,
Desserts = list,
Other= drugInfos
};
}
//抽屉加药、取药获取数据
public async Task<ChannelStockWithDrawerCount<ChannelStock>> GetChannelStockByDrawerNoWithDrawers(int DrawerNo, int Quantity = 0)
{
var query = _connection.ChannelStock.AsQueryable()
.LoadWith(cs => cs.Drug)
.LoadWith(cs => cs.drugManuNo)
.LoadWith(cs => cs.Drug.Manus)
.Where(cs => cs.DrawerNo == DrawerNo)
.Where(cs => cs.DrugId != String.Empty)
.Where(cs => cs.DrawerType == 1)
.Where(cs => cs.MachineId == _setting.machineId);
if (Quantity > 0)
{
query = query.Where(cs => cs.Quantity > 0);
}
int[] ints = _connection.ChannelStock.Where(cs => cs.MachineId == _setting.machineId).GroupBy(cs=>cs.DrawerNo).Select(cs=>cs.Key).ToArray();
List<ChannelStock> channelStocks= await query
.OrderBy((cs) => cs.DrawerNo)
.ThenBy((cs) => cs.ColNo)
.ToListAsync();
return new ChannelStockWithDrawerCount<ChannelStock>() { DrawerArray = ints, ChannelStocks = channelStocks };
}
//盘点
public async Task<bool> DrawerCheckFinish(List<ChannelStock> Stocks)
{
try
{
_connection.BeginTransaction();
string InvoiceId = "DRAWER_" + CurrentTimeMillis();
var flag = true;
for (var i = 0; i < Stocks.Count; i++)
{
var stock = Stocks[i];
//var ManuNo = !stock.drugManuNo.ManuNo.Equals(stock.ManuNo) ? stock.drugManuNo.ManuNo : stock.ManuNo;
//var EffDate = !stock.drugManuNo.ManuNo.Equals(stock.ManuNo) ? stock.drugManuNo.EffDate : stock.EffDate;
var ManuNo = stock.ManuNo;
var EffDate = stock.EffDate;
// 出入库记录
int mid = _connection.InsertWithInt32Identity(new MachineRecord()
{
MachineId = _setting.machineId,
DrawerNo = stock.DrawerNo,
ColNo = stock.ColNo,
DrugId = stock.DrugId,
ManuNo = ManuNo,
EffDate = !String.IsNullOrEmpty(EffDate) ? DateTime.ParseExact(EffDate, "yyyy-MM-dd", System.Globalization.CultureInfo.CurrentCulture) : null,
OperationTime = DateTime.Now,
Type = 4,
Quantity =stock.CheckQuantity,
Operator = _globalStateService.Operator.Id,
Reviewer = _globalStateService.Reviewer?.Id ?? _globalStateService.Operator.Id,
InvoiceId = InvoiceId
});
// 更新库存
var stockQ = _connection.ChannelStock.Where(cs => cs.Id == stock.Id)
.Set(cs => cs.Quantity, stock.CheckQuantity);
int r = stockQ.Update();
// 获取更新完库存之后的药品库存
List<ChannelStock> list = await _connection.ChannelStock.AsQueryable()
.InnerJoin(
_connection.ChannelList.Where(cl => cl.MachineId.Equals(_setting.machineId)).Where(cl => cl.DrawerType == 1),
(cs, cl) => cs.ListId == cl.Id,
(cs, cl) => cs
)
.Where(cs => cs.DrugId.Equals(stock.DrugId))
.ToListAsync();
// 保存账册
int acid = _connection.InsertWithInt32Identity(new AccountBook()
{
MachineId = _setting.machineId,
DrugId = stock.DrugId,
ManuNo = ManuNo,
EffDate = !String.IsNullOrEmpty(EffDate) ? DateTime.ParseExact(EffDate, "yyyy-MM-dd", System.Globalization.CultureInfo.CurrentCulture) : null,
OperationTime = DateTime.Now,
Type = 3,
OutQuantity = stock.TakeQuantity,
AddQuantity = stock.AddQuantity,
Operator = _globalStateService.Operator.Id,
Reviewer = _globalStateService.Reviewer?.Id ?? _globalStateService.Operator.Id,
ManuStock = list.Where(it => it.ManuNo == stock.ManuNo).Sum(it => it.Quantity),
TotalStock = list.Sum(it => it.Quantity),
InvoiceId = InvoiceId
});
if (mid > 0 && r > 0 && acid > 0)
{
//根据抽屉类型判断是否需要写标签
if (stock.BoardType.ToString().Contains("5"))
{
await _portUtil.WriteQuantityMethod(stock.CheckQuantity, stock.DrawerNo, stock.ColNo);
}
}
else
{
flag = false;
break;
}
}
if (flag)
{
_connection.CommitTransaction();
}
else
{
_connection.RollbackTransaction();
}
return flag;
}
catch (Exception ex)
{
logger.Error($"抽屉盘点操作完成保存数据库失败,错误:" + ex.Message);
_connection.RollbackTransaction();
return false;
}
}
}
}

View File

@ -0,0 +1,132 @@
using LinqToDB;
using log4net;
using MasaBlazorApp3.DataAccess.Dao;
using MasaBlazorApp3.Pojo;
using MasaBlazorApp3.Pojo.Config;
using Microsoft.Extensions.Options;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MasaBlazorApp3.DataAccess.Impl
{
public class DrugInfoDao : IDrugInfoDao
{
private AppDataConnection _connection;
private readonly SettingConfig _setting;
private readonly ILog logger = LogManager.GetLogger(typeof(DrugInfoDao));
public DrugInfoDao(AppDataConnection connection, IOptions<SettingConfig> setting)
{
_connection = connection;
_setting = setting.Value;
}
public async Task<List<DrugInfo>> GetAllDrugAndStock()
{
var query = _connection.DrugInfo.AsQueryable();
return await query
.LoadWith(di => di.Stocks.Where(cs => cs.Quantity > 0 && cs.MachineId == _setting.machineId))
.InnerJoin(
_connection.ChannelStock.Where(cl => cl.MachineId == _setting.machineId && cl.DrawerType == 1).GroupBy(cl => cl.DrugId),
(di, cl) => di.DrugId == cl.Key,
(di, cl) => di
)
//.Where(cs => cs.Quantity > 0)
.OrderBy((di) => di.DrugId)
.ToListAsync();
}
public async Task<PageData<DrugInfo>> GetAllDrug(string drugId, string drugName, int? take, int? skip)
{
var query = _connection.DrugInfo.AsQueryable();
if (!String.IsNullOrEmpty(drugId))
{
query = query.Where(di => di.DrugId.Contains(drugId));
}
if (!String.IsNullOrEmpty(drugName))
{
query = query.Where(di => di.DrugName.Contains(drugName));
}
int pagedData = await query.CountAsync();
query = query
.LoadWith(di => di.Manus)
.OrderBy((di) => di.DrugId)
.Skip((int)skip)
.Take((int)take);
List<DrugInfo> list = await query
.ToListAsync();
return new PageData<DrugInfo>()
{
TotalDesserts = pagedData,
Desserts = list
};
}
public async Task<List<DrugInfo>> GetAllDrug()
{
var query = _connection.DrugInfo.AsQueryable();
return await query
.LoadWith(di => di.Manus)
.OrderBy((di) => di.DrugId)
.ToListAsync();
}
public async Task<DrugManuNo> GetDrugManuNo(string drugId, string manuNo)
{
var query = _connection.DrugManuNo.AsQueryable();
return await query.Where(m => m.DrugId.Equals(drugId))
.Where(m => m.ManuNo.Equals(manuNo))
.FirstAsync();
}
public int AddDrugInfo(DrugInfo drugInfo)
{
return _connection.InsertWithInt32Identity(drugInfo);
}
public async Task<bool> DeleteDrugInfo(string drugId)
{
try
{
logger.Error($"删除药品{drugId}");
return _connection.DrugInfo.Where(di => di.DrugId == drugId).Delete() > 0;
}
catch (Exception ex)
{
logger.Error("删除药品失败,错误:" + ex.Message);
return false;
}
}
public async Task<bool> UpdateDrugInfo(DrugInfo drugInfo)
{
try
{
var statement = _connection.DrugInfo
.Where(di => di.DrugId == drugInfo.DrugId)
.Set(di => di.DrugName, drugInfo.DrugName)
.Set(di => di.DrugSpec, drugInfo.DrugSpec)
.Set(di => di.Manufactory, drugInfo.Manufactory);
return statement.Update() > 0;
}
catch (Exception ex)
{
logger.Error($"修改药品{drugInfo.DrugId}失败,错误:" + ex.Message);
return false;
}
}
}
}

View File

@ -0,0 +1,44 @@
using LinqToDB;
using MasaBlazorApp3.DataAccess.Dao;
using MasaBlazorApp3.Pages;
using MasaBlazorApp3.Pojo;
using System;
using System.Collections.Generic;
using System.Data.Common;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MasaBlazorApp3.DataAccess.Impl
{
public class DrugManuNoDao : IDrugManuNoDao
{
private readonly AppDataConnection _connection;
public DrugManuNoDao(AppDataConnection connection)
{
_connection = connection;
}
public int AddDrugManuNo(DrugManuNo drugManuNo)
{
if(drugManuNo!=null&& drugManuNo.EffDate!=null)
{
drugManuNo.EffDate= drugManuNo.EffDate.ToString().Length>10 ?new DateTime(drugManuNo.EffDate.Value.Year, drugManuNo.EffDate.Value.Month, drugManuNo.EffDate.Value.Day) : drugManuNo.EffDate;
}
return _connection.InsertWithInt32Identity(drugManuNo);
}
public bool DeleteDrugManuNo(string id)
{
return _connection.DrugManuNo.Where(dm => dm.Id == id).Delete() > 0;
}
public bool UpdateDrugManuNo(DrugManuNo drugManuNo)
{
var statement = _connection.DrugManuNo
.Where(dm => dm.Id == drugManuNo.Id)
.Set(dm => dm.ManuNo, drugManuNo.ManuNo)
.Set(dm => dm.EffDate, drugManuNo.EffDate);
return statement.Update() > 0;
}
}
}

View File

@ -0,0 +1,510 @@
using LinqToDB;
using log4net;
using MasaBlazorApp3.DataAccess.Dao;
using MasaBlazorApp3.Pages;
using MasaBlazorApp3.Pojo;
using MasaBlazorApp3.Pojo.Config;
using MasaBlazorApp3.Pojo.Vo;
using MasaBlazorApp3.Port;
using Microsoft.Extensions.Options;
using System;
using System.Collections.Generic;
using System.Data.Common;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MasaBlazorApp3.DataAccess.Impl
{
public class InOutInvoiceDao : IInOutInvoiceDao
{
private AppDataConnection _connection;
private readonly SettingConfig _setting;
private readonly ILog logger = LogManager.GetLogger(typeof(InOutInvoiceDao));
private GlobalStateService _globalStateService;
private readonly PortUtil _portUtil;
public InOutInvoiceDao(AppDataConnection connection, IOptions<SettingConfig> setting, GlobalStateService globalStateService, PortUtil portUtil)
{
_connection = connection;
_setting = setting.Value;
_globalStateService = globalStateService;
_portUtil = portUtil;
}
public async Task<PageData<InOutInvoice>> GetAllInvoiceByType(string invoiceNo, DateTime invoiceDate, int? take, int? skip, int type = 1)
{
var query2 = from cl in _connection.ChannelList.Where(c => c.MachineId == _setting.machineId)
group cl by cl.DrugId into temp
select new { temp.Key };
var query3 = from ioi in _connection.InOutInvoice
from od in query2.InnerJoin(od => od.Key == ioi.DrugId)
group ioi by ioi.InvoiceNo into temp
select new InOutInvoice{
InvoiceNo= temp.First().InvoiceNo,
InPharmacyId = temp.First().InPharmacyId,
OutPharmacyId = temp.First().OutPharmacyId,
InvoiceDate = temp.First().InvoiceDate,
CreateTime = temp.First().CreateTime,
Type = temp.First().Type,
CancelFlag = temp.First().CancelFlag,
Status = temp.First().Status,
};
//var query = _connection.FromSql<InOutInvoice>($@"
// SELECT ioi.invoice_no,ioi.in_pharmacy_id, ioi.out_pharmacy_id, ioi.invoice_date, ioi.create_time, ioi.type, ioi.cancel_flag, ioi.status FROM in_out_invoice ioi
// INNER JOIN (SELECT drug_id FROM channel_list WHERE machine_id = ""{_setting.machineId}"" GROUP BY drug_id) c ON c.drug_id = ioi.drug_id
// GROUP BY ioi.invoice_no");
if (!String.IsNullOrEmpty(invoiceNo))
{
//query = query.Where(ioi => ioi.InvoiceNo.Contains(invoiceNo));
query3 = query3.Where(ioi => ioi.InvoiceNo.Contains(invoiceNo));
}
if(invoiceDate != DateTime.MinValue)
{
//query = query.Where(ioi => ioi.CreateTime.Date.Equals(invoiceDate.Date));
query3 = query3.Where(ioi => ioi.InvoiceNo.Contains(invoiceNo));
}
if(!String.IsNullOrEmpty(_setting.storage))
{
if (type == 1)
{
//query = query.Where(ioi => ioi.OutPharmacyId.Equals(_setting.storage));
query3 = query3.Where(ioi => ioi.OutPharmacyId.Equals(_setting.storage));
}
// 调拨出库
else if (type == 2)
{
//query = query.Where(ioi => ioi.InPharmacyId.Equals(_setting.storage));
query3 = query3.Where(ioi => ioi.OutPharmacyId.Equals(_setting.storage));
}
}
// 调拨入库
if (type == 1)
{
//query = query.Where(ioi => (ioi.Type == 0 && ioi.Status == 2) || (ioi.Type == 1 && ioi.Status == 0));
query3 = query3.Where(ioi => (ioi.Type == 0 && ioi.Status == 2) || (ioi.Type == 1 && ioi.Status == 0));
}
// 调拨出库
else if (type == 2)
{
//query = query.Where(ioi => new int[] { 0, 2 }.Contains(ioi.Type) && ioi.Status == 0);
query3 = query3.Where(ioi => new int[] { 0, 2 }.Contains(ioi.Type) && ioi.Status == 0);
}
//query = query.Where(ioi => ioi.CancelFlag == 0);
//query = query.Select(ioi => new InOutInvoice()
//{
// InPharmacyId = ioi.InPharmacyId,
// OutPharmacyId = ioi.OutPharmacyId,
// InvoiceDate = ioi.InvoiceDate,
// InvoiceNo = ioi.InvoiceNo,
// CreateTime = ioi.CreateTime,
// Type = ioi.Type,
// Status = ioi.Status,
// CancelFlag = ioi.CancelFlag,
//});
query3 = query3.Where(ioi => ioi.CancelFlag == 0);
List <InOutInvoice> list = await query3
.OrderByDescending(ioi => ioi.CreateTime)
.Skip((int)skip)
.Take((int)take)
.ToListAsync();
int pagedData = await query3.CountAsync();
return new PageData<InOutInvoice>()
{
TotalDesserts = pagedData,
Desserts = list
};
}
public async Task<DrugManuNo> GetDrugManuNo(string drugId, string manuNo)
{
var query = _connection.DrugManuNo.AsQueryable();
return await query.Where(m => m.DrugId.Equals(drugId))
.Where(m => m.ManuNo.Equals(manuNo))
.FirstAsync();
}
public async Task<List<ChannelStock>> GetChannelStockByDrugId(string DrugId, string manuNo, int quantity = 0)
{
var query = _connection.ChannelStock.AsQueryable();
query = query.Where(cs => cs.MachineId.Equals(_setting.machineId)).Where(cs => cs.DrawerType == 1).Where(cs => cs.DrugId.Equals(DrugId));
if (quantity > 0)
{
query = query.Where(cs => cs.Quantity > 0);
if (!String.IsNullOrEmpty(manuNo))
{
query = query.Where(cs => cs.ManuNo.Equals(manuNo));
}
} else
{
if (!String.IsNullOrEmpty(manuNo))
{
query = query.Where(cs => cs.ManuNo.Equals(manuNo) || String.IsNullOrEmpty(cs.ManuNo) || cs.Quantity == 0);
}
}
return await query.OrderBy((cs) => cs.EffDate)
.ThenBy((cs) => cs.DrawerNo)
.ThenBy((cs) => cs.ColNo)
.ToListAsync();
}
public async Task<List<InOutInvoice>> getInvoiceByInvoiceNo(string invoiceNo)
{
var query = _connection.InOutInvoice.AsQueryable();
query = query.InnerJoin(
_connection.ChannelStock.Where(cs => cs.MachineId.Equals(_setting.machineId)).GroupBy(cs => cs.DrugId).Select(cs => cs.Key),
(ioi, key) => key == ioi.DrugId,
(ioi, key) => ioi)
.Where(ioi => ioi.InvoiceNo.Equals(invoiceNo))
.OrderBy(ioi => ioi.DrugId);
return await query.ToListAsync();
}
public async Task<DrugInfo> getDrugInfoById(string DrugId)
{
return await _connection.DrugInfo.Where(di => di.DrugId == DrugId).FirstOrDefaultAsync();
}
public async Task<List<InvoiceVo>> getTakeInfoByInvoiceNo(string invoiceNo)
{
List<InvoiceVo> tempData = new();
var flag = true;
List<InOutInvoice> details = await this.getInvoiceByInvoiceNo(invoiceNo);
for (var i = 0; i < details.Count; i++)
{
//List<IDictionary<string, object>> tempData = new();
InOutInvoice detail = details[i];
DrugInfo Drug = await this.getDrugInfoById(detail.DrugId);
// 当前detail取药数量
var Quantity = detail.quantity;
List<ChannelStock> stockList = await this.GetChannelStockByDrugId(detail.DrugId, detail.DrugManuNo, Quantity);
// 当前药品的库存总量
var total = stockList.Sum(cs => cs.Quantity);
if (flag)
{
// 盘点库存是否足够
if (total >= Quantity)
{
for (var j = 0; Quantity > 0; j++)
{
ChannelStock stock = stockList[j];
if (Quantity > stock.Quantity)
{
// 取药数量大于库存
stock.TakeQuantity = stock.Quantity;
Quantity -= stock.Quantity;
}
else
{
//取药数量小于库存
stock.TakeQuantity = Quantity;
Quantity = 0;
}
}
}
else
{
// 库存不足
flag = false;
}
}
tempData.Add(new InvoiceVo()
{
Drug = Drug,
Invoice = detail,
StockQuantity = total,
Quantity = detail.quantity,
ChannelStocks = stockList,
});
}
return tempData;
}
public async Task<List<InvoiceVo>> getAddInfoByInvoiceNo(string invoiceNo)
{
List<InvoiceVo> tempData = new();
List<InOutInvoice> details = await this.getInvoiceByInvoiceNo(invoiceNo);
for (var i = 0; i < details.Count; i++)
{
//List<IDictionary<string, object>> tempData = new();
InOutInvoice detail = details[i];
List<ChannelStock> stockList = await this.GetChannelStockByDrugId(detail.DrugId, detail.DrugManuNo);
DrugInfo Drug = await this.getDrugInfoById(detail.DrugId);
// 当前药品的库存总量
var total = stockList.Aggregate(0, (current, next) => current + next.Quantity);
// 当前detail加药数量
var Quantity = detail.quantity;
stockList.First().AddQuantity = Quantity;
tempData.Add(new InvoiceVo()
{
Drug = Drug,
Invoice = detail,
StockQuantity = total,
Quantity = Quantity,
ChannelStocks = stockList,
});
}
return tempData;
}
public async Task<bool> InvoiceOutFinish(List<InvoiceVo> datas)
{
try
{
_connection.BeginTransaction();
var flag = true;
// 更新处方状态
int r1 = _connection.InOutInvoice.Where(oi => oi.InvoiceNo == datas.First().Invoice.InvoiceNo)
.Set(oi => oi.Status, 2)
.Update();
if (!(r1 > 0))
{
flag = false;
logger.Error("调拨取药完成更新状态失败");
_connection.RollbackTransaction();
return flag;
}
for (var i = 0; i < datas.Count; i++)
{
var invoiceVo = datas[i];
List<ChannelStock> stocks = invoiceVo.ChannelStocks.Where(cs => cs.TakeQuantity > 0).ToList();
for (var j = 0; j < stocks.Count; j++)
{
var ChannelStock = stocks[j];
// 出库记录
int mid = _connection.InsertWithInt32Identity(new MachineRecord()
{
MachineId = _setting.machineId,
DrawerNo = ChannelStock.DrawerNo,
ColNo = ChannelStock.ColNo,
DrugId = ChannelStock.DrugId,
ManuNo = ChannelStock.ManuNo,
EffDate = !String.IsNullOrEmpty(ChannelStock.EffDate) ? DateTime.ParseExact(ChannelStock.EffDate, "yyyy-MM-dd", System.Globalization.CultureInfo.CurrentCulture) : null,
OperationTime = DateTime.Now,
Type = 2,
Quantity = ChannelStock.TakeQuantity,
Operator = _globalStateService.Operator.Id,
Reviewer = _globalStateService.Reviewer?.Id ?? _globalStateService.Operator.Id,
InvoiceId = invoiceVo.Invoice.InvoiceNo,
});
// 更新库存
int r = _connection.ChannelStock.Where(cs => cs.Id == ChannelStock.Id)
.Set(cs => cs.Quantity, ChannelStock.Quantity - ChannelStock.TakeQuantity)
.Update();
// 获取更新完库存之后的药品库存
List<ChannelStock> list = await _connection.ChannelStock.AsQueryable()
.InnerJoin(
_connection.ChannelList.Where(cl => cl.MachineId.Equals(_setting.machineId)).Where(cl => cl.DrawerType == 1),
(cs, cl) => cs.ListId == cl.Id,
(cs, cl) => cs
)
.Where(cs => cs.DrugId.Equals(ChannelStock.DrugId))
.ToListAsync();
// 保存账册
int acid = _connection.InsertWithInt32Identity(new AccountBook()
{
MachineId = _setting.machineId,
DrugId = ChannelStock.DrugId,
ManuNo = ChannelStock.ManuNo,
EffDate = !String.IsNullOrEmpty(ChannelStock.EffDate) ? DateTime.ParseExact(ChannelStock.EffDate, "yyyy-MM-dd", System.Globalization.CultureInfo.CurrentCulture) : null,
OperationTime = DateTime.Now,
Type = 2,
OutQuantity = ChannelStock.TakeQuantity,
AddQuantity = 0,
Operator = _globalStateService.Operator.Id,
Reviewer = _globalStateService.Reviewer?.Id ?? _globalStateService.Operator.Id,
ManuStock = list.Where(it => it.ManuNo == ChannelStock.ManuNo).Sum(it => it.Quantity),
TotalStock = list.Sum(it => it.Quantity),
InvoiceId = invoiceVo.Invoice.InvoiceNo
});
if (mid > 0 && r > 0 && acid > 0)
{
//根据抽屉类型判断是否需要写标签
if (ChannelStock.BoardType.ToString().Contains("5"))
{
await _portUtil.WriteQuantityMethod(ChannelStock.Quantity- ChannelStock.TakeQuantity, ChannelStock.DrawerNo, ChannelStock.ColNo);
}
}
else
{
flag = false;
break;
}
}
if (!flag)
{
break;
}
}
if (flag)
{
_connection.CommitTransaction();
}
else
{
_connection.RollbackTransaction();
}
return flag;
}
catch (Exception ex)
{
logger.Error("调拨取药完成保存数据库失败,错误:" + ex.Message);
_connection.RollbackTransaction();
return false;
}
}
public async Task<bool> InvoiceAddFinish(List<InvoiceVo> datas)
{
try
{
_connection.BeginTransaction();
var flag = true;
// 更新调拨单状态
int r1 = _connection.InOutInvoice.Where(oi => oi.InvoiceNo == datas.First().Invoice.InvoiceNo)
.Set(oi => oi.Status, 4)
.Update();
if (!(r1 > 0))
{
flag = false;
logger.Error("调拨加药完成更新状态失败");
_connection.RollbackTransaction();
return flag;
}
for (var i = 0; i < datas.Count; i++)
{
var invoiceVo = datas[i];
List<ChannelStock> stocks = invoiceVo.ChannelStocks.Where(cs => cs.AddQuantity > 0).ToList();
for (var j = 0; j < stocks.Count; j++)
{
var ChannelStock = stocks[j];
// 更新库存
var q = _connection.ChannelStock.Where(cs => cs.Id == ChannelStock.Id)
.Set(cs => cs.Quantity, ChannelStock.Quantity + ChannelStock.AddQuantity);
if (String.IsNullOrEmpty(ChannelStock.ManuNo) || (ChannelStock.Quantity == 0 && !ChannelStock.ManuNo.Equals(invoiceVo.Invoice.DrugManuNo)))
{
DrugManuNo drugManuNo = await GetDrugManuNo(ChannelStock.DrugId, invoiceVo.Invoice.DrugManuNo);
ChannelStock.Dmnguid = drugManuNo.Id;
ChannelStock.ManuNo = drugManuNo.ManuNo;
ChannelStock.EffDate = drugManuNo.EffDate.ToString();
q = q.Set(cs => cs.Dmnguid, drugManuNo.Id)
.Set(cs => cs.ManuNo, drugManuNo.ManuNo)
.Set(cs => cs.EffDate, drugManuNo.EffDate.ToString());
}
int r = q.Update();
// 入库记录
int mid = _connection.InsertWithInt32Identity(new MachineRecord()
{
MachineId = _setting.machineId,
DrawerNo = ChannelStock.DrawerNo,
ColNo = ChannelStock.ColNo,
DrugId = ChannelStock.DrugId,
ManuNo = ChannelStock.ManuNo,
EffDate = !String.IsNullOrEmpty(ChannelStock.EffDate) ? DateTime.ParseExact(ChannelStock.EffDate, "yyyy-MM-dd", System.Globalization.CultureInfo.CurrentCulture) : null,
OperationTime = DateTime.Now,
Type = 1,
Quantity = ChannelStock.AddQuantity,
Operator = _globalStateService.Operator.Id,
Reviewer = _globalStateService.Reviewer?.Id ?? _globalStateService.Operator.Id,
InvoiceId = invoiceVo.Invoice.InvoiceNo,
});
// 获取更新完库存之后的药品库存
List<ChannelStock> list = await _connection.ChannelStock.AsQueryable()
.Where(cs => cs.MachineId.Equals(_setting.machineId))
.Where(cs => cs.DrawerType == 1)
.Where(cs => cs.DrugId.Equals(ChannelStock.DrugId))
.ToListAsync();
// 保存账册
int acid = _connection.InsertWithInt32Identity(new AccountBook()
{
MachineId = _setting.machineId,
DrugId = ChannelStock.DrugId,
ManuNo = ChannelStock.ManuNo,
EffDate = !String.IsNullOrEmpty(ChannelStock.EffDate) ? DateTime.ParseExact(ChannelStock.EffDate, "yyyy-MM-dd", System.Globalization.CultureInfo.CurrentCulture) : null,
OperationTime = DateTime.Now,
Type = 1,
OutQuantity = 0,
AddQuantity = ChannelStock.AddQuantity,
Operator = _globalStateService.Operator.Id,
Reviewer = _globalStateService.Reviewer?.Id ?? _globalStateService.Operator.Id,
ManuStock = list.Where(it => it.ManuNo == ChannelStock.ManuNo).Sum(it => it.Quantity),
TotalStock = list.Sum(it => it.Quantity),
InvoiceId = invoiceVo.Invoice.InvoiceNo
});
if (mid > 0 && r > 0 && acid > 0)
{
//根据抽屉类型判断是否需要写标签
if (ChannelStock.BoardType.ToString().Contains("5"))
{
await _portUtil.WriteQuantityMethod(ChannelStock.Quantity - ChannelStock.TakeQuantity, ChannelStock.DrawerNo, ChannelStock.ColNo);
}
}
else
{
flag = false;
break;
}
}
if(!flag)
{
break;
}
}
if (flag)
{
_connection.CommitTransaction();
}
else
{
_connection.RollbackTransaction();
}
return flag;
}
catch (Exception ex)
{
logger.Error("调拨加药完成保存数据库失败,错误:" + ex.Message);
_connection.RollbackTransaction();
return false;
}
}
}
}

View File

@ -0,0 +1,406 @@
using LinqToDB;
using log4net;
using MasaBlazorApp3.DataAccess.Dao;
using MasaBlazorApp3.Pages;
using MasaBlazorApp3.Pojo;
using MasaBlazorApp3.Pojo.Config;
using MasaBlazorApp3.Pojo.Vo;
using MasaBlazorApp3.Port;
using Microsoft.Extensions.Options;
using Mysqlx.Crud;
using static LinqToDB.Common.Configuration;
namespace MasaBlazorApp3.DataAccess.Impl
{
public class MachineRecordDao : IMachineRecordDao
{
private readonly AppDataConnection _connection;
private readonly SettingConfig _setting;
private readonly ILog logger = LogManager.GetLogger(typeof(MachineRecordDao));
private readonly PortUtil _portUtil;
//public UserDao(MyContext context)
//{
// Context = context;
//}
public MachineRecordDao(AppDataConnection connection, IOptions<SettingConfig> setting, PortUtil portUtil)
{
_connection = connection;
_setting = setting.Value;
_portUtil = portUtil;
}
public async Task<List<ChannelStock>> GetChannelStockByDrugId(string DrugId, String ManuNo)
{
var query = _connection.ChannelStock.AsQueryable();
query = query.Where(cs => cs.MachineId.Equals(_setting.machineId)).Where(cs => cs.DrawerType == 1)
.Where(cs => cs.Quantity > 0)
.Where(cs => cs.DrugId.Equals(DrugId))
.Where(cs => cs.ManuNo.Equals(ManuNo));
return await query.OrderBy((cs) => cs.EffDate)
.ThenBy((cs) => cs.DrawerNo)
.ThenBy((cs) => cs.ColNo)
.ToListAsync();
}
//还药时有库位即可不需要库存大于0的条件
public async Task<List<ChannelStock>> GetChannelStockByDrugIdForReturn(string DrugId, String ManuNo)
{
var query = _connection.ChannelStock.AsQueryable();
query = query.Where(cs => cs.MachineId.Equals(_setting.machineId)).Where(cs => cs.DrawerType == 1)
//.Where(cs => cs.Quantity > 0)
.Where(cs => cs.DrugId.Equals(DrugId))
.Where(cs => cs.ManuNo.Equals(ManuNo));
return await query.OrderBy((cs) => cs.EffDate)
.ThenBy((cs) => cs.DrawerNo)
.ThenBy((cs) => cs.ColNo)
.ToListAsync();
}
public async Task<PageData<MachineRecord>> GetCanReturnRecords(DateTime start, DateTime end, int operatorId, string drugId, int? take, int? skip)
{
var query = _connection.MachineRecord.AsQueryable().Where(it => it.MachineId.Equals(_setting.machineId));
if (start != null && start != DateTime.MinValue)
{
query = query.Where(mr => mr.OperationTime > start);
}
if (end != null && end != DateTime.MinValue)
{
query = query.Where(mr => mr.OperationTime < end);
}
if (operatorId != 0)
{
query = query.Where(mr => mr.Operator == operatorId);
}
query = query.Where(mr => mr.Type == 2);
query = query.Where(mr => mr.Status < 2);
if (!String.IsNullOrEmpty(drugId))
{
query = query.Where(mr => mr.DrugId == drugId);
}
int pagedData = await query.CountAsync();
List<MachineRecord> MachineRecords = await query.LoadWith(mr => mr.Drug)
.LoadWith(mr => mr.OperatorUser)
.OrderByDescending(mr => mr.OperationTime)
.Skip((int)skip)
.Take((int)take)
.ToListAsync();
return new PageData<MachineRecord>() { Desserts = MachineRecords, TotalDesserts = pagedData };
}
public async Task<PageData<MachineRecord>> GetMachineRecordAsync(DateTime start, DateTime end, int operatorId, string drugId, int type, int? take, int? skip)
{
var query = _connection.MachineRecord.AsQueryable().Where(it => it.MachineId.Equals(_setting.machineId));
if (start != null && start != DateTime.MinValue)
{
query = query.Where(mr => mr.OperationTime > start);
}
if (end != null && end != DateTime.MinValue)
{
query = query.Where(mr => mr.OperationTime < end);
}
if (operatorId != 0)
{
query = query.Where(mr => mr.Operator == operatorId);
}
if (type != 0)
{
query = query.Where(mr => mr.Type == type);
}
if (!String.IsNullOrEmpty(drugId))
{
query = query.Where(mr => mr.DrugId == drugId);
}
int pagedData = await query.CountAsync();
List<MachineRecord> MachineRecords = await query.LoadWith(mr => mr.Drug)
.LoadWith(mr => mr.OperatorUser)
.OrderByDescending(mr => mr.OperationTime)
.Skip((int)skip)
.Take((int)take)
.ToListAsync();
return new PageData<MachineRecord>() { Desserts = MachineRecords, TotalDesserts = pagedData };
}
public int InsertMachineRecord(MachineRecord record)
{
record.MachineId = _setting.machineId;
return _connection.InsertWithInt32Identity(record);
}
public async Task<List<OperationVo<List<MachineRecord>>>> getReturnDrugInfoByRecords(List<MachineRecord> records)
{
List<OperationVo<List<MachineRecord>>> list = new();
for (int i = 0; i < records.Count; i++)
{
var record = records[i];
//var index = list.FindIndex(it => it.Drug.DrugId == record.DrugId && it.data.Count > 0 && it.data.First().ManuNo == record.ManuNo);
var index = list.FindIndex(it => it.Drug.DrugId == record.DrugId && it.data.First().ManuNo == record.ManuNo);
if (index > -1)
{
list[index].Quantity += record.CurrentReturnQuantity;
list[index].data.Add(record);
if (list[index].ChannelStocks.Count > 0)
{
list[index].ChannelStocks.First().ReturnQuantity += record.CurrentReturnQuantity;
}
}
else
{
//List<ChannelStock> stockList = await this.GetChannelStockByDrugId(record.DrugId, record.ManuNo);
List<ChannelStock> stockList = await this.GetChannelStockByDrugIdForReturn(record.DrugId, record.ManuNo);
// 当前药品的库存总量
var total = stockList.Sum(current => current.Quantity);
if (stockList.Count > 0)
{
stockList.First().ReturnQuantity = record.CurrentReturnQuantity;
}
list.Add(new OperationVo<List<MachineRecord>>()
{
Drug = record.Drug,
ChannelStocks = stockList,
data = new List<MachineRecord> { record },
Quantity = record.CurrentReturnQuantity,
StockQuantity = total,
});
}
}
return list;
}
public async Task<bool> ReturnDrugFinish(List<OperationVo<List<MachineRecord>>> datas)
{
//throw new NotImplementedException();
//还药完成
try
{
_connection.BeginTransaction();
if (datas.Count > 0)
{
datas = datas.Select(it =>
{
it.ChannelStocks = it.ChannelStocks.Where(cs => cs.ReturnQuantity > 0).ToList();
return it;
}).ToList();
if (datas.Count > 0)
{
foreach (var data in datas)
{
int sumQuantity = data.data.Sum(mr => mr.CurrentReturnQuantity);
//更新 库存
foreach (ChannelStock record in data.ChannelStocks)
{
record.Quantity = record.Quantity + record.ReturnQuantity;
record.Id = record.Id;
_connection.Update(record);
// 保存数据 还药记录
int acid = _connection.InsertWithInt32Identity(new MachineRecord()
{
MachineId = record.MachineId,
DrawerNo = record.DrawerNo,
ColNo = record.ColNo,
DrugId = record.DrugId,
ManuNo = record.ManuNo,
EffDate = !String.IsNullOrEmpty(record.EffDate) ? DateTime.ParseExact(record.EffDate, "yyyy-MM-dd", System.Globalization.CultureInfo.CurrentCulture) : null,
Operator = data.data.First().Operator,
OperationTime = DateTime.Now,
Quantity = record.ReturnQuantity,
Type = 31,
InvoiceId = data.data.First().InvoiceId,
GetId = data.data.First().GetId
});
//称重计数或称重+智能显示+管控药盒 类型需要 发26指令
if (record.BoardType == 5 || record.BoardType == 6)
{
//计数数量设置发送称重26指令
_portUtil.SetNumCount(record.DrawerNo, record.ColNo, record.ReturnQuantity);
Thread.Sleep(80);
}
}
// 更新 取药记录 设置还药数量、状态
foreach (MachineRecord record in data.data)
{
record.ReturnQuantity1 = record.ReturnQuantity1 + record.CurrentReturnQuantity;
record.Id = record.Id;
record.Status = (record.Quantity - (record.ReturnQuantity1 + record.ReturnQuantity2 + sumQuantity)) == 0 ? 2 : 1;
_connection.Update(record);
}
}
_connection.CommitTransaction();
}
}
else
{
_connection.RollbackTransaction();
return false;
}
return true;
}
catch (Exception ex)
{
logger.Error("还药完成保存数据库失败,错误:" + ex.Message);
_connection.RollbackTransaction();
return false;
}
}
#region
public async Task<List<ChannelStock>> GetReturnEmpty()
{
List<ChannelStock> channelStocks = new();
var query = _connection.ChannelStock.AsQueryable().Where(it => it.MachineId == _setting.machineId && it.DrawerType == 2);
channelStocks= await query.LoadWith(cs => cs.Drug).ToListAsync();
//获取可归还数量
return channelStocks;
//if (start != null && start != DateTime.MinValue)
//{
// query = query.Where(mr => mr.OperationTime > start);
//}
//if (end != null && end != DateTime.MinValue)
//{
// query = query.Where(mr => mr.OperationTime < end);
//}
//if (operatorId != 0)
//{
// query = query.Where(mr => mr.Operator == operatorId);
//}
//query = query.Where(mr => mr.Type == 2);
//query = query.Where(mr => mr.Status < 2);
//if (!String.IsNullOrEmpty(drugId))
//{
// query = query.Where(mr => mr.DrugId == drugId);
//}
//int pagedData = await query.CountAsync();
//List<MachineRecord> MachineRecords = await query.LoadWith(mr => mr.Drug)
// .LoadWith(mr => mr.OperatorUser)
// .OrderByDescending(mr => mr.OperationTime)
// .Skip((int)skip)
// .Take((int)take)
// .ToListAsync();
//return new PageData<MachineRecord>() { Desserts = MachineRecords, TotalDesserts = pagedData };
}
public async Task<PageData<MachineRecord>> getReturnEmptyInfoByRecords(ChannelStock records)
{
List<MachineRecord> machineRecords = new();
int pagedData = 0;
if (records != null && !string.IsNullOrEmpty(records.DrugId))
{
var query = _connection.MachineRecord.Where(it => it.DrugId == records.DrugId && it.MachineId == _setting.machineId && it.Type == 2 && it.Status != 2).AsQueryable();
machineRecords = await query.LoadWith(cs => cs.OperatorUser).ToListAsync();
pagedData = await query.CountAsync();
}
return new PageData<MachineRecord>() { Desserts = machineRecords, TotalDesserts = pagedData };
}
public async Task<bool> ReturnEmptyFinish(List<MachineRecord> datas, ChannelStock channelStock)
{
try
{
_connection.BeginTransaction();
// 更新数据 库存信息
channelStock.Quantity = channelStock.Quantity+ datas.Sum(it => it.CurrentReturnQuantity);
int iStock = _connection.Update(channelStock);
for (int i = 0; i < datas.Count; i++)
{
MachineRecord _MachineRecord = datas[i];
_MachineRecord.ReturnQuantity2 = _MachineRecord.ReturnQuantity2+ _MachineRecord.CurrentReturnQuantity;
_MachineRecord.Status = _MachineRecord.ReturnQuantity2 + _MachineRecord.ReturnQuantity1 >= _MachineRecord.Quantity ? 2 : 1;
// 更新数据 取药记录 设置还药数量、状态
_connection.Update(_MachineRecord);
// 保存数据 还药空瓶记录
int iMachineRecord = _connection.InsertWithInt32Identity(new MachineRecord() {
MachineId= channelStock.MachineId,
DrawerNo = channelStock.DrawerNo,
ColNo = channelStock.ColNo,
DrugId = channelStock.DrugId,
ManuNo = channelStock.ManuNo,
EffDate = !String.IsNullOrEmpty(channelStock.EffDate) ? DateTime.ParseExact(channelStock.EffDate, "yyyy-MM-dd", System.Globalization.CultureInfo.CurrentCulture) : null,
Operator = _MachineRecord.Operator,
OperationTime = DateTime.Now,
Quantity = _MachineRecord.CurrentReturnQuantity,
Type = 31,
InvoiceId = _MachineRecord.InvoiceId,
GetId = _MachineRecord.GetId
});
////称重计数或称重+智能显示+管控药盒 类型需要 发26指令
//if (channelStock.BoardType == 5 || channelStock.BoardType == 6)
//{
// //计数数量设置发送称重26指令
// _portUtil.SetNumCount(channelStock.DrawerNo, channelStock.ColNo, channelStock.ReturnQuantity);
// Thread.Sleep(80);
//}
if (channelStock.BoardType.ToString().Contains("5"))
{
await _portUtil.WriteQuantityMethod(channelStock.Quantity + datas.Sum(it => it.CurrentReturnQuantity), channelStock.DrawerNo, channelStock.ColNo);
}
}
// 更新屏显库存
if (channelStock.BoardType == 5 || channelStock.BoardType == 35)
{
_portUtil.WriteQuantity(channelStock.DrawerNo, channelStock.ColNo, channelStock.Quantity);
}
_connection.CommitTransaction();
return true;
}
catch (Exception ex)
{
logger.Error("还空瓶完成保存数据库失败,错误:" + ex.Message);
_connection.RollbackTransaction();
return false;
}
}
public async Task<List<ChannelStock>> GetReturnEmptyWithCanReturnQuantiy()
{
List<ChannelStock> channelStocks = new();
var queryStock = _connection.ChannelStock.Where(cs => cs.DrawerType == 2 && cs.MachineId == _setting.machineId);
var queryMachineRecord = _connection.MachineRecord.Where(dm => dm.Type == 2 && dm.Status != 2);
var query = from cs in queryStock
join other in queryMachineRecord on cs.DrugId equals other.DrugId
where cs.MachineId==other.MachineId
group other by cs.DrugId into g
select new
{
ChannelStockId = g.Key,
SumValue = g.Sum(x => x.Quantity-x.ReturnQuantity1-x.ReturnQuantity2)
};
var results = await query.ToListAsync();
channelStocks= await queryStock.LoadWith(cs => cs.Drug).ToListAsync();
foreach (var itemStock in channelStocks)
{
foreach (var itemResult in results)
{
if(itemStock.DrugId==itemResult.ChannelStockId)
{
itemStock.CanReturnQuantity = itemResult.SumValue;
}
}
}
return channelStocks;
}
#endregion
}
}

View File

@ -0,0 +1,544 @@
using LinqToDB;
using LinqToDB.SqlQuery;
using log4net;
using MasaBlazorApp3.DataAccess.Dao;
using MasaBlazorApp3.Pages;
using MasaBlazorApp3.Pojo;
using MasaBlazorApp3.Pojo.Config;
using MasaBlazorApp3.Pojo.Vo;
using MasaBlazorApp3.Port;
using Microsoft.Extensions.Options;
using Mysqlx.Crud;
using Radzen.Blazor.Rendering;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MasaBlazorApp3.DataAccess.Impl
{
public class OrderInfoDao : IOrderInfoDao
{
private readonly SettingConfig _setting;
private AppDataConnection _connection;
private GlobalStateService _globalStateService;
private readonly ILog logger = LogManager.GetLogger(typeof(OrderInfoDao));
private readonly PortUtil _portUtil;
public OrderInfoDao(AppDataConnection connection, IOptions<SettingConfig> setting, GlobalStateService globalStateService,PortUtil portUtil)
{
_connection = connection;
_setting = setting.Value;
_globalStateService = globalStateService;
_portUtil = portUtil;
}
public async Task<PageData<OrderInfo>> GetAllOrderInfo(string OrderrNo, DateTime OrderDate, int? take, int? skip)
{
//var query = _connection.OrderInfo.AsQueryable();
//query.InnerJoin<OrderDetail>((oi, od) => oi.OrderNo == od.OrderNo);
var query2 = from od in _connection.OrderDetail
from cl in _connection.ChannelStock.Where(c => c.MachineId == _setting.machineId).InnerJoin(c => c.DrugId == od.DrugId)
group od by od.OrderNo into temp
select new { temp.Key };
var query = from oi in _connection.OrderInfo
from od in query2.InnerJoin(od => od.Key == oi.OrderNo)
select oi;
if (!String.IsNullOrEmpty(OrderrNo))
{
query = query.Where(oi => oi.OrderNo.Equals(OrderrNo));
}
if(OrderDate !=null && OrderDate!= DateTime.MinValue)
{
query = query.Where(oi => oi.OrderDate.Date.Equals(OrderDate.Date));
}
query = query.Where(oi => oi.Status == 0);
query = query.Where(oi => oi.HisDispFlag == 0);
query = query.Where(oi => oi.CancelFlag == 0);
int pagedData = await query.CountAsync();
List<OrderInfo> list = await query
.OrderBy((oi) => oi.RecvDate)
.ThenBy((oi => oi.OrderNo))
.Skip((int)skip)
.Take((int)take)
.ToListAsync();
return new PageData<OrderInfo>()
{
TotalDesserts = pagedData,
Desserts = list
};
}
public async Task<List<OrderDetail>> getDetailByOrderNo(string OrderrNo)
{
var query2 = from cl in _connection.ChannelStock
where cl.MachineId == _setting.machineId
group cl by cl.DrugId into temp
select new { temp.Key };
;
var query = from od in _connection.OrderDetail.Where(od => od.OrderNo == OrderrNo)
from cl in query2.InnerJoin(c => c.Key == od.DrugId)
orderby od.DrugId
select od;
query = query.LoadWith(od => od.Drug);
return await query.ToListAsync();
}
public async Task<List<ChannelStock>> GetChannelStockByDrugId(string DrugId, String ManuNo, int quantity = 0)
{
var query = _connection.ChannelStock.AsQueryable();
query = query.Where(cs => cs.MachineId.Equals(_setting.machineId)).Where(cs => cs.DrawerType == 1)
.Where(cs => cs.Quantity > 0)
.Where(cs => cs.DrugId.Equals(DrugId));
if (quantity > 0)
{
if (!String.IsNullOrEmpty(ManuNo))
{
query = query.Where(cs => cs.ManuNo.Equals(ManuNo));
}
} else
{
if (!String.IsNullOrEmpty(ManuNo))
{
query = query.Where(cs => cs.ManuNo.Equals(ManuNo) || cs.Quantity == 0);
}
}
return await query.OrderBy((cs) => cs.EffDate)
.ThenBy((cs) => cs.DrawerNo)
.ThenBy((cs) => cs.ColNo)
.ToListAsync();
}
public async Task<List<OrderTakeVo>> getTakeInfoByOrderNo(string OrderrNo)
{
List<OrderTakeVo> tempData = new();
List<OrderTakeVo> tempData2 = new();
List<OrderDetail> details = await this.getDetailByOrderNo(OrderrNo);
var flag = true;
for (var i = 0; i < details.Count; i++)
{
//List<IDictionary<string, object>> tempData = new();
OrderDetail detail = details[i];
// 当前detail取药数量
var Quantity = detail.Quantity;
List<ChannelStock> stockList = await this.GetChannelStockByDrugId(detail.DrugId, detail.SetManuNo, Quantity);
// 当前药品的库存总量
var total = stockList.Sum(current => current.Quantity);
tempData2.Add(new OrderTakeVo()
{
Drug = detail.Drug,
OrderDetail = detail,
StockQuantity = total,
Quantity = Quantity
});
if (flag)
{
// 盘点库存是否足够
if (total > Quantity)
{
for (var j = 0; Quantity > 0; j++)
{
ChannelStock stock = stockList[j];
if (Quantity > stock.Quantity)
{
// 取药数量大于库存
tempData.Add(new OrderTakeVo()
{
Drug = detail.Drug,
OrderDetail = detail,
ChannelStock = stock,
StockQuantity = total,
Quantity = stock.Quantity,
});
Quantity -= stock.Quantity;
}
else
{
//取药数量小于库存
tempData.Add(new OrderTakeVo()
{
Drug = detail.Drug,
OrderDetail = detail,
ChannelStock = stock,
StockQuantity = total,
Quantity = Quantity,
});
Quantity = 0;
}
}
}
else
{
// 库存不足
flag = false;
}
}
}
if (flag)
{
return tempData;
}
else
{
return tempData2;
}
}
public async Task<bool> OrderTakeFinish(List<OrderTakeVo> datas)
{
try
{
_connection.BeginTransaction();
var flag = true;
// 更新处方状态
int r1 = _connection.OrderInfo.Where(oi => oi.OrderNo == datas.First().OrderDetail.OrderNo)
.Set(oi => oi.Status, 1)
.Update();
if (!(r1 > 0))
{
flag = false;
logger.Error("处方取药完成更新处方状态失败");
_connection.RollbackTransaction();
return flag;
}
for (var i = 0; i < datas.Count; i++)
{
var orderTakeVo = datas[i];
// 出库记录
int mid = _connection.InsertWithInt32Identity(new MachineRecord()
{
MachineId = _setting.machineId,
DrawerNo = orderTakeVo.ChannelStock.DrawerNo,
ColNo = orderTakeVo.ChannelStock.ColNo,
DrugId = orderTakeVo.ChannelStock.DrugId,
ManuNo = orderTakeVo.ChannelStock.ManuNo,
EffDate = !String.IsNullOrEmpty(orderTakeVo.ChannelStock.EffDate) ? DateTime.ParseExact(orderTakeVo.ChannelStock.EffDate, "yyyy-MM-dd", System.Globalization.CultureInfo.CurrentCulture) : null,
OperationTime = DateTime.Now,
Type = 2,
Quantity = orderTakeVo.GetQuantity,
Operator = _globalStateService.Operator.Id,
Reviewer = _globalStateService.Reviewer?.Id ?? _globalStateService.Operator.Id,
InvoiceId = orderTakeVo.OrderDetail.Id.ToString(),
});
// 更新库存
int r = _connection.ChannelStock.Where(cs => cs.Id == orderTakeVo.ChannelStock.Id)
.Set(cs => cs.Quantity, orderTakeVo.ChannelStock.Quantity - orderTakeVo.GetQuantity)
.Update();
// 获取更新完库存之后的药品库存
List<ChannelStock> list = await _connection.ChannelStock.AsQueryable()
.InnerJoin(
_connection.ChannelList.Where(cl => cl.MachineId.Equals(_setting.machineId)).Where(cl => cl.DrawerType == 1),
(cs, cl) => cs.ListId == cl.Id,
(cs, cl) => cs
)
.Where(cs => cs.DrugId.Equals(orderTakeVo.ChannelStock.DrugId))
.ToListAsync();
// 保存账册
int acid = _connection.InsertWithInt32Identity(new AccountBook()
{
MachineId = _setting.machineId,
DrugId = orderTakeVo.ChannelStock.DrugId,
ManuNo = orderTakeVo.ChannelStock.ManuNo,
EffDate = !String.IsNullOrEmpty(orderTakeVo.ChannelStock.EffDate) ? DateTime.ParseExact(orderTakeVo.ChannelStock.EffDate, "yyyy-MM-dd", System.Globalization.CultureInfo.CurrentCulture) : null,
OperationTime = DateTime.Now,
Type = 2,
OutQuantity = orderTakeVo.GetQuantity,
AddQuantity = 0,
Operator = _globalStateService.Operator.Id,
Reviewer = _globalStateService.Reviewer?.Id ?? _globalStateService.Operator.Id,
ManuStock = list.Where(it => it.ManuNo == orderTakeVo.ChannelStock.ManuNo).Sum(it => it.Quantity),
TotalStock = list.Sum(it => it.Quantity),
InvoiceId = orderTakeVo.OrderDetail.Id.ToString()
});
if (mid > 0 && r > 0 && acid > 0)
{
if (orderTakeVo.ChannelStock.BoardType.ToString().Contains("5"))
{
await _portUtil.WriteQuantityMethod(orderTakeVo.ChannelStock.Quantity - orderTakeVo.GetQuantity, orderTakeVo.ChannelStock.DrawerNo, orderTakeVo.ChannelStock.ColNo);
}
}
else
{
flag = false;
break;
}
}
if (flag)
{
_connection.CommitTransaction();
}
else
{
_connection.RollbackTransaction();
}
return flag;
}
catch (Exception ex)
{
logger.Error("处方取药完成保存数据库失败,错误:" + ex.Message);
_connection.RollbackTransaction();
return false;
}
}
public async Task<PageData<OrderInfo>> GetAllCanReturnOrderInfo(string OrderrNo, DateTime OrderDate, int? take, int? skip)
{
var query2 = from od in _connection.OrderDetail
from cl in _connection.ChannelStock.Where(c => c.MachineId == _setting.machineId).InnerJoin(c => c.DrugId == od.DrugId)
group od by od.OrderNo into temp
select new { temp.Key };
var query = from oi in _connection.OrderInfo
from od in query2.InnerJoin(od => od.Key == oi.OrderNo)
select oi;
if (!String.IsNullOrEmpty(OrderrNo))
{
query = query.Where(oi => oi.OrderNo.Equals(OrderrNo));
}
if (OrderDate != null && OrderDate != DateTime.MinValue)
{
query = query.Where(oi => oi.OrderDate.Date.Equals(OrderDate.Date));
}
query = query.Where(oi => oi.Status == 1);
query = query.Where(oi => oi.CancelFlag == 1);
int pagedData = await query.CountAsync();
List<OrderInfo> list = await query
.OrderBy((oi) => oi.RecvDate)
.ThenBy((oi => oi.OrderNo))
.Skip((int)skip)
.Take((int)take)
.ToListAsync();
return new PageData<OrderInfo>()
{
TotalDesserts = pagedData,
Desserts = list
};
}
public async Task<List<MachineRecord>> GetMachineRecordByOrderNo(string OrderrNo)
{
var query = _connection.MachineRecord.AsQueryable();
query = query.InnerJoin(
_connection.OrderDetail.Where(od => od.OrderNo.Equals(OrderrNo)),
(mr, od) => mr.InvoiceId.Equals(od.Id),
(mr, od) => mr
)
.Where(md => md.Type == 2)
.LoadWith(md => md.Drug)
;
return await query.ToListAsync();
}
public async Task<List<OperationVo<MachineRecord>>> getReturnInfoByOrderNo(string OrderrNo)
{
List<OperationVo<MachineRecord>> tempData = new();
List<MachineRecord> details = await this.GetMachineRecordByOrderNo(OrderrNo);
for (var i = 0; i < details.Count; i++)
{
//List<IDictionary<string, object>> tempData = new();
MachineRecord detail = details[i];
List<ChannelStock> stockList = await this.GetChannelStockByDrugId(detail.DrugId, detail.ManuNo);
// 当前药品的库存总量
var total = stockList.Sum(current => current.Quantity);
// 当前detail出库数量
var Quantity = detail.Quantity;
stockList.First().AddQuantity = Quantity;
tempData.Add(new OperationVo<MachineRecord>()
{
Drug = detail.Drug,
data = detail,
StockQuantity = total,
Quantity = Quantity,
ChannelStocks = stockList,
});
}
return tempData;
}
public async Task<DrugManuNo> GetDrugManuNo(string drugId, string manuNo)
{
var query = _connection.DrugManuNo.AsQueryable();
return await query.Where(m => m.DrugId.Equals(drugId))
.Where(m => m.ManuNo.Equals(manuNo))
.FirstAsync();
}
public async Task<bool> OrderReturnFinish(List<OperationVo<MachineRecord>> datas, string OrderNo)
{
try
{
_connection.BeginTransaction();
var flag = true;
// 更新处方状态
int r1 = _connection.OrderInfo.Where(oi => oi.OrderNo == OrderNo)
.Set(oi => oi.Status, 0)
.Update();
if (!(r1 > 0))
{
flag = false;
logger.Error("处方取药完成更新处方状态失败");
_connection.RollbackTransaction();
return flag;
}
for (var i = 0; i < datas.Count; i++)
{
var operationVo = datas[i];
List<ChannelStock> stocks = operationVo.ChannelStocks.Where(cs => cs.ReturnQuantity > 0).ToList();
// 更新取出记录状态
var r2 = _connection.MachineRecord.Where(cs => cs.Id == operationVo.data.Id)
.Set(cs => cs.Status, 2)
.Set(cs => cs.ReturnQuantity1, operationVo.data.Quantity).Update();
if(r2 > 0)
{
} else
{
flag = false;
break;
}
for (var j = 0; j < stocks.Count; j++)
{
var channelStock = stocks[j];
// 更新库存
var q = _connection.ChannelStock.Where(cs => cs.Id == channelStock.Id)
.Set(cs => cs.Quantity, channelStock.Quantity + channelStock.ReturnQuantity);
if (String.IsNullOrEmpty(channelStock.ManuNo) || (channelStock.Quantity == 0 && !channelStock.ManuNo.Equals(operationVo.data.ManuNo)))
{
DrugManuNo drugManuNo = await GetDrugManuNo(channelStock.DrugId, operationVo.data.ManuNo);
channelStock.Dmnguid = drugManuNo.Id;
channelStock.ManuNo = drugManuNo.ManuNo;
channelStock.EffDate = drugManuNo.EffDate.ToString();
q = q.Set(cs => cs.Dmnguid, drugManuNo.Id)
.Set(cs => cs.ManuNo, drugManuNo.ManuNo)
.Set(cs => cs.EffDate, drugManuNo.EffDate.ToString());
}
int r = q.Update();
// 退回记录
int mid = _connection.InsertWithInt32Identity(new MachineRecord()
{
MachineId = _setting.machineId,
DrawerNo = channelStock.DrawerNo,
ColNo = channelStock.ColNo,
DrugId = channelStock.DrugId,
ManuNo = channelStock.ManuNo,
EffDate = !String.IsNullOrEmpty(channelStock.EffDate) ? DateTime.ParseExact(channelStock.EffDate, "yyyy-MM-dd", System.Globalization.CultureInfo.CurrentCulture) : null,
OperationTime = DateTime.Now,
Type = 31,
Quantity = channelStock.ReturnQuantity,
Operator = _globalStateService.Operator.Id,
Reviewer = _globalStateService.Reviewer?.Id ?? _globalStateService.Operator.Id,
InvoiceId = operationVo.data.InvoiceId.ToString(),
GetId = operationVo.data.Id
});
// 获取更新完库存之后的药品库存
List<ChannelStock> list = await _connection.ChannelStock.AsQueryable()
.InnerJoin(
_connection.ChannelList.Where(cl => cl.MachineId.Equals(_setting.machineId)).Where(cl => cl.DrawerType == 1),
(cs, cl) => cs.ListId == cl.Id,
(cs, cl) => cs
)
.Where(cs => cs.DrugId.Equals(channelStock.DrugId))
.ToListAsync();
// 保存账册
int acid = _connection.InsertWithInt32Identity(new AccountBook()
{
MachineId = _setting.machineId,
DrugId = channelStock.DrugId,
ManuNo = channelStock.ManuNo,
EffDate = !String.IsNullOrEmpty(channelStock.EffDate) ? DateTime.ParseExact(channelStock.EffDate, "yyyy-MM-dd", System.Globalization.CultureInfo.CurrentCulture) : null,
OperationTime = DateTime.Now,
Type = 2,
OutQuantity = channelStock.ReturnQuantity,
AddQuantity = 0,
Operator = _globalStateService.Operator.Id,
Reviewer = _globalStateService.Reviewer?.Id ?? _globalStateService.Operator.Id,
ManuStock = list.Where(it => it.ManuNo == channelStock.ManuNo).Sum(it => it.Quantity),
TotalStock = list.Sum(it => it.Quantity),
InvoiceId = operationVo.data.InvoiceId
});
if (mid > 0 && r > 0 && acid > 0)
{
if(channelStock.BoardType.ToString().Contains("5"))
{
await _portUtil.WriteQuantityMethod(channelStock.Quantity - channelStock.ReturnQuantity, channelStock.DrawerNo, channelStock.ColNo);
}
}
else
{
flag = false;
break;
}
}
}
if (flag)
{
_connection.CommitTransaction();
}
else
{
_connection.RollbackTransaction();
}
return flag;
}
catch (Exception ex)
{
logger.Error("处方取药完成保存数据库失败,错误:" + ex.Message);
_connection.RollbackTransaction();
return false;
}
}
}
}

View File

@ -0,0 +1,75 @@
using LinqToDB;
using MasaBlazorApp3.DataAccess.Dao;
using MasaBlazorApp3.Pojo;
using MasaBlazorApp3.Pojo.Config;
using Microsoft.Extensions.Options;
using System.Linq;
namespace MasaBlazorApp3.DataAccess.Impl
{
public class RoleDao : IRoleDao
{
private AppDataConnection _connection;
private readonly SettingConfig _setting;
public RoleDao(AppDataConnection connection, IOptions<SettingConfig> setting) { _connection = connection; _setting = setting.Value; }
public async Task<Role> GetRoleById(int id)
{
return await _connection.Role.AsQueryable().FirstAsync(x => x.Id == id);
}
public int InsertRole(Role role)
{
role.MachineId = _setting.machineId;
return _connection.InsertWithInt32Identity(role);
}
public bool UpdateRole(Role role)
{
int r = _connection.Role
.Where(r => r.Id == role.Id)
.Set(r => r.RoleName, role.RoleName)
.Set(r => r.permissions, role.permissions)
.Update();
return r > 0;
}
public bool DeleteRole(int id)
{
return _connection.Role.Where(r => r.Id ==id).Delete() > 0;
}
public async Task<PageData<Role>> GetRolesByName(string name, int? take, int? skip)
{
var query = _connection.Role.AsQueryable();
if (!String.IsNullOrEmpty(name))
{
query = query.Where(r => r.RoleName.IndexOf(name) > -1);
}
query = query.Where(r => r.MachineId == _setting.machineId);
List<Role> list = await query
.OrderBy(r => r.Id)
.Skip((int)skip)
.Take((int)take)
.ToListAsync();
int pagedData = await query.CountAsync();
return new PageData<Role>()
{
TotalDesserts = pagedData,
Desserts = list
};
}
public async Task<List<Role>> GetAllRoles()
{
return await _connection.Role.Where(r => r.MachineId == _setting.machineId).ToListAsync();
}
}
}

View File

@ -0,0 +1,300 @@
using LinqToDB;
using log4net;
using MasaBlazorApp3.DataAccess.Dao;
using MasaBlazorApp3.Pages;
using MasaBlazorApp3.Pojo;
using MasaBlazorApp3.Pojo.Config;
using MasaBlazorApp3.Pojo.Vo;
using MasaBlazorApp3.Port;
using Microsoft.Extensions.Options;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Channels;
using System.Threading.Tasks;
namespace MasaBlazorApp3.DataAccess.Impl
{
public class SelfTakeDao : ISelfTakeDao
{
private AppDataConnection _connection;
private readonly SettingConfig _setting;
ILog logger = LogManager.GetLogger(typeof(SelfTake));
private GlobalStateService _globalStateService;
private readonly PortUtil _portUtil;
public SelfTakeDao(AppDataConnection connection, IOptions<SettingConfig> setting, GlobalStateService globalStateService, PortUtil portUtil)
{
_connection = connection;
_setting = setting.Value;
_globalStateService = globalStateService;
_portUtil = portUtil;
}
/// <summary>
/// 根据药品信息 获取药品库存信息
/// </summary>
/// <param name="drugInfos"></param>
/// <returns></returns>
public async Task<List<ChannelStock>> GetChannelStocksByDrug(List<DrugInfo> drugInfos)
{
List<ChannelStock> channelStocks = new List<ChannelStock>();
try
{
foreach (var drugInfo in drugInfos)
{
var query = _connection.ChannelStock.AsQueryable();
ChannelStock channelStock = query.Where(cs => cs.MachineId == _setting.machineId && cs.DrawerType == 1 && cs.DrugId == drugInfo.DrugId).First();
if (channelStock != null)
{
channelStocks.Add(channelStock);
}
else
{
logger.Info($"药品{drugInfo.DrugName}未绑定");
channelStocks.Add(new ChannelStock()
{
DrugId = drugInfo.DrugId,
DrawerType = 1,
MachineId = _setting.machineId,
Quantity = 0
});
}
}
}
catch (Exception ex)
{
logger.Info($"SelfTakeDao异常{ex.Message}");
}
return channelStocks;
}
/// <summary>
/// 根据药品明细获取数据
/// </summary>
/// <param name="orderDetails"></param>
/// <returns></returns>
public async Task<List<OrderTakeVo>> getTakeInfoByOrderNo(List<OrderDetail> orderDetails)
{
List<OrderTakeVo> tempData = new();
List<OrderTakeVo> tempData2 = new();
var flag = true;
for (var i = 0; i < orderDetails.Count; i++)
{
//List<IDictionary<string, object>> tempData = new();
OrderDetail detail = orderDetails[i];
// 当前detail取药数量
var Quantity = detail.Quantity;
List<ChannelStock> stockList = await this.GetChannelStockByDrugId(detail.Drug.DrugId, detail.SetManuNo, Quantity);
// 当前药品的库存总量
var total = stockList.Sum(current => current.Quantity);
tempData2.Add(new OrderTakeVo()
{
Drug = detail.Drug,
OrderDetail = detail,
StockQuantity = total,
Quantity = Quantity
});
if (flag)
{
// 盘点库存是否足够
if (total > Quantity)
{
for (var j = 0; Quantity > 0; j++)
{
ChannelStock stock = stockList[j];
if (Quantity > stock.Quantity)
{
// 取药数量大于库存
tempData.Add(new OrderTakeVo()
{
Drug = detail.Drug,
OrderDetail = detail,
ChannelStock = stock,
StockQuantity = total,
Quantity = stock.Quantity,
});
Quantity -= stock.Quantity;
}
else
{
//取药数量小于库存
tempData.Add(new OrderTakeVo()
{
Drug = detail.Drug,
OrderDetail = detail,
ChannelStock = stock,
StockQuantity = total,
Quantity = Quantity,
});
Quantity = 0;
}
}
}
else
{
// 库存不足
flag = false;
}
}
}
if (flag)
{
return tempData;
}
else
{
return tempData2;
}
}
public async Task<List<ChannelStock>> GetChannelStockByDrugId(string DrugId, String ManuNo, int quantity = 0)
{
var query = _connection.ChannelStock.AsQueryable();
query = query.Where(cs => cs.MachineId.Equals(_setting.machineId)).Where(cs => cs.DrawerType == 1)
.Where(cs => cs.Quantity > 0)
.Where(cs => cs.DrugId.Equals(DrugId));
if (quantity > 0)
{
if (!String.IsNullOrEmpty(ManuNo))
{
query = query.Where(cs => cs.ManuNo.Equals(ManuNo));
}
}
else
{
if (!String.IsNullOrEmpty(ManuNo))
{
query = query.Where(cs => cs.ManuNo.Equals(ManuNo) || cs.Quantity == 0);
}
}
return await query.OrderBy((cs) => cs.EffDate)
.ThenBy((cs) => cs.DrawerNo)
.ThenBy((cs) => cs.ColNo)
.ToListAsync();
}
/// <summary>
/// 保存自选取药完成数据
/// </summary>
/// <param name="datas"></param>
/// <returns></returns>
public async Task<bool> OrderTakeFinish(List<OrderTakeVo> datas, OrderInfo order)
{
try
{
_connection.BeginTransaction();
var flag = true;
// 保存处方信息
order.Status = 1;
order.PatientId = order.PatientId == null ? "0" : order.PatientId;
int r1 = _connection.InsertWithInt32Identity<OrderInfo>(order);
if (!(r1 > 0))
{
flag = false;
logger.Error("处方取药完成更新处方状态失败");
_connection.RollbackTransaction();
return flag;
}
for (var i = 0; i < datas.Count; i++)
{
var orderTakeVo = datas[i];
//保存处方明细
orderTakeVo.OrderDetail.PatientId = orderTakeVo.OrderDetail.PatientId == null ? order.PatientId : orderTakeVo.OrderDetail.PatientId;
orderTakeVo.OrderDetail.ChargeDate = orderTakeVo.OrderDetail.ChargeDate == null ? order.ChargeDate : orderTakeVo.OrderDetail.ChargeDate;
orderTakeVo.OrderDetail.OrderNo = order.OrderNo;
orderTakeVo.OrderDetail.DrugId = orderTakeVo.Drug.DrugId;
orderTakeVo.OrderDetail.SetManuNo = orderTakeVo.ChannelStock.ManuNo;
orderTakeVo.OrderDetail.SetEffDate = orderTakeVo.ChannelStock.EffDate;
int od = _connection.InsertWithInt32Identity<OrderDetail>(orderTakeVo.OrderDetail);
// 出库记录
int mid = _connection.InsertWithInt32Identity(new MachineRecord()
{
MachineId = _setting.machineId,
DrawerNo = orderTakeVo.ChannelStock.DrawerNo,
ColNo = orderTakeVo.ChannelStock.ColNo,
DrugId = orderTakeVo.ChannelStock.DrugId,
ManuNo = orderTakeVo.ChannelStock.ManuNo,
EffDate = !String.IsNullOrEmpty(orderTakeVo.ChannelStock.EffDate) ? DateTime.ParseExact(orderTakeVo.ChannelStock.EffDate, "yyyy-MM-dd", System.Globalization.CultureInfo.CurrentCulture) : null,
OperationTime = DateTime.Now,
Type = 2,
Quantity = orderTakeVo.GetQuantity,
Operator = _globalStateService.Operator.Id,
Reviewer = _globalStateService.Reviewer?.Id ?? _globalStateService.Operator.Id,
InvoiceId = orderTakeVo.OrderDetail.Id.ToString(),
});
// 更新库存
int r = _connection.ChannelStock.Where(cs => cs.Id == orderTakeVo.ChannelStock.Id)
.Set(cs => cs.Quantity, orderTakeVo.ChannelStock.Quantity - orderTakeVo.GetQuantity)
.Update();
// 获取更新完库存之后的药品库存
List<ChannelStock> list = await _connection.ChannelStock.AsQueryable()
.InnerJoin(
_connection.ChannelList.Where(cl => cl.MachineId.Equals(_setting.machineId)).Where(cl => cl.DrawerType == 1),
(cs, cl) => cs.ListId == cl.Id,
(cs, cl) => cs
)
.Where(cs => cs.DrugId.Equals(orderTakeVo.ChannelStock.DrugId))
.ToListAsync();
// 保存账册
int acid = _connection.InsertWithInt32Identity(new AccountBook()
{
MachineId = _setting.machineId,
DrugId = orderTakeVo.ChannelStock.DrugId,
ManuNo = orderTakeVo.ChannelStock.ManuNo,
EffDate = !String.IsNullOrEmpty(orderTakeVo.ChannelStock.EffDate) ? DateTime.ParseExact(orderTakeVo.ChannelStock.EffDate, "yyyy-MM-dd", System.Globalization.CultureInfo.CurrentCulture) : null,
OperationTime = DateTime.Now,
Type = 2,
OutQuantity = orderTakeVo.GetQuantity,
AddQuantity = 0,
Operator = _globalStateService.Operator.Id,
Reviewer = _globalStateService.Reviewer?.Id ?? _globalStateService.Operator.Id,
ManuStock = list.Where(it => it.ManuNo == orderTakeVo.ChannelStock.ManuNo).Sum(it => it.Quantity),
TotalStock = list.Sum(it => it.Quantity),
InvoiceId = orderTakeVo.OrderDetail.Id.ToString()
});
if (mid > 0 && r > 0 && acid > 0)
{
//根据抽屉类型判断是否需要写标签
if (orderTakeVo.ChannelStock.BoardType.ToString().Contains("5"))
{
await _portUtil.WriteQuantityMethod(orderTakeVo.ChannelStock.Quantity - orderTakeVo.GetQuantity, orderTakeVo.ChannelStock.DrawerNo, orderTakeVo.ChannelStock.ColNo);
}
}
else
{
flag = false;
break;
}
}
if (flag)
{
_connection.CommitTransaction();
}
else
{
_connection.RollbackTransaction();
}
return flag;
}
catch (Exception ex)
{
logger.Error("自选取药完成保存数据库失败,错误:" + ex.Message);
_connection.RollbackTransaction();
return false;
}
}
}
}

View File

@ -0,0 +1,111 @@
using Google.Protobuf.WellKnownTypes;
using LinqToDB;
using MasaBlazorApp3.DataAccess.Dao;
using MasaBlazorApp3.Pojo;
using MasaBlazorApp3.Pojo.Config;
using MasaBlazorApp3.Util;
using Microsoft.Extensions.Options;
using System.Data;
using System.Xml.Linq;
namespace MasaBlazorApp3.DataAccess.Impl
{
public class UserDao : IUserDao
{
//private MyContext Context;
private readonly AppDataConnection _connection;
private readonly SettingConfig _setting;
//public UserDao(MyContext context)
//{
// Context = context;
//}
public UserDao(AppDataConnection connection, IOptions<SettingConfig> setting)
{
_connection = connection;
_setting = setting.Value;
}
public async Task<PageData<User>> GetAllByNickname(string nickname, int? take, int? skip)
{
var query = _connection.User.AsQueryable();
if (!String.IsNullOrEmpty(nickname))
{
query = query.Where(r => r.NickName.IndexOf(nickname) > -1);
}
query = query.Where(u => u.MachineId == _setting.machineId);
List<User> list = await query
.LoadWith(u => u.role)
.OrderBy(u => u.Id)
.Skip((int)skip)
.Take((int)take)
.ToListAsync();
int pagedData = await query.CountAsync();
return new PageData<User>()
{
TotalDesserts = pagedData,
Desserts = list
};
}
public User GetById(int id)
{
return _connection.User.LoadWith(u => u.role).FirstOrDefault(u => u.Id == id);
}
public User GetByUsername(string username)
{
return _connection.User.LoadWith(u => (u.role)).FirstOrDefault(u => u.Username == username&&u.MachineId== _setting.machineId);
}
public int InsertUser(User user)
{
user.MachineId = _setting.machineId;
user.Password = MD5.GetMD5Hash("123456").ToLower();
return _connection.InsertWithInt32Identity(user);
}
public bool UpdateUser(User user)
{
var statement = _connection.User
.Where(u => u.Id == user.Id)
.Set(u => u.NickName, user.NickName)
.Set(u => u.Username, user.Username)
.Set(u => u.RoleId, user.RoleId);
//if(!String.IsNullOrEmpty(user.Password))
//{
// statement.Set(u => user.Password, MD5.GetMD5Hash(user.Password).ToLower());
//}
return statement.Update() > 0;
}
public bool DeleteeUser(int id)
{
return _connection.User.Where(u => u.Id == id).Delete() > 0;
}
//重置用户密码
public bool ResetPassword(int id)
{
var statement= _connection.User.Where(u => u.Id == id).Set(u=>u.Password, MD5.GetMD5Hash("123456").ToLower());
return statement.Update() > 0;
}
public async Task<bool> UpdateSign(int id, string sign)
{
var statement = _connection.User
.Where(u => u.Id == id)
.Set(u => u.Sign, Convert.FromBase64String(sign));
//if(!String.IsNullOrEmpty(user.Password))
//{
// statement.Set(u => user.Password, MD5.GetMD5Hash(user.Password).ToLower());
//}
return (await statement.UpdateAsync()) > 0;
}
}
}

View File

@ -0,0 +1,14 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MasaBlazorApp3.DataAccess
{
public class PageData<T>
{
public int TotalDesserts { get; set; }
public List<T> Desserts { get; set; } = new List<T>();
}
}

View File

@ -0,0 +1,15 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MasaBlazorApp3.DataAccess
{
public class PageMultiData<T,S>
{
public int TotalDesserts { get; set; }
public List<T> Desserts { get; set; } = new List<T>();
public List<S> Other { get; set; } = new List<S>();
}
}

View File

@ -0,0 +1,142 @@
using log4net;
using MasaBlazorApp3.Pojo;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using zkemkeeper;
using Microsoft.Extensions.Options;
using MasaBlazorApp3.Pojo.Config;
namespace MasaBlazorApp3.Finger
{
public class FingerprintUtil
{
private readonly ILog logger = LogManager.GetLogger(typeof(FingerprintUtil));
private readonly FingerPojo _options;
public CZKEMClass axCZKEM1 = new CZKEMClass();
public bool bIsConnected = false;
private int fingerPort = 4370;
private int machineNumber = 1;
private int machineType = 2;
public FingerprintUtil(IOptions<FingerPojo> options)
{
_options = options.Value;
logger.Info($"进入构造器,开始连接指纹机");
// ConnectionMain();
}
public async void ConnectionMain()
{
await Task.Run(() =>
{
try
{
bIsConnected = axCZKEM1.Connect_Net(_options.ip, fingerPort);
logger.Info($"连接指纹机,IP:{_options.ip},端口:{fingerPort},机器号:{machineNumber},连接结果:{bIsConnected}");
if (bIsConnected)
{
if (axCZKEM1.RegEvent(machineNumber, 65535))
{
this.axCZKEM1.OnAttTransactionEx += new zkemkeeper._IZKEMEvents_OnAttTransactionExEventHandler(axCZKEM1_OnAttTransactionEx);
//this.axCZKEM1.OnEnrollFinger += new zkemkeeper._IZKEMEvents_OnEnrollFingerEventHandler(axCZKEM1_OnEnrollFinger);
this.axCZKEM1.OnEnrollFingerEx += new zkemkeeper._IZKEMEvents_OnEnrollFingerExEventHandler(axCZKEM1_OnEnrollFingerEx);
}
}
}
catch
{
}
});
}
//If your fingerprint(or your card) passes the verification,this event will be triggered
private void axCZKEM1_OnAttTransactionEx(string sEnrollNumber, int iIsInValid, int iAttState, int iVerifyMethod, int iYear, int iMonth, int iDay, int iHour, int iMinute, int iSecond, int iWorkCode)
{
logger.Info($"触发用户验证通过事件用户id:{sEnrollNumber}验证方式:{iVerifyMethod}");
}
//When you are enrolling your finger,this event will be triggered.
private void axCZKEM1_OnEnrollFinger(int iEnrollNumber, int iFingerIndex, int iActionResult, int iTemplateLength)
{
axCZKEM1.StartIdentify();
axCZKEM1.RefreshData(1);
logger.Info($"触发用户登记指纹事件用户id:{iEnrollNumber}指纹索引:{iFingerIndex}登记结果:{(iActionResult == 0)}");
}
private void axCZKEM1_OnEnrollFingerEx(string iEnrollNumber, int iFingerIndex, int iActionResult, int iTemplateLength)
{
axCZKEM1.StartIdentify();
axCZKEM1.RefreshData(1);
logger.Info($"触发用户登记指纹事件1用户id:{iEnrollNumber}指纹索引:{iFingerIndex}登记结果:{(iActionResult == 0)}");
}
/**
*
*/
public bool DelUser(int Id)
{
bool result = false;
axCZKEM1.EnableDevice(machineNumber, false);
if (machineType == 1)
{
result = axCZKEM1.DeleteEnrollData(machineNumber, Id, machineNumber, 12);
}
else
{
result = axCZKEM1.SSR_DeleteEnrollData(machineNumber, Id.ToString(), 12);
}
axCZKEM1.RefreshData(machineNumber);
axCZKEM1.EnableDevice(machineNumber, true);
return result;
}
/**
*
*/
public bool SaveUser(User User)
{
bool result = false;
//axCZKEM1.SetStrCardNumber(User.UserBarcode);
if (machineType == 1)
{
result = axCZKEM1.SetUserInfo(machineNumber, User.Id, User.NickName, "123456", 0, true);
}
else
{
result = axCZKEM1.SSR_SetUserInfo(machineNumber, User.Id.ToString(), User.NickName, "123456", 0, true);
}
return result;
}
/**
*
*/
public bool SaveFingerprint(int Id, int FingerIndex)
{
bool result = false;
// 取消其他操作
bool res2 = axCZKEM1.CancelOperation();
// 删除源指纹
bool res = axCZKEM1.SSR_DelUserTmp(machineNumber, Id.ToString(), FingerIndex);
// 添加新指纹
result = axCZKEM1.StartEnrollEx(Id.ToString(), FingerIndex, 3);
return result;
}
}
}

View File

@ -0,0 +1,40 @@
using System.ComponentModel;
using MasaBlazorApp3.Pojo;
namespace MasaBlazorApp3
{
public class GlobalStateService : INotifyPropertyChanged
{
private User _operator;
private User _reviewer;
public User Operator
{
get { return _operator; }
set
{
_operator = value;
//OnPropertyChanged();
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Operator"));
}
}
public User Reviewer
{
get => _reviewer;
set
{
_reviewer = value;
//OnPropertyChanged();
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Reviewer"));
}
}
public event PropertyChangedEventHandler? PropertyChanged;
//protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
//{
//}
}
}

View File

@ -0,0 +1,96 @@
<Project Sdk="Microsoft.NET.Sdk.Razor">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<ApplicationIcon>favicon.ico</ApplicationIcon>
</PropertyGroup>
<ItemGroup>
<COMReference Include="zkemkeeper">
<WrapperTool>tlbimp</WrapperTool>
<VersionMinor>0</VersionMinor>
<VersionMajor>1</VersionMajor>
<Guid>fe9ded34-e159-408e-8490-b720a5e632c7</Guid>
<Lcid>0</Lcid>
<Isolated>false</Isolated>
<EmbedInteropTypes>False</EmbedInteropTypes>
</COMReference>
<COMReference Include="gregn6Lib">
<WrapperTool>tlbimp</WrapperTool>
<VersionMinor>0</VersionMinor>
<VersionMajor>6</VersionMajor>
<Guid>4018f953-1bfe-441e-8a04-dc8ba1ff060e</Guid>
<Lcid>0</Lcid>
<Isolated>false</Isolated>
<EmbedInteropTypes>False</EmbedInteropTypes>
</COMReference>
</ItemGroup>
<ItemGroup>
<PackageReference Include="FluentValidation" Version="11.9.1" />
<PackageReference Include="linq2db.AspNet" Version="5.4.1" />
<PackageReference Include="log4net" Version="2.0.17" />
<PackageReference Include="MySql.Data" Version="8.4.0" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="Photino.Blazor" Version="2.7.0" />
<PackageReference Include="Radzen.Blazor" Version="4.32.1" />
<PackageReference Include="SharpPromise" Version="1.7.0" />
<PackageReference Include="SuperSimpleTcp" Version="3.0.14" />
<PackageReference Include="System.IO.Ports" Version="8.0.0" />
<PackageReference Include="System.Management" Version="8.0.0" />
<PackageReference Include="System.Speech" Version="8.0.0" />
</ItemGroup>
<ItemGroup>
<Content Update="wwwroot\**">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
</ItemGroup>
<ItemGroup>
<Content Update="log4net.config">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
</ItemGroup>
<ItemGroup>
<None Remove="i18ntext\MyText.zh.json" />
</ItemGroup>
<ItemGroup>
<None Remove="i18ntext\MyText.en.json" />
</ItemGroup>
<ItemGroup>
<Content Include="favicon.ico">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
</ItemGroup>
<ItemGroup>
<None Update="favicon.ico">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="ReportTemp\account_book_temp.grf">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="ReportTemp\machine_log_add.grf">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="ReportTemp\machine_log_check.grf">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="ReportTemp\machine_log_return.grf">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="ReportTemp\machine_log_take.grf">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="ReportTemp\stock_template.grf">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project>

View File

@ -0,0 +1,288 @@
@page "/stock/biaoDing"
@using MasaBlazorApp3.Pojo.Config;
@using MasaBlazorApp3.Util;
@using Microsoft.AspNetCore.Components
@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"
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">
<RadzenButton IsBusy="@(status>0)" BusyText="抽屉已打开。。。" ButtonStyle="ButtonStyle.Warning" Variant="Variant.Outlined" Shade="Shade.Light" Text="开抽屉" Click="@OpenDrawer" />
</RadzenRow>
</HeaderTemplate>
<Columns>
<RadzenDataGridColumn Width="70px" Title="库位" Property="ColNo"></RadzenDataGridColumn>
<RadzenDataGridColumn 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 Title="批次" Property="ManuNo">
<Template Context="channel">
<RadzenText TextStyle="TextStyle.Subtitle2" class="mb-0">@channel.drugManuNo?.ManuNo</RadzenText>
<RadzenText TextStyle="TextStyle.Caption">@channel.drugManuNo?.EffDate</RadzenText>
</Template>
<EditTemplate Context="channel">
@if (channel.Quantity == 0 && !String.IsNullOrEmpty(channel.DrugId))
{
<RadzenDropDown TValue="DrugManuNo" Name="ManuNo" @bind-Value="channel.drugManuNo" Data="@channel.Drug?.Manus" Style="width:100%; display: block;">
<Template>
<RadzenText TextStyle="TextStyle.Subtitle2" class="mb-0">@((context as DrugManuNo)?.ManuNo)</RadzenText>
<RadzenText TextStyle="TextStyle.Caption">@((context as DrugManuNo)?.EffDate)</RadzenText>
</Template>
<ValueTemplate>
<RadzenStack Orientation="Orientation.Horizontal">
<RadzenText TextStyle="TextStyle.Subtitle2" class="mb-0">@((context as DrugManuNo)?.ManuNo)</RadzenText>
<RadzenText TextStyle="TextStyle.Caption">@((context as DrugManuNo)?.EffDate)</RadzenText>
</RadzenStack>
</ValueTemplate>
</RadzenDropDown>
<RadzenRequiredValidator Text="请选择批次" Component="ManuNo" Popup="true" />
}
else
{
<RadzenText TextStyle="TextStyle.Subtitle2" class="mb-0">@channel.drugManuNo?.ManuNo</RadzenText>
<RadzenText TextStyle="TextStyle.Caption">@channel.drugManuNo?.EffDate</RadzenText>
}
</EditTemplate>
</RadzenDataGridColumn>
<RadzenDataGridColumn Title="库存" Property="Quantity">
<Template Context="cs">
<RadzenButton ButtonStyle="ButtonStyle.Info" Variant="Variant.Flat" Shade="Shade.Lighter" class="m-1" Text="@cs.Quantity.ToString()" />
</Template>
</RadzenDataGridColumn>
<RadzenDataGridColumn MinWidth="100px" Title="加药数量" Property="AddQuantity">
<EditTemplate Context="cs">
@if (cs.BoardType == 2)
{
@cs.AddQuantity
}
else
{
<RadzenNumeric Min="0" Style="display: block" Name="Quantity" @bind-Value=@cs.AddQuantity />
<RadzenNumericRangeValidator Style="position: absolute;z-index: 9999;" Min="0" 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;
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, 9, 10, 11, 12, 13, 14, 15, 16};
int[] BeforeQuantity = new int[9];
int[] AfterQuantity = new int[9];
private readonly ILog logger = LogManager.GetLogger(typeof(DrawerAdd));
// 当前操作的库位号列表
public List<int> ColNos { get; set; } = new List<int>();
int currentCol = 0;
bool CompleteIsEnable = true;
bool CancleIsEnable = true;
void SelectDrawer(int drawerNo)
{
this.drawerNo = drawerNo;
grid.Reload();
}
async Task LoadData(LoadDataArgs args)
{
isLoading = true;
var result = await channelListDao.GetChannelStockByDrawerNoWithDrawers(drawerNo);
DrawerNos = result.DrawerArray;
channels = result.ChannelStocks;
count = result.ChannelStocks.Count;
isLoading = false;
}
async Task OpenDrawer()
{
this.status = 1;
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(库存》0)
// {}
}
var b = await PortUtil.OpenDrawerStatus(this.drawerNo);
if (b)
{
PortUtil.SpeakAsync($"{drawerNo}号抽屉已经打开,请,加药");
this.status = 2;
PortUtil.Operate = true;
next();
}
// else
// {
// _message.Notify(
// new NotificationMessage { Severity = NotificationSeverity.Error, Summary = "提示", Detail = $"抽屉【{drawerNo}】打开失败,请检测硬件", Duration = 4000 }
// );
// logger.Info($"抽屉打开失败");
// RestData();
// PortUtil.Operate = false;
// stop();
// }
else if (this.status == 2)
{
if (setting.Value.box != null && setting.Value.box.Contains(this.drawerNo))
{
//药盒抽屉,开药盒
for (int i = 0; i < ColNos.Count; i++)
{
await PortUtil.OpenBoxByColNo(ColNos[i]);
}
}
// 查询抽屉是否为关闭状态
var b2 = await PortUtil.CheckDrawerStatus2(drawerNo);
// 关闭则改变状态并终止循环
if (b2)
{
PortUtil.SpeakAsync($"加药完成,请,核对,或,录入,正确的,添加数量");
// 判断是否为称重抽屉
if (setting.Value.weigh != null && setting.Value.weigh.Contains(this.drawerNo))
{
//关闭抽屉后获取称重稳定数量
// await GetWeightQuantity();
}
this.status = 3;
PortUtil.Operate = false;
stop();
}
else
{
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)}】");
channels.ForEach(cl =>
{
cl.AddQuantity = this.AfterQuantity[cl.ColNo - 1] - this.BeforeQuantity[cl.ColNo - 1];
});
}
// 判断是否为称重抽屉
if (setting.Value.weigh != null && setting.Value.weigh.Contains(this.drawerNo))
{
//开抽屉后查数
for (int i = 0; i < 9; i++)
{
int afterQuantity = await PortUtil.CheckQuantityForSingle(i);
AfterQuantity[i] = afterQuantity;
logger.Info($"AfterQuantity:{i}-{AfterQuantity}数量{string.Join(",", BeforeQuantity)}");
}
channels.ForEach(cl =>
{
cl.AddQuantity = this.AfterQuantity[cl.ColNo - 1] - this.BeforeQuantity[cl.ColNo - 1];
});
}
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 != null && setting.Value.single.Contains(this.drawerNo))
{
PortUtil.AllLightOff();
}
RestData();
stop();
}
});
}
void RestData()
{
this.status = 0;
}
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);
}
}
}

View File

@ -0,0 +1,27 @@

<RadzenStack>
<RadzenText TextStyle="TextStyle.Body1" Style="color: var(--rz-text-tertiary-color); align-content:center; text-align:center; font-size:medium;">确认要@(confirmInfo) 吗?</RadzenText>
<RadzenStack Orientation="Orientation.Horizontal" JustifyContent="JustifyContent.Center" Gap="0.5rem">
<RadzenButton Click="@ConfirmOK" ButtonStyle="ButtonStyle.Success" Variant="Variant.Flat" Text="确认" Style="width: 120px" />
<RadzenButton Click="@((args) => dialogService.Close(false))" Variant="Variant.Flat" Text="取消" Style="width: 120px" />
</RadzenStack>
</RadzenStack>
@code {
@inject Radzen.DialogService dialogService;
[Parameter] public string confirmInfo { get; set; }
protected override async Task OnInitializedAsync()
{
var info = confirmInfo;
base.OnInitializedAsync();
}
async Task ConfirmOK()
{
// 关闭弹窗
dialogService.Close(true);
}
}

View File

@ -0,0 +1,446 @@
@page "/add/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">
<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">
@* <RadzenStack AlignItems="AlignItems.Center" JustifyContent="JustifyContent.Center" Orientation="Orientation.Vertical" Style="margin-top: 220px"> *@
<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>
@* </RadzenStack> *@
</div>
</div>
<RadzenDataGrid @ref="grid"
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)
{
<RadzenButton IsBusy="@(status>0)" BusyText="加药中。。。" ButtonStyle="ButtonStyle.Warning" Variant="Variant.Outlined" Shade="Shade.Light" Text="加药" Click="@OpenDrawer" />
}
@if (status == 3)
{
<RadzenButton Visible="@CompleteIsEnable" ButtonStyle="ButtonStyle.Warning" Variant="Variant.Outlined" Shade="Shade.Light" Text="完成" Click="@AddFinish" />
}
@if (status > 0 && status <= 3)
{
<RadzenButton Visible="@CancleIsEnable" Variant="Variant.Flat" Text="取消" Click="@Cancel" Style="width: 120px" />
}
</RadzenRow>
</HeaderTemplate>
<Columns>
<RadzenDataGridColumn Width="70px" Title="库位" Property="ColNo"></RadzenDataGridColumn>
<RadzenDataGridColumn 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 Title="批次" Property="ManuNo">
<Template Context="channel">
<RadzenText TextStyle="TextStyle.Subtitle2" class="mb-0">@channel.drugManuNo?.ManuNo</RadzenText>
<RadzenText TextStyle="TextStyle.Caption">@channel.drugManuNo?.EffDate</RadzenText>
</Template>
<EditTemplate Context="channel">
@if (channel.Quantity == 0 && !String.IsNullOrEmpty(channel.DrugId))
{
<RadzenDropDown TValue="DrugManuNo" Name="ManuNo" @bind-Value="channel.drugManuNo" Data="@channel.Drug?.Manus" Style="width:100%; display: block;">
<Template>
<RadzenText TextStyle="TextStyle.Subtitle2" class="mb-0">@((context as DrugManuNo)?.ManuNo)</RadzenText>
<RadzenText TextStyle="TextStyle.Caption">@((context as DrugManuNo)?.EffDate)</RadzenText>
</Template>
<ValueTemplate>
<RadzenStack Orientation="Orientation.Horizontal">
<RadzenText TextStyle="TextStyle.Subtitle2" class="mb-0">@((context as DrugManuNo)?.ManuNo)</RadzenText>
<RadzenText TextStyle="TextStyle.Caption">@((context as DrugManuNo)?.EffDate)</RadzenText>
</RadzenStack>
</ValueTemplate>
</RadzenDropDown>
<RadzenRequiredValidator Text="请选择批次" Component="ManuNo" Popup="true" />
}
else
{
<RadzenText TextStyle="TextStyle.Subtitle2" class="mb-0">@channel.drugManuNo?.ManuNo</RadzenText>
<RadzenText TextStyle="TextStyle.Caption">@channel.drugManuNo?.EffDate</RadzenText>
}
</EditTemplate>
</RadzenDataGridColumn>
<RadzenDataGridColumn Title="库存" Property="Quantity">
<Template Context="cs">
<RadzenButton ButtonStyle="ButtonStyle.Info" Variant="Variant.Flat" Shade="Shade.Lighter" class="m-1" Text="@cs.Quantity.ToString()" />
</Template>
</RadzenDataGridColumn>
<RadzenDataGridColumn MinWidth="100px" Title="加药数量" Property="AddQuantity">
<EditTemplate Context="cs">
@if (cs.BoardType == 2)
{
@cs.AddQuantity
}
else
{
<RadzenNumeric Min="0" Style="display: block" Name="Quantity" @bind-Value=@cs.AddQuantity />
<RadzenNumericRangeValidator Style="position: absolute;z-index: 9999;" Min="0" 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;
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, 9, 10, 11, 12, 13, 14, 15, 16 };
int[] BeforeQuantity = new int[9];
int[] AfterQuantity = new int[9];
private readonly ILog logger = LogManager.GetLogger(typeof(DrawerAdd));
// 当前操作的库位号列表
public List<int> ColNos { get; set; } = new List<int>();
int currentCol = 0;
bool CompleteIsEnable = true;
bool CancleIsEnable=true;
async Task LoadData(LoadDataArgs args)
{
isLoading = true;
var result = await channelListDao.GetChannelStockByDrawerNoWithDrawers(drawerNo);
// var result = await channelListDao.GetChannelStockByDrawerNo(drawerNo);
// Update the Data property
DrawerNos = result.DrawerArray;
channels = result.ChannelStocks;
// Update the count
count = result.ChannelStocks.Count;
isLoading = false;
}
async Task OpenDrawer()
{
this.status = 1;
// 根据抽屉类型来决定打开前是否需要查询数量
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)}】");
}
// 判断是否为称重抽屉
if (setting.Value.weigh != null && setting.Value.weigh.Contains(this.drawerNo))
{
//开抽屉前先查数
for (int i = 0; i < 9; i++)
{
int beforeQuantity = await PortUtil.CheckQuantityForSingle(i);
BeforeQuantity[i] = beforeQuantity;
logger.Info($"BeforeQuantity:{i}-{beforeQuantity}数量{string.Join(",", BeforeQuantity)}");
}
}
var b = await PortUtil.OpenDrawerStatus(this.drawerNo);
if (b)
{
PortUtil.SpeakAsync($"{drawerNo}号抽屉已经打开,请,加药");
this.status = 2;
PortUtil.Operate = true;
next();
}
else
{
_message.Notify(
new NotificationMessage { Severity = NotificationSeverity.Error, Summary = "提示", Detail = $"抽屉【{drawerNo}】打开失败,请检测硬件", Duration = 4000 }
);
logger.Info($"抽屉打开失败");
RestData();
PortUtil.Operate = false;
stop();
}
}
// 检测状态
else if (this.status == 2)
{
if (setting.Value.box != null && setting.Value.box.Contains(this.drawerNo))
{
//药盒抽屉,开药盒
for(int i=0;i< ColNos.Count;i++)
{
await PortUtil.OpenBoxByColNo(ColNos[i]);
}
}
// 查询抽屉是否为关闭状态
var b = await PortUtil.CheckDrawerStatus2(drawerNo);
// 关闭则改变状态并终止循环
if (b)
{
PortUtil.SpeakAsync($"加药完成,请,核对,或,录入,正确的,添加数量");
// 判断是否为称重抽屉
if (setting.Value.weigh != null && setting.Value.weigh.Contains(this.drawerNo))
{
//关闭抽屉后获取称重稳定数量
await GetWeightQuantity();
}
this.status = 3;
PortUtil.Operate = false;
stop();
}
else
{
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)}】");
channels.ForEach(cl =>
{
cl.AddQuantity = this.AfterQuantity[cl.ColNo - 1] - this.BeforeQuantity[cl.ColNo - 1];
});
}
// 判断是否为称重抽屉
if (setting.Value.weigh != null && setting.Value.weigh.Contains(this.drawerNo))
{
//开抽屉后查数
for (int i = 0; i < 9; i++)
{
int afterQuantity = await PortUtil.CheckQuantityForSingle(i);
AfterQuantity[i] = afterQuantity;
logger.Info($"AfterQuantity:{i}-{AfterQuantity}数量{string.Join(",", BeforeQuantity)}");
}
channels.ForEach(cl =>
{
cl.AddQuantity = this.AfterQuantity[cl.ColNo - 1] - this.BeforeQuantity[cl.ColNo - 1];
});
}
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 != null && setting.Value.single.Contains(this.drawerNo))
{
PortUtil.AllLightOff();
}
RestData();
stop();
}
});
}
void RestData()
{
this.status = 0;
this.BeforeQuantity = new int[9];
this.AfterQuantity = new int[9];
}
//关闭抽屉后获取称重稳定数量
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();
}
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();
channels.ForEach(cl =>
{
cl.AddQuantity = this.AfterQuantity[cl.ColNo - 1] - this.BeforeQuantity[cl.ColNo - 1];
});
}
else
{
finallyQuantity.RemoveAt(0);
next();
}
}
else
{
if (finallyQuantity.Count >= 9)
{
CancleIsEnable = true;
}
else
{
CancleIsEnable = false;
}
CompleteIsEnable = false;
PortUtil.DrawerNo = drawerNo;
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)}");
channels.ForEach(cl =>
{
cl.AddQuantity = this.AfterQuantity[cl.ColNo - 1] - this.BeforeQuantity[cl.ColNo - 1];
});
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));
}
async Task AddFinish()
{
if (channels.Any(cl => cl.AddQuantity != 0 && cl.DrugId != null && cl.drugManuNo != null))
{
// 保存账册、操作记录
var b = await channelListDao.DrawerOperationFinish(channels.Where(cl => cl.AddQuantity != 0).ToList(), 1);
if (!b)
{
_message.Notify(new NotificationMessage { Severity = NotificationSeverity.Error, Summary = "提示", Detail = $"数据保存失败", Duration = 4000 });
logger.Error($"抽屉加药保存数据库失败,数据{JsonConvert.SerializeObject(channels)}");
}
else
{
// 判断是否为标签抽屉
if (setting.Value.label.Contains(this.drawerNo))
{
//写标签数量
channels.ForEach(async it =>
{
await PortUtil.WriteQuantityMethod(it.Quantity + it.AddQuantity, it.DrawerNo, it.ColNo);
});
}
}
}
//重置状态
this.RestData();
// 重新查询库存
await grid.Reload();
}
void Cancel()
{
this.status = 0;
}
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);
}
}
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();
}
}

View File

@ -0,0 +1,445 @@
@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 align-items-center">
<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: 240px; height:650px">
<RadzenStack AlignItems="AlignItems.Center" JustifyContent="JustifyContent.Center" Orientation="Orientation.Vertical" Style="margin-top: 220px">
@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)" />
}
</RadzenStack>
</div>
</div> *@
<div class="row justify-content-center">
<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">
@* <RadzenStack AlignItems="AlignItems.Center" JustifyContent="JustifyContent.Center" Orientation="Orientation.Vertical" Style="margin-top: 220px"> *@
<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>
@* </RadzenStack> *@
</div>
</div>
<RadzenDataGrid @ref="grid"
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)
{
<RadzenButton IsBusy="@(status>0)" BusyText="取药中。。。" ButtonStyle="ButtonStyle.Warning" Variant="Variant.Flat" Shade="Shade.Light" Text="取药" Click="@OpenDrawer" />
}
@if (status == 3)
{
<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="70px" Title="库位" Property="ColNo"></RadzenDataGridColumn>
<RadzenDataGridColumn 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 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="库存" 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="120px" Title="取药数量" Property="TakeQuantity">
<EditTemplate Context="channel">
@if (channel.BoardType == 2)
{
@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;
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>();
bool CompleteIsEnable = true;
bool CancleIsEnable = true;
private readonly ILog logger = LogManager.GetLogger(typeof(DrawerTake));
async Task LoadData(LoadDataArgs args)
{
isLoading = true;
// var result = await channelListDao.GetChannelStockByDrawerNo(drawerNo, 1);
var result = await channelListDao.GetChannelStockByDrawerNoWithDrawers(drawerNo);
DrawerNos = result.DrawerArray;
// Update the Data property
channels = result.ChannelStocks;
// Update the count
count = result.ChannelStocks.Count;
isLoading = false;
}
async Task OpenDrawer()
{
this.status = 1;
// 根据抽屉类型来决定打开前是否需要查询数量
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)}】");
}
// 判断是否为称重抽屉
if (setting.Value.weigh!=null&&setting.Value.weigh.Contains(this.drawerNo))
{
//开抽屉前先查数
for (int i = 0; i < 9; i++)
{
int beforeQuantity = await PortUtil.CheckQuantityForSingle(i);
BeforeQuantity[i] = beforeQuantity;
logger.Info($"BeforeQuantity:{i}-{beforeQuantity}数量{string.Join(",", BeforeQuantity)}");
}
}
var b = await PortUtil.OpenDrawerStatus(this.drawerNo);
if (b)
{
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)
{
if (setting.Value.box != null && setting.Value.box.Contains(this.drawerNo))
{
//药盒抽屉,开药盒
for (int i = 0; i < ColNos.Count; i++)
{
await PortUtil.OpenBoxByColNo(ColNos[i]);
}
}
// 查询抽屉是否为关闭状态
var b = await PortUtil.CheckDrawerStatus2(drawerNo);
// 关闭则改变状态并终止循环
if (b)
{
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.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)}】");
channels.ForEach(cl =>
{
cl.TakeQuantity = this.BeforeQuantity[cl.ColNo - 1] - this.AfterQuantity[cl.ColNo - 1];
});
}
// 判断是否为称重抽屉
if (setting.Value.weigh!=null&&setting.Value.weigh.Contains(this.drawerNo))
{
//开抽屉后查数
for (int i = 0; i < 9; i++)
{
int afterQuantity = await PortUtil.CheckQuantityForSingle(i);
AfterQuantity[i] = afterQuantity;
logger.Info($"AfterQuantity:{i}-{AfterQuantity}数量{string.Join(",", BeforeQuantity)}");
}
channels.ForEach(cl =>
{
cl.TakeQuantity = this.AfterQuantity[cl.ColNo - 1] - this.BeforeQuantity[cl.ColNo - 1];
});
}
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.AllLightOff();
}
RestData();
stop();
}
});
}
//关闭抽屉后获取称重稳定数量
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];
});
}
else
{
finallyQuantity.RemoveAt(0);
CancleIsEnable = true;
next();
}
}
else
{
if (finallyQuantity.Count >= 9)
{
CancleIsEnable = true;
}
else
{
CancleIsEnable = false;
}
CompleteIsEnable = false;
PortUtil.DrawerNo = drawerNo;
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)}");
channels.ForEach(cl =>
{
cl.TakeQuantity = this.BeforeQuantity[cl.ColNo - 1] - this.AfterQuantity[cl.ColNo - 1];
});
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()
{
this.status = 0;
this.BeforeQuantity = new int[9];
this.AfterQuantity = new int[9];
InvokeAsync(StateHasChanged);
}
async Task TakeFinish()
{
if (channels.Any(cl => cl.TakeQuantity != 0))
{
// 保存账册、操作记录
var b = await channelListDao.DrawerOperationFinish(channels.Where(cl => cl.TakeQuantity != 0).ToList(), 2);
if (!b)
{
_message.Notify(new NotificationMessage { Severity = NotificationSeverity.Error, Summary = "提示", Detail = $"数据保存失败", Duration = 4000 });
logger.Error($"抽屉取药保存数据库失败,数据{JsonConvert.SerializeObject(channels)}");
}
else
{
// 判断是否为标签抽屉
if (setting.Value.label.Contains(this.drawerNo))
{
//写标签数量
channels.ForEach(async it =>
{
await PortUtil.WriteQuantityMethod(it.Quantity + it.AddQuantity, it.DrawerNo, it.ColNo);
});
}
}
}
//重置状态
this.RestData();
// 重新查询库存
await grid.Reload();
}
void Cancel()
{
this.status = 0;
}
void SelectDrawer(int drawerNo)
{
this.drawerNo = drawerNo;
InvokeAsync(StateHasChanged);
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);
}
}
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();
}
}

View File

@ -0,0 +1,338 @@
@page "/stock/drug"
<style>
.rz-custom-header {
width: 100%;
}
</style>
<div class="container-fluid">
<div class="row">
<div class="col-12 mb-4">
<form onsubmit="@(() => grid.Reload())">
<RadzenFieldset Text="查询">
<RadzenStack Orientation="Orientation.Horizontal" Gap="1rem">
<RadzenRow AlignItems="AlignItems.Center">
<RadzenColumn Size="4">
<RadzenLabel Text="药品编码" Component="DrugId" />
</RadzenColumn>
<RadzenColumn Size="8">
<RadzenTextBox @bind-Value="DrugId" Style="width: 100%;" Name="DrugId"></RadzenTextBox>
</RadzenColumn>
</RadzenRow>
<RadzenRow AlignItems="AlignItems.Center">
<RadzenColumn Size="4">
<RadzenLabel Text="药品名称" Component="DrugName" />
</RadzenColumn>
<RadzenColumn Size="8">
<RadzenTextBox @bind-Value="DrugName" Style="width: 100%;" Name="DrugName"></RadzenTextBox>
</RadzenColumn>
</RadzenRow>
<RadzenRow AlignItems="AlignItems.Center">
<RadzenColumn Size="12">
<RadzenButton Size="ButtonSize.Large" ButtonType="ButtonType.Submit" IsBusy="isLoading" Icon="search" Text="查询" />
<RadzenButton Size="ButtonSize.Large" Click="reloadGrid" IsBusy="isLoading" Icon="refresh" Text="重置" ButtonStyle="ButtonStyle.Warning" />
<RadzenButton Size="ButtonSize.Large" ButtonStyle="ButtonStyle.Success" Icon="add_circle_outline" Click="@InsertDrugRow" Text="新增药品" />
</RadzenColumn>
</RadzenRow>
</RadzenStack>
</RadzenFieldset>
</form>
</div>
<div class="col-6 mb-4">
<RadzenDataGrid @ref="grid"
LoadData="@LoadData"
@bind-Value="@SelectedDrugs"
IsLoading="@isLoading"
Count="@count"
EmptyText="无数据"
Data="@_forecasts"
AllowColumnResize="true" AllowAlternatingRows="false"
SelectionMode="DataGridSelectionMode.Single" RowUpdate="@((DrugInfo di)=>{OnDrugUpdateRow(di);})" RowCreate="@((DrugInfo di)=>{OnDrugCreateRow(di);})"
AllowPaging="true" PageSize="10" PagerHorizontalAlign="HorizontalAlign.Left" ColumnWidth="100px" ShowPagingSummary="true" PagingSummaryFormat="{0}/{1} 共{2}条数据">
<Columns>
<RadzenDataGridColumn Frozen="true" Title="编码" Property="DrugId">
<EditTemplate Context="drugInfo">
<RadzenTextBox Name="DrugId" @bind-Value="drugInfo.DrugId" Style="width:100%; display: block;" />
<RadzenRequiredValidator Text="请填写编码" Component="DrugId" Popup="true" />
</EditTemplate>
</RadzenDataGridColumn>
<RadzenDataGridColumn Width="200px" Title="药品名称" Property="DrugName">
<EditTemplate Context="drugInfo">
<RadzenTextBox Name="DrugName" @bind-Value="drugInfo.DrugName" Style="width:100%;display:block;" />
<RadzenRequiredValidator Text="请填写药品名称" Component="DrugName" Popup="true"/>
</EditTemplate>
</RadzenDataGridColumn>
<RadzenDataGridColumn Title="规格" Property="DrugSpec">
<EditTemplate Context="drugInfo">
<RadzenTextBox Name="DrugSpec" @bind-Value="drugInfo.DrugSpec" Style="width:100%;display:block;" />
<RadzenRequiredValidator Text="请填写规格" Component="DrugSpec" Popup="true"/>
</EditTemplate>
</RadzenDataGridColumn>
<RadzenDataGridColumn Width="200px" Title="厂家" Property="Manufactory">
<EditTemplate Context="drugInfo">
<RadzenTextBox Name="Manufactory" @bind-Value="drugInfo.Manufactory" Style="width:100%;display:block;" />
<RadzenRequiredValidator Text="请填写厂家" Component="Manufactory" Popup="true"/>
</EditTemplate>
</RadzenDataGridColumn>
<RadzenDataGridColumn Context="drugInfo" Title="操作" Filterable="false" Sortable="false" TextAlign="TextAlign.Left" Frozen="true" FrozenPosition="FrozenColumnPosition.Right">
<Template Context="drugInfo">
<RadzenButton Icon="edit" ButtonStyle="ButtonStyle.Light" Variant="Variant.Flat" Size="ButtonSize.Medium" Click="@(args => EditDrugRow(drugInfo))" @onclick:stopPropagation="true">
</RadzenButton>
<RadzenButton ButtonStyle="ButtonStyle.Danger" Icon="delete" Variant="Variant.Flat" Shade="Shade.Lighter" Size="ButtonSize.Medium" class="my-1 ms-1" Click="@(args => DeleteDrugRow(drugInfo))" @onclick:stopPropagation="true">
</RadzenButton>
</Template>
<EditTemplate Context="drugInfo">
<RadzenButton Icon="check" ButtonStyle="ButtonStyle.Success" Variant="Variant.Flat" Size="ButtonSize.Medium" Click="@((args) => SaveDrugRow(drugInfo))" aria-label="Save">
</RadzenButton>
<RadzenButton Icon="close" ButtonStyle="ButtonStyle.Light" Variant="Variant.Flat" Size="ButtonSize.Medium" class="my-1 ms-1" Click="@((args) => CancelDrugEdit(drugInfo))" aria-label="Cancel">
</RadzenButton>
<RadzenButton ButtonStyle="ButtonStyle.Danger" Icon="delete" Variant="Variant.Flat" Shade="Shade.Lighter" Size="ButtonSize.Medium" class="my-1 ms-1" Click="@(args => DeleteDrugRow(drugInfo))" aria-label="Delete">
</RadzenButton>
</EditTemplate>
</RadzenDataGridColumn>
</Columns>
</RadzenDataGrid>
</div>
<div class="col-6 mb-4">
@* <RadzenCard Style="margin-bottom:20px">
批次列表
</RadzenCard> *@
@if (SelectedDrugs.Count > 0)
{
<RadzenDataGrid @ref="ManusGrid" EmptyText="无数据"
Data="@(SelectedDrugs.FirstOrDefault()?.Manus)"
RowUpdate="@((DrugManuNo dm) => { OnUpdateRow(dm); })" RowCreate="@((DrugManuNo dm) => { OnCreateRow(dm); })"
AllowColumnResize="true" AllowAlternatingRows="false">
@* <HeaderTemplate>
<RadzenRow JustifyContent="JustifyContent.End" AlignItems="AlignItems.Center">
<RadzenButton Icon="download" Text="添加" Variant="Variant.Outlined" />
</RadzenRow>
</HeaderTemplate> *@
<Columns>
<RadzenDataGridColumn Title="序号" Property="index">
<Template Context="data">
@(SelectedDrugs.FirstOrDefault()?.Manus.IndexOf(data) + 1)
</Template>
</RadzenDataGridColumn>
<RadzenDataGridColumn Title="批次" Property="ManuNo">
<EditTemplate Context="drugManuNo">
<RadzenTextBox Name="ManuNo" @bind-Value="drugManuNo.ManuNo" Style="width:100%; display: block;" />
<RadzenRequiredValidator Text="请填写批次" Component="ManuNo" Popup="true" />
</EditTemplate>
</RadzenDataGridColumn>
<RadzenDataGridColumn Title="效期" Property="EffDate">
<EditTemplate Context="drugManuNo">
<RadzenDatePicker DateFormat="yyyy-MM-dd" @bind-Value="drugManuNo.EffDate" Style="width: 100%;" Name="EffDate" />
<RadzenRequiredValidator Text="请填写效期" Component="EffDate" Popup="true" />
</EditTemplate>
</RadzenDataGridColumn>
<RadzenDataGridColumn Context="drugManuNo" Title="操作" Filterable="false" Sortable="false" TextAlign="TextAlign.Left" Frozen="true" FrozenPosition="FrozenColumnPosition.Right">
<Template Context="drugManuNo">
<RadzenButton Icon="edit" ButtonStyle="ButtonStyle.Light" Variant="Variant.Flat" Size="ButtonSize.Medium" Click="@(args => EditRow(drugManuNo))" @onclick:stopPropagation="true">
</RadzenButton>
<RadzenButton ButtonStyle="ButtonStyle.Danger" Icon="delete" Variant="Variant.Flat" Shade="Shade.Lighter" Size="ButtonSize.Medium" class="my-1 ms-1" Click="@(args => DeleteRow(drugManuNo))" @onclick:stopPropagation="true">
</RadzenButton>
</Template>
<EditTemplate Context="drugManuNo">
<RadzenButton Icon="check" ButtonStyle="ButtonStyle.Success" Variant="Variant.Flat" Size="ButtonSize.Medium" Click="@((args) => SaveRow(drugManuNo))" aria-label="Save">
</RadzenButton>
<RadzenButton Icon="close" ButtonStyle="ButtonStyle.Light" Variant="Variant.Flat" Size="ButtonSize.Medium" class="my-1 ms-1" Click="@((args) => CancelEdit(drugManuNo))" aria-label="Cancel">
</RadzenButton>
<RadzenButton ButtonStyle="ButtonStyle.Danger" Icon="delete" Variant="Variant.Flat" Shade="Shade.Lighter" Size="ButtonSize.Medium" class="my-1 ms-1" Click="@(args => DeleteRow(drugManuNo))" aria-label="Delete">
</RadzenButton>
</EditTemplate>
</RadzenDataGridColumn>
</Columns>
</RadzenDataGrid>
<div style="margin-top:5px">
<RadzenButton Size="ButtonSize.Medium" ButtonStyle="ButtonStyle.Success" Icon="add_circle_outline" Click="@InsertRow" Text="新增批次" />
</div>
}
</div>
</div>
</div>
@code {
@inject IDrugInfoDao drugInfoDao;
@inject DialogService dialogService;
@inject IDrugManuNoDao drugManuNoDao;
RadzenDataGrid<DrugInfo> grid;
RadzenDataGrid<DrugManuNo> ManusGrid;
List<DrugManuNo> manuNoToInsert = new List<DrugManuNo>();
List<DrugManuNo> manuNoToUpdate = new List<DrugManuNo>();
bool isLoading;
int count;
private IEnumerable<DrugInfo>? _forecasts;
IList<DrugInfo> SelectedDrugs { get; set; } = new List<DrugInfo>();
string DrugId;
string DrugName;
async Task LoadData(LoadDataArgs args)
{
isLoading = true;
var result = await drugInfoDao.GetAllDrug(DrugId, DrugName, args.Top, args.Skip);
// Update the Data property
_forecasts = result.Desserts;
count = result.TotalDesserts;
SelectedDrugs = new List<DrugInfo>() { _forecasts.FirstOrDefault() };
isLoading = false;
}
async Task reloadGrid()
{
DrugId = String.Empty;
DrugName = String.Empty;
await grid.Reload();
}
void Reset()
{
manuNoToInsert.Clear();
manuNoToUpdate.Clear();
}
void Reset(DrugManuNo drugManuNo)
{
manuNoToInsert.Remove(drugManuNo);
manuNoToUpdate.Remove(drugManuNo);
}
/// 新增药品
async Task InsertDrugRow()
{
var drugInfo = new DrugInfo();
drugInfo.Manus.Add(new DrugManuNo());
SelectedDrugs.Add(drugInfo);
await grid.InsertRow(drugInfo);
}
// //更新药品数据信息
async Task OnDrugUpdateRow(DrugInfo drugInfo)
{
// 数据库更新药品
drugInfoDao.UpdateDrugInfo(drugInfo);
grid.Reload();
}
//新增药品数据信息
async Task OnDrugCreateRow(DrugInfo drugInfo)
{
// 数据库添加药品
drugInfoDao.AddDrugInfo(drugInfo);
grid.Reload();
}
async Task EditDrugRow(DrugInfo drugInfo)
{
drugInfoDao.UpdateDrugInfo(drugInfo);
await grid.EditRow(drugInfo);
}
async Task SaveDrugRow(DrugInfo drugInfo)
{
await grid.UpdateRow(drugInfo);
}
void CancelDrugEdit(DrugInfo drugInfo)
{
Reset();
grid.CancelEditRow(drugInfo);
grid.Reload();
}
async Task DeleteDrugRow(DrugInfo drugInfo)
{
Reset();
if(!string.IsNullOrEmpty(drugInfo.DrugId))
{
//弹出确认提示框
var b = await dialogService.OpenAsync<ConfirmDialo>(
$"删除确认",
new Dictionary<string, object>() { { "confirmInfo", "删除药品:"+drugInfo.DrugName } },
new DialogOptions() { Width = "45vw", Resizable = true, Draggable = true, ShowClose = false });
if(b)
{
// 数据库删除
drugInfoDao.DeleteDrugInfo(drugInfo.DrugId);
}
grid.Reload();
}
}
/// 新增批次
async Task InsertRow()
{
var drugManuNo = new Pojo.DrugManuNo()
{
Id = Guid.NewGuid().ToString(),
DrugId = SelectedDrugs.FirstOrDefault().DrugId
};
SelectedDrugs.FirstOrDefault().Manus.Add(drugManuNo);
await ManusGrid.InsertRow(drugManuNo);
}
async Task EditRow(DrugManuNo drugManuNo)
{
Reset();
manuNoToUpdate.Add(drugManuNo);
await ManusGrid.EditRow(drugManuNo);
}
async Task SaveRow(DrugManuNo drugManuNo)
{
await ManusGrid.UpdateRow(drugManuNo);
}
void CancelEdit(DrugManuNo drugManuNo)
{
Reset(drugManuNo);
ManusGrid.CancelEditRow(drugManuNo);
ManusGrid.Reload();
}
async Task DeleteRow(DrugManuNo drugManuNo)
{
Reset(drugManuNo);
if (SelectedDrugs.FirstOrDefault().Manus.Contains(drugManuNo))
{
//弹出确认提示框
var b = await dialogService.OpenAsync<ConfirmDialo>(
$"确认删除",
new Dictionary<string, object>() { { "confirmInfo", "删除批次:"+drugManuNo.ManuNo } },
new DialogOptions() { Width = "45vw", Resizable = true, Draggable = true, ShowClose = false }
);
if(b)
{
// 数据库删除
drugManuNoDao.DeleteDrugManuNo(drugManuNo.Id);
await ManusGrid.Reload();
}
}
else
{
ManusGrid.CancelEditRow(drugManuNo);
await ManusGrid.Reload();
}
}
void OnUpdateRow(DrugManuNo dm)
{
Reset(dm);
// 数据库更新
drugManuNoDao.UpdateDrugManuNo(dm);
ManusGrid.Reload();
}
void OnCreateRow(DrugManuNo dm)
{
// 数据库添加批次
drugManuNoDao.AddDrugManuNo(dm);
manuNoToInsert.Remove(dm);
ManusGrid.Reload();
}
}

View File

@ -0,0 +1,70 @@
@page "/user/finger/{userId}"
@using log4net;
<RadzenStack Gap="1.5rem">
<RadzenStack Orientation="Orientation.Horizontal" Gap="0.5rem" AlignItems="AlignItems.Center" JustifyContent="JustifyContent.Center">
<RadzenLabel Text="选择手指" Component="DropDownBindValue" Style="margin-right: 8px; vertical-align: middle;" />
<RadzenDropDown @bind-Value=@fingerName Data=@fingerNames Style="width: 100%; max-width: 400px;" Name="DropDownBindValue" />
</RadzenStack>
<RadzenStack Orientation="Orientation.Horizontal" Gap="0.5rem" AlignItems="AlignItems.Center" JustifyContent="JustifyContent.SpaceBetween">
<RadzenStack Orientation="Orientation.Horizontal">
<RadzenButton IsBusy="@regLoading" Text="录入" Click="() => RegZWJSubmit()" Style="width: 80px;" />
<RadzenButton Text="取消" Click="() => RegZWJCancel()" ButtonStyle="ButtonStyle.Light" />
</RadzenStack>
</RadzenStack>
</RadzenStack>
@code {
[Parameter] public int userId { get; set; }
@inject DialogService dialogService;
@inject FingerprintUtil FingerprintUtil;
private readonly ILog logger = LogManager.GetLogger(typeof(FingerRegDialog));
List<string> fingerNames = new List<string>()
{
"左小拇指","左无名指","左中指", "左食指", "左大拇指", "右小拇指", "右无名指", "右中指" ,"右食指", "右大拇指"
};
string fingerName = "左小拇指";
bool regLoading = false;
void RegZWJSubmit()
{
regLoading = true;
InvokeAsync(StateHasChanged);
FingerprintUtil.axCZKEM1.OnEnrollFingerEx += axCZKEM1_OnEnrollFingerEx;
FingerprintUtil.SaveFingerprint(userId, fingerNames.FindIndex(n => n.Equals(fingerName)));
}
void RegZWJCancel()
{
FingerprintUtil.axCZKEM1.CancelOperation();
regLoading = false;
InvokeAsync(StateHasChanged);
FingerprintUtil.axCZKEM1.OnEnrollFingerEx -= axCZKEM1_OnEnrollFingerEx;
dialogService.Close();
}
private void axCZKEM1_OnEnrollFingerEx(string iEnrollNumber, int iFingerIndex, int iActionResult, int iTemplateLength)
{
FingerprintUtil.axCZKEM1.StartIdentify();
FingerprintUtil.axCZKEM1.RefreshData(1);
regLoading = false;
InvokeAsync(StateHasChanged);
dialogService.Close();
logger.Info($"触发用户登记指纹事件1用户id:{iEnrollNumber}指纹索引:{iFingerIndex}登记结果:{(iActionResult == 0)}");
FingerprintUtil.axCZKEM1.OnEnrollFingerEx -= axCZKEM1_OnEnrollFingerEx;
}
}

View File

@ -0,0 +1,220 @@
@page "/home"
@using MasaBlazorApp3.Util
@using log4net
@layout EmptyLayout
<style>
.home-menu{
transition: box-shadow 0.3s ease; /* 平滑过渡阴影效果 */
cursor: pointer;
position: relative;
z-index: 1;
box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.7);
}
.home-menu>h2{
font-weight: bold;
}
.home-menu:hover {
box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.7); /* 阴影效果 */
}
.mask {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: black;
opacity: 0.6;
z-index: 2;
cursor: not-allowed;
}
.rz-gauge .rz-tick-text {
fill: #ffffff !important;
}
</style>
<RadzenStack Orientation="Orientation.Vertical" class="rz-background-color-primary-light" AlignItems="AlignItems.Center" Style="width:100vw;height:100vh" Gap="0">
<RadzenRow Style="width:100vw;height:25vh;" Gap="0" RowGap="0">
<RadzenColumn Size="4">
</RadzenColumn>
<RadzenColumn Size="8">
<RadzenRow Style="height: 100%;width:100%" Orientation="Orientation.Horizontal" JustifyContent="JustifyContent.End" AlignItems="AlignItems.Center">
<RadzenColumn Size="3">
<RadzenText Style="" class="rz-color-white" TextStyle="TextStyle.H5" TextAlign="TextAlign.Center">操作人:@Operator.NickName</RadzenText>
@if (Reviewer != null)
{
<RadzenText Style="" class="rz-color-white" TextStyle="TextStyle.H5" TextAlign="TextAlign.Center">复核人:@Reviewer.NickName</RadzenText>
}
</RadzenColumn>
<RadzenColumn Size="3">
<RadzenIcon Icon="exit_to_app" Style="font-size:3rem;cursor: pointer;" class="rz-ripple" IconColor="white" @onclick="@(() => { logout(); })" />
</RadzenColumn>
</RadzenRow>
</RadzenColumn>
</RadzenRow>
<RadzenStack class="rz-background-color-info-lighter" Orientation="Orientation.Horizontal" JustifyContent="JustifyContent.Center" AlignItems="AlignItems.Center" Style="width: 75vw;height: 57vh" Gap="20">
<RadzenStack Style="height: 100%;width:41%" Gap="20">
<RadzenStack class="home-menu rz-background-color-info-lighter rz-ripple" JustifyContent="JustifyContent.Center" Style="height: 50%" @onclick="@(() => jump2Page(1))">
<RadzenText Style="" class="rz-color-white" TextStyle="TextStyle.H2" TextAlign="TextAlign.Center" >出库</RadzenText>
@if (!Operator.role.permissionIds.Any(id => id - 10 < 10))
{
<div class="mask">
<RadzenImage Path="images/no_auth.png" />
</div>
}
</RadzenStack>
<RadzenStack class="home-menu rz-background-color-success-light rz-text-white rz-ripple" JustifyContent="JustifyContent.Center" @onclick="@(() => jump2Page(2))" Style="height: 50%">
<RadzenText class="rz-color-white" TextStyle="TextStyle.H2" TextAlign="TextAlign.Center">入库</RadzenText>
@if (!Operator.role.permissionIds.Any(id => id - 20 > 0 && id - 20 < 10))
{
<div class="mask">
<RadzenImage Path="images/no_auth.png" />
</div>
}
</RadzenStack>
</RadzenStack>
<RadzenStack Style="height: 100%;width:59%" Gap="20">
<RadzenStack class="home-menu rz-background-color-series-2 rz-text-white rz-ripple" JustifyContent="JustifyContent.Center" @onclick="@(() => jump2Page(3))" Style="height: 43%;width:100%">
<RadzenText class="rz-color-white" TextStyle="TextStyle.H2" TextAlign="TextAlign.Center">归还</RadzenText>
@if (!Operator.role.permissionIds.Any(id => id - 30 > 0 && id - 30 < 10))
{
<div class="mask">
<RadzenImage Path="images/no_auth.png" />
</div>
}
</RadzenStack>
<RadzenStack Orientation="Orientation.Horizontal" Style="height: 57%;width:100%">
<RadzenStack class="home-menu rz-background-color-primary rz-text-white rz-ripple" JustifyContent="JustifyContent.Center" @onclick="@(() => jump2Page(4))" Style="height: 100%;width:50%">
<RadzenText class="rz-color-white" TextStyle="TextStyle.H2" TextAlign="TextAlign.Center">库存管理</RadzenText>
@if (!Operator.role.permissionIds.Any(id => id - 40 > 0 && id - 40 < 10))
{
<div class="mask">
<RadzenImage Path="images/no_auth.png" />
</div>
}
</RadzenStack>
<RadzenStack class="home-menu rz-background-color-success-lighter rz-text-white rz-ripple" JustifyContent="JustifyContent.Center" @onclick="@(() => jump2Page(5))" Style="height: 100%;width:50%">
<RadzenText class="rz-color-white" TextStyle="TextStyle.H2" TextAlign="TextAlign.Center">系统设置</RadzenText>
@if (!Operator.role.permissionIds.Any(id => id - 50 > 0 && id - 50 < 10))
{
<div class="mask">
<RadzenImage Path="images/no_auth.png" />
</div>
}
</RadzenStack>
</RadzenStack>
</RadzenStack>
</RadzenStack>
</RadzenStack>
@code {
@inject NavigationManager na;
@inject TooltipService tooltipService
private List<Premission> userPremissions { get; set; } = new();
@inject GlobalStateService globalStateService;
Pojo.User Operator;
Pojo.User Reviewer;
Timer timer;
@inject PortUtil _portUtil;
private readonly ILog logger = LogManager.GetLogger(typeof(Home));
@inject Microsoft.Extensions.Options.IOptions<Pojo.Config.SettingConfig> setting;
bool currentPage = true;
protected override void OnInitialized()
{
Operator = globalStateService.Operator;
Reviewer = globalStateService.Reviewer;
// timer = new Timer(state =>
// {
// var now = DateTime.Now;
// InvokeAsync(StateHasChanged);
// }, null, 0, 1000);
if (setting.Value.autoOutLog > 0)
{
// 是否需要自动退出
var promiseUtil = new PromiseUtil<object>();
promiseUtil.taskAsyncLoop(500, null, async (data, next, stop) =>
{
if (globalStateService.Operator == null || !currentPage)
{
logger.Info($"Home页自动退出循环停止{globalStateService.Operator==null},{!currentPage}");
stop();
}
else
{
try
{
//没有在操作抽屉
if (!_portUtil.Operate)
{
// 无人操作鼠标键盘
if ((DateTime.Now - _portUtil.dateTime).TotalSeconds > setting.Value.autoOutLog && CheckComputerFreeState.GetLastInputTime() > setting.Value.autoOutLog)
{
logger.Info($"设备{setting.Value.autoOutLog}内无人操作,用户【{Operator?.NickName}】自动退出登录,_portUtil.Operate:{_portUtil.Operate},totalSecond:{(DateTime.Now - _portUtil.dateTime).TotalSeconds},lastInputTime:{CheckComputerFreeState.GetLastInputTime()},autoOutLog:{setting.Value.autoOutLog}");
globalStateService.Operator = null;
globalStateService.Reviewer = null;
na.NavigateTo("");
stop();
}
else
{
next();
}
}
else
{
next();
}
}
catch (Exception ex)
{
logger.Info($"检查是否自动退出循环异常:{ex.Message}");
next();
}
}
});
}
base.OnInitialized();
}
public void Dispose()
{
timer?.Dispose();
}
void jump2Page(int parentId)
{
List<int> childrenIds = Operator.role.permissionIds.Where(id => id - (parentId * 10) > 0 && id - (parentId * 10) < 10).ToList();
if(childrenIds.Count > 0)
{
childrenIds.Sort();
int minId = childrenIds[0];
string path = new Premission().getAdminPremission().Find(p => p.Id == parentId).Items.ToList().Find(p2 => p2.Id == minId).PremissionPath;
na.NavigateTo(path);
currentPage = false;
}
}
void logout()
{
globalStateService.Operator = null;
globalStateService.Reviewer = null;
na.NavigateTo("");
}
}

View File

@ -0,0 +1,234 @@
@page "/"
@layout EmptyLayout
@using System.ComponentModel;
@using log4net;
<style>
body{
background-image: url(/images/body-bg.png);
/* background-repeat:repeat; */
/* background: var(--rz-primary-light) no-repeat 100% 70% fixed url('data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTIwNCIgaGVpZ2h0PSIxNDU4IiB2aWV3Qm94PSIwIDAgMTIwNCAxNDU4IiBmaWxsPSJub25lIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPgo8ZyBvcGFjaXR5PSIwLjUiIGZpbHRlcj0idXJsKCNmaWx0ZXIwX2ZfNDkzXzEwMTM0KSI+CjxjaXJjbGUgY3g9IjcyMi4xMjgiIGN5PSI4MzkuMDIiIHI9IjQ4MS40MTkiIGZpbGw9InVybCgjcGFpbnQwX3JhZGlhbF80OTNfMTAxMzQpIi8+CjwvZz4KPGcgb3BhY2l0eT0iMC41IiBmaWx0ZXI9InVybCgjZmlsdGVyMV9mXzQ5M18xMDEzNCkiPgo8Y2lyY2xlIGN4PSI0NzAuMzMzIiBjeT0iNTcwLjMzMyIgcj0iNDcwLjMzMyIgZmlsbD0idXJsKCNwYWludDFfcmFkaWFsXzQ5M18xMDEzNCkiLz4KPC9nPgo8ZyBvcGFjaXR5PSIwLjUiIGZpbHRlcj0idXJsKCNmaWx0ZXIyX2ZfNDkzXzEwMTM0KSI+CjxjaXJjbGUgY3g9IjY5MS41MTEiIGN5PSI1MjIuMjk3IiByPSIzMzEuNTAzIiBmaWxsPSJ1cmwoI3BhaW50Ml9yYWRpYWxfNDkzXzEwMTM0KSIvPgo8L2c+CjxnIG9wYWNpdHk9IjAuNSIgZmlsdGVyPSJ1cmwoI2ZpbHRlcjNfZl80OTNfMTAxMzQpIj4KPGNpcmNsZSBjeD0iNjA4LjI0NCIgY3k9IjEwNzkuOTciIHI9IjMzMS41MDMiIHRyYW5zZm9ybT0icm90YXRlKC04MS4yMjQ0IDYwOC4yNDQgMTA3OS45NykiIGZpbGw9InVybCgjcGFpbnQzX3JhZGlhbF80OTNfMTAxMzQpIi8+CjwvZz4KPGRlZnM+CjxmaWx0ZXIgaWQ9ImZpbHRlcjBfZl80OTNfMTAxMzQiIHg9IjE0MC43MDkiIHk9IjI1Ny42MDEiIHdpZHRoPSIxMTYyLjg0IiBoZWlnaHQ9IjExNjIuODQiIGZpbHRlclVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgY29sb3ItaW50ZXJwb2xhdGlvbi1maWx0ZXJzPSJzUkdCIj4KPGZlRmxvb2QgZmxvb2Qtb3BhY2l0eT0iMCIgcmVzdWx0PSJCYWNrZ3JvdW5kSW1hZ2VGaXgiLz4KPGZlQmxlbmQgbW9kZT0ibm9ybWFsIiBpbj0iU291cmNlR3JhcGhpYyIgaW4yPSJCYWNrZ3JvdW5kSW1hZ2VGaXgiIHJlc3VsdD0ic2hhcGUiLz4KPGZlR2F1c3NpYW5CbHVyIHN0ZERldmlhdGlvbj0iNTAiIHJlc3VsdD0iZWZmZWN0MV9mb3JlZ3JvdW5kQmx1cl80OTNfMTAxMzQiLz4KPC9maWx0ZXI+CjxmaWx0ZXIgaWQ9ImZpbHRlcjFfZl80OTNfMTAxMzQiIHg9Ii0xMDAiIHk9IjAiIHdpZHRoPSIxMTQwLjY3IiBoZWlnaHQ9IjExNDAuNjciIGZpbHRlclVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgY29sb3ItaW50ZXJwb2xhdGlvbi1maWx0ZXJzPSJzUkdCIj4KPGZlRmxvb2QgZmxvb2Qtb3BhY2l0eT0iMCIgcmVzdWx0PSJCYWNrZ3JvdW5kSW1hZ2VGaXgiLz4KPGZlQmxlbmQgbW9kZT0ibm9ybWFsIiBpbj0iU291cmNlR3JhcGhpYyIgaW4yPSJCYWNrZ3JvdW5kSW1hZ2VGaXgiIHJlc3VsdD0ic2hhcGUiLz4KPGZlR2F1c3NpYW5CbHVyIHN0ZERldmlhdGlvbj0iNTAiIHJlc3VsdD0iZWZmZWN0MV9mb3JlZ3JvdW5kQmx1cl80OTNfMTAxMzQiLz4KPC9maWx0ZXI+CjxmaWx0ZXIgaWQ9ImZpbHRlcjJfZl80OTNfMTAxMzQiIHg9IjI2MC4wMDgiIHk9IjkwLjc5MzkiIHdpZHRoPSI4NjMuMDA2IiBoZWlnaHQ9Ijg2My4wMDYiIGZpbHRlclVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgY29sb3ItaW50ZXJwb2xhdGlvbi1maWx0ZXJzPSJzUkdCIj4KPGZlRmxvb2QgZmxvb2Qtb3BhY2l0eT0iMCIgcmVzdWx0PSJCYWNrZ3JvdW5kSW1hZ2VGaXgiLz4KPGZlQmxlbmQgbW9kZT0ibm9ybWFsIiBpbj0iU291cmNlR3JhcGhpYyIgaW4yPSJCYWNrZ3JvdW5kSW1hZ2VGaXgiIHJlc3VsdD0ic2hhcGUiLz4KPGZlR2F1c3NpYW5CbHVyIHN0ZERldmlhdGlvbj0iNTAiIHJlc3VsdD0iZWZmZWN0MV9mb3JlZ3JvdW5kQmx1cl80OTNfMTAxMzQiLz4KPC9maWx0ZXI+CjxmaWx0ZXIgaWQ9ImZpbHRlcjNfZl80OTNfMTAxMzQiIHg9IjE3Ni42OTQiIHk9IjY0OC40MjMiIHdpZHRoPSI4NjMuMSIgaGVpZ2h0PSI4NjMuMSIgZmlsdGVyVW5pdHM9InVzZXJTcGFjZU9uVXNlIiBjb2xvci1pbnRlcnBvbGF0aW9uLWZpbHRlcnM9InNSR0IiPgo8ZmVGbG9vZCBmbG9vZC1vcGFjaXR5PSIwIiByZXN1bHQ9IkJhY2tncm91bmRJbWFnZUZpeCIvPgo8ZmVCbGVuZCBtb2RlPSJub3JtYWwiIGluPSJTb3VyY2VHcmFwaGljIiBpbjI9IkJhY2tncm91bmRJbWFnZUZpeCIgcmVzdWx0PSJzaGFwZSIvPgo8ZmVHYXVzc2lhbkJsdXIgc3RkRGV2aWF0aW9uPSI1MCIgcmVzdWx0PSJlZmZlY3QxX2ZvcmVncm91bmRCbHVyXzQ5M18xMDEzNCIvPgo8L2ZpbHRlcj4KPHJhZGlhbEdyYWRpZW50IGlkPSJwYWludDBfcmFkaWFsXzQ5M18xMDEzNCIgY3g9IjAiIGN5PSIwIiByPSIxIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgZ3JhZGllbnRUcmFuc2Zvcm09InRyYW5zbGF0ZSg3MjIuMTI4IDgzOS4wMikgcm90YXRlKDkwKSBzY2FsZSg0ODEuNDE5KSI+CjxzdG9wIHN0b3AtY29sb3I9IiNGRjFBNkMiLz4KPHN0b3Agb2Zmc2V0PSIxIiBzdG9wLWNvbG9yPSIjRkYxQTZDIiBzdG9wLW9wYWNpdHk9IjAiLz4KPC9yYWRpYWxHcmFkaWVudD4KPHJhZGlhbEdyYWRpZW50IGlkPSJwYWludDFfcmFkaWFsXzQ5M18xMDEzNCIgY3g9IjAiIGN5PSIwIiByPSIxIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgZ3JhZGllbnRUcmFuc2Zvcm09InRyYW5zbGF0ZSg0NzAuMzMzIDU3MC4zMzMpIHJvdGF0ZSg5MCkgc2NhbGUoNDcwLjMzMykiPgo8c3RvcCBzdG9wLWNvbG9yPSIjM0FBQ0ZGIi8+CjxzdG9wIG9mZnNldD0iMSIgc3RvcC1jb2xvcj0iIzNBOTVGRiIgc3RvcC1vcGFjaXR5PSIwIi8+CjwvcmFkaWFsR3JhZGllbnQ+CjxyYWRpYWxHcmFkaWVudCBpZD0icGFpbnQyX3JhZGlhbF80OTNfMTAxMzQiIGN4PSIwIiBjeT0iMCIgcj0iMSIgZ3JhZGllbnRVbml0cz0idXNlclNwYWNlT25Vc2UiIGdyYWRpZW50VHJhbnNmb3JtPSJ0cmFuc2xhdGUoNjkxLjUxMSA1MjIuMjk3KSByb3RhdGUoOTApIHNjYWxlKDMzMS41MDMpIj4KPHN0b3Agc3RvcC1jb2xvcj0iIzQ4M0FGRiIvPgo8c3RvcCBvZmZzZXQ9IjEiIHN0b3AtY29sb3I9IiM0ODNBRkYiIHN0b3Atb3BhY2l0eT0iMCIvPgo8L3JhZGlhbEdyYWRpZW50Pgo8cmFkaWFsR3JhZGllbnQgaWQ9InBhaW50M19yYWRpYWxfNDkzXzEwMTM0IiBjeD0iMCIgY3k9IjAiIHI9IjEiIGdyYWRpZW50VW5pdHM9InVzZXJTcGFjZU9uVXNlIiBncmFkaWVudFRyYW5zZm9ybT0idHJhbnNsYXRlKDYwOC4yNDQgMTA3OS45Nykgcm90YXRlKDkwKSBzY2FsZSgzMzEuNTAzKSI+CjxzdG9wIHN0b3AtY29sb3I9IiNGRkM4M0EiLz4KPHN0b3Agb2Zmc2V0PSIxIiBzdG9wLWNvbG9yPSIjRkZDODNBIiBzdG9wLW9wYWNpdHk9IjAiLz4KPC9yYWRpYWxHcmFkaWVudD4KPC9kZWZzPgo8L3N2Zz4K'); */
width: 100vw;
height: 100vh;
}
.finner-bg {
background: url('/images/finger-bg-r.png') repeat;
}
</style>
<RadzenStack Orientation="Orientation.Horizontal" JustifyContent="JustifyContent.Center" AlignItems="AlignItems.Center" Style="width:100vw;height:100vh">
<RadzenRow>
<RadzenColumn></RadzenColumn>
</RadzenRow>
<RadzenRow Gap="0" Class="rz-my-12 rz-mx-auto rz-border-radius-3 rz-shadow-10" Style="overflow: hidden;width:55vw;height:45vh">
<RadzenColumn Size="12" SizeMD="5">
<RadzenCard class="rz-shadow-0 rz-border-radius-0 rz-text-align-center rz-p-12" Style="height: 100%; background: var(--rz-primary-light) no-repeat 100% 70% fixed url('data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTIwNCIgaGVpZ2h0PSIxNDU4IiB2aWV3Qm94PSIwIDAgMTIwNCAxNDU4IiBmaWxsPSJub25lIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPgo8ZyBvcGFjaXR5PSIwLjUiIGZpbHRlcj0idXJsKCNmaWx0ZXIwX2ZfNDkzXzEwMTM0KSI+CjxjaXJjbGUgY3g9IjcyMi4xMjgiIGN5PSI4MzkuMDIiIHI9IjQ4MS40MTkiIGZpbGw9InVybCgjcGFpbnQwX3JhZGlhbF80OTNfMTAxMzQpIi8+CjwvZz4KPGcgb3BhY2l0eT0iMC41IiBmaWx0ZXI9InVybCgjZmlsdGVyMV9mXzQ5M18xMDEzNCkiPgo8Y2lyY2xlIGN4PSI0NzAuMzMzIiBjeT0iNTcwLjMzMyIgcj0iNDcwLjMzMyIgZmlsbD0idXJsKCNwYWludDFfcmFkaWFsXzQ5M18xMDEzNCkiLz4KPC9nPgo8ZyBvcGFjaXR5PSIwLjUiIGZpbHRlcj0idXJsKCNmaWx0ZXIyX2ZfNDkzXzEwMTM0KSI+CjxjaXJjbGUgY3g9IjY5MS41MTEiIGN5PSI1MjIuMjk3IiByPSIzMzEuNTAzIiBmaWxsPSJ1cmwoI3BhaW50Ml9yYWRpYWxfNDkzXzEwMTM0KSIvPgo8L2c+CjxnIG9wYWNpdHk9IjAuNSIgZmlsdGVyPSJ1cmwoI2ZpbHRlcjNfZl80OTNfMTAxMzQpIj4KPGNpcmNsZSBjeD0iNjA4LjI0NCIgY3k9IjEwNzkuOTciIHI9IjMzMS41MDMiIHRyYW5zZm9ybT0icm90YXRlKC04MS4yMjQ0IDYwOC4yNDQgMTA3OS45NykiIGZpbGw9InVybCgjcGFpbnQzX3JhZGlhbF80OTNfMTAxMzQpIi8+CjwvZz4KPGRlZnM+CjxmaWx0ZXIgaWQ9ImZpbHRlcjBfZl80OTNfMTAxMzQiIHg9IjE0MC43MDkiIHk9IjI1Ny42MDEiIHdpZHRoPSIxMTYyLjg0IiBoZWlnaHQ9IjExNjIuODQiIGZpbHRlclVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgY29sb3ItaW50ZXJwb2xhdGlvbi1maWx0ZXJzPSJzUkdCIj4KPGZlRmxvb2QgZmxvb2Qtb3BhY2l0eT0iMCIgcmVzdWx0PSJCYWNrZ3JvdW5kSW1hZ2VGaXgiLz4KPGZlQmxlbmQgbW9kZT0ibm9ybWFsIiBpbj0iU291cmNlR3JhcGhpYyIgaW4yPSJCYWNrZ3JvdW5kSW1hZ2VGaXgiIHJlc3VsdD0ic2hhcGUiLz4KPGZlR2F1c3NpYW5CbHVyIHN0ZERldmlhdGlvbj0iNTAiIHJlc3VsdD0iZWZmZWN0MV9mb3JlZ3JvdW5kQmx1cl80OTNfMTAxMzQiLz4KPC9maWx0ZXI+CjxmaWx0ZXIgaWQ9ImZpbHRlcjFfZl80OTNfMTAxMzQiIHg9Ii0xMDAiIHk9IjAiIHdpZHRoPSIxMTQwLjY3IiBoZWlnaHQ9IjExNDAuNjciIGZpbHRlclVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgY29sb3ItaW50ZXJwb2xhdGlvbi1maWx0ZXJzPSJzUkdCIj4KPGZlRmxvb2QgZmxvb2Qtb3BhY2l0eT0iMCIgcmVzdWx0PSJCYWNrZ3JvdW5kSW1hZ2VGaXgiLz4KPGZlQmxlbmQgbW9kZT0ibm9ybWFsIiBpbj0iU291cmNlR3JhcGhpYyIgaW4yPSJCYWNrZ3JvdW5kSW1hZ2VGaXgiIHJlc3VsdD0ic2hhcGUiLz4KPGZlR2F1c3NpYW5CbHVyIHN0ZERldmlhdGlvbj0iNTAiIHJlc3VsdD0iZWZmZWN0MV9mb3JlZ3JvdW5kQmx1cl80OTNfMTAxMzQiLz4KPC9maWx0ZXI+CjxmaWx0ZXIgaWQ9ImZpbHRlcjJfZl80OTNfMTAxMzQiIHg9IjI2MC4wMDgiIHk9IjkwLjc5MzkiIHdpZHRoPSI4NjMuMDA2IiBoZWlnaHQ9Ijg2My4wMDYiIGZpbHRlclVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgY29sb3ItaW50ZXJwb2xhdGlvbi1maWx0ZXJzPSJzUkdCIj4KPGZlRmxvb2QgZmxvb2Qtb3BhY2l0eT0iMCIgcmVzdWx0PSJCYWNrZ3JvdW5kSW1hZ2VGaXgiLz4KPGZlQmxlbmQgbW9kZT0ibm9ybWFsIiBpbj0iU291cmNlR3JhcGhpYyIgaW4yPSJCYWNrZ3JvdW5kSW1hZ2VGaXgiIHJlc3VsdD0ic2hhcGUiLz4KPGZlR2F1c3NpYW5CbHVyIHN0ZERldmlhdGlvbj0iNTAiIHJlc3VsdD0iZWZmZWN0MV9mb3JlZ3JvdW5kQmx1cl80OTNfMTAxMzQiLz4KPC9maWx0ZXI+CjxmaWx0ZXIgaWQ9ImZpbHRlcjNfZl80OTNfMTAxMzQiIHg9IjE3Ni42OTQiIHk9IjY0OC40MjMiIHdpZHRoPSI4NjMuMSIgaGVpZ2h0PSI4NjMuMSIgZmlsdGVyVW5pdHM9InVzZXJTcGFjZU9uVXNlIiBjb2xvci1pbnRlcnBvbGF0aW9uLWZpbHRlcnM9InNSR0IiPgo8ZmVGbG9vZCBmbG9vZC1vcGFjaXR5PSIwIiByZXN1bHQ9IkJhY2tncm91bmRJbWFnZUZpeCIvPgo8ZmVCbGVuZCBtb2RlPSJub3JtYWwiIGluPSJTb3VyY2VHcmFwaGljIiBpbjI9IkJhY2tncm91bmRJbWFnZUZpeCIgcmVzdWx0PSJzaGFwZSIvPgo8ZmVHYXVzc2lhbkJsdXIgc3RkRGV2aWF0aW9uPSI1MCIgcmVzdWx0PSJlZmZlY3QxX2ZvcmVncm91bmRCbHVyXzQ5M18xMDEzNCIvPgo8L2ZpbHRlcj4KPHJhZGlhbEdyYWRpZW50IGlkPSJwYWludDBfcmFkaWFsXzQ5M18xMDEzNCIgY3g9IjAiIGN5PSIwIiByPSIxIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgZ3JhZGllbnRUcmFuc2Zvcm09InRyYW5zbGF0ZSg3MjIuMTI4IDgzOS4wMikgcm90YXRlKDkwKSBzY2FsZSg0ODEuNDE5KSI+CjxzdG9wIHN0b3AtY29sb3I9IiNGRjFBNkMiLz4KPHN0b3Agb2Zmc2V0PSIxIiBzdG9wLWNvbG9yPSIjRkYxQTZDIiBzdG9wLW9wYWNpdHk9IjAiLz4KPC9yYWRpYWxHcmFkaWVudD4KPHJhZGlhbEdyYWRpZW50IGlkPSJwYWludDFfcmFkaWFsXzQ5M18xMDEzNCIgY3g9IjAiIGN5PSIwIiByPSIxIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgZ3JhZGllbnRUcmFuc2Zvcm09InRyYW5zbGF0ZSg0NzAuMzMzIDU3MC4zMzMpIHJvdGF0ZSg5MCkgc2NhbGUoNDcwLjMzMykiPgo8c3RvcCBzdG9wLWNvbG9yPSIjM0FBQ0ZGIi8+CjxzdG9wIG9mZnNldD0iMSIgc3RvcC1jb2xvcj0iIzNBOTVGRiIgc3RvcC1vcGFjaXR5PSIwIi8+CjwvcmFkaWFsR3JhZGllbnQ+CjxyYWRpYWxHcmFkaWVudCBpZD0icGFpbnQyX3JhZGlhbF80OTNfMTAxMzQiIGN4PSIwIiBjeT0iMCIgcj0iMSIgZ3JhZGllbnRVbml0cz0idXNlclNwYWNlT25Vc2UiIGdyYWRpZW50VHJhbnNmb3JtPSJ0cmFuc2xhdGUoNjkxLjUxMSA1MjIuMjk3KSByb3RhdGUoOTApIHNjYWxlKDMzMS41MDMpIj4KPHN0b3Agc3RvcC1jb2xvcj0iIzQ4M0FGRiIvPgo8c3RvcCBvZmZzZXQ9IjEiIHN0b3AtY29sb3I9IiM0ODNBRkYiIHN0b3Atb3BhY2l0eT0iMCIvPgo8L3JhZGlhbEdyYWRpZW50Pgo8cmFkaWFsR3JhZGllbnQgaWQ9InBhaW50M19yYWRpYWxfNDkzXzEwMTM0IiBjeD0iMCIgY3k9IjAiIHI9IjEiIGdyYWRpZW50VW5pdHM9InVzZXJTcGFjZU9uVXNlIiBncmFkaWVudFRyYW5zZm9ybT0idHJhbnNsYXRlKDYwOC4yNDQgMTA3OS45Nykgcm90YXRlKDkwKSBzY2FsZSgzMzEuNTAzKSI+CjxzdG9wIHN0b3AtY29sb3I9IiNGRkM4M0EiLz4KPHN0b3Agb2Zmc2V0PSIxIiBzdG9wLWNvbG9yPSIjRkZDODNBIiBzdG9wLW9wYWNpdHk9IjAiLz4KPC9yYWRpYWxHcmFkaWVudD4KPC9kZWZzPgo8L3N2Zz4K')">
@if(loginMode == 2)
{
<RadzenText TextStyle="TextStyle.H6" class="rz-color-white">操作人:@globalStateService.Operator?.NickName</RadzenText>
<RadzenText TextStyle="TextStyle.H6" class="rz-color-white">复核人:@globalStateService.Reviewer?.NickName</RadzenText>
}
</RadzenCard>
</RadzenColumn>
<RadzenColumn Size="12" SizeMD="7">
<RadzenCard Class="rz-shadow-0 rz-border-radius-0 rz-p-12" Style="width:100%;height:100%">
<RadzenText TextStyle="TextStyle.H5" TagName="TagName.H2" class="rz-mb-6">
登录
</RadzenText>
<RadzenTemplateForm Data="@loginModel" Submit="@((Pojo.User args) => { Submit(args); })" Style="width:100%;height:100%" >
<div class="rz-form-row">
<label class="rz-label" for="username">账号</label>
<div class="rz-form-input-wrapper">
<RadzenTextBox id="username" Name="Username" @bind-Value="@loginModel.Username" Style="width:100%" />
<RadzenRequiredValidator Component="Username" Text="请填写用户名" />
</div>
</div>
<div class="rz-form-row">
<label class="rz-label" for="password">密码</label>
<div class="rz-form-input-wrapper">
<RadzenPassword id="password" Name="Password" @bind-Value="@loginModel.Password" Style="width:100%" />
<RadzenRequiredValidator Component="Password" Text="请填写密码" />
</div>
</div>
<div class="rz-form-row">
<label class="rz-label"></label>
<div class="rz-form-input-wrapper rz-login-buttons">
<RadzenButton Style="background:#255dd4;color:white;width:110px" ButtonType="ButtonType.Submit" Text="登录" />
<RadzenButton Style="border-color:#255dd4;width:110px" Variant="Variant.Outlined" Text="退出" Click="@Exit" />
</div>
</div>
</RadzenTemplateForm>
</RadzenCard>
</RadzenColumn>
</RadzenRow>
</RadzenStack>
@code {
@inject FingerprintUtil FingerprintUtil;
@inject PortUtil PortUtil;
@inject NavigationManager na;
@inject NotificationService _message
@inject GlobalStateService globalStateService;
@inject IUserDao userDao;
@inject Microsoft.Extensions.Options.IOptions<Pojo.Config.SettingConfig> setting;
private readonly ILog logger = LogManager.GetLogger(typeof(Index));
private int loginMode = 1;
private bool opFirst = true;
bool isShow;
private Pojo.User loginModel = new();
protected override Task OnInitializedAsync()
{
FingerprintUtil.axCZKEM1.OnAttTransactionEx += axCZKEM1_OnAttTransactionEx;
loginMode = setting.Value.loginMode;
opFirst = setting.Value.opFirst;
return base.OnInitializedAsync();
}
private void SetUser(Pojo.User user)
{
// 判断是否为双人登录模式
if (loginMode == 2)
{
// 判断是否是操作人优先登录
if (opFirst)
{
// 判断操作人是否已经登录,已经登录说明此时为第二人登录
if (globalStateService.Operator != null)
{
// 判断是否还是操作人的验证
if (globalStateService.Operator.Id != user.Id)
{
FingerprintUtil.axCZKEM1.OnAttTransactionEx -= axCZKEM1_OnAttTransactionEx;
globalStateService.Reviewer = user;
na.NavigateTo("/home");
logger.Info($"双人登录模式:操作人【{globalStateService.Operator.NickName}】复核人【{user.NickName}】登录");
} else
{
_message.Notify(
new NotificationMessage { Severity = NotificationSeverity.Error, Summary = "提示", Detail = $"验证重复,请使用其他账号", Duration = 3000 }
);
}
} else
{
// 此时为第一人登录
globalStateService.Operator = user;
InvokeAsync(StateHasChanged);
loginModel = new();
}
}
// 操作人为第二人登录
else
{
// 判断复核人是否已经登录,已经登录说明此时为第二人登录
if (globalStateService.Reviewer != null)
{
// 判断是否还是复核人的验证
if (globalStateService.Reviewer.Id != user.Id)
{
FingerprintUtil.axCZKEM1.OnAttTransactionEx -= axCZKEM1_OnAttTransactionEx;
globalStateService.Operator = user;
na.NavigateTo("/home");
logger.Info($"双人登录模式:操作人【{user.NickName}】复核人【{globalStateService.Reviewer.NickName}】登录");
}
else
{
_message.Notify(
new NotificationMessage { Severity = NotificationSeverity.Error, Summary = "提示", Detail = $"验证重复,请使用其他账号", Duration = 3000 }
);
}
}
else
{
// 此时为第一人登录
globalStateService.Reviewer = user;
InvokeAsync(StateHasChanged);
loginModel = new();
}
}
} else
{
FingerprintUtil.axCZKEM1.OnAttTransactionEx -= axCZKEM1_OnAttTransactionEx;
globalStateService.Operator = user;
na.NavigateTo("/home");
logger.Info($"单人登录模式:用户【{user.NickName}】登录");
}
}
private void Submit(Pojo.User user)
{
Pojo.User u = userDao.GetByUsername(loginModel.Username);
if (u != null)
{
if (Util.MD5.GetMD5Hash(loginModel.Password).ToLower().Equals(u.Password))
{
SetUser(u);
} else
{
_message.Notify(
new NotificationMessage { Severity = NotificationSeverity.Error, Summary = "提示", Detail = $"密码错误", Duration = 4000 }
);
logger.Info($"用户【{u.NickName}】密码输入错误");
}
}
else
{
_message.Notify(
new NotificationMessage { Severity = NotificationSeverity.Error, Summary = "提示", Detail = $"无此用户", Duration = 4000 }
);
logger.Info($"没有用户:【{loginModel.Username}】");
}
}
private void axCZKEM1_OnAttTransactionEx(string sEnrollNumber, int iIsInValid, int iAttState, int iVerifyMethod, int iYear, int iMonth, int iDay, int iHour, int iMinute, int iSecond, int iWorkCode)
{
Pojo.User u = userDao.GetById(Convert.ToInt32(sEnrollNumber));
if(u != null)
{
SetUser(u);
} else
{
_message.Notify(
new NotificationMessage { Severity = NotificationSeverity.Error, Summary = "提示", Detail = $"系统中没有ID为【{sEnrollNumber}】的用户", Duration = 4000 }
);
logger.Info($"指纹机验证通过id为【{sEnrollNumber}】,但是华康数据库中无此用户");
}
}
private void Exit()
{
Environment.Exit(0);
}
}

View File

@ -0,0 +1,114 @@
@page "/add/invoice"
<div class="container-fluid">
<div class="row">
<div class="col-12 mb-4">
<form onsubmit="@(() => grid.Reload())">
<RadzenFieldset Text="查询">
<RadzenStack Orientation="Orientation.Horizontal" Gap="1rem">
<RadzenRow AlignItems="AlignItems.Center">
<RadzenColumn Size="4">
<RadzenLabel Text="单据号" Component="InvoiceNo" />
</RadzenColumn>
<RadzenColumn Size="8">
<RadzenTextBox @bind-Value="InvoiceNo" Style="width: 100%;" Name="InvoiceNo"></RadzenTextBox>
</RadzenColumn>
</RadzenRow>
<RadzenRow AlignItems="AlignItems.Center">
<RadzenColumn Size="4">
<RadzenLabel Text="请领日期" Component="InvoiceDate" />
</RadzenColumn>
<RadzenColumn Size="8">
<RadzenDatePicker DateFormat="yyyy-MM-dd" CurrentDateChanged="@OnCurrentDateChanged" @bind-Value="InvoiceDate" Style="width: 100%;" Name="InvoiceDate" />
</RadzenColumn>
</RadzenRow>
<RadzenRow AlignItems="AlignItems.Center">
<RadzenColumn Size="12">
<RadzenButton Size="ButtonSize.Large" ButtonType="ButtonType.Submit" IsBusy="isLoading" Icon="search" Text="查询" />
<RadzenButton Size="ButtonSize.Large" Click="reloadGrid" IsBusy="isLoading" Icon="refresh" Text="重置" ButtonStyle="ButtonStyle.Warning" />
</RadzenColumn>
</RadzenRow>
</RadzenStack>
</RadzenFieldset>
</form>
</div>
<div class="col-12 mb-4">
<RadzenDataGrid @ref="grid"
LoadData="@LoadData"
RowSelect="@((InOutInvoice oi) => { InvoiceSelected(oi); })"
IsLoading="@isLoading"
Count="@count"
EmptyText="无数据"
Data="@_forecasts"
AllowColumnResize="true" AllowAlternatingRows="false"
SelectionMode="DataGridSelectionMode.Single"
AllowPaging="true" PageSize="10" PagerHorizontalAlign="HorizontalAlign.Left" ShowPagingSummary="true" PagingSummaryFormat="{0}/{1} 共{2}条数据">
<Columns>
<RadzenDataGridColumn Frozen="true" Title="单据号" Property="InvoiceNo"></RadzenDataGridColumn>
<RadzenDataGridColumn Width="170px" Title="时间" Property="InvoiceDate"></RadzenDataGridColumn>
<RadzenDataGridColumn Title="请领药房" Property="InPharmacyId"></RadzenDataGridColumn>
<RadzenDataGridColumn Title="出库药房" Property="OutPharmacyId"></RadzenDataGridColumn>
</Columns>
</RadzenDataGrid>
</div>
</div>
</div>
@code {
@inject IInOutInvoiceDao inOutInvoiceDao;
@inject DialogService dialogService;
RadzenDataGrid<InOutInvoice> grid;
bool isLoading;
int count;
private IEnumerable<InOutInvoice>? _forecasts;
string InvoiceNo;
DateTime InvoiceDate = DateTime.MinValue;
void OnCurrentDateChanged(DateTime args)
{
InvoiceDate = new DateTime(args.Year, args.Month, args.Day);
}
async Task LoadData(LoadDataArgs args)
{
isLoading = true;
var result = await inOutInvoiceDao.GetAllInvoiceByType(InvoiceNo, InvoiceDate, args.Top, args.Skip, 1);
// Update the Data property
_forecasts = result.Desserts;
// Update the count
count = result.TotalDesserts;
isLoading = false;
}
async Task reloadGrid()
{
InvoiceNo = "";
InvoiceDate = DateTime.MinValue;
await grid.Reload();
}
async Task InvoiceSelected(InOutInvoice oi)
{
var b = await dialogService.OpenAsync<InvoiceAddDialog>(
$"调拨入库详情",
new Dictionary<string, object>() { { "invoice", oi } },
new DialogOptions() { Width = "85vw", Resizable = true, Draggable = true, ShowClose = false }
);
if (b)
{
await reloadGrid();
}
}
}

View File

@ -0,0 +1,300 @@
@page "/invoice/add/{invoice}"
@using MasaBlazorApp3.Pojo.Config;
@using MasaBlazorApp3.Pojo.Vo;
@using MasaBlazorApp3.Util;
@using Microsoft.Extensions.Options;
@using Newtonsoft.Json;
@using log4net;
<RadzenStack Gap="1rem" Orientation="Orientation.Vertical" JustifyContent="JustifyContent.SpaceBetween" Style="height: 100%;">
<RadzenStack class="rz-p-4 rz-border-radius-1" Style="border: var(--rz-grid-cell-border)" Orientation="Orientation.Horizontal" Gap="1rem">
<RadzenText TextStyle="TextStyle.Overline" Class="rz-mt-2 rz-my-0" Style="color: var(--rz-text-tertiary-color);">单据号:</RadzenText>
<RadzenText TextStyle="TextStyle.Body1" Class="rz-text-truncate"><b>@(invoice?.InvoiceNo)</b></RadzenText>
<RadzenText TextStyle="TextStyle.Overline" Class="rz-mt-2 rz-my-0" Style="color: var(--rz-text-tertiary-color);">时间:</RadzenText>
<RadzenText TextStyle="TextStyle.Body1" Class="rz-text-truncate"><b>@(invoice?.InvoiceDate)</b></RadzenText>
</RadzenStack>
<RadzenStack>
<RadzenDataGrid @ref="grid" Data="@data" ExpandMode="DataGridExpandMode.Multiple"
RowRender="@RowRender"
EmptyText="无数据" AllowAlternatingRows="false">
<Template Context="di">
<RadzenDataGrid Data="@di.ChannelStocks" EmptyText="无数据" @ref="di.Grid"
CellClick="@((DataGridCellMouseEventArgs<ChannelStock> args) => OnCellClick(args, di.Grid))">
<Columns>
<RadzenDataGridColumn Title="库位" Property="DrawerNo">
<Template Context="s">
@s.DrawerNo - @s.ColNo
</Template>
</RadzenDataGridColumn>
<RadzenDataGridColumn Title="库存" Property="Quantity"></RadzenDataGridColumn>
@* <RadzenDataGridColumn Title="批次" Property="ManuNo"></RadzenDataGridColumn>
<RadzenDataGridColumn Title="效期" Property="EffDate"></RadzenDataGridColumn> *@
<RadzenDataGridColumn Title="入库数量" Property="AddQuantity">
<EditTemplate Context="cs">
<RadzenNumeric Disabled="status > 0" Style="display: block" Min="0" Max="@di.Quantity" Name="Quantity" @bind-Value=@cs.AddQuantity />
<RadzenNumericRangeValidator Style="position: absolute;z-index: 9999;" Min="0" Max="@di.Quantity" Text="请填写正确的添加数量" Component="Quantity" />
<RadzenCustomValidator Validator="@(() => di.ChannelStocks.Sum(cs2 => cs2.AddQuantity) == di.Quantity)" Component="Quantity" Text="入库总量应等于请领数量" Style="position: absolute;z-index: 9999;" />
</EditTemplate>
</RadzenDataGridColumn>
</Columns>
</RadzenDataGrid>
</Template>
<Columns>
<RadzenDataGridColumn Property="Drug.DrugName" Title="药品" />
<RadzenDataGridColumn Property="Drug.DrugSpec" Title="规格" />
<RadzenDataGridColumn Property="Invoice.DrugManuNo" Title="批次" />
<RadzenDataGridColumn Property="Invoice.EffDate" Title="效期" />
<RadzenDataGridColumn Property="Quantity" Title="请领数量" />
<RadzenDataGridColumn Property="StockQuantity" Title="总库存" />
</Columns>
</RadzenDataGrid>
</RadzenStack>
<RadzenStack Orientation="Orientation.Horizontal" JustifyContent="JustifyContent.Center" Gap="0.5rem">
@if (status < 2)
{
<RadzenButton Click="@StartAdd" Disabled="!CanTakeDrug" IsBusy="status > 0" BusyText="加药中。。。" ButtonStyle="ButtonStyle.Warning" Variant="Variant.Flat" Text="加药" Style="width: 120px" />
}
@if (status == 2)
{
<RadzenButton Click="@AddFinish" ButtonStyle="ButtonStyle.Success" Variant="Variant.Flat" Text="完成" Style="width: 120px" />
}
@if (status < 2)
{
<RadzenButton Click="@((args) => CancelOpera())" Variant="Variant.Flat" Text="取消" Style="width: 120px" />
}
</RadzenStack>
</RadzenStack>
@code {
@inject Radzen.DialogService dialogService;
@inject IInOutInvoiceDao inOutInvoiceDao;
@inject IOptions<DrawerConfig> setting;
@inject NotificationService _message
@inject PortUtil PortUtil;
RadzenDataGrid<InvoiceVo> grid;
private readonly ILog logger = LogManager.GetLogger(typeof(InvoiceAddDialog));
[Parameter] public InOutInvoice invoice { get; set; }
private bool CanTakeDrug = true;
int status = 0;
public List<InvoiceVo> data { get; set; }
async Task StartAdd()
{
if(data.Any(it => it.Quantity != it.ChannelStocks.Sum(cs => cs.AddQuantity)))
{
_message.Notify(
new NotificationMessage { Severity = NotificationSeverity.Error, Summary = "提示", Detail = $"请填写正确的入库数量!", Duration = 4000 }
);
} else
{
await OpenDrawer();
}
}
async Task CancelOpera()
{
status = 0;
dialogService.Close(false);
}
async Task OpenDrawer()
{
this.status = 1;
// 解析需要打开的抽屉列表
List<ChannelStock> channels = new();
for (int i = 0; i < data.Count; i++)
{
channels = channels.Concat(data[i].ChannelStocks.Where(cs => cs.AddQuantity > 0)).ToList();
}
List<int> drawerNos = channels.GroupBy(it => it.DrawerNo).Select(it => it.Key).ToList();
// 根据抽屉类型来决定打开前是否需要查询数量
int index = 0;
var BeforeQuantity = new int[9];
var AfterQuantity = new int[9];
await new PromiseUtil<int>().taskAsyncLoop(500, 0, async (options, next, stop) =>
{
var drawerNo = drawerNos[index];
try
{
if (this.status == 0)
{
stop();
}
// 开启抽屉
else if (this.status == 1)
{
if (options._data == 0)
{
BeforeQuantity = new int[9];
AfterQuantity = new int[9];
// 判断是否为单支抽屉
if (setting.Value.single.Contains(drawerNo))
{
byte[] quantity = await PortUtil.CheckQuantityByDrawer(drawerNo);
BeforeQuantity = quantity.Select(it => Convert.ToInt32(it)).ToArray().Skip(3).Take(9).ToArray();
logger.Info($"单支抽屉【{drawerNo}】,开抽屉前检测数量【{string.Join(",", BeforeQuantity)}】");
await PortUtil.NoLightOnByCol(drawerNo, data.Select(ot => ot.ChannelStocks.Where(cs => cs.DrawerNo == drawerNo).Select(cs => cs.ColNo)).Cast<int>().ToArray());
}
var b = await PortUtil.OpenDrawerStatus(drawerNo);
if (b)
{
PortUtil.SpeakAsync($"{drawerNo}号抽屉已经打开,请,加药");
options._data = 1;
next();
}
else
{
_message.Notify(
new NotificationMessage { Severity = NotificationSeverity.Error, Summary = "提示", Detail = $"抽屉【{drawerNo}】打开失败,请检测硬件", Duration = 4000 }
);
logger.Info($"抽屉打开失败");
PortUtil.AllLightOff();
RestData();
stop();
}
}
// 检测状态
else if (options._data == 1)
{
// 查询抽屉是否为关闭状态
var b = await PortUtil.CheckDrawerStatus2(drawerNo);
// 关闭则改变状态并终止循环
if (b)
{
options._data = 0;
if (setting.Value.single.Contains(drawerNo))
{
PortUtil.AllLightOff();
}
if (index == drawerNos.Count - 1)
{
PortUtil.SpeakAsync($"加药完成,请,点击完成按钮进行确认");
this.status = 2;
stop();
}
else
{
index += 1;
next();
}
}
else
{
if (setting.Value.single.Contains(drawerNo))
{
byte[] quantity = await PortUtil.CheckQuantityByDrawer(drawerNo);
AfterQuantity = quantity.Select(it => Convert.ToInt32(it)).ToArray().Skip(3).Take(9).ToArray();
logger.Info($"单支抽屉【{drawerNo}】,抽屉未关检测数量【{string.Join(",", AfterQuantity)}】");
data.ForEach(cl =>
{
cl.ChannelStocks.Where(cs => cs.DrawerNo == drawerNo).ToList().ForEach(cs =>
{
logger.Info($"单支抽屉【{drawerNo}】,应加药品数量【{cs.AddQuantity}】,现实取数量【{AfterQuantity[cs.ColNo - 1] - BeforeQuantity[cs.ColNo - 1]}】");
});
});
}
next(); // continue iteration
}
}
}
}
catch (Exception e)
{
RestData();
logger.Info($"调拨加药发生错误,{e.Message}");
_message.Notify(
new NotificationMessage { Severity = NotificationSeverity.Error, Summary = "提示", Detail = $"发生错误,{e.Message}", Duration = 4000 }
);
if (setting.Value.single.Contains(drawerNo))
{
PortUtil.AllLightOff();
}
stop();
}
});
}
void RestData()
{
this.status = 0;
}
async Task AddFinish()
{
// 保存账册、操作记录
var b = await inOutInvoiceDao.InvoiceAddFinish(data);
if (!b)
{
_message.Notify(new NotificationMessage { Severity = NotificationSeverity.Error, Summary = "提示", Detail = $"数据保存失败", Duration = 4000 });
logger.Error($"抽屉加药保存数据库失败,数据{JsonConvert.SerializeObject(data)}");
// 关闭弹窗
dialogService.Close(false);
}
else
{
// 关闭弹窗
dialogService.Close(true);
}
//重置状态
this.RestData();
}
protected override async Task OnInitializedAsync()
{
data = await inOutInvoiceDao.getAddInfoByInvoiceNo(invoice.InvoiceNo);
// 如果有库位列表未空则说明不能取药,需要增加库位
if (data.Any(it => it.ChannelStocks.Count == 0))
{
CanTakeDrug = false;
}
base.OnInitializedAsync();
}
protected override async Task OnAfterRenderAsync(bool firstRender)
{
base.OnAfterRender(firstRender);
if (firstRender)
{
await Task.Delay(15);
await grid.ExpandRows(grid.PagedView.Where(it => it.ChannelStocks.Count > 0));
}
}
void RowRender(RowRenderEventArgs<InvoiceVo> args)
{
args.Expandable = args.Data.ChannelStocks != null && args.Data.ChannelStocks.Count > 0;
}
void OnCellClick(DataGridCellMouseEventArgs<ChannelStock> args, RadzenDataGrid<ChannelStock> Grid)
{
Grid.EditRow(args.Data);
}
}

View File

@ -0,0 +1,114 @@
@page "/take/invoice"
<div class="container-fluid">
<div class="row">
<div class="col-12 mb-4">
<form onsubmit="@(() => grid.Reload())">
<RadzenFieldset Text="查询">
<RadzenStack Orientation="Orientation.Horizontal" Gap="1rem">
<RadzenRow AlignItems="AlignItems.Center">
<RadzenColumn Size="4">
<RadzenLabel Text="单据号" Component="InvoiceNo" />
</RadzenColumn>
<RadzenColumn Size="8">
<RadzenTextBox @bind-Value="InvoiceNo" Style="width: 100%;" Name="InvoiceNo"></RadzenTextBox>
</RadzenColumn>
</RadzenRow>
<RadzenRow AlignItems="AlignItems.Center">
<RadzenColumn Size="4">
<RadzenLabel Text="请领日期" Component="InvoiceDate" />
</RadzenColumn>
<RadzenColumn Size="8">
<RadzenDatePicker DateFormat="yyyy-MM-dd" CurrentDateChanged="@OnCurrentDateChanged" @bind-Value="InvoiceDate" Style="width: 100%;" Name="InvoiceDate" />
</RadzenColumn>
</RadzenRow>
<RadzenRow AlignItems="AlignItems.Center">
<RadzenColumn Size="12">
<RadzenButton Size="ButtonSize.Medium" ButtonType="ButtonType.Submit" IsBusy="isLoading" Icon="search" Text="查询" />
<RadzenButton Size="ButtonSize.Medium" Click="reloadGrid" IsBusy="isLoading" Icon="refresh" Text="重置" ButtonStyle="ButtonStyle.Warning" />
</RadzenColumn>
</RadzenRow>
</RadzenStack>
</RadzenFieldset>
</form>
</div>
<div class="col-12 mb-4">
<RadzenDataGrid @ref="grid"
LoadData="@LoadData"
RowSelect="@((InOutInvoice oi) => { InvoiceSelected(oi); })"
IsLoading="@isLoading"
Count="@count"
EmptyText="无数据"
Data="@_forecasts"
AllowColumnResize="true" AllowAlternatingRows="false"
SelectionMode="DataGridSelectionMode.Single"
AllowPaging="true" PageSize="10" PagerHorizontalAlign="HorizontalAlign.Left" ShowPagingSummary="true" PagingSummaryFormat="{0}/{1} 共{2}条数据">
<Columns>
<RadzenDataGridColumn Frozen="true" Title="单据号" Property="InvoiceNo"></RadzenDataGridColumn>
<RadzenDataGridColumn Width="170px" Title="时间" Property="InvoiceDate"></RadzenDataGridColumn>
<RadzenDataGridColumn Title="请领药房" Property="InPharmacyId"></RadzenDataGridColumn>
<RadzenDataGridColumn Title="出库药房" Property="OutPharmacyId"></RadzenDataGridColumn>
</Columns>
</RadzenDataGrid>
</div>
</div>
</div>
@code {
@inject IInOutInvoiceDao inOutInvoiceDao;
@inject DialogService dialogService;
RadzenDataGrid<InOutInvoice> grid;
bool isLoading;
int count;
private IEnumerable<InOutInvoice>? _forecasts;
string InvoiceNo;
DateTime InvoiceDate = DateTime.MinValue;
void OnCurrentDateChanged(DateTime args)
{
InvoiceDate = new DateTime(args.Year, args.Month, args.Day);
}
async Task LoadData(LoadDataArgs args)
{
isLoading = true;
var result = await inOutInvoiceDao.GetAllInvoiceByType(InvoiceNo, InvoiceDate, args.Top, args.Skip, 2);
// Update the Data property
_forecasts = result.Desserts;
// Update the count
count = result.TotalDesserts;
isLoading = false;
}
async Task reloadGrid()
{
InvoiceNo = "";
InvoiceDate = DateTime.MinValue;
await grid.Reload();
}
async Task InvoiceSelected(InOutInvoice oi)
{
var b = await dialogService.OpenAsync<InvoiceOutDialog>(
$"调拨出库详情",
new Dictionary<string, object>() { { "invoice", oi } },
new DialogOptions() { Width = "85vw", Resizable = true, Draggable = true, ShowClose = false }
);
if (b)
{
await reloadGrid();
}
}
}

View File

@ -0,0 +1,298 @@
@page "/invoice/out/{invoice}"
@using MasaBlazorApp3.Pojo.Config;
@using MasaBlazorApp3.Pojo.Vo;
@using MasaBlazorApp3.Util;
@using Microsoft.Extensions.Options;
@using Newtonsoft.Json;
@using log4net;
<RadzenStack Gap="1rem" Orientation="Orientation.Vertical" JustifyContent="JustifyContent.SpaceBetween" Style="height: 100%;">
<RadzenStack class="rz-p-4 rz-border-radius-1" Style="border: var(--rz-grid-cell-border)" Orientation="Orientation.Horizontal" Gap="1rem">
<RadzenText TextStyle="TextStyle.Overline" Class="rz-mt-2 rz-my-0" Style="color: var(--rz-text-tertiary-color);">单据号:</RadzenText>
<RadzenText TextStyle="TextStyle.Body1" Class="rz-text-truncate"><b>@(invoice?.InvoiceNo)</b></RadzenText>
<RadzenText TextStyle="TextStyle.Overline" Class="rz-mt-2 rz-my-0" Style="color: var(--rz-text-tertiary-color);">时间:</RadzenText>
<RadzenText TextStyle="TextStyle.Body1" Class="rz-text-truncate"><b>@(invoice?.InvoiceDate)</b></RadzenText>
</RadzenStack>
<RadzenStack>
<RadzenDataGrid @ref="grid" Data="@data" ExpandMode="DataGridExpandMode.Multiple"
RowRender="@RowRender"
EmptyText="无数据" AllowAlternatingRows="false">
<Template Context="di">
<RadzenDataGrid Data="@di.ChannelStocks" EmptyText="无数据" @ref="di.Grid"
CellClick="@((DataGridCellMouseEventArgs<ChannelStock> args) => OnCellClick(args, di.Grid))">
<Columns>
<RadzenDataGridColumn Title="库位" Property="DrawerNo">
<Template Context="s">
@s.DrawerNo - @s.ColNo
</Template>
</RadzenDataGridColumn>
<RadzenDataGridColumn Title="库存" Property="Quantity"></RadzenDataGridColumn>
@* <RadzenDataGridColumn Title="批次" Property="ManuNo"></RadzenDataGridColumn>
<RadzenDataGridColumn Title="效期" Property="EffDate"></RadzenDataGridColumn> *@
<RadzenDataGridColumn Title="出库数量" Property="TakeQuantity">
<EditTemplate Context="cs">
<RadzenNumeric Style="display: block" Min="0" Max="@cs.Quantity" Name="Quantity" @bind-Value=@cs.TakeQuantity />
<RadzenNumericRangeValidator Style="position: absolute;z-index: 9999;" Min="0" Max="@cs.Quantity" Text="请填写正确的取出数量" Component="Quantity" />
<RadzenCustomValidator Validator="@(() => di.ChannelStocks.Sum(cs2 => cs2.TakeQuantity) == di.Quantity)" Component="Quantity" Text="出库总量应等于请领数量" Style="position: absolute;z-index: 9999;" />
</EditTemplate>
</RadzenDataGridColumn>
</Columns>
</RadzenDataGrid>
</Template>
<Columns>
<RadzenDataGridColumn Property="Drug.DrugName" Title="药品" />
<RadzenDataGridColumn Property="Drug.DrugSpec" Title="规格" />
<RadzenDataGridColumn Property="Invoice.DrugManuNo" Title="批次" />
<RadzenDataGridColumn Property="Invoice.EffDate" Title="效期" />
<RadzenDataGridColumn Property="Quantity" Title="请领数量" />
<RadzenDataGridColumn Property="StockQuantity" Title="总库存" />
</Columns>
</RadzenDataGrid>
</RadzenStack>
<RadzenStack Orientation="Orientation.Horizontal" JustifyContent="JustifyContent.Center" Gap="0.5rem">
@if (status < 2)
{
<RadzenButton Click="@StartTake" Disabled="!CanTakeDrug" IsBusy="status > 0" BusyText="取药中。。。" ButtonStyle="ButtonStyle.Warning" Variant="Variant.Flat" Text="取药" Style="width: 120px" />
}
@if (status == 2)
{
<RadzenButton Click="@TakeFinish" ButtonStyle="ButtonStyle.Success" Variant="Variant.Flat" Text="完成" Style="width: 120px" />
}
@if (status <= 2)
{
<RadzenButton Click="@((args) => CancelOpera())" Variant="Variant.Flat" Text="取消" Style="width: 120px" />
}
</RadzenStack>
</RadzenStack>
@code {
@inject Radzen.DialogService dialogService;
@inject IInOutInvoiceDao inOutInvoiceDao;
@inject IOptions<DrawerConfig> setting;
@inject NotificationService _message
@inject PortUtil PortUtil;
RadzenDataGrid<InvoiceVo> grid;
private readonly ILog logger = LogManager.GetLogger(typeof(InvoiceOutDialog));
[Parameter] public InOutInvoice invoice { get; set; }
private bool CanTakeDrug = true;
int status = 0;
public List<InvoiceVo> data { get; set; }
async Task StartTake()
{
if(data.Any(it => it.Quantity != it.ChannelStocks.Sum(cs => cs.TakeQuantity)))
{
_message.Notify(
new NotificationMessage { Severity = NotificationSeverity.Error, Summary = "提示", Detail = $"请填写正确的出库数量!", Duration = 4000 }
);
} else
{
await OpenDrawer();
}
}
async Task CancelOpera()
{
status = 0;
dialogService.Close(false);
}
async Task OpenDrawer()
{
this.status = 1;
// 解析需要打开的抽屉列表
List<ChannelStock> channels = new();
for(int i = 0; i < data.Count; i++)
{
channels = channels.Concat(data[i].ChannelStocks.Where(cs => cs.TakeQuantity > 0)).ToList();
}
List<int> drawerNos = channels.GroupBy(it => it.DrawerNo).Select(it => it.Key).ToList();
// 根据抽屉类型来决定打开前是否需要查询数量
var promiseUtil = new PromiseUtil<int>();
int index = 0;
var BeforeQuantity = new int[9];
var AfterQuantity = new int[9];
await promiseUtil.taskAsyncLoop(500, 0 , async (options, next, stop) =>
{
var drawerNo = drawerNos[index];
try
{
if (this.status == 0)
{
stop();
}
// 开启抽屉
else if (this.status == 1)
{
if (options._data == 0)
{
BeforeQuantity = new int[9];
AfterQuantity = new int[9];
// 判断是否为单支抽屉
if (setting.Value.single.Contains(drawerNo))
{
byte[] quantity = await PortUtil.CheckQuantityByDrawer(drawerNo);
BeforeQuantity = quantity.Select(it => Convert.ToInt32(it)).ToArray().Skip(3).Take(9).ToArray();
logger.Info($"单支抽屉【{drawerNo}】,开抽屉前检测数量【{string.Join(",", BeforeQuantity)}】");
await PortUtil.HasLightOnByCol(drawerNo, data.Select(ot => ot.ChannelStocks.Where(cs => cs.DrawerNo == drawerNo).Select(cs => cs.ColNo)).Cast<int>().ToArray());
}
var b = await PortUtil.OpenDrawerStatus(drawerNo);
if (b)
{
PortUtil.SpeakAsync($"{drawerNo}号抽屉已经打开,请,取药");
options._data = 1;
next();
}
else
{
_message.Notify(
new NotificationMessage { Severity = NotificationSeverity.Error, Summary = "提示", Detail = $"抽屉【{drawerNo}】打开失败,请检测硬件", Duration = 4000 }
);
logger.Info($"抽屉打开失败");
PortUtil.AllLightOff();
RestData();
stop();
}
}
// 检测状态
else if (options._data == 1)
{
// 查询抽屉是否为关闭状态
var b = await PortUtil.CheckDrawerStatus2(drawerNo);
// 关闭则改变状态并终止循环
if (b)
{
options._data = 0;
if (setting.Value.single.Contains(drawerNo))
{
PortUtil.AllLightOff();
}
if (index == drawerNos.Count - 1)
{
PortUtil.SpeakAsync($"取药完成,请,点击完成按钮进行确认");
this.status = 2;
stop();
}
else
{
index += 1;
next();
}
}
else
{
if (setting.Value.single.Contains(drawerNo))
{
byte[] quantity = await PortUtil.CheckQuantityByDrawer(drawerNo);
AfterQuantity = quantity.Select(it => Convert.ToInt32(it)).ToArray().Skip(3).Take(9).ToArray();
logger.Info($"单支抽屉【{drawerNo}】,抽屉未关检测数量【{string.Join(",", AfterQuantity)}】");
data.ForEach(cl =>
{
cl.ChannelStocks.Where(cs => cs.DrawerNo == drawerNo).ToList().ForEach(cs =>
{
logger.Info($"单支抽屉【{drawerNo}】,应取药品数量【{cs.TakeQuantity}】,现实取数量【{BeforeQuantity[cs.ColNo - 1] - AfterQuantity[cs.ColNo - 1]}】");
});
});
}
next(); // continue iteration
}
}
}
}
catch (Exception e)
{
RestData();
logger.Info($"调拨取药发生错误,{e.Message}");
_message.Notify(
new NotificationMessage { Severity = NotificationSeverity.Error, Summary = "提示", Detail = $"发生错误,{e.Message}", Duration = 4000 }
);
if (setting.Value.single.Contains(drawerNo))
{
PortUtil.AllLightOff();
}
stop();
}
});
}
void RestData()
{
this.status = 0;
}
async Task TakeFinish()
{
// 保存账册、操作记录
var b = await inOutInvoiceDao.InvoiceOutFinish(data);
if (!b)
{
_message.Notify(new NotificationMessage { Severity = NotificationSeverity.Error, Summary = "提示", Detail = $"数据保存失败", Duration = 4000 });
logger.Error($"抽屉加药保存数据库失败,数据{JsonConvert.SerializeObject(data)}");
// 关闭弹窗
dialogService.Close(false);
}
else
{
// 关闭弹窗
dialogService.Close(true);
}
//重置状态
this.RestData();
}
protected override async Task OnInitializedAsync()
{
data = await inOutInvoiceDao.getTakeInfoByInvoiceNo(invoice.InvoiceNo);
// 如果有【stockQuantity】字段说明有药品库存不足
if (data.Any(it => it.ChannelStocks == null || it.ChannelStocks.Count == 0))
{
CanTakeDrug = false;
}
base.OnInitializedAsync();
}
protected override async Task OnAfterRenderAsync(bool firstRender)
{
base.OnAfterRender(firstRender);
if (firstRender)
{
await Task.Delay(15);
await grid.ExpandRows(grid.PagedView.Where(it => it.ChannelStocks.Count > 0));
}
}
void RowRender(RowRenderEventArgs<InvoiceVo> args)
{
args.Expandable = args.Data.ChannelStocks != null && args.Data.ChannelStocks.Count > 0;
}
void OnCellClick(DataGridCellMouseEventArgs<ChannelStock> args, RadzenDataGrid<ChannelStock> Grid)
{
Grid.EditRow(args.Data);
}
}

View File

@ -0,0 +1,118 @@
@page "/take/record/{type}"
@page "/add/record/{type}"
@page "/return/record1/{type}"
@page "/return/record2/{type}"
@page "/stock/record/{type}"
<div class="container-fluid">
<div class="row">
<div class="col-12 mb-4">
<form onsubmit="@(() => grid.Reload())">
<RadzenFieldset Text="查询">
<RadzenStack Orientation="Orientation.Horizontal" Gap="1rem">
<RadzenRow AlignItems="AlignItems.Center">
<RadzenColumn Size="4">
<RadzenLabel Text="开始时间" Component="Start" />
</RadzenColumn>
<RadzenColumn Size="8">
<RadzenDatePicker DateFormat="yyyy-MM-dd HH:mm:ss" ShowTime="true" @bind-Value="start" Style="width: 100%;" Name="Start" />
</RadzenColumn>
</RadzenRow>
<RadzenRow AlignItems="AlignItems.Center">
<RadzenColumn Size="4">
<RadzenLabel Text="结束时间" Component="End" />
</RadzenColumn>
<RadzenColumn Size="8">
<RadzenDatePicker DateFormat="yyyy-MM-dd HH:mm:ss" ShowTime="true" @bind-Value="end" Style="width: 100%;" Name="End" />
</RadzenColumn>
</RadzenRow>
<RadzenRow AlignItems="AlignItems.Center">
<RadzenColumn Size="12">
<RadzenButton Size="ButtonSize.Large" ButtonType="ButtonType.Submit" IsBusy="isLoading" Icon="search" Text="查询" />
<RadzenButton Size="ButtonSize.Large" Click="reloadGrid" IsBusy="isLoading" Icon="refresh" Text="重置" ButtonStyle="ButtonStyle.Warning" />
</RadzenColumn>
</RadzenRow>
</RadzenStack>
</RadzenFieldset>
</form>
</div>
<div class="col-12 mb-4">
<RadzenDataGrid @ref="grid"
LoadData="@LoadData"
IsLoading="@isLoading"
Count="@count"
EmptyText="无数据"
Data="@_forecasts"
AllowColumnResize="true" AllowAlternatingRows="false"
SelectionMode="DataGridSelectionMode.Single"
AllowPaging="true" PageSize="10" PagerHorizontalAlign="HorizontalAlign.Left" ShowPagingSummary="true" PagingSummaryFormat="{0}/{1} 共{2}条数据">
<Columns>
<RadzenDataGridColumn Frozen="true" Title="操作人" Property="OperatorUser.NickName"></RadzenDataGridColumn>
<RadzenDataGridColumn Width="170px" Title="操作时间" Property="OperationTime"></RadzenDataGridColumn>
<RadzenDataGridColumn Width="200px" Title="药品名称" Property="Drug.DrugName"></RadzenDataGridColumn>
<RadzenDataGridColumn Title="规格" Property="Drug.DrugSpec"></RadzenDataGridColumn>
<RadzenDataGridColumn Title="数量" Property="Quantity"></RadzenDataGridColumn>
<RadzenDataGridColumn Title="批次" Property="ManuNo"></RadzenDataGridColumn>
<RadzenDataGridColumn Title="效期" Property="EffDate">
<Template Context="mr">
@mr.EffDate?.ToString("yyyy-MM-dd")
</Template>
</RadzenDataGridColumn>
<RadzenDataGridColumn title="库位" Property="Location"></RadzenDataGridColumn>
</Columns>
</RadzenDataGrid>
</div>
</div>
</div>
@code {
@inject IMachineRecordDao machineRecordDao;
@inject DialogService dialogService;
@inject NavigationManager navigate;
RadzenDataGrid<MachineRecord> grid;
bool isLoading;
int count;
private IEnumerable<MachineRecord>? _forecasts;
DateTime start;
DateTime end;
[Parameter] public string type { get; set; }
protected override void OnParametersSet()
{
if(grid != null)
{
reloadGrid();
}
}
async Task LoadData(LoadDataArgs args)
{
isLoading = true;
var result = await machineRecordDao.GetMachineRecordAsync(start, end, 0, "", int.Parse(type), args.Top, args.Skip);
// Update the Data property
_forecasts = result.Desserts;
// Update the count
count = result.TotalDesserts;
isLoading = false;
}
async Task reloadGrid()
{
start = DateTime.MinValue;
end = DateTime.MinValue;
await grid.Reload();
}
}

View File

@ -0,0 +1,259 @@
@page "/orderDetail/{order}"
@using MasaBlazorApp3.Pojo.Config;
@using MasaBlazorApp3.Pojo.Vo;
@using MasaBlazorApp3.Util;
@using Microsoft.Extensions.Options;
@using Newtonsoft.Json;
@using log4net;
<RadzenStack Gap="1rem" Orientation="Orientation.Vertical" Style="height: 100%;">
<RadzenStack>
<RadzenStack class="rz-p-4 rz-border-radius-1" Style="border: var(--rz-grid-cell-border)" Orientation="Orientation.Horizontal" Gap="1rem">
<RadzenText TextStyle="TextStyle.Overline" Class="rz-mt-2 rz-my-0" Style="color: var(--rz-text-tertiary-color);">处方号:</RadzenText>
<RadzenText TextStyle="TextStyle.Body1" Class="rz-text-truncate"><b>@(order?.OrderNo)</b></RadzenText>
<RadzenText TextStyle="TextStyle.Overline" Class="rz-mt-2 rz-my-0" Style="color: var(--rz-text-tertiary-color);">患者姓名:</RadzenText>
<RadzenText TextStyle="TextStyle.Body1" Class="rz-text-truncate"><b>@(order?.PatientName)</b></RadzenText>
<RadzenText TextStyle="TextStyle.Overline" Class="rz-mt-2 rz-my-0" Style="color: var(--rz-text-tertiary-color);">性别:</RadzenText>
<RadzenText TextStyle="TextStyle.Body1" Class="rz-text-truncate"><b>@(order?.Sex)</b></RadzenText>
<RadzenText TextStyle="TextStyle.Overline" Class="rz-mt-2 rz-my-0" Style="color: var(--rz-text-tertiary-color);">年龄:</RadzenText>
<RadzenText TextStyle="TextStyle.Body1" Class="rz-text-truncate"><b>@(order?.Age)</b></RadzenText>
</RadzenStack>
@if (CanTakeDrug)
{
<RadzenDataGrid Data="@data" AllowAlternatingRows="false">
<Columns>
<RadzenDataGridColumn Property="ChannelStock" Title="库位">
<Template>
@context.ChannelStock.DrawerNo - @context.ChannelStock.ColNo
</Template>
</RadzenDataGridColumn>
<RadzenDataGridColumn Property="Drug.DrugName" Title="药品" />
<RadzenDataGridColumn Property="Drug.DrugSpec" Title="规格" />
<RadzenDataGridColumn Property="ChannelStock.ManuNo" Title="批次" />
<RadzenDataGridColumn Property="ChannelStock.EffDate" Title="效期" />
<RadzenDataGridColumn Property="Quantity" Title="数量" />
</Columns>
</RadzenDataGrid>
}
else
{
<RadzenDataGrid Data="@data" AllowAlternatingRows="false">
<Columns>
<RadzenDataGridColumn Property="Drug.DrugName" Title="药品" />
<RadzenDataGridColumn Property="Drug.DrugSpec" Title="规格" />
<RadzenDataGridColumn Property="Quantity" Title="取药数量" />
<RadzenDataGridColumn Property="StockQuantity" Title="库存" />
</Columns>
</RadzenDataGrid>
}
</RadzenStack>
<RadzenStack Orientation="Orientation.Horizontal" JustifyContent="JustifyContent.Center" Gap="0.5rem">
@if (status < 2)
{
<RadzenButton Click="@OpenDrawer" Disabled="!CanTakeDrug" IsBusy="status > 0" BusyText="取药中。。。" ButtonStyle="ButtonStyle.Warning" Variant="Variant.Flat" Text="取药" Style="width: 120px" />
}
@if (status == 2)
{
<RadzenButton Click="@TakeFinish" ButtonStyle="ButtonStyle.Success" Variant="Variant.Flat" Text="完成" Style="width: 120px" />
}
@if (status <= 2)
{
<RadzenButton Click="@((args) => dialogService.Close(false))" Variant="Variant.Flat" Text="取消" Style="width: 120px" />
}
</RadzenStack>
</RadzenStack>
@code {
@inject Radzen.DialogService dialogService;
@inject IOrderInfoDao orderInfoDao;
@inject IChannelListDao channelListDao;
@inject IOptions<DrawerConfig> setting;
@inject NotificationService _message
@inject PortUtil PortUtil;
private readonly ILog logger = LogManager.GetLogger(typeof(OrderDetailDialog));
int status;
[Parameter] public OrderInfo order { get; set; }
private bool CanTakeDrug = true;
public List<OrderTakeVo> data { get; set; }
protected override async Task OnInitializedAsync()
{
data = await orderInfoDao.getTakeInfoByOrderNo(order.OrderNo);
// 如果有【stockQuantity】字段说明有药品库存不足
if (data.Any(it => it.ChannelStock == null))
{
CanTakeDrug = false;
}
base.OnInitializedAsync();
}
async Task OpenDrawer()
{
this.status = 1;
// 解析需要打开的抽屉列表
List<OrderTakeVo> drawerNos = this.data.GroupBy(it => it.ChannelStock.DrawerNo).Select(it => it.First()).ToList();
// 根据抽屉类型来决定打开前是否需要查询数量
var promiseUtil = new PromiseUtil<int>();
await promiseUtil.taskAsyncLoop(500, 0, async (options, next, stop) =>
{
var orderTakeVo = drawerNos[options._data];
var drawerNo = orderTakeVo.ChannelStock.DrawerNo;
try
{
if (this.status == 0)
{
stop();
}
// 开启抽屉
else if (this.status == 1)
{
if (orderTakeVo.Status == 0)
{
// 判断是否为单支抽屉
if (setting.Value.single.Contains(drawerNo))
{
byte[] quantity = await PortUtil.CheckQuantityByDrawer(drawerNo);
orderTakeVo.BeforeQuantity = quantity.Select(it => Convert.ToInt32(it)).ToArray().Skip(3).Take(9).ToArray();
logger.Info($"单支抽屉,开抽屉前检测数量【{string.Join(",", orderTakeVo.BeforeQuantity)}】");
await PortUtil.HasLightOnByCol(drawerNo, data.Where(ot => ot.ChannelStock.DrawerNo == drawerNo).Select(ot => ot.ChannelStock.ColNo).ToArray());
}
var b = await PortUtil.OpenDrawerStatus(drawerNo);
if (b)
{
PortUtil.SpeakAsync($"{drawerNo}号抽屉已经打开,请,取药");
orderTakeVo.Status = 1;
next();
}
else
{
_message.Notify(
new NotificationMessage { Severity = NotificationSeverity.Error, Summary = "提示", Detail = $"抽屉【{drawerNo}】打开失败,请检测硬件", Duration = 4000 }
);
logger.Info($"抽屉打开失败");
PortUtil.AllLightOff();
RestData();
stop();
}
}
// 检测状态
else if (orderTakeVo.Status == 1)
{
// 查询抽屉是否为关闭状态
var b = await PortUtil.CheckDrawerStatus2(drawerNo);
// 关闭则改变状态并终止循环
if (b)
{
data.ForEach(cl =>
{
if (cl.ChannelStock.DrawerNo == drawerNo)
{
cl.GetQuantity = cl.Quantity;
}
});
orderTakeVo.Status = 2;
PortUtil.AllLightOff();
if (options._data == drawerNos.Count - 1)
{
PortUtil.SpeakAsync($"取药完成,请,点击完成按钮进行确认");
this.status = 2;
stop();
}
else
{
options._data += 1;
next();
}
}
else
{
if (setting.Value.single.Contains(drawerNo))
{
byte[] quantity = await PortUtil.CheckQuantityByDrawer(drawerNo);
orderTakeVo.AfterQuantity = quantity.Select(it => Convert.ToInt32(it)).ToArray().Skip(3).Take(9).ToArray();
logger.Info($"单支抽屉,抽屉未关检测数量【{string.Join(",", orderTakeVo.AfterQuantity)}】");
data.ForEach(cl =>
{
if (cl.ChannelStock.DrawerNo == drawerNo)
{
logger.Info($"单支抽屉【{drawerNo}】,应取药品数量【{orderTakeVo.Quantity}】,现实取数量【{orderTakeVo.BeforeQuantity[cl.ChannelStock.ColNo - 1] - orderTakeVo.AfterQuantity[cl.ChannelStock.ColNo - 1]}】");
}
});
}
next(); // continue iteration
}
}
}
}
catch (Exception e)
{
RestData();
logger.Info($"处方取药发生错误,{e.Message}");
_message.Notify(
new NotificationMessage { Severity = NotificationSeverity.Error, Summary = "提示", Detail = $"发生错误,{e.Message}", Duration = 4000 }
);
if (setting.Value.single.Contains(drawerNo))
{
PortUtil.AllLightOff();
}
stop();
}
});
}
void RestData()
{
this.status = 0;
}
async Task TakeFinish()
{
// 保存账册、操作记录
var b = await orderInfoDao.OrderTakeFinish(data);
if (!b)
{
_message.Notify(new NotificationMessage { Severity = NotificationSeverity.Error, Summary = "提示", Detail = $"数据保存失败", Duration = 4000 });
logger.Error($"处方取药保存数据库失败,数据{JsonConvert.SerializeObject(data)}");
// 关闭弹窗
dialogService.Close(false);
}
else
{
// for (int i = 0; i < data.Count; i++)
// {
// // 判断是否为标签抽屉
// if (setting.Value.label.Contains(data[i].ChannelStock.DrawerNo))
// {
// //写标签数量
// await PortUtil.WriteQuantityMethod(data[i].Quantity + data[i].GetQuantity, data[i].ChannelStock.DrawerNo, data[i].ChannelStock.ColNo);
// }
// }
// 关闭弹窗
dialogService.Close(true);
}
//重置状态
this.RestData();
}
}

View File

@ -0,0 +1,280 @@
@page "/orderDetailReturn/{order}"
@using MasaBlazorApp3.Pojo.Config;
@using MasaBlazorApp3.Pojo.Vo;
@using MasaBlazorApp3.Util;
@using Microsoft.Extensions.Options;
@using Newtonsoft.Json;
@using log4net;
<RadzenStack Gap="1rem" Orientation="Orientation.Vertical" Style="height: 100%;">
<RadzenStack>
<RadzenStack class="rz-p-4 rz-border-radius-1" Style="border: var(--rz-grid-cell-border)" Orientation="Orientation.Horizontal" Gap="1rem">
<RadzenText TextStyle="TextStyle.Overline" Class="rz-mt-2 rz-my-0" Style="color: var(--rz-text-tertiary-color);">处方号:</RadzenText>
<RadzenText TextStyle="TextStyle.Body1" Class="rz-text-truncate"><b>@(order?.OrderNo)</b></RadzenText>
<RadzenText TextStyle="TextStyle.Overline" Class="rz-mt-2 rz-my-0" Style="color: var(--rz-text-tertiary-color);">患者姓名:</RadzenText>
<RadzenText TextStyle="TextStyle.Body1" Class="rz-text-truncate"><b>@(order?.PatientName)</b></RadzenText>
<RadzenText TextStyle="TextStyle.Overline" Class="rz-mt-2 rz-my-0" Style="color: var(--rz-text-tertiary-color);">性别:</RadzenText>
<RadzenText TextStyle="TextStyle.Body1" Class="rz-text-truncate"><b>@(order?.Sex)</b></RadzenText>
<RadzenText TextStyle="TextStyle.Overline" Class="rz-mt-2 rz-my-0" Style="color: var(--rz-text-tertiary-color);">年龄:</RadzenText>
<RadzenText TextStyle="TextStyle.Body1" Class="rz-text-truncate"><b>@(order?.Age)</b></RadzenText>
</RadzenStack>
<RadzenDataGrid @ref="grid" Data="@data" ExpandMode="DataGridExpandMode.Multiple"
RowRender="@RowRender"
EmptyText="无数据" AllowAlternatingRows="false">
<Template Context="di">
<RadzenDataGrid Data="@di.ChannelStocks" EmptyText="无数据" @ref="di.Grid"
CellClick="@((DataGridCellMouseEventArgs<ChannelStock> args) => OnCellClick(args, di.Grid))">
<Columns>
<RadzenDataGridColumn Title="库位" Property="DrawerNo">
<Template Context="s">
@s.DrawerNo - @s.ColNo
</Template>
</RadzenDataGridColumn>
<RadzenDataGridColumn Title="库存" Property="Quantity"></RadzenDataGridColumn>
<RadzenDataGridColumn Title="入库数量" Property="AddQuantity">
<EditTemplate Context="cs">
<RadzenNumeric Disabled="status > 0" Style="display: block" Min="0" Max="@di.Quantity" Name="Quantity" @bind-Value=@cs.ReturnQuantity />
<RadzenNumericRangeValidator Style="position: absolute;z-index: 9999;" Min="0" Max="@di.Quantity" Text="请填写正确的添加数量" Component="Quantity" />
<RadzenCustomValidator Validator="@(() => di.ChannelStocks.Sum(cs2 => cs2.ReturnQuantity) == di.Quantity)" Component="Quantity" Text="添加总量应等于退药量" Style="position: absolute;z-index: 9999;" />
</EditTemplate>
</RadzenDataGridColumn>
</Columns>
</RadzenDataGrid>
</Template>
<Columns>
<RadzenDataGridColumn Property="Drug.DrugName" Title="药品" />
<RadzenDataGridColumn Property="Drug.DrugSpec" Title="规格" />
<RadzenDataGridColumn Property="data.ManuNo" Title="批次" />
<RadzenDataGridColumn Property="data.EffDate" Title="效期" />
<RadzenDataGridColumn Property="Quantity" Title="退药量" />
<RadzenDataGridColumn Property="StockQuantity" Title="总库存" />
</Columns>
</RadzenDataGrid>
</RadzenStack>
<RadzenStack Orientation="Orientation.Horizontal" JustifyContent="JustifyContent.Center" Gap="0.5rem">
@if(status < 2)
{
<RadzenButton Click="@OpenDrawer" Disabled="!CanReturnDrug" IsBusy="status > 0" BusyText="退药中。。。" ButtonStyle="ButtonStyle.Warning" Variant="Variant.Flat" Text="退药" Style="width: 120px" />
}
@if(status == 2)
{
<RadzenButton Click="@TakeFinish" ButtonStyle="ButtonStyle.Success" Variant="Variant.Flat" Text="完成" Style="width: 120px" />
}
@if(status < 2)
{
<RadzenButton Click="@((args) => dialogService.Close(false))" Variant="Variant.Flat" Text="取消" Style="width: 120px" />
}
</RadzenStack>
</RadzenStack>
@code {
@inject Radzen.DialogService dialogService;
@inject IOrderInfoDao orderInfoDao;
@inject IChannelListDao channelListDao;
@inject IOptions<DrawerConfig> setting;
@inject NotificationService _message
@inject PortUtil PortUtil;
private readonly ILog logger = LogManager.GetLogger(typeof(OrderDetailDialog));
RadzenDataGrid<OperationVo<MachineRecord>> grid;
int status;
[Parameter] public OrderInfo order { get; set; }
private bool CanReturnDrug = true;
public List<OperationVo<MachineRecord>> data { get; set; }
protected override async Task OnInitializedAsync()
{
data = await orderInfoDao.getReturnInfoByOrderNo(order.OrderNo);
// 如果有【stockQuantity】字段说明有药品库存不足
if (data.Any(it => it.ChannelStocks == null))
{
CanReturnDrug = false;
}
base.OnInitializedAsync();
}
protected override async Task OnAfterRenderAsync(bool firstRender)
{
base.OnAfterRender(firstRender);
if (firstRender)
{
await Task.Delay(15);
await grid.ExpandRows(grid.PagedView.Where(it => it.ChannelStocks.Count > 0));
}
}
async Task OpenDrawer()
{
this.status = 1;
// 解析需要打开的抽屉列表
List<ChannelStock> channels = new();
for (int i = 0; i < data.Count; i++)
{
channels = channels.Concat(data[i].ChannelStocks.Where(cs => cs.AddQuantity > 0)).ToList();
}
List<int> drawerNos = channels.GroupBy(it => it.DrawerNo).Select(it => it.Key).ToList();
// 根据抽屉类型来决定打开前是否需要查询数量
int index = 0;
var BeforeQuantity = new int[9];
var AfterQuantity = new int[9];
await new PromiseUtil<int>().taskAsyncLoop(500, 0, async (options, next, stop) =>
{
var drawerNo = drawerNos[index];
try
{
if (this.status == 0)
{
stop();
}
// 开启抽屉
else if (this.status == 1)
{
if (options._data == 0)
{
BeforeQuantity = new int[9];
AfterQuantity = new int[9];
// 判断是否为单支抽屉
if (setting.Value.single.Contains(drawerNo))
{
byte[] quantity = await PortUtil.CheckQuantityByDrawer(drawerNo);
BeforeQuantity = quantity.Select(it => Convert.ToInt32(it)).ToArray().Skip(3).Take(9).ToArray();
logger.Info($"单支抽屉【{drawerNo}】,开抽屉前检测数量【{string.Join(",", BeforeQuantity)}】");
await PortUtil.NoLightOnByCol(drawerNo, data.Select(ot => ot.ChannelStocks.Where(cs => cs.DrawerNo == drawerNo).Select(cs => cs.ColNo)).Cast<int>().ToArray());
}
var b = await PortUtil.OpenDrawerStatus(drawerNo);
if (b)
{
PortUtil.SpeakAsync($"{drawerNo}号抽屉已经打开,请,放置退回药品");
options._data = 1;
next();
}
else
{
_message.Notify(
new NotificationMessage { Severity = NotificationSeverity.Error, Summary = "提示", Detail = $"抽屉【{drawerNo}】打开失败,请检测硬件", Duration = 4000 }
);
logger.Info($"处方退药抽屉【{drawerNo}】打开失败");
PortUtil.AllLightOff();
RestData();
stop();
}
}
// 检测状态
else if (options._data == 1)
{
// 查询抽屉是否为关闭状态
var b = await PortUtil.CheckDrawerStatus2(drawerNo);
// 关闭则改变状态并终止循环
if (b)
{
options._data = 0;
if (setting.Value.single.Contains(drawerNo))
{
PortUtil.AllLightOff();
}
if (index == drawerNos.Count - 1)
{
PortUtil.SpeakAsync($"退药完成,请,点击完成按钮进行确认");
this.status = 2;
stop();
}
else
{
index += 1;
next();
}
}
else
{
if (setting.Value.single.Contains(drawerNo))
{
byte[] quantity = await PortUtil.CheckQuantityByDrawer(drawerNo);
AfterQuantity = quantity.Select(it => Convert.ToInt32(it)).ToArray().Skip(3).Take(9).ToArray();
logger.Info($"单支抽屉【{drawerNo}】,抽屉未关检测数量【{string.Join(",", AfterQuantity)}】");
data.ForEach(cl =>
{
cl.ChannelStocks.Where(cs => cs.DrawerNo == drawerNo).ToList().ForEach(cs =>
{
logger.Info($"单支抽屉【{drawerNo}】,应退药品数量【{cs.AddQuantity}】,现实退数量【{AfterQuantity[cs.ColNo - 1] - BeforeQuantity[cs.ColNo - 1]}】");
});
});
}
next(); // continue iteration
}
}
}
}
catch (Exception e)
{
RestData();
logger.Info($"处方退药发生错误,{e.Message}");
_message.Notify(
new NotificationMessage { Severity = NotificationSeverity.Error, Summary = "提示", Detail = $"发生错误,{e.Message}", Duration = 4000 }
);
if (setting.Value.single.Contains(drawerNo))
{
PortUtil.AllLightOff();
}
stop();
}
});
}
void RestData()
{
this.status = 0;
}
async Task TakeFinish()
{
// 保存账册、操作记录
var b = await orderInfoDao.OrderReturnFinish(data, order.OrderNo);
if (!b)
{
_message.Notify(new NotificationMessage { Severity = NotificationSeverity.Error, Summary = "提示", Detail = $"数据保存失败", Duration = 4000 });
logger.Error($"处方取药保存数据库失败,数据{JsonConvert.SerializeObject(data)}");
// 关闭弹窗
dialogService.Close(false);
}
else
{
// 关闭弹窗
dialogService.Close(true);
}
//重置状态
this.RestData();
}
void RowRender(RowRenderEventArgs<OperationVo<MachineRecord>> args)
{
args.Expandable = args.Data.ChannelStocks != null && args.Data.ChannelStocks.Count > 0;
}
void OnCellClick(DataGridCellMouseEventArgs<ChannelStock> args, RadzenDataGrid<ChannelStock> Grid)
{
Grid.EditRow(args.Data);
}
}

View File

@ -0,0 +1,118 @@
@page "/return/order"
<div class="container-fluid">
<div class="row">
<div class="col-12 mb-4">
<form onsubmit="@(() => grid.Reload())">
<RadzenFieldset Text="查询">
<RadzenStack Orientation="Orientation.Horizontal" Gap="1rem">
<RadzenRow AlignItems="AlignItems.Center">
<RadzenColumn Size="4">
<RadzenLabel Text="处方号" Component="OrderNo" />
</RadzenColumn>
<RadzenColumn Size="8">
<RadzenTextBox @bind-Value="OrderNo" Style="width: 100%;" Name="OrderNo"></RadzenTextBox>
</RadzenColumn>
</RadzenRow>
<RadzenRow AlignItems="AlignItems.Center">
<RadzenColumn Size="4">
<RadzenLabel Text="处方时间" Component="OrderDate" />
</RadzenColumn>
<RadzenColumn Size="8">
<RadzenDatePicker DateFormat="yyyy-MM-dd" CurrentDateChanged="@OnCurrentDateChanged" @bind-Value="OrderDate" Style="width: 100%;" Name="OrderDate" />
</RadzenColumn>
</RadzenRow>
<RadzenRow AlignItems="AlignItems.Center">
<RadzenColumn Size="12">
<RadzenButton Size="ButtonSize.Medium" ButtonType="ButtonType.Submit" IsBusy="isLoading" Icon="search" Text="查询" />
<RadzenButton Size="ButtonSize.Medium" Click="reloadGrid" IsBusy="isLoading" Icon="refresh" Text="重置" ButtonStyle="ButtonStyle.Warning" />
</RadzenColumn>
</RadzenRow>
</RadzenStack>
</RadzenFieldset>
</form>
</div>
<div class="col-12 mb-4">
<RadzenDataGrid @ref="grid"
LoadData="@LoadData"
RowSelect="@((OrderInfo oi) => { OrderSelected(oi); })"
IsLoading="@isLoading"
Count="@count"
EmptyText="无数据"
Data="@_forecasts"
AllowColumnResize="true" AllowAlternatingRows="false"
SelectionMode="DataGridSelectionMode.Single"
AllowPaging="true" PageSize="10" PagerHorizontalAlign="HorizontalAlign.Left" ShowPagingSummary="true" PagingSummaryFormat="{0}/{1} 共{2}条数据">
<Columns>
<RadzenDataGridColumn Frozen="true" Title="处方号" Property="OrderNo"></RadzenDataGridColumn>
<RadzenDataGridColumn Width="170px" Title="开方时间" Property="OrderDate"></RadzenDataGridColumn>
<RadzenDataGridColumn Title="医生" Property="DoctorName"></RadzenDataGridColumn>
<RadzenDataGridColumn Title="姓名" Property="PatientName"></RadzenDataGridColumn>
<RadzenDataGridColumn Title="性别" Property="Sex"></RadzenDataGridColumn>
<RadzenDataGridColumn Title="年龄" Property="Age"></RadzenDataGridColumn>
<RadzenDataGridColumn Title="科室" Property="DeptName"></RadzenDataGridColumn>
<RadzenDataGridColumn Title="诊断" Property="Disease"></RadzenDataGridColumn>
</Columns>
</RadzenDataGrid>
</div>
</div>
</div>
@code {
@inject IOrderInfoDao orderInfoDao;
@inject DialogService dialogService;
RadzenDataGrid<OrderInfo> grid;
bool isLoading;
int count;
private IEnumerable<OrderInfo>? _forecasts;
string OrderNo;
DateTime OrderDate;
void OnCurrentDateChanged(DateTime args)
{
OrderDate = new DateTime(args.Year, args.Month, args.Day);
}
async Task LoadData(LoadDataArgs args)
{
isLoading = true;
var result = await orderInfoDao.GetAllCanReturnOrderInfo(OrderNo, OrderDate, args.Top, args.Skip);
// Update the Data property
_forecasts = result.Desserts;
// Update the count
count = result.TotalDesserts;
isLoading = false;
}
async Task reloadGrid()
{
OrderNo = "";
OrderDate = DateTime.MinValue;
await grid.Reload();
}
async Task OrderSelected(OrderInfo oi)
{
var b = await dialogService.OpenAsync<OrderDetailReturnDialog>(
$"退药处方详情",
new Dictionary<string, object>() { { "order", oi } },
new DialogOptions() { Width = "85vw", Resizable = true, Draggable = true, ShowClose = false }
);
if(b)
{
await reloadGrid();
}
}
}

View File

@ -0,0 +1,118 @@
@page "/take/order"
<div class="container-fluid">
<div class="row">
<div class="col-12 mb-4">
<form onsubmit="@(() => grid.Reload())">
<RadzenFieldset Text="查询">
<RadzenStack Orientation="Orientation.Horizontal" Gap="1rem">
<RadzenRow AlignItems="AlignItems.Center">
<RadzenColumn Size="4">
<RadzenLabel Text="处方号" Component="OrderNo" />
</RadzenColumn>
<RadzenColumn Size="8">
<RadzenTextBox @bind-Value="OrderNo" Style="width: 100%;" Name="OrderNo"></RadzenTextBox>
</RadzenColumn>
</RadzenRow>
<RadzenRow AlignItems="AlignItems.Center">
<RadzenColumn Size="4">
<RadzenLabel Text="处方时间" Component="OrderDate" />
</RadzenColumn>
<RadzenColumn Size="8">
<RadzenDatePicker DateFormat="yyyy-MM-dd" CurrentDateChanged="@OnCurrentDateChanged" @bind-Value="OrderDate" Style="width: 100%;" Name="OrderDate" />
</RadzenColumn>
</RadzenRow>
<RadzenRow AlignItems="AlignItems.Center">
<RadzenColumn Size="12">
<RadzenButton Size="ButtonSize.Medium" ButtonType="ButtonType.Submit" IsBusy="isLoading" Icon="search" Text="查询" />
<RadzenButton Size="ButtonSize.Medium" Click="reloadGrid" IsBusy="isLoading" Icon="refresh" Text="重置" ButtonStyle="ButtonStyle.Warning" />
</RadzenColumn>
</RadzenRow>
</RadzenStack>
</RadzenFieldset>
</form>
</div>
<div class="col-12 mb-4">
<RadzenDataGrid @ref="grid"
LoadData="@LoadData"
RowSelect="@((OrderInfo oi) => { OrderSelected(oi); })"
IsLoading="@isLoading"
Count="@count"
EmptyText="无数据"
Data="@_forecasts"
AllowColumnResize="true" AllowAlternatingRows="false"
SelectionMode="DataGridSelectionMode.Single"
AllowPaging="true" PageSize="10" PagerHorizontalAlign="HorizontalAlign.Left" ShowPagingSummary="true" PagingSummaryFormat="{0}/{1} 共{2}条数据">
<Columns>
<RadzenDataGridColumn Frozen="true" Title="处方号" Property="OrderNo"></RadzenDataGridColumn>
<RadzenDataGridColumn Width="170px" Title="开方时间" Property="OrderDate"></RadzenDataGridColumn>
<RadzenDataGridColumn Title="医生" Property="DoctorName"></RadzenDataGridColumn>
<RadzenDataGridColumn Title="姓名" Property="PatientName"></RadzenDataGridColumn>
<RadzenDataGridColumn Title="性别" Property="Sex"></RadzenDataGridColumn>
<RadzenDataGridColumn Title="年龄" Property="Age"></RadzenDataGridColumn>
<RadzenDataGridColumn Title="科室" Property="DeptName"></RadzenDataGridColumn>
<RadzenDataGridColumn Title="诊断" Property="Disease"></RadzenDataGridColumn>
</Columns>
</RadzenDataGrid>
</div>
</div>
</div>
@code {
@inject IOrderInfoDao orderInfoDao;
@inject DialogService dialogService;
RadzenDataGrid<OrderInfo> grid;
bool isLoading;
int count;
private IEnumerable<OrderInfo>? _forecasts;
string OrderNo;
DateTime OrderDate;
void OnCurrentDateChanged(DateTime args)
{
OrderDate = new DateTime(args.Year, args.Month, args.Day);
}
async Task LoadData(LoadDataArgs args)
{
isLoading = true;
var result = await orderInfoDao.GetAllOrderInfo(OrderNo, OrderDate, args.Top, args.Skip);
// Update the Data property
_forecasts = result.Desserts;
// Update the count
count = result.TotalDesserts;
isLoading = false;
}
async Task reloadGrid()
{
OrderNo = "";
OrderDate = DateTime.MinValue;
await grid.Reload();
}
async Task OrderSelected(OrderInfo oi)
{
var b = await dialogService.OpenAsync<OrderDetailDialog>(
$"处方详情",
new Dictionary<string, object>() { { "order", oi } },
new DialogOptions() { Width = "85vw", Resizable = true, Draggable = true, ShowClose = false }
);
if(b)
{
await reloadGrid();
}
}
}

View File

@ -0,0 +1,144 @@
@page "/return/byRecord"
<style>
.rz-custom-header {
width: 100%;
}
</style>
<div class="container-fluid">
<div class="row">
<div class="col-12 mb-4">
<form onsubmit="@(() => grid.Reload())">
<RadzenFieldset Text="查询">
<RadzenStack Orientation="Orientation.Horizontal" Gap="1rem">
<RadzenRow AlignItems="AlignItems.Center">
<RadzenColumn Size="4">
<RadzenLabel Text="开始时间" Component="Start" />
</RadzenColumn>
<RadzenColumn Size="8">
<RadzenDatePicker DateFormat="yyyy-MM-dd HH:mm:ss" ShowTime="true" @bind-Value="start" Style="width: 100%;" Name="Start" />
</RadzenColumn>
</RadzenRow>
<RadzenRow AlignItems="AlignItems.Center">
<RadzenColumn Size="4">
<RadzenLabel Text="结束时间" Component="End" />
</RadzenColumn>
<RadzenColumn Size="8">
<RadzenDatePicker DateFormat="yyyy-MM-dd HH:mm:ss" ShowTime="true" @bind-Value="end" Style="width: 100%;" Name="End" />
</RadzenColumn>
</RadzenRow>
<RadzenRow AlignItems="AlignItems.Center">
<RadzenColumn Size="12">
<RadzenButton Size="ButtonSize.Large" ButtonType="ButtonType.Submit" IsBusy="isLoading" Icon="search" Text="查询" />
<RadzenButton Size="ButtonSize.Large" Click="reloadGrid" IsBusy="isLoading" Icon="refresh" Text="重置" ButtonStyle="ButtonStyle.Warning" />
</RadzenColumn>
</RadzenRow>
</RadzenStack>
</RadzenFieldset>
</form>
</div>
<div class="col-12 mb-4">
<RadzenDataGrid @ref="grid"
LoadData="@LoadData"
IsLoading="@isLoading"
Count="@count"
EmptyText="无数据"
Data="@_forecasts"
AllowColumnResize="true" AllowAlternatingRows="false"
AllowRowSelectOnRowClick="true"
CellClick="@((DataGridCellMouseEventArgs<MachineRecord> args) => OnCellClick(args))"
AllowPaging="true" PageSize="8" PagerHorizontalAlign="HorizontalAlign.Left" ShowPagingSummary="true" PagingSummaryFormat="{0}/{1} 共{2}条数据">
<HeaderTemplate>
<RadzenRow JustifyContent="JustifyContent.End">
<RadzenButton ButtonStyle="ButtonStyle.Warning" Disabled="_forecasts == null || !_forecasts.Any(mr => mr.CurrentReturnQuantity > 0)" Variant="Variant.Outlined" Shade="Shade.Light" Text="归还" Click="@OpenReturnDialog" />
</RadzenRow>
</HeaderTemplate>
<Columns>
<RadzenDataGridColumn Frozen="true" Title="操作人" Property="OperatorUser.NickName"></RadzenDataGridColumn>
<RadzenDataGridColumn Width="170px" Title="操作时间" Property="OperationTime"></RadzenDataGridColumn>
<RadzenDataGridColumn Width="200px" Title="药品名称" Property="Drug.DrugName">
<Template Context="mr">
<RadzenText TextStyle="TextStyle.Subtitle2" class="mb-0">@mr.Drug?.DrugName</RadzenText>
<RadzenText TextStyle="TextStyle.Caption">@mr.Drug?.DrugSpec</RadzenText>
</Template>
</RadzenDataGridColumn>
<RadzenDataGridColumn Title="批次" Property="ManuNo">
<Template Context="mr">
<RadzenText TextStyle="TextStyle.Subtitle2" class="mb-0">@mr.ManuNo</RadzenText>
<RadzenText TextStyle="TextStyle.Caption"> @mr.EffDate?.ToString("yyyy-MM-dd")</RadzenText>
</Template>
</RadzenDataGridColumn>
<RadzenDataGridColumn Title="借出数量" Property="Quantity"></RadzenDataGridColumn>
<RadzenDataGridColumn Title="已还药品" Property="ReturnQuantity1"></RadzenDataGridColumn>
<RadzenDataGridColumn Title="已还空瓶" Property="ReturnQuantity2"></RadzenDataGridColumn>
<RadzenDataGridColumn Title="本次归还" Property="CurrentReturnQuantity">
<EditTemplate Context="mr">
<RadzenNumeric Min="0" Style="display: block" Max="@(mr.Quantity - mr.ReturnQuantity1 - mr.ReturnQuantity2)" Name="Quantity" @bind-Value=@mr.CurrentReturnQuantity />
</EditTemplate>
</RadzenDataGridColumn>
</Columns>
</RadzenDataGrid>
</div>
</div>
</div>
@code {
@inject IMachineRecordDao machineRecordDao;
@inject DialogService dialogService;
RadzenDataGrid<MachineRecord> grid;
bool isLoading;
int count;
private List<MachineRecord>? _forecasts;
DateTime start;
DateTime end;
async Task LoadData(LoadDataArgs args)
{
isLoading = true;
var result = await machineRecordDao.GetCanReturnRecords(start, end, 0, "", args.Top, args.Skip);
// Update the Data property
_forecasts = result.Desserts;
// Update the count
count = result.TotalDesserts;
isLoading = false;
}
async Task reloadGrid()
{
start = DateTime.MinValue;
end = DateTime.MinValue;
await grid.Reload();
}
async Task OpenReturnDialog()
{
var list = _forecasts.Where(mr => mr.CurrentReturnQuantity > 0).ToList();
var b = await dialogService.OpenAsync<RecordReturnDrugDialog>(
$"记录还药",
new Dictionary<string, object>() { { "records", list } },
new DialogOptions() { Width = "85vw", Resizable = true, Draggable = true, ShowClose = false }
);
if (b)
{
await reloadGrid();
}
}
void OnCellClick(DataGridCellMouseEventArgs<MachineRecord> args)
{
grid.EditRow(args.Data);
}
}

View File

@ -0,0 +1,309 @@
@page "/return/drug/{records}"
@using MasaBlazorApp3.Pojo.Config;
@using MasaBlazorApp3.Pojo.Vo;
@using MasaBlazorApp3.Util;
@using Microsoft.Extensions.Options;
@using Newtonsoft.Json;
@using log4net;
<RadzenStack Gap="1rem" Orientation="Orientation.Vertical" JustifyContent="JustifyContent.SpaceBetween" Style="height: 100%;">
<RadzenStack>
<RadzenDataGrid @ref="grid" Data="@data" ExpandMode="DataGridExpandMode.Multiple"
RowRender="@RowRender"
EmptyText="无数据" AllowAlternatingRows="false">
<Template Context="di">
<RadzenDataGrid Data="@di.ChannelStocks" EmptyText="无数据" @ref="di.Grid"
CellClick="@((DataGridCellMouseEventArgs<ChannelStock> args) => OnCellClick(args, di.Grid))">
<Columns>
<RadzenDataGridColumn Title="库位" Property="DrawerNo">
<Template Context="s">
@s.DrawerNo - @s.ColNo
</Template>
</RadzenDataGridColumn>
<RadzenDataGridColumn Title="库存" Property="Quantity"></RadzenDataGridColumn>
@* <RadzenDataGridColumn Title="批次" Property="ManuNo"></RadzenDataGridColumn>
<RadzenDataGridColumn Title="效期" Property="EffDate"></RadzenDataGridColumn> *@
<RadzenDataGridColumn Title="入库数量" Property="ReturnQuantity">
<EditTemplate Context="cs">
<RadzenNumeric Disabled="status > 0" Style="display: block" Min="0" Max="@di.Quantity" Name="Quantity" @bind-Value=@cs.ReturnQuantity />
<RadzenNumericRangeValidator Style="position: absolute;z-index: 9999;" Min="0" Max="@di.Quantity" Text="请填写正确的添加数量" Component="Quantity" />
<RadzenCustomValidator Validator="@(() => di.ChannelStocks.Sum(cs2 => cs2.ReturnQuantity) == di.Quantity)" Component="Quantity" Text="入库总量应等于请领数量" Style="position: absolute;z-index: 9999;" />
</EditTemplate>
</RadzenDataGridColumn>
</Columns>
</RadzenDataGrid>
</Template>
<Columns>
<RadzenDataGridColumn Property="Drug.DrugName" Title="药品" />
<RadzenDataGridColumn Property="Drug.DrugSpec" Title="规格" />
<RadzenDataGridColumn Property="ManuNo" Title="批次">
<Template Context="ov">
@ov.data.First().ManuNo
</Template>
</RadzenDataGridColumn>
<RadzenDataGridColumn Property="EffDate" Title="效期">
<Template Context="ov">
@ov.data.First().EffDate
</Template>
</RadzenDataGridColumn>
<RadzenDataGridColumn Property="Quantity" Title="请领数量" />
<RadzenDataGridColumn Property="StockQuantity" Title="总库存" />
</Columns>
</RadzenDataGrid>
</RadzenStack>
<RadzenStack Orientation="Orientation.Horizontal" JustifyContent="JustifyContent.Center" Gap="0.5rem">
@if (status < 2)
{
<RadzenButton Click="@StartAdd" Disabled="!CanTakeDrug" IsBusy="status > 0" BusyText="加药中。。。" ButtonStyle="ButtonStyle.Warning" Variant="Variant.Flat" Text="加药" Style="width: 120px" />
}
@if (status == 2)
{
<RadzenButton Click="@AddFinish" ButtonStyle="ButtonStyle.Success" Variant="Variant.Flat" Text="完成" Style="width: 120px" />
}
@if (status < 2)
{
<RadzenButton Click="@((args) => CancelOpera())" Variant="Variant.Flat" Text="取消" Style="width: 120px" />
}
</RadzenStack>
</RadzenStack>
@code {
@inject Radzen.DialogService dialogService;
@inject IMachineRecordDao machineRecordDao;
@inject IOptions<DrawerConfig> setting;
@inject NotificationService _message
@inject PortUtil PortUtil;
RadzenDataGrid<OperationVo<List<MachineRecord>>> grid;
private readonly ILog logger = LogManager.GetLogger(typeof(InvoiceAddDialog));
[Parameter] public List<MachineRecord> records { get; set; }
private bool CanTakeDrug = true;
int status = 0;
public List<OperationVo<List<MachineRecord>>> data { get; set; }
async Task StartAdd()
{
if(data.Any(it => it.Quantity != it.ChannelStocks.Sum(cs => cs.ReturnQuantity)))
{
_message.Notify(
new NotificationMessage { Severity = NotificationSeverity.Error, Summary = "提示", Detail = $"请填写正确的入库数量!", Duration = 4000 }
);
} else
{
await OpenDrawer();
}
}
async Task CancelOpera()
{
status = 0;
dialogService.Close(false);
}
async Task OpenDrawer()
{
this.status = 1;
// 解析需要打开的抽屉列表
List<ChannelStock> channels = new();
for (int i = 0; i < data.Count; i++)
{
channels = channels.Concat(data[i].ChannelStocks.Where(cs => cs.ReturnQuantity > 0)).ToList();
}
if (channels.Count == 0)
{
_message.Notify(
new NotificationMessage { Severity = NotificationSeverity.Error, Summary = "提示", Detail = $"请填写正确的入库数量!", Duration = 4000 }
);
return;
}
List<int> drawerNos = channels.GroupBy(it => it.DrawerNo).Select(it => it.Key).ToList();
// 根据抽屉类型来决定打开前是否需要查询数量
int index = 0;
var BeforeQuantity = new int[9];
var AfterQuantity = new int[9];
await new PromiseUtil<int>().taskAsyncLoop(500, 0, async (options, next, stop) =>
{
var drawerNo = drawerNos[index];
try
{
if (this.status == 0)
{
stop();
}
// 开启抽屉
else if (this.status == 1)
{
if (options._data == 0)
{
BeforeQuantity = new int[9];
AfterQuantity = new int[9];
// 判断是否为单支抽屉
if (setting.Value.single.Contains(drawerNo))
{
byte[] quantity = await PortUtil.CheckQuantityByDrawer(drawerNo);
BeforeQuantity = quantity.Select(it => Convert.ToInt32(it)).ToArray().Skip(3).Take(9).ToArray();
logger.Info($"单支抽屉【{drawerNo}】,开抽屉前检测数量【{string.Join(",", BeforeQuantity)}】");
await PortUtil.NoLightOnByCol(drawerNo, data.Select(ot => ot.ChannelStocks.Where(cs => cs.DrawerNo == drawerNo).Select(cs => cs.ColNo)).Cast<int>().ToArray());
}
var b = await PortUtil.OpenDrawerStatus(drawerNo);
if (b)
{
PortUtil.SpeakAsync($"{drawerNo}号抽屉已经打开,请,加药");
options._data = 1;
next();
}
else
{
_message.Notify(
new NotificationMessage { Severity = NotificationSeverity.Error, Summary = "提示", Detail = $"抽屉【{drawerNo}】打开失败,请检测硬件", Duration = 4000 }
);
logger.Info($"抽屉打开失败");
PortUtil.AllLightOff();
RestData();
stop();
}
}
// 检测状态
else if (options._data == 1)
{
// 查询抽屉是否为关闭状态
var b = await PortUtil.CheckDrawerStatus2(drawerNo);
// 关闭则改变状态并终止循环
if (b)
{
options._data = 0;
if (setting.Value.single.Contains(drawerNo))
{
PortUtil.AllLightOff();
}
if (index == drawerNos.Count - 1)
{
PortUtil.SpeakAsync($"加药完成,请,点击完成按钮进行确认");
this.status = 2;
stop();
}
else
{
index += 1;
next();
}
}
else
{
if (setting.Value.single.Contains(drawerNo))
{
byte[] quantity = await PortUtil.CheckQuantityByDrawer(drawerNo);
AfterQuantity = quantity.Select(it => Convert.ToInt32(it)).ToArray().Skip(3).Take(9).ToArray();
logger.Info($"单支抽屉【{drawerNo}】,抽屉未关检测数量【{string.Join(",", AfterQuantity)}】");
data.ForEach(cl =>
{
cl.ChannelStocks.Where(cs => cs.DrawerNo == drawerNo).ToList().ForEach(cs =>
{
logger.Info($"单支抽屉【{drawerNo}】,应加药品数量【{cs.AddQuantity}】,现实取数量【{AfterQuantity[cs.ColNo - 1] - BeforeQuantity[cs.ColNo - 1]}】");
});
});
}
next(); // continue iteration
}
}
}
}
catch (Exception e)
{
RestData();
logger.Info($"调拨加药发生错误,{e.Message}");
_message.Notify(
new NotificationMessage { Severity = NotificationSeverity.Error, Summary = "提示", Detail = $"发生错误,{e.Message}", Duration = 4000 }
);
if (setting.Value.single.Contains(drawerNo))
{
PortUtil.AllLightOff();
}
stop();
}
});
}
void RestData()
{
this.status = 0;
}
async Task AddFinish()
{
// 保存账册、操作记录
var b = await machineRecordDao.ReturnDrugFinish(data);
if (!b)
{
_message.Notify(new NotificationMessage { Severity = NotificationSeverity.Error, Summary = "提示", Detail = $"数据保存失败", Duration = 4000 });
logger.Error($"抽屉加药保存数据库失败,数据{JsonConvert.SerializeObject(data)}");
// 关闭弹窗
dialogService.Close(false);
}
else
{
// 关闭弹窗
dialogService.Close(true);
}
//重置状态
this.RestData();
}
protected override async Task OnInitializedAsync()
{
data = await machineRecordDao.getReturnDrugInfoByRecords(records);
// 如果有库位列表未空则说明不能取药,需要增加库位
if (data.Any(it => it.ChannelStocks.Count == 0))
{
CanTakeDrug = false;
}
base.OnInitializedAsync();
}
protected override async Task OnAfterRenderAsync(bool firstRender)
{
base.OnAfterRender(firstRender);
if (firstRender)
{
await Task.Delay(15);
await grid.ExpandRows(grid.PagedView.Where(it => it.ChannelStocks.Count > 0));
}
}
void RowRender(RowRenderEventArgs<OperationVo<List<MachineRecord>>> args)
{
args.Expandable = args.Data.ChannelStocks != null && args.Data.ChannelStocks.Count > 0;
}
void OnCellClick(DataGridCellMouseEventArgs<ChannelStock> args, RadzenDataGrid<ChannelStock> Grid)
{
Grid.EditRow(args.Data);
}
}

View File

@ -0,0 +1,129 @@
@page "/return/empty"
<style>
.rz-custom-header {
width: 100%;
}
</style>
<div class="container-fluid">
<div class="row">
@* <div class="col-12 mb-4">
<form onsubmit="@(() => grid.Reload())">
<RadzenFieldset Text="查询">
<RadzenStack Orientation="Orientation.Horizontal" Gap="1rem">
<RadzenRow AlignItems="AlignItems.Center">
<RadzenColumn Size="4">
<RadzenLabel Text="开始时间" Component="Start" />
</RadzenColumn>
<RadzenColumn Size="8">
<RadzenDatePicker DateFormat="yyyy-MM-dd HH:mm:ss" ShowTime="true" @bind-Value="start" Style="width: 100%;" Name="Start" />
</RadzenColumn>
</RadzenRow>
<RadzenRow AlignItems="AlignItems.Center">
<RadzenColumn Size="4">
<RadzenLabel Text="结束时间" Component="End" />
</RadzenColumn>
<RadzenColumn Size="8">
<RadzenDatePicker DateFormat="yyyy-MM-dd HH:mm:ss" ShowTime="true" @bind-Value="end" Style="width: 100%;" Name="End" />
</RadzenColumn>
</RadzenRow>
<RadzenRow AlignItems="AlignItems.Center">
<RadzenColumn Size="12">
<RadzenButton Size="ButtonSize.Large" ButtonType="ButtonType.Submit" IsBusy="isLoading" Icon="search" Text="查询" />
<RadzenButton Size="ButtonSize.Large" Click="reloadGrid" IsBusy="isLoading" Icon="refresh" Text="重置" ButtonStyle="ButtonStyle.Warning" />
</RadzenColumn>
</RadzenRow>
</RadzenStack>
</RadzenFieldset>
</form>
</div> *@
<div class="col-12 mb-4">
<RadzenDataGrid @ref="grid"
LoadData="@LoadData"
IsLoading="@isLoading"
EmptyText="无数据"
Data="@_forecasts"
AllowColumnResize="true" AllowAlternatingRows="false"
AllowRowSelectOnRowClick="true"
CellClick="@((DataGridCellMouseEventArgs<ChannelStock> args) => OnCellClick(args))" >
@* <HeaderTemplate>
<RadzenRow JustifyContent="JustifyContent.End">
<RadzenButton ButtonStyle="ButtonStyle.Warning" Disabled="_forecasts == null || !_forecasts.Any(mr => mr.DrawerNo > 0)" Variant="Variant.Outlined" Shade="Shade.Light" Text="归还" Click="@OpenReturnDialog" />
</RadzenRow>
</HeaderTemplate> *@
<Columns>
<RadzenDataGridColumn Frozen="true" Title="库位" Property="Location"></RadzenDataGridColumn>
<RadzenDataGridColumn Width="200px" Title="药品名称" Property="Drug.DrugName">
@* <Template Context="mr">
<RadzenText TextStyle="TextStyle.Subtitle2" class="mb-0">@mr.Drug?.DrugName</RadzenText>
<RadzenText TextStyle="TextStyle.Caption">@mr.Drug?.DrugSpec</RadzenText>
</Template> *@
</RadzenDataGridColumn>
<RadzenDataGridColumn Title="厂家" Property="Drug.Manufactory"></RadzenDataGridColumn>
<RadzenDataGridColumn Title="库存" Property="Quantity"></RadzenDataGridColumn>
<RadzenDataGridColumn Title="可归还数量" Property="CanReturnQuantity"></RadzenDataGridColumn>
@*<RadzenDataGridColumn Title="本次归还" Property="CurrentReturnQuantity">
<EditTemplate Context="mr">
<RadzenNumeric Min="0" Style="display: block" Max="@(mr.Quantity - mr.ReturnQuantity1 - mr.ReturnQuantity2)" Name="Quantity" @bind-Value=@mr.CurrentReturnQuantity />
</EditTemplate>
</RadzenDataGridColumn>*@
</Columns>
</RadzenDataGrid>
</div>
</div>
</div>
@code {
@inject IMachineRecordDao machineRecordDao;
@inject DialogService dialogService;
@inject NotificationService _message
RadzenDataGrid<ChannelStock> grid;
bool isLoading;
int count;
private List<ChannelStock>? _forecasts;
// DateTime start;
// DateTime end;
async Task LoadData(LoadDataArgs args)
{
isLoading = true;
_forecasts = await machineRecordDao.GetReturnEmptyWithCanReturnQuantiy();
// _forecasts = await machineRecordDao.GetReturnEmpty();
isLoading = false;
}
async Task reloadGrid()
{
await grid.Reload();
}
async Task OnCellClick(DataGridCellMouseEventArgs<ChannelStock> args)
{
if (string.IsNullOrEmpty(args.Data.DrugId))
{
_message.Notify(
new NotificationMessage { Style = "position: absolute; inset-inline-start: -1000px;", Severity = NotificationSeverity.Error, Summary = "提示", Detail = $"该库位无药品,请先绑药!", Duration = 4000 }
);
return;
}
// grid.EditRow(args.Data);
var list = args.Data;// _forecasts.Where(mr => mr.DrawerNo > 0).ToList();
var b = await dialogService.OpenAsync<RecordReturnEmptyDialog>(
$"归还空瓶",
new Dictionary<string, object>() { { "records", list } },
new DialogOptions() { Width = "85vw", Resizable = true, Draggable = true, ShowClose = false }
);
if (b)
{
await reloadGrid();
}
}
}

View File

@ -0,0 +1,305 @@
@page "/return/empty/{records}"
@using MasaBlazorApp3.Pojo.Config;
@using MasaBlazorApp3.Pojo.Vo;
@using MasaBlazorApp3.Util;
@using Microsoft.Extensions.Options;
@using Newtonsoft.Json;
@using log4net;
<RadzenFieldset Text="药品信息">
<RadzenStack Orientation="Orientation.Horizontal" Gap="10px" JustifyContent="JustifyContent.Center" AlignItems="AlignItems.Center" Wrap="FlexWrap.NoWrap" Style="height: 80px;padding:20px;">
<RadzenStack class="rz-p-1 rz-text-align-center" Style="width:500px">
药品:@drugName
</RadzenStack>
<RadzenStack class="rz-p-1 rz-text-align-center" Style="width:500px">
规格:@drugSpec
</RadzenStack>
<RadzenStack class="rz-p-1 rz-text-align-center" Style="width:500px">
厂家:@drugManufactory
</RadzenStack>
<RadzenStack class="rz-p-1 rz-text-align-center" Style="width:500px">
可还空瓶数:@emptyQuantity
</RadzenStack>
</RadzenStack>
</RadzenFieldset>
<RadzenDataGrid @ref="grid"
LoadData="@LoadData"
IsLoading="@isLoading"
Count="@count"
EmptyText="无数据"
Data="@_returnEmptys"
AllowColumnResize="true" AllowAlternatingRows="false"
AllowRowSelectOnRowClick="true"
CellClick="@((DataGridCellMouseEventArgs<MachineRecord> args) => OnCellClick(args))"
AllowPaging="true" PageSize="8" PagerHorizontalAlign="HorizontalAlign.Left" ShowPagingSummary="true" PagingSummaryFormat="{0}/{1} 共{2}条数据">
<Columns>
<RadzenDataGridColumn Width="60px" Sortable="false" Filterable="false">
<HeaderTemplate>
选择
</HeaderTemplate>
<Template Context="LoadData">
<RadzenCheckBox TriState="false" Value="@LoadData.IsSelected" InputAttributes="@(new Dictionary<string,object>(){ { "aria-label", "Select item" }})"
TValue="bool" />
</Template>
</RadzenDataGridColumn>
<RadzenDataGridColumn Frozen="true" Title="操作人" Property="OperatorUser.NickName"></RadzenDataGridColumn>
<RadzenDataGridColumn Width="170px" Title="操作时间" Property="OperationTime"></RadzenDataGridColumn>
<RadzenDataGridColumn Title="批次" Property="ManuNo">
<Template Context="mr">
<RadzenText TextStyle="TextStyle.Subtitle2" class="mb-0">@mr.ManuNo</RadzenText>
<RadzenText TextStyle="TextStyle.Caption"> @mr.EffDate?.ToString("yyyy-MM-dd")</RadzenText>
</Template>
</RadzenDataGridColumn>
<RadzenDataGridColumn Title="数量" Property="Quantity"></RadzenDataGridColumn>
<RadzenDataGridColumn Title="已还药品" Property="ReturnQuantity1"></RadzenDataGridColumn>
<RadzenDataGridColumn Title="已还空瓶" Property="ReturnQuantity2"></RadzenDataGridColumn>
<RadzenDataGridColumn Title="本次归还" Property="CurrentReturnQuantity">
<EditTemplate Context="mr">
<RadzenNumeric Min="0" Style="display: block" Max="@(mr.Quantity - mr.ReturnQuantity1 - mr.ReturnQuantity2)" Name="Quantity" @bind-Value=@mr.CurrentReturnQuantity />
</EditTemplate>
</RadzenDataGridColumn>
</Columns>
</RadzenDataGrid>
<RadzenStack Orientation="Orientation.Horizontal" JustifyContent="JustifyContent.Center" Gap="0.5rem" Style="margin-top:15px;">
@if (status < 2)
{
<RadzenButton Click="@StartAdd" IsBusy="status > 0" BusyText="还空瓶中。。。" ButtonStyle="ButtonStyle.Warning" Variant="Variant.Flat" Text="归还" Style="width: 120px" />
}
@if (status == 2)
{
<RadzenButton Click="@AddFinish" ButtonStyle="ButtonStyle.Success" Variant="Variant.Flat" Text="完成" Style="width: 120px" />
}
@if (status < 2)
{
<RadzenButton Click="@((args) => CancelOpera())" Variant="Variant.Flat" Text="取消" Style="width: 120px" />
}
</RadzenStack>
@code
{
@inject IMachineRecordDao machineRecordDao;
@inject Radzen.DialogService dialogService;
@inject IMachineRecordDao machineRecordDao;
@inject IOptions<DrawerConfig> setting;
@inject NotificationService _message
@inject PortUtil PortUtil;
[Parameter]
public ChannelStock records { get; set; }
// public PageData<MachineRecord> data { get; set; }
string drugName = string.Empty;
string drugSpec = string.Empty;
string drugManufactory = string.Empty;
int emptyQuantity = 0;
RadzenDataGrid<MachineRecord> grid;
bool isLoading;
int count;
private List<MachineRecord>? _returnEmptys;
async Task LoadData(LoadDataArgs args)
{
isLoading = true;
drugName = records.Drug.DrugName;
drugSpec = records.Drug.DrugSpec;
drugManufactory = records.Drug.Manufactory;
var result = await machineRecordDao.getReturnEmptyInfoByRecords(records);
// Update the Data property
_returnEmptys = result.Desserts;
emptyQuantity = _returnEmptys.Sum(it=>it.Quantity-it.ReturnQuantity1-it.ReturnQuantity2);
// Update the count
count = result.TotalDesserts;
isLoading = false;
}
async Task reloadGrid()
{
await grid.Reload();
}
void OnCellClick(DataGridCellMouseEventArgs<MachineRecord> args)
{
MachineRecord machineRecord = args.Data;
grid.EditRow(machineRecord);
if (machineRecord.CurrentReturnQuantity > 0 && args.Column.ColumnPickerTitle == "本次归还")
{
machineRecord.IsSelected = true;
}
else
{
machineRecord.IsSelected = !machineRecord.IsSelected;
if (machineRecord.IsSelected)
{
machineRecord.CurrentReturnQuantity = machineRecord.Quantity - machineRecord.ReturnQuantity1 - machineRecord.ReturnQuantity2;
}
else
{
machineRecord.CurrentReturnQuantity = 0;
}
}
}
private readonly ILog logger = LogManager.GetLogger(typeof(RecordReturnEmptyDialog));
int status = 0;
async Task StartAdd()
{
if (_returnEmptys.Where(it => it.CurrentReturnQuantity>0).Count()<=0)
{
_message.Notify(
new NotificationMessage { Style = "position: absolute; inset-inline-start: -1000px;", Severity = NotificationSeverity.Error, Summary = "提示", Detail = $"请选择药品!", Duration = 4000 }
);
}
else
{
await OpenDrawer();
}
}
async Task CancelOpera()
{
status = 0;
dialogService.Close(false);
}
async Task OpenDrawer()
{
this.status = 1;
// 解析需要打开的抽屉列表
int drawerNo = records.DrawerNo;
// 根据抽屉类型来决定打开前是否需要查询数量
int index = 0;
var BeforeQuantity = new int[9];
var AfterQuantity = new int[9];
await new PromiseUtil<int>().taskAsyncLoop(500, 0, async (options, next, stop) =>
{
try
{
if (this.status == 0)
{
stop();
}
// 开启抽屉
else if (this.status == 1)
{
if (options._data == 0)
{
BeforeQuantity = new int[9];
AfterQuantity = new int[9];
// 判断是否为单支抽屉
if (setting.Value.single.Contains(drawerNo))
{
byte[] quantity = await PortUtil.CheckQuantityByDrawer(drawerNo);
BeforeQuantity = quantity.Select(it => Convert.ToInt32(it)).ToArray().Skip(3).Take(9).ToArray();
logger.Info($"单支抽屉【{drawerNo}】,开抽屉前检测数量【{string.Join(",", BeforeQuantity)}】");
//await PortUtil.NoLightOnByCol(drawerNo, data.Select(ot => ot.ChannelStocks.Where(cs => cs.DrawerNo == drawerNo).Select(cs => cs.ColNo)).Cast<int>().ToArray());
}
var b = await PortUtil.OpenDrawerStatus(drawerNo);
if (b)
{
PortUtil.SpeakAsync($"{drawerNo}号抽屉已经打开,请放入空瓶");
options._data = 1;
next();
}
else
{
_message.Notify(
new NotificationMessage { Severity = NotificationSeverity.Error, Summary = "提示", Detail = $"抽屉【{drawerNo}】打开失败,请检测硬件", Duration = 4000 }
);
logger.Info($"抽屉打开失败");
PortUtil.AllLightOff();
RestData();
stop();
}
}
// 检测状态
else if (options._data == 1)
{
// 查询抽屉是否为关闭状态
var b = await PortUtil.CheckDrawerStatus2(drawerNo);
// 关闭则改变状态并终止循环
if (b)
{
options._data = 0;
if (setting.Value.single.Contains(drawerNo))
{
PortUtil.AllLightOff();
}
PortUtil.SpeakAsync($"加药完成,请,点击完成按钮进行确认");
this.status = 2;
stop();
}
else
{
if (setting.Value.single.Contains(drawerNo))
{
byte[] quantity = await PortUtil.CheckQuantityByDrawer(drawerNo);
AfterQuantity = quantity.Select(it => Convert.ToInt32(it)).ToArray().Skip(3).Take(9).ToArray();
logger.Info($"单支抽屉【{drawerNo}】,抽屉未关检测数量【{string.Join(",", AfterQuantity)}】");
// data.ForEach(cl =>
// {
// cl.ChannelStocks.Where(cs => cs.DrawerNo == drawerNo).ToList().ForEach(cs =>
// {
// logger.Info($"单支抽屉【{drawerNo}】,应还空瓶数量【{cs.AddQuantity}】,现实还数量【{AfterQuantity[cs.ColNo - 1] - BeforeQuantity[cs.ColNo - 1]}】");
// });
// });
}
next(); // continue iteration
}
}
}
}
catch (Exception e)
{
RestData();
logger.Info($"还空瓶发生错误,{e.Message}");
_message.Notify(
new NotificationMessage { Severity = NotificationSeverity.Error, Summary = "提示", Detail = $"发生错误,{e.Message}", Duration = 4000 }
);
if (setting.Value.single.Contains(drawerNo))
{
PortUtil.AllLightOff();
}
stop();
}
});
}
void RestData()
{
this.status = 0;
}
async Task AddFinish()
{
// 保存账册、操作记录
var b = await machineRecordDao.ReturnEmptyFinish(_returnEmptys.Where(it => it.CurrentReturnQuantity > 0).ToList(), records);
if (!b)
{
_message.Notify(new NotificationMessage { Style = "position: absolute; inset-inline-start: -1000px;", Severity = NotificationSeverity.Error, Summary = "提示", Detail = $"数据保存失败", Duration = 4000 });
logger.Error($"还空瓶保存数据库失败,数据{JsonConvert.SerializeObject(_returnEmptys)}");
// 关闭弹窗
dialogService.Close(false);
}
else
{
// 关闭弹窗
dialogService.Close(true);
_message.Notify(new NotificationMessage { Style = "position: absolute; inset-inline-start: -1000px;", Severity = NotificationSeverity.Success, Summary = "提示", Detail = $"还空瓶操作完成!", Duration = 4000 });
}
//重置状态
this.RestData();
}
}

View File

@ -0,0 +1,101 @@
@page "/return/record2"
<div class="container-fluid">
<div class="row">
<div class="col-12 mb-4">
<form onsubmit="@(() => grid.Reload())">
<RadzenFieldset Text="查询">
<RadzenStack Orientation="Orientation.Horizontal" Gap="1rem">
<RadzenRow AlignItems="AlignItems.Center">
<RadzenColumn Size="4">
<RadzenLabel Text="开始时间" Component="Start" />
</RadzenColumn>
<RadzenColumn Size="8">
<RadzenDatePicker DateFormat="yyyy-MM-dd HH:mm:ss" ShowTime="true" @bind-Value="start" Style="width: 100%;" Name="Start" />
</RadzenColumn>
</RadzenRow>
<RadzenRow AlignItems="AlignItems.Center">
<RadzenColumn Size="4">
<RadzenLabel Text="结束时间" Component="End" />
</RadzenColumn>
<RadzenColumn Size="8">
<RadzenDatePicker DateFormat="yyyy-MM-dd HH:mm:ss" ShowTime="true" @bind-Value="end" Style="width: 100%;" Name="End" />
</RadzenColumn>
</RadzenRow>
<RadzenRow AlignItems="AlignItems.Center">
<RadzenColumn Size="12">
<RadzenButton Size="ButtonSize.Large" ButtonType="ButtonType.Submit" IsBusy="isLoading" Icon="search" Text="查询" />
<RadzenButton Size="ButtonSize.Large" Click="reloadGrid" IsBusy="isLoading" Icon="refresh" Text="重置" ButtonStyle="ButtonStyle.Warning" />
</RadzenColumn>
</RadzenRow>
</RadzenStack>
</RadzenFieldset>
</form>
</div>
<div class="col-12 mb-4">
<RadzenDataGrid @ref="grid"
LoadData="@LoadData"
IsLoading="@isLoading"
Count="@count"
EmptyText="无数据"
Data="@_forecasts"
AllowColumnResize="true" AllowAlternatingRows="false"
SelectionMode="DataGridSelectionMode.Single"
AllowPaging="true" PageSize="10" PagerHorizontalAlign="HorizontalAlign.Left" ShowPagingSummary="true" PagingSummaryFormat="{0}/{1} 共{2}条数据">
<Columns>
<RadzenDataGridColumn Frozen="true" Title="操作人" Property="OperatorUser.NickName"></RadzenDataGridColumn>
<RadzenDataGridColumn Width="170px" Title="操作时间" Property="OperationTime"></RadzenDataGridColumn>
<RadzenDataGridColumn Width="200px" Title="药品名称" Property="Drug.DrugName"></RadzenDataGridColumn>
<RadzenDataGridColumn Title="规格" Property="Drug.DrugSpec"></RadzenDataGridColumn>
<RadzenDataGridColumn Title="数量" Property="Quantity"></RadzenDataGridColumn>
<RadzenDataGridColumn Title="批次" Property="ManuNo"></RadzenDataGridColumn>
<RadzenDataGridColumn Title="效期" Property="EffDate">
<Template Context="mr">
@mr.EffDate?.ToString("yyyy-MM-dd")
</Template>
</RadzenDataGridColumn>
</Columns>
</RadzenDataGrid>
</div>
</div>
</div>
@code {
@inject IMachineRecordDao machineRecordDao;
@inject DialogService dialogService;
RadzenDataGrid<MachineRecord> grid;
bool isLoading;
int count;
private IEnumerable<MachineRecord>? _forecasts;
DateTime start;
DateTime end;
async Task LoadData(LoadDataArgs args)
{
isLoading = true;
var result = await machineRecordDao.GetMachineRecordAsync(start, end, 0, "", 32, args.Top, args.Skip);
// Update the Data property
_forecasts = result.Desserts;
// Update the count
count = result.TotalDesserts;
isLoading = false;
}
async Task reloadGrid()
{
start = DateTime.MinValue;
end = DateTime.MinValue;
await grid.Reload();
}
}

View File

@ -0,0 +1,268 @@
@page "/manage/role"
<div class="container-fluid">
<div class="row">
<div class="col-12 mb-4">
<form onsubmit="@(() => grid.Reload())">
<RadzenFieldset Text="查询">
<RadzenStack Orientation="Orientation.Horizontal" JustifyContent="JustifyContent.SpaceBetween">
<RadzenStack Orientation="Orientation.Horizontal" Gap="1rem">
<RadzenRow AlignItems="AlignItems.Center">
<RadzenColumn Size="4">
<RadzenLabel Text="角色名称" Component="RoleName" />
</RadzenColumn>
<RadzenColumn Size="8">
<RadzenTextBox @bind-Value="RoleName" Style="width: 100%;" Name="RoleName"></RadzenTextBox>
</RadzenColumn>
</RadzenRow>
<RadzenRow AlignItems="AlignItems.Center">
<RadzenColumn Size="12">
<RadzenButton Size="ButtonSize.Medium" ButtonType="ButtonType.Submit" IsBusy="isLoading" Icon="search" Text="查询" />
<RadzenButton Size="ButtonSize.Medium" Click="reloadGrid" IsBusy="isLoading" Icon="refresh" Text="重置" ButtonStyle="ButtonStyle.Warning" />
</RadzenColumn>
</RadzenRow>
</RadzenStack>
<RadzenButton Size="ButtonSize.Medium" ButtonStyle="ButtonStyle.Success" Icon="add_circle_outline" Click="@(() => InsertRow())" Disabled="@(rolesToInsert.Count() > 0)" Text="新增" />
</RadzenStack>
</RadzenFieldset>
</form>
</div>
<div class="col-12 mb-4">
<RadzenDataGrid @ref="grid"
LoadData="@LoadData"
IsLoading="@isLoading"
Count="@count"
EmptyText="无数据"
Data="@roleList"
AllowColumnResize="true" AllowAlternatingRows="false"
RowUpdate="@((Pojo.Role r) => { OnUpdateRow(r); })" RowCreate="@((Pojo.Role r) => { OnCreateRow(r); })"
SelectionMode="DataGridSelectionMode.Single"
AllowPaging="true" PageSize="10" PagerHorizontalAlign="HorizontalAlign.Left" ShowPagingSummary="true" PagingSummaryFormat="{0}/{1} 共{2}条数据">
<Columns>
<RadzenDataGridColumn Width="50px" Title="ID" Property="Id"></RadzenDataGridColumn>
<RadzenDataGridColumn Width="120px" Title="角色名称" Property="RoleName">
<EditTemplate Context="role">
<RadzenTextBox Name="RoleName" @bind-Value="role.RoleName" Style="width:100%; display: block;" />
<RadzenRequiredValidator Style="position: absolute;z-index: 9999;" Text="请填写角色名称" Component="RoleName" Popup="true" />
</EditTemplate>
</RadzenDataGridColumn>
<RadzenDataGridColumn Title="权限" Property="permissions">
<Template Context="role">
@string.Join(", ", allPremissions.Where(g => role.permissionIds?.Contains(g.Id) == true).Select(g => $"{g.PremissionName}"))
</Template>
<EditTemplate Context="role">
<RadzenDropDown @ref=dd @bind-Value=@role.permissionIds TValue="IEnumerable<int>" AllowClear="true" Name="Permissions"
Data=@allPremissions Style="width: 100%; max-width: 400px; display: block;" ItemRender="ItemRender">
<Template Context="p">
<RadzenCheckBox TValue="bool?" TriState=false Value="@IsGroupSelected(role,p)" Change="@(args => SelectGroup(args, role, (Premission)p))" />
<RadzenLabel Style=@($"margin-inline-start: 0.5rem; font-weight: {(p.Parent == null ? "bold" : "normal")}")
Text="@(p.PremissionName)"
onclick="event.target.previousElementSibling.querySelector('.rz-chkbox-box').click()" />
</Template>
<ValueTemplate Context="p">
@string.Join(", ", allPremissions.Where(g => role.permissionIds?.Contains(g.Id) == true).Take(dd.MaxSelectedLabels).Select(g => $"{g.PremissionName}"))
</ValueTemplate>
</RadzenDropDown>
<RadzenRequiredValidator Style="position: absolute;z-index: 9999;" Text="请选择权限" Component="Permissions" Popup="true" />
</EditTemplate>
</RadzenDataGridColumn>
<RadzenDataGridColumn Width="200px" Context="role" Filterable="false" Sortable="false" TextAlign="TextAlign.Right" Frozen="true" FrozenPosition="FrozenColumnPosition.Right">
<Template Context="role">
<RadzenButton Icon="edit" ButtonStyle="ButtonStyle.Light" Variant="Variant.Flat" Size="ButtonSize.Medium" Click="@(args => EditRow(role))" @onclick:stopPropagation="true">
</RadzenButton>
<RadzenButton ButtonStyle="ButtonStyle.Danger" Icon="delete" Variant="Variant.Flat" Shade="Shade.Lighter" Size="ButtonSize.Medium" class="my-1 ms-1" Click="@(args => DeleteRow(role))" @onclick:stopPropagation="true">
</RadzenButton>
</Template>
<EditTemplate Context="role">
<RadzenButton Icon="check" ButtonStyle="ButtonStyle.Success" Variant="Variant.Flat" Size="ButtonSize.Medium" Click="@((args) => SaveRow(role))" aria-label="Save">
</RadzenButton>
<RadzenButton Icon="close" ButtonStyle="ButtonStyle.Light" Variant="Variant.Flat" Size="ButtonSize.Medium" class="my-1 ms-1" Click="@((args) => CancelEdit(role))" aria-label="Cancel">
</RadzenButton>
<RadzenButton ButtonStyle="ButtonStyle.Danger" Icon="delete" Variant="Variant.Flat" Shade="Shade.Lighter" Size="ButtonSize.Medium" class="my-1 ms-1" Click="@(args => DeleteRow(role))" aria-label="Delete">
</RadzenButton>
</EditTemplate>
</RadzenDataGridColumn>
</Columns>
</RadzenDataGrid>
</div>
</div>
</div>
@code {
@inject IRoleDao roleDao;
@inject DialogService dialogService;
RadzenDataGrid<Pojo.Role> grid;
bool isLoading;
int count;
private IEnumerable<Pojo.Role>? roleList;
RadzenDropDown<IEnumerable<int>> dd;
IEnumerable<Premission> allPremissions;
string RoleName;
protected override async Task OnInitializedAsync()
{
await base.OnInitializedAsync();
List<Premission> t = new Premission().getAdminPremission();
IEnumerable<Premission> t2 = Enumerable.Empty<Premission>();
for (var i = 0; i < t.Count; i++)
{
t2 = t2.Concat(new Premission[] { t[i] });
t2 = t2.Concat(t[i].Items);
}
allPremissions = t2;
}
async Task LoadData(LoadDataArgs args)
{
isLoading = true;
var result = await roleDao.GetRolesByName(RoleName, args.Top, args.Skip);
// Update the Data property
roleList = result.Desserts;
// Update the count
count = result.TotalDesserts;
isLoading = false;
}
async Task reloadGrid()
{
RoleName = "";
await grid.Reload();
}
List<Pojo.Role> rolesToInsert = new List<Pojo.Role>();
List<Pojo.Role> rolesToUpdate = new List<Pojo.Role>();
void Reset()
{
rolesToInsert.Clear();
rolesToUpdate.Clear();
}
void Reset(Pojo.Role role)
{
rolesToInsert.Remove(role);
rolesToUpdate.Remove(role);
}
async Task EditRow(Pojo.Role role)
{
Reset();
rolesToUpdate.Add(role);
await grid.EditRow(role);
}
void OnUpdateRow(Pojo.Role role)
{
Reset(role);
// 数据库更新
roleDao.UpdateRole(role);
}
async Task SaveRow(Pojo.Role role)
{
await grid.UpdateRow(role);
}
void CancelEdit(Pojo.Role role)
{
Reset(role);
grid.CancelEditRow(role);
grid.Reload();
}
async Task DeleteRow(Pojo.Role role)
{
Reset(role);
if (roleList.Contains(role))
{
//弹出确认提示框
var b = await dialogService.OpenAsync<ConfirmDialo>(
$"删除确认",
new Dictionary<string, object>() { { "confirmInfo", "删除角色:" + role.RoleName } },
new DialogOptions() { Width = "45vw", Resizable = true, Draggable = true, ShowClose = false });
if (b)
{
// 数据库删除
roleDao.DeleteRole(role.Id);
}
await grid.Reload();
}
else
{
grid.CancelEditRow(role);
await grid.Reload();
}
}
async Task InsertRow()
{
Reset();
var role = new Pojo.Role();
rolesToInsert.Add(role);
await grid.InsertRow(role);
}
void OnCreateRow(Pojo.Role role)
{
// 数据库添加用户
int id = roleDao.InsertRole(role);
rolesToInsert.Remove(role);
grid.Reload();
}
void ItemRender(DropDownItemRenderEventArgs<IEnumerable<int>> args)
{
// Use this code to prevent default item selection.
args.Disabled = true;
args.Attributes.Add("style", $"opacity:1;{(((Premission)args.Item).Parent == null ? "" : "margin-inline-start:1rem")}");
}
bool? IsGroupSelected(Pojo.Role role,Premission p)
{
IEnumerable<int> permissionIds = role.permissionIds;
if (p.Parent == null)
{
return p.Items.Any() && p.Items.All(i => permissionIds?.Contains(i.Id) == true) ? true :
p.Items.Any(i => permissionIds?.Contains(i.Id) == true) ? null : false;
}
return permissionIds?.Contains(p.Id) == true;
}
void SelectGroup(bool? value, Pojo.Role role, Premission p)
{
IEnumerable<int> permissionIds = role.permissionIds;
var newValues = permissionIds ?? Enumerable.Empty<int>();
var items = p.Parent == null ? p.Items.Select(i => i.Id) : new int[] { p.Id };
role.permissionIds = value == true ? newValues.Concat(items) : newValues.Except(items);
}
}

View File

@ -0,0 +1,294 @@
@page "/take/self"
<div class="container-fluid">
<div class="row">
<div class="col-12 mb-4">
<RadzenTemplateForm Data="@orderInfo" Submit="@(((OrderInfo args) => { Submit(args); }))">
<RadzenFieldset Text="手写处方">
<RadzenRow Gap="1rem">
<RadzenColumn Size="4">
<RadzenRow AlignItems="AlignItems.Center">
<RadzenColumn Size="4">
<RadzenLabel Text="处方号" Component="OrderNo" />
</RadzenColumn>
<RadzenColumn Size="8">
<RadzenTextBox @bind-Value="orderInfo.OrderNo" Style="width: 100%;" Name="OrderNo"></RadzenTextBox>
<RadzenRequiredValidator Text="请输入处方号" Component="OrderNo" />
</RadzenColumn>
</RadzenRow>
</RadzenColumn>
<RadzenColumn Size="4">
<RadzenRow AlignItems="AlignItems.Center">
<RadzenColumn Size="4">
<RadzenLabel Text="处方时间" Component="OrderDate" />
</RadzenColumn>
<RadzenColumn Size="8">
<RadzenDatePicker DateFormat="yyyy-MM-dd HH:mm:ss" CurrentDateChanged="@OnCurrentDateChanged"
ShowTime="true" ShowSeconds="true"
@bind-Value="orderInfo.OrderDate" Style="width: 100%;" Name="OrderDate" />
<RadzenRequiredValidator Text="请输入处方时间" Component="OrderDate" />
</RadzenColumn>
</RadzenRow>
</RadzenColumn>
<RadzenColumn Size="4">
<RadzenRow AlignItems="AlignItems.Center">
<RadzenColumn Size="4">
<RadzenLabel Text="患者姓名" Component="PatientName" />
</RadzenColumn>
<RadzenColumn Size="8">
<RadzenTextBox @bind-Value="orderInfo.PatientName" Style="width: 100%;" Name="PatientName"></RadzenTextBox>
<RadzenRequiredValidator Text="请输入患者姓名" Component="PatientName" />
</RadzenColumn>
</RadzenRow>
</RadzenColumn>
<RadzenColumn Size="2">
<RadzenRow AlignItems="AlignItems.Center">
<RadzenColumn Size="4">
<RadzenLabel Text="性别" Component="Sex" />
</RadzenColumn>
<RadzenColumn Size="8">
<RadzenTextBox @bind-Value="orderInfo.Sex" Style="width: 100%;" Name="Sex"></RadzenTextBox>
<RadzenRequiredValidator Text="请输入患者性别" Component="Sex" />
</RadzenColumn>
</RadzenRow>
</RadzenColumn>
<RadzenColumn Size="2">
<RadzenRow AlignItems="AlignItems.Center">
<RadzenColumn Size="4">
<RadzenLabel Text="年龄" Component="Age" />
</RadzenColumn>
<RadzenColumn Size="8">
<RadzenTextBox @bind-Value="orderInfo.Age" Style="width: 100%;" Name="Age"></RadzenTextBox>
<RadzenRequiredValidator Text="请输入患者年龄" Component="Age" />
</RadzenColumn>
</RadzenRow>
</RadzenColumn>
<RadzenColumn Size="4">
<RadzenRow AlignItems="AlignItems.Center">
<RadzenColumn Size="4">
<RadzenLabel Text="处方医生" Component="DoctorName" />
</RadzenColumn>
<RadzenColumn Size="8">
<RadzenTextBox @bind-Value="orderInfo.DoctorName" Style="width: 100%;" Name="DoctorName"></RadzenTextBox>
<RadzenRequiredValidator Text="请输入处方医生" Component="DoctorName" />
</RadzenColumn>
</RadzenRow>
</RadzenColumn>
<RadzenColumn Size="4">
<RadzenRow AlignItems="AlignItems.Center">
<RadzenColumn Size="4">
<RadzenLabel Text="科室" Component="DeptName" />
</RadzenColumn>
<RadzenColumn Size="8">
<RadzenTextBox @bind-Value="orderInfo.DeptName" Style="width: 100%;" Name="DeptName"></RadzenTextBox>
<RadzenRequiredValidator Text="请输入科室" Component="DeptName" />
</RadzenColumn>
</RadzenRow>
</RadzenColumn>
<RadzenColumn Size="6">
<RadzenRow AlignItems="AlignItems.Center">
<RadzenColumn Size="2">
<RadzenLabel Text="诊断" Component="Disease" />
</RadzenColumn>
<RadzenColumn Size="10">
<RadzenTextBox @bind-Value="orderInfo.Disease" Style="width: 100%;" Name="Disease"></RadzenTextBox>
<RadzenRequiredValidator Text="请输入诊断" Component="Disease" />
</RadzenColumn>
</RadzenRow>
</RadzenColumn>
<RadzenColumn Size="6">
<RadzenStack Orientation="Orientation.Horizontal" AlignItems="AlignItems.Center" JustifyContent="JustifyContent.SpaceBetween">
<RadzenButton Size="ButtonSize.Large" ButtonType="ButtonType.Submit" Disabled="@(detailsToInsert.Count() > 0 || detailsToUpdate.Count() > 0)" Text="确定" />
<RadzenButton Size="ButtonSize.Large" Icon="add_circle_outline" ButtonStyle="ButtonStyle.Success" Click="@InsertRow" Disabled="@(detailsToInsert.Count() > 0)" Text="添加" />
</RadzenStack>
</RadzenColumn>
</RadzenRow>
</RadzenFieldset>
</RadzenTemplateForm>
</div>
<div class="col-12 mb-4">
<RadzenDataGrid @ref="grid"
EmptyText="请添加手写处方详情"
Data="@orderDetails"
EditMode="DataGridEditMode.Single"
RowUpdate="@((OrderDetail od) => { OnUpdateRow(od); })" RowCreate="@((OrderDetail od) => { OnCreateRow(od); })"
AllowColumnResize="true" AllowAlternatingRows="false"
SelectionMode="DataGridSelectionMode.Single">
<Columns>
<RadzenDataGridColumn Title="药品名称" Property="Drug.DrugName">
<EditTemplate Context="od">
@* <RadzenDropDown Name="Drug" TValue="DrugInfo" @bind-Value="od.Drug" Data="@drugInfos" Style="width:100%; display: block;" /> *@
<RadzenDropDownDataGrid AllowVirtualization="true" Name="Drug" TValue="DrugInfo" @bind-Value="od.Drug" Data="@drugInfos" Style="width:100%; display: block;" AllowFilteringByAllStringColumns="true">
<Columns>
<RadzenDropDownDataGridColumn Property="DrugId" Title="药品编码" />
<RadzenDropDownDataGridColumn Property="DrugName" Width="120px" Title="名称" />
<RadzenDropDownDataGridColumn Property="DrugSpec" Title="规格" />
<RadzenDropDownDataGridColumn Property="StockQuantity" Title="库存" Frozen="true" FrozenPosition="FrozenColumnPosition.Right" />
</Columns>
</RadzenDropDownDataGrid>
<RadzenCustomValidator Style="position: absolute;z-index: 9999;" Component="Drug" Validator="@(() => !String.IsNullOrEmpty(od.Drug.DrugId ))" Text="请选择药品" />
<RadzenCustomValidator Component="Drug" Validator="@(() => ValidateDrug(od.Drug))" Text="已经选择的药品不能再次选择" />
</EditTemplate>
</RadzenDataGridColumn>
<RadzenDataGridColumn Title="规格" Property="Drug.DrugSpec"></RadzenDataGridColumn>
<RadzenDataGridColumn Title="数量" Property="Quantity">
<EditTemplate Context="od">
<RadzenNumeric Style="width:100%; display: block;" Name="Quantity" @bind-Value=@od.Quantity />
<RadzenNumericRangeValidator Style="position: absolute;z-index: 9999;" Min="1" Max="@od.Drug.StockQuantity" Text="请填写正确的取出数量" Component="Quantity" />
</EditTemplate>
</RadzenDataGridColumn>
<RadzenDataGridColumn Context="detail" Filterable="false" Sortable="false" TextAlign="TextAlign.Right" Frozen="true" FrozenPosition="FrozenColumnPosition.Right">
<Template Context="detail">
<RadzenButton Icon="edit" ButtonStyle="ButtonStyle.Light" Variant="Variant.Flat" Size="ButtonSize.Medium" Click="@(args => EditRow(detail))" @onclick:stopPropagation="true">
</RadzenButton>
<RadzenButton ButtonStyle="ButtonStyle.Danger" Icon="delete" Variant="Variant.Flat" Shade="Shade.Lighter" Size="ButtonSize.Medium" class="my-1 ms-1" Click="@(args => DeleteRow(detail))" @onclick:stopPropagation="true">
</RadzenButton>
</Template>
<EditTemplate Context="detail">
<RadzenButton Icon="check" ButtonStyle="ButtonStyle.Success" Variant="Variant.Flat" Size="ButtonSize.Medium" Click="@((args) => SaveRow(detail))" aria-label="Save">
</RadzenButton>
<RadzenButton Icon="close" ButtonStyle="ButtonStyle.Light" Variant="Variant.Flat" Size="ButtonSize.Medium" class="my-1 ms-1" Click="@((args) => CancelEdit(detail))" aria-label="Cancel">
</RadzenButton>
<RadzenButton ButtonStyle="ButtonStyle.Danger" Icon="delete" Variant="Variant.Flat" Shade="Shade.Lighter" Size="ButtonSize.Medium" class="my-1 ms-1" Click="@(args => DeleteRow(detail))" aria-label="Delete">
</RadzenButton>
</EditTemplate>
</RadzenDataGridColumn>
</Columns>
</RadzenDataGrid>
</div>
</div>
</div>
@code {
@inject IChannelListDao channelListDao;
@inject IDrugInfoDao drugInfoDao;
@inject NotificationService _message
@inject DialogService dialogService;
RadzenDataGrid<OrderDetail> grid;
List<OrderDetail> orderDetails = new();
List<DrugInfo> drugInfos = new();
List<OrderDetail> detailsToInsert = new();
List<OrderDetail> detailsToUpdate = new();
OrderInfo orderInfo = new OrderInfo()
{
OrderDate = DateTime.Now
};
void Reset()
{
detailsToInsert.Clear();
detailsToUpdate.Clear();
}
void Reset(OrderDetail orderDetail)
{
detailsToInsert.Remove(orderDetail);
detailsToUpdate.Remove(orderDetail);
}
async Task InsertRow()
{
Reset();
var orderDetail = new OrderDetail();
detailsToInsert.Add(orderDetail);
await grid.InsertRow(orderDetail);
}
async Task EditRow(OrderDetail orderDetail)
{
Reset();
detailsToUpdate.Add(orderDetail);
await grid.EditRow(orderDetail);
}
async Task SaveRow(OrderDetail orderDetail)
{
await grid.UpdateRow(orderDetail);
}
void CancelEdit(OrderDetail orderDetail)
{
Reset(orderDetail);
grid.CancelEditRow(orderDetail);
grid.Reload();
}
async Task DeleteRow(OrderDetail orderDetail)
{
Reset(orderDetail);
orderDetails.Remove(orderDetail);
grid.CancelEditRow(orderDetail);
await grid.Reload();
}
void OnUpdateRow(OrderDetail orderDetail)
{
Reset(orderDetail);
grid.Reload();
}
void OnCreateRow(OrderDetail orderDetail)
{
// 数据库添加用户
detailsToInsert.Remove(orderDetail);
orderDetails.Add(orderDetail);
grid.Reload();
}
async void Submit(OrderInfo orderInfo)
{
if (orderDetails.Count == 0)
{
_message.Notify(
new NotificationMessage { Severity = NotificationSeverity.Error, Summary = "提示", Detail = $"请添加用药详情", Duration = 3000 }
);
}
else
{
//弹出待取药品所在库位、库存信息
var b = await dialogService.OpenAsync<SelfTakeDialog>(
$"取药详情",
new Dictionary<string, object>() { { "order", orderInfo }, { "orderDetails", orderDetails } },
new DialogOptions() { Width = "85vw", Resizable = true, Draggable = true, ShowClose = false }
);
if (b)
{
_message.Notify(
new NotificationMessage { Severity = NotificationSeverity.Success, Summary = "提示", Detail = $"取药完成", Duration = 3000 }
);
}
}
}
async Task reloadGrid()
{
await grid.Reload();
}
bool ValidateDrug(DrugInfo drugInfo)
{
return !orderDetails.Any(od => od.Drug.DrugId.Equals(drugInfo?.DrugId));
}
protected override async Task OnInitializedAsync()
{
drugInfos = await drugInfoDao.GetAllDrugAndStock();
base.OnInitializedAsync();
}
void OnCurrentDateChanged(DateTime args)
{
orderInfo.OrderDate = new DateTime(args.Year, args.Month, args.Day, args.Hour, args.Minute, args.Second);
}
}

View File

@ -0,0 +1,247 @@
@page "/selfDetail/{order}"
@using MasaBlazorApp3.Pojo.Config
@using MasaBlazorApp3.Pojo.Vo
@using MasaBlazorApp3.Util
@using Microsoft.Extensions.Options
@using Newtonsoft.Json
@using log4net
<RadzenStack Gap="1rem" Orientation="Orientation.Vertical" Style="height: 100%;">
<RadzenStack>
<RadzenStack class="rz-p-4 rz-border-radius-1" Style="border: var(--rz-grid-cell-border)" Orientation="Orientation.Horizontal" Gap="1rem">
<RadzenText TextStyle="TextStyle.Overline" Class="rz-mt-2 rz-my-0" Style="color: var(--rz-text-tertiary-color);">处方号:</RadzenText>
<RadzenText TextStyle="TextStyle.Body1" Class="rz-text-truncate"><b>@(order?.OrderNo)</b></RadzenText>
<RadzenText TextStyle="TextStyle.Overline" Class="rz-mt-2 rz-my-0" Style="color: var(--rz-text-tertiary-color);">患者姓名:</RadzenText>
<RadzenText TextStyle="TextStyle.Body1" Class="rz-text-truncate"><b>@(order?.PatientName)</b></RadzenText>
<RadzenText TextStyle="TextStyle.Overline" Class="rz-mt-2 rz-my-0" Style="color: var(--rz-text-tertiary-color);">性别:</RadzenText>
<RadzenText TextStyle="TextStyle.Body1" Class="rz-text-truncate"><b>@(order?.Sex)</b></RadzenText>
<RadzenText TextStyle="TextStyle.Overline" Class="rz-mt-2 rz-my-0" Style="color: var(--rz-text-tertiary-color);">年龄:</RadzenText>
<RadzenText TextStyle="TextStyle.Body1" Class="rz-text-truncate"><b>@(order?.Age)</b></RadzenText>
</RadzenStack>
@if (CanTakeDrug)
{
<RadzenDataGrid Data="@data" AllowAlternatingRows="false">
<Columns>
<RadzenDataGridColumn Property="ChannelStock" Title="库位">
<Template>
@context.ChannelStock.DrawerNo - @context.ChannelStock.ColNo
</Template>
</RadzenDataGridColumn>
<RadzenDataGridColumn Property="Drug.DrugName" Title="药品" />
<RadzenDataGridColumn Property="Drug.DrugSpec" Title="规格" />
<RadzenDataGridColumn Property="ChannelStock.ManuNo" Title="批次" />
<RadzenDataGridColumn Property="ChannelStock.EffDate" Title="效期" />
<RadzenDataGridColumn Property="Quantity" Title="数量" />
</Columns>
</RadzenDataGrid>
}
else
{
<RadzenDataGrid Data="@data" AllowAlternatingRows="false">
<Columns>
<RadzenDataGridColumn Property="Drug.DrugName" Title="药品" />
<RadzenDataGridColumn Property="Drug.DrugSpec" Title="规格" />
<RadzenDataGridColumn Property="Quantity" Title="取药数量" />
<RadzenDataGridColumn Property="StockQuantity" Title="库存" />
</Columns>
</RadzenDataGrid>
}
</RadzenStack>
<RadzenStack Orientation="Orientation.Horizontal" JustifyContent="JustifyContent.Center" Gap="0.5rem">
@if (status < 2)
{
<RadzenButton Click="@OpenDrawer" Disabled="!CanTakeDrug" IsBusy="status > 0" BusyText="取药中。。。" ButtonStyle="ButtonStyle.Warning" Variant="Variant.Flat" Text="取药" Style="width: 120px" />
}
@if (status == 2)
{
<RadzenButton Click="@TakeFinish" ButtonStyle="ButtonStyle.Success" Variant="Variant.Flat" Text="完成" Style="width: 120px" />
}
@if (status <= 2)
{
<RadzenButton Click="@((args) => dialogService.Close(false))" Variant="Variant.Flat" Text="取消" Style="width: 120px" />
}
</RadzenStack>
</RadzenStack>
@code {
@inject Radzen.DialogService dialogService;
@inject NotificationService _message
@inject PortUtil PortUtil;
@inject ISelfTakeDao selfTakeDao;
@inject IOptions<DrawerConfig> setting;
private readonly ILog logger = LogManager.GetLogger(typeof(OrderDetailDialog));
int status;
[Parameter] public OrderInfo order { get; set; }
[Parameter] public List<OrderDetail> orderDetails{ get; set; }
private bool CanTakeDrug = true;
public List<OrderTakeVo> data { get; set; }
protected override async Task OnInitializedAsync()
{
data = await selfTakeDao.getTakeInfoByOrderNo(orderDetails);
// 如果有【stockQuantity】字段说明有药品库存不足
if (data.Any(it => it.ChannelStock == null))
{
CanTakeDrug = false;
}
base.OnInitializedAsync();
}
async Task OpenDrawer()
{
this.status = 1;
// 解析需要打开的抽屉列表
List<OrderTakeVo> drawerNos = this.data.GroupBy(it => it.ChannelStock.DrawerNo).Select(it => it.First()).ToList();
// 根据抽屉类型来决定打开前是否需要查询数量
var promiseUtil = new PromiseUtil<int>();
await promiseUtil.taskAsyncLoop(500, 0, async (options, next, stop) =>
{
var orderTakeVo = drawerNos[options._data];
var drawerNo = orderTakeVo.ChannelStock.DrawerNo;
try
{
if (this.status == 0)
{
stop();
}
// 开启抽屉
else if (this.status == 1)
{
if (orderTakeVo.Status == 0)
{
// 判断是否为单支抽屉
if (setting.Value.single.Contains(drawerNo))
{
byte[] quantity = await PortUtil.CheckQuantityByDrawer(drawerNo);
orderTakeVo.BeforeQuantity = quantity.Select(it => Convert.ToInt32(it)).ToArray().Skip(3).Take(9).ToArray();
logger.Info($"单支抽屉,开抽屉前检测数量【{string.Join(",", orderTakeVo.BeforeQuantity)}】");
await PortUtil.HasLightOnByCol(drawerNo, data.Where(ot => ot.ChannelStock.DrawerNo == drawerNo).Select(ot => ot.ChannelStock.ColNo).ToArray());
}
var b = await PortUtil.OpenDrawerStatus(drawerNo);
if (b)
{
PortUtil.Operate = true;
PortUtil.SpeakAsync($"{drawerNo}号抽屉已经打开,请,取药");
orderTakeVo.Status = 1;
next();
}
else
{
_message.Notify(
new NotificationMessage { Severity = NotificationSeverity.Error, Summary = "提示", Detail = $"抽屉【{drawerNo}】打开失败,请检测硬件", Duration = 4000 }
);
logger.Info($"抽屉打开失败");
PortUtil.AllLightOff();
RestData();
stop();
}
}
// 检测状态
else if (orderTakeVo.Status == 1)
{
// 查询抽屉是否为关闭状态
var b = await PortUtil.CheckDrawerStatus2(drawerNo);
// 关闭则改变状态并终止循环
if (b)
{
data.ForEach(cl =>
{
if (cl.ChannelStock.DrawerNo == drawerNo)
{
cl.GetQuantity = cl.Quantity;
}
});
PortUtil.Operate = false;
orderTakeVo.Status = 2;
PortUtil.AllLightOff();
if (options._data == drawerNos.Count - 1)
{
PortUtil.SpeakAsync($"取药完成,请,点击完成按钮进行确认");
this.status = 2;
stop();
}
else
{
options._data += 1;
next();
}
}
else
{
if (setting.Value.single.Contains(drawerNo))
{
byte[] quantity = await PortUtil.CheckQuantityByDrawer(drawerNo);
orderTakeVo.AfterQuantity = quantity.Select(it => Convert.ToInt32(it)).ToArray().Skip(3).Take(9).ToArray();
logger.Info($"单支抽屉,抽屉未关检测数量【{string.Join(",", orderTakeVo.AfterQuantity)}】");
data.ForEach(cl =>
{
if (cl.ChannelStock.DrawerNo == drawerNo)
{
logger.Info($"单支抽屉【{drawerNo}】,应取药品数量【{orderTakeVo.Quantity}】,现实取数量【{orderTakeVo.BeforeQuantity[cl.ChannelStock.ColNo - 1] - orderTakeVo.AfterQuantity[cl.ChannelStock.ColNo - 1]}】");
}
});
}
next(); // continue iteration
}
}
}
}
catch (Exception e)
{
RestData();
logger.Info($"处方取药发生错误,{e.Message}");
_message.Notify(
new NotificationMessage { Severity = NotificationSeverity.Error, Summary = "提示", Detail = $"发生错误,{e.Message}", Duration = 4000 }
);
if (setting.Value.single.Contains(drawerNo))
{
PortUtil.AllLightOff();
}
stop();
}
});
}
void RestData()
{
this.status = 0;
}
async Task TakeFinish()
{
// 保存账册、操作记录
var b = await selfTakeDao.OrderTakeFinish(data,order);
if (!b)
{
_message.Notify(new NotificationMessage { Severity = NotificationSeverity.Error, Summary = "提示", Detail = $"数据保存失败", Duration = 4000 });
logger.Error($"自选取药保存数据库失败,数据{JsonConvert.SerializeObject(data)}");
// 关闭弹窗
dialogService.Close(false);
}
else
{
// 关闭弹窗
dialogService.Close(true);
}
//重置状态
this.RestData();
}
}

View File

@ -0,0 +1,66 @@
@page "/signature/{user}"
@layout EmptyLayout
<RadzenStack AlignItems="AlignItems.Center" JustifyContent="JustifyContent.Center">
@if (user.Sign != null)
{
<RadzenImage Path="@($"data:image/png;base64,{Convert.ToBase64String(user.Sign)}")" Style="width:160px;height:80px;" />
}
<div class="border">
<canvas />
</div>
<RadzenStack Orientation="Orientation.Horizontal" AlignItems="AlignItems.Center" JustifyContent="JustifyContent.Center">
<RadzenButton Text="清除" Click="@(() => handleClear())" />
<RadzenButton Text="撤销" Click="@(() => handleUndo())" />
<RadzenButton Text="保存" Click="@(() => handlePreview())" />
</RadzenStack>
</RadzenStack>
<div>
</div>
@code {
@inject IJSRuntime JsRuntime;
@inject NotificationService _message;
@inject IUserDao userDao;
private IJSObjectReference module;
@inject DialogService dialogService;
[Parameter] public Pojo.User user { get; set; }
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
// 导入。路径是相对wwwroot写的其他位置参考顶部链接
module = await JsRuntime.InvokeAsync<IJSObjectReference>("import", "./signatureInit.js");
await module.InvokeVoidAsync("createSignatrue");
}
}
async Task handleClear()
{
await module.InvokeVoidAsync("clear");
}
async Task handleUndo()
{
await module.InvokeVoidAsync("undo");
}
async Task handlePreview()
{
bool flag = await module.InvokeAsync<bool>("isEmpty");
if (flag)
{
}
else
{
string base64 = await module.InvokeAsync<string>("getPNG");
await userDao.UpdateSign(user.Id, base64.Split(",")[1]);
dialogService.Close(true);
}
}
}

View File

@ -0,0 +1,290 @@
@page "/stock/binding"
<div class="container-fluid">
<div class="row">
@* <div class="col-12 mb-4">
<form onsubmit="@(() => grid.Reload())">
<RadzenFieldset Text="查询">
<RadzenStack Orientation="Orientation.Horizontal" Gap="1rem">
<RadzenRow AlignItems="AlignItems.Center">
<RadzenColumn Size="4">
<RadzenLabel Text="药品" Component="Drug" />
</RadzenColumn>
<RadzenColumn Size="8">
<RadzenDropDownDataGrid AllowVirtualization="true" Name="Drug" TValue="DrugInfo" @bind-Value="drugInfo" Data="@drugInfos"
Style="width:100%; display: block;" AllowFilteringByAllStringColumns="true" TextProperty="DrugName">
<Columns>
<RadzenDropDownDataGridColumn Property="DrugId" Title="药品编码" />
<RadzenDropDownDataGridColumn Property="DrugName" Width="120px" Title="名称" />
<RadzenDropDownDataGridColumn Property="DrugSpec" Title="规格" />
</Columns>
</RadzenDropDownDataGrid>
</RadzenColumn>
</RadzenRow>
<RadzenRow AlignItems="AlignItems.Center">
<RadzenColumn Size="4">
<RadzenLabel Text="批次" Component="DropDownBindValue" />
</RadzenColumn>
<RadzenColumn Size="8">
<RadzenDropDownDataGrid @bind-Value=@drugManuNo Data=@drugInfo?.Manus Disabled="@(drugInfo == null)" Name="DropDownBindValue" TextProperty="ManuNo">
<Columns>
<RadzenDropDownDataGridColumn Property="ManuNo" Title="批次" />
<RadzenDropDownDataGridColumn Property="EffDate" Title="效期" />
</Columns>
</RadzenDropDownDataGrid>
</RadzenColumn>
</RadzenRow>
<RadzenRow AlignItems="AlignItems.Center">
<RadzenColumn Size="12">
<RadzenButton Size="ButtonSize.Medium" ButtonType="ButtonType.Submit" IsBusy="isLoading" Icon="search" Text="绑定" />
<RadzenButton Size="ButtonSize.Medium" Click="reloadGrid" IsBusy="isLoading" Icon="refresh" Text="解绑" ButtonStyle="ButtonStyle.Warning" />
<RadzenButton Size="ButtonSize.Medium" Click="reloadGrid" IsBusy="isLoading" Icon="refresh" Text="刷新" ButtonStyle="ButtonStyle.Warning" />
</RadzenColumn>
</RadzenRow>
</RadzenStack>
</RadzenFieldset>
</form>
</div> *@
<div class="col-12 mb-4">
<RadzenDataList @ref="grid" LoadData="@LoadData" WrapItems="true" Count="@count" IsLoading="@isLoading" Data="@_forecasts" PageSize="6" AllowPaging="true" PagerHorizontalAlign="HorizontalAlign.Left"
ShowPagingSummary="true" PagingSummaryFormat="{0}/{1} 共{2}条数据">
<Template Context="channel">
<RadzenCard class="col-3">
<RadzenRow>
<RadzenColumn Size="8" Class="rz-text-truncate">
<b class="rz-pr-3">@(channel.DrawerNo) - @(channel.ColNo)</b>
@if(channel.DrawerType == 1)
{
switch(channel.BoardType)
{
case 1:
<b>物理隔板</b>
break;
case 2:
<b>单支计数</b>
break;
case 3:
<b>管控药盒</b>
break;
case 4:
<b>储物箱</b>
break;
case 5:
<b>智能显示</b>
break;
case 6:
<b>称重计数</b>
break;
case 63:
<b>称重计数药盒</b>
break;
case 653:
<b>称重计数药盒智能显示</b>
break;
}
}
else if (channel.DrawerType == 2)
{
switch (channel.BoardType)
{
case 1:
<b>内置回收</b>
break;
case 2:
<b>内置计数回收</b>
break;
case 3:
<b>内置药盒回收</b>
break;
case 4:
<b>储物回收箱</b>
break;
case 5:
<b>内置智能显示回收</b>
break;
case 6:
<b>内置称重计数回收</b>
break;
case 63:
<b>内置称重计数药盒回收</b>
break;
case 653:
<b>内置称重计数药盒智能显示回收</b>
break;
}
}
else
{
switch (channel.BoardType)
{
case 1:
<b>外置回收</b>
break;
}
}
</RadzenColumn>
<RadzenColumn Size="4" Class="rz-text-align-end">
@if(channel.Quantity == 0)
{
<RadzenButton ButtonStyle="ButtonStyle.Secondary" Variant="Variant.Outlined" Size="ButtonSize.Small" Click="@(() => EditChannel(channel))" Text="绑定/解绑" />
}
</RadzenColumn>
</RadzenRow>
<hr style="border: none; background-color: rgba(0,0,0,.2); height: 1px; margin: 1rem 0;" />
<RadzenStack Orientation="Orientation.Horizontal" AlignItems="AlignItems.Center">
<RadzenStack Gap="0">
<RadzenText TextStyle="TextStyle.Overline" class="rz-display-flex rz-mt-2 rz-my-0">药品</RadzenText>
@if (channel.DrugId == null || channel.Quantity == 0)
{
<RadzenDropDownDataGrid Change="@((args) => { channel.drugManuNo = null; })" AllowVirtualization="true" Name="@("Drug_" + channel.Id)" TValue="DrugInfo" @bind-Value="channel.Drug" Data="@drugInfos"
Style="width:100%; display: block;" AllowFilteringByAllStringColumns="true" TextProperty="DrugName">
<Columns>
<RadzenDropDownDataGridColumn Property="DrugId" Title="药品编码" />
<RadzenDropDownDataGridColumn Property="DrugName" Width="120px" Title="名称" />
<RadzenDropDownDataGridColumn Property="DrugSpec" Title="规格" />
</Columns>
</RadzenDropDownDataGrid>
} else
{
<RadzenText TextStyle="TextStyle.Body1"><b>@(channel.Drug?.DrugName)</b></RadzenText>
<RadzenText TextStyle="TextStyle.Body1"><b>@(channel.Drug?.DrugSpec)</b></RadzenText>
}
@if(channel.DrawerType == 1)
{
<RadzenText TextStyle="TextStyle.Overline" class="rz-display-flex rz-mt-4 rz-mb-0">批次</RadzenText>
@if (channel.DrugId == null || channel.Quantity == 0)
{
<RadzenDropDownDataGrid @bind-Value=@channel.drugManuNo Data=@channel.Drug?.Manus Disabled="@(channel.Drug == null)" TValue="DrugManuNo" Name="@("Drugmanu_" + channel.Id)" TextProperty="ManuNo">
<Columns>
<RadzenDropDownDataGridColumn Property="ManuNo" Title="批次" />
<RadzenDropDownDataGridColumn Property="EffDate" Title="效期" />
</Columns>
</RadzenDropDownDataGrid>
}
else
{
<RadzenText TextStyle="TextStyle.Body1"><b>@(channel.ManuNo)</b></RadzenText>
<RadzenText TextStyle="TextStyle.Body1"><b>@(channel.EffDate)</b></RadzenText>
}
}
<RadzenText TextStyle="TextStyle.Overline" class="rz-display-flex rz-mt-4 rz-mb-0">库存</RadzenText>
<RadzenText TextStyle="TextStyle.Body1"><b>@(channel.Quantity)</b></RadzenText>
</RadzenStack>
</RadzenStack>
</RadzenCard>
</Template>
</RadzenDataList>
</div>
</div>
</div>
@code {
@inject IChannelListDao channelListDao;
@inject IDrugInfoDao drugInfoDao;
@inject DialogService dialogService;
@inject NotificationService _message
RadzenDataList<ChannelStock> grid;
bool isLoading;
int count;
private IEnumerable<ChannelStock>? _forecasts;
List<DrugInfo> drugInfos;
List<DrugManuNo> drugManuNos;
DrugInfo drugInfo;
DrugManuNo drugManuNo;
protected override async Task OnInitializedAsync()
{
await base.OnInitializedAsync();
//drugInfos = await drugInfoDao.GetAllDrug();
}
async Task LoadData(LoadDataArgs args)
{
isLoading = true;
// var result = await channelListDao.GetAllChannelList(0, "", args.Top, args.Skip);
var result = await channelListDao.GetAllChannelListWithDrug(0, "", args.Top, args.Skip);
// Update the Data property
_forecasts = result.Desserts;
// Update the count
count = result.TotalDesserts;
isLoading = false;
drugInfos = result.Other;
}
async Task reloadGrid()
{
await grid.Reload();
}
async Task EditChannel(ChannelStock stock)
{
if(stock.drugManuNo != null)
{
// 说明之前有绑定并且未改变,那么就是在进行解绑
if(stock.drugManuNo.ManuNo.Equals(stock.ManuNo))
{
var b = await channelListDao.UnBind(stock.Id);
if(b)
{
_message.Notify(
new NotificationMessage { Severity = NotificationSeverity.Success, Summary = "提示", Detail = $"解除绑定成功", Duration = 4000 }
);
await reloadGrid();
}
}
// 否则是进行绑定
else
{
var b = await channelListDao.Bind(stock);
if (b)
{
_message.Notify(
new NotificationMessage { Severity = NotificationSeverity.Success, Summary = "提示", Detail = $"绑定成功", Duration = 4000 }
);
await reloadGrid();
}
}
} else
{
if (stock.Drug != null)
{
// 说明只设置了药品
var b = await channelListDao.Bind(stock);
if (b)
{
_message.Notify(
new NotificationMessage { Severity = NotificationSeverity.Success, Summary = "提示", Detail = $"绑定成功", Duration = 4000 }
);
await reloadGrid();
}
}
// 什么都没有选择或者么有改变,只是点击了按钮,此时不操作
else
{
}
}
}
}

View File

@ -0,0 +1,307 @@
@page "/stock/check"
@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">
<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">
@* <RadzenStack AlignItems="AlignItems.Center" JustifyContent="JustifyContent.Center" Orientation="Orientation.Vertical" Style="margin-top: 220px"> *@
<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>
@* </RadzenStack> *@
</div>
</div>
<RadzenDataGrid @ref="grid"
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)
{
<RadzenButton IsBusy="@(status>0)" BusyText="盘点中。。。" ButtonStyle="ButtonStyle.Warning" Variant="Variant.Flat" Shade="Shade.Light" Text="盘点" Click="@OpenDrawer" />
}
@if (status == 3)
{
<RadzenButton ButtonStyle="ButtonStyle.Warning" Variant="Variant.Flat" Shade="Shade.Light" Text="完成" Click="@CheckFinish" />
}
@if (status > 0 && status <= 3)
{
<RadzenButton Variant="Variant.Flat" Shade="Shade.Light" Text="取消" Click="@Cancel" Style="width: 120px" />
}
</RadzenRow>
</HeaderTemplate>
<Columns>
<RadzenDataGridColumn Width="70px" Title="库位" Property="ColNo"></RadzenDataGridColumn>
<RadzenDataGridColumn 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 Title="批次" Property="ManuNo">
<Template Context="channel">
<RadzenText TextStyle="TextStyle.Subtitle2" class="mb-0">@channel.drugManuNo?.ManuNo</RadzenText>
<RadzenText TextStyle="TextStyle.Caption">@channel.drugManuNo?.EffDate</RadzenText>
</Template>
<EditTemplate Context="channel">
@if (channel.Quantity == 0 && !String.IsNullOrEmpty(channel.DrugId))
{
<RadzenDropDown TValue="DrugManuNo" Name="ManuNo" @bind-Value="channel.drugManuNo" Data="@channel.Drug?.Manus" Style="width:100%; display: block;">
<Template>
<RadzenText TextStyle="TextStyle.Subtitle2" class="mb-0">@((context as DrugManuNo)?.ManuNo)</RadzenText>
<RadzenText TextStyle="TextStyle.Caption">@((context as DrugManuNo)?.EffDate)</RadzenText>
</Template>
<ValueTemplate>
<RadzenStack Orientation="Orientation.Horizontal">
<RadzenText TextStyle="TextStyle.Subtitle2" class="mb-0">@((context as DrugManuNo)?.ManuNo)</RadzenText>
<RadzenText TextStyle="TextStyle.Caption">@((context as DrugManuNo)?.EffDate)</RadzenText>
</RadzenStack>
</ValueTemplate>
</RadzenDropDown>
<RadzenRequiredValidator Text="请选择批次" Component="ManuNo" Popup="true" />
}
else
{
<RadzenText TextStyle="TextStyle.Subtitle2" class="mb-0">@channel.drugManuNo?.ManuNo</RadzenText>
<RadzenText TextStyle="TextStyle.Caption">@channel.drugManuNo?.EffDate</RadzenText>
}
</EditTemplate>
</RadzenDataGridColumn>
<RadzenDataGridColumn Title="库存" Property="Quantity">
<Template Context="cs">
<RadzenButton ButtonStyle="ButtonStyle.Info" Variant="Variant.Flat" Shade="Shade.Lighter" class="m-1" Text="@cs.Quantity.ToString()" />
</Template>
</RadzenDataGridColumn>
<RadzenDataGridColumn MinWidth="120px" Title="盘点数量" Property="CheckQuantity">
<EditTemplate Context="cs">
@if (cs.BoardType == 2)
{
@cs.CheckQuantity
}
else
{
<RadzenNumeric Min="0" Style="display: block" Name="CheckQuantity" @bind-Value=@cs.CheckQuantity />
<RadzenNumericRangeValidator Style="position: absolute;z-index: 9999;" Min="0" Text="请填写正确的盘点数量" Component="CheckQuantity" Popup="true" />
}
</EditTemplate>
</RadzenDataGridColumn>
</Columns>
</RadzenDataGrid>
</RadzenStack>
@code {
@inject IChannelListDao channelListDao;
@inject NavigationManager na;
@inject PortUtil PortUtil;
@inject NotificationService _message
@inject IOptions<DrawerConfig> setting;
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, 9, 10, 11, 12, 13, 14, 15, 16 };
int[] BeforeQuantity = new int[9];
int[] AfterQuantity = new int[9];
private readonly ILog logger = LogManager.GetLogger(typeof(DrawerAdd));
async Task LoadData(LoadDataArgs args)
{
isLoading = true;
var result = await channelListDao.GetChannelStockByDrawerNoWithDrawers(drawerNo);
// var result = await channelListDao.GetChannelStockByDrawerNo(drawerNo);
// Update the Data property
DrawerNos = result.DrawerArray;
// for (int i = 0; i < result.ChannelStocks.Count; i++)
// {
// result.ChannelStocks[i].CheckQuantity = result.ChannelStocks[i].Quantity;
// }
result.ChannelStocks.ForEach(cs => cs.CheckQuantity = cs.Quantity);
channels = result.ChannelStocks;
// Update the count
count = result.ChannelStocks.Count;
isLoading = false;
}
async Task OpenDrawer()
{
this.status = 1;
// 根据抽屉类型来决定打开前是否需要查询数量
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.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.SpeakAsync($"{drawerNo}号抽屉已经打开,请,盘点");
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.SpeakAsync($"盘点完成,请,核对,或,录入,正确的,盘点数量");
this.status = 3;
stop();
}
else
{
if (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)}】");
channels.ForEach(cl =>
{
cl.CheckQuantity = this.AfterQuantity[cl.ColNo - 1];// - this.BeforeQuantity[cl.ColNo - 1];
});
}
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.AllLightOff();
}
RestData();
stop();
}
});
}
void RestData()
{
this.status = 0;
this.BeforeQuantity = new int[9];
this.AfterQuantity = new int[9];
}
async Task CheckFinish()
{
if (channels.Any(cl => cl.CheckQuantity != cl.Quantity && cl.DrugId != null && cl.drugManuNo != null))
{
// 保存账册、操作记录
var b = await channelListDao.DrawerCheckFinish(channels.Where(cl => cl.CheckQuantity != cl.Quantity).ToList());
if (!b)
{
_message.Notify(new NotificationMessage { Severity = NotificationSeverity.Error, Summary = "提示", Detail = $"数据保存失败", Duration = 4000 });
logger.Error($"盘点保存数据库失败,数据{JsonConvert.SerializeObject(channels)}");
}
else
{
_message.Notify(new NotificationMessage { Severity = NotificationSeverity.Info, Summary = "提示", Detail = $"盘点完成", Duration = 4000 });
logger.Error($"盘点完成");
}
}
//重置状态
this.RestData();
// 重新查询库存
await grid.Reload();
}
void Cancel()
{
this.status = 0;
}
void SelectDrawer(int drawerNo)
{
this.drawerNo = drawerNo;
grid.Reload();
}
void OnCellClick(DataGridCellMouseEventArgs<ChannelStock> args)
{
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();
}
}

View File

@ -0,0 +1,90 @@
@page "/stock/list"
<style>
.rz-custom-header {
width: 100%;
}
</style>
<div class="container-fluid">
<RadzenDataGrid @ref="grid"
IsLoading="@isLoading"
RowRender="@RowRender"
EmptyText="无数据"
Data="@_forecasts"
AllowColumnResize="true" AllowAlternatingRows="false"
SelectionMode="DataGridSelectionMode.Single"
ExpandMode="DataGridExpandMode.Multiple">
<HeaderTemplate>
<RadzenRow JustifyContent="JustifyContent.End" AlignItems="AlignItems.Center">
<RadzenButton Icon="download" Text="库存导出" Variant="Variant.Outlined" />
<RadzenButton Icon="download" Text="专用账册导出" Variant="Variant.Outlined" />
</RadzenRow>
</HeaderTemplate>
<Template Context="di">
<RadzenDataGrid Data="@di.Stocks" EmptyText="无数据">
<Columns>
<RadzenDataGridColumn Title="库位" Property="DrawerNo">
<Template Context="s">
@s.DrawerNo - @s.ColNo
</Template>
</RadzenDataGridColumn>
<RadzenDataGridColumn Title="数量" Property="Quantity"></RadzenDataGridColumn>
<RadzenDataGridColumn Title="批次" Property="ManuNo"></RadzenDataGridColumn>
<RadzenDataGridColumn Title="效期" Property="EffDate"></RadzenDataGridColumn>
</Columns>
</RadzenDataGrid>
</Template>
<Columns>
<RadzenDataGridColumn Frozen="true" Width="200px" Title="药品名称" Property="DrugName"></RadzenDataGridColumn>
<RadzenDataGridColumn Title="规格" Property="DrugSpec"></RadzenDataGridColumn>
<RadzenDataGridColumn Title="总库存" Property="StockQuantity"></RadzenDataGridColumn>
</Columns>
</RadzenDataGrid>
</div>
@code {
@inject IDrugInfoDao drugInfoDao;
@inject DialogService dialogService;
RadzenDataGrid<DrugInfo> grid;
bool isLoading;
int count;
private IEnumerable<DrugInfo>? _forecasts;
DateTime start;
DateTime end;
protected override async Task OnInitializedAsync()
{
await base.OnInitializedAsync();
isLoading = true;
var result = await drugInfoDao.GetAllDrugAndStock();
// Update the Data property
_forecasts = result;
isLoading = false;
}
protected override async Task OnAfterRenderAsync(bool firstRender)
{
base.OnAfterRender(firstRender);
if (firstRender)
{
await grid.ExpandRows(grid.PagedView.Where(di => di.Stocks.Count > 0));
}
}
void RowRender(RowRenderEventArgs<DrugInfo> args)
{
args.Expandable = args.Data.Stocks.Count > 0;
}
}

View File

@ -0,0 +1,87 @@
@page "/TEST"
@layout EmptyLayout
<RadzenStack Orientation="Orientation.Horizontal" JustifyContent="JustifyContent.Center" AlignItems="AlignItems.Center" Gap="0.5rem" class="rz-p-12">
<RadzenLabel Text="Select Value" Component="DropDownDataGridBindValue" />
<RadzenDropDownDataGrid @ref=grid Data="@data" ColumnWidth="200px" TValue="IDictionary<string, object>"
AllowFiltering="true" AllowSorting="true" Value="@selectedItem" Change="@OnChange">
@* TextProperty="@(PropertyAccess.GetDynamicPropertyExpression("LastName", typeof(string)))"> *@
<ValueTemplate>
@string.Join(", ", columns.Where(c => c.Value == typeof(string)).Take(grid.MaxSelectedLabels).Select(c => context[c.Key]))
</ValueTemplate>
<Columns>
@foreach (var column in columns)
{
<RadzenDropDownDataGridColumn @key=@column.Key Title="@column.Key" Type="column.Value">
@* Property="@PropertyAccess.GetDynamicPropertyExpression(column.Key, column.Value)"> *@
<Template>
@context[@column.Key]
</Template>
</RadzenDropDownDataGridColumn>
}
</Columns>
</RadzenDropDownDataGrid>
</RadzenStack>
@code {
RadzenDropDownDataGrid<IDictionary<string, object>> grid;
IDictionary<string, object> selectedItem;
public IEnumerable<IDictionary<string, object>> data { get; set; }
public IDictionary<string, Type> columns { get; set; }
public enum EnumTest
{
EnumValue1,
EnumValue2
}
void OnChange(object value)
{
selectedItem = (IDictionary<string, object>)value;
}
protected override async Task OnInitializedAsync()
{
await base.OnInitializedAsync();
columns = new Dictionary<string, Type>()
{
{ "EmployeeID", typeof(int) },
{ "MyColumn", typeof(EnumTest) },
{ "FirstName", typeof(string) },
{ "LastName", typeof(string) },
{ "HireDate", typeof(DateTime) },
};
foreach (var i in Enumerable.Range(0, 50))
{
columns.Add($"Column{i}", typeof(string));
}
data = Enumerable.Range(0, 100).Select(i =>
{
var row = new Dictionary<string, object>();
foreach (var column in columns)
{
row.Add(
column.Key,
column.Value == typeof(EnumTest)
? (i % 2 == 0 ? EnumTest.EnumValue1 : EnumTest.EnumValue2)
: column.Value == typeof(int)
? i
: column.Value == typeof(DateTime)
? DateTime.Now.AddMonths(i)
: $"{column.Key}{i}"
);
}
return row;
});
}
}

View File

@ -0,0 +1,306 @@
@page "/manage/user"
@using log4net;
<div class="container-fluid">
<div class="row">
<div class="col-12 mb-4">
<form onsubmit="@(() => grid.Reload())">
<RadzenFieldset Text="查询">
<RadzenStack Orientation="Orientation.Horizontal" JustifyContent="JustifyContent.SpaceBetween">
<RadzenStack Orientation="Orientation.Horizontal" Gap="1rem">
<RadzenRow AlignItems="AlignItems.Center">
<RadzenColumn Size="4">
<RadzenLabel Text="用户名" Component="nickname" />
</RadzenColumn>
<RadzenColumn Size="8">
<RadzenTextBox @bind-Value="nickname" Style="width: 100%;" Name="nickname"></RadzenTextBox>
</RadzenColumn>
</RadzenRow>
<RadzenRow AlignItems="AlignItems.Center">
<RadzenColumn Size="12">
<RadzenButton Size="ButtonSize.Medium" ButtonType="ButtonType.Submit" IsBusy="isLoading" Icon="search" Text="查询" />
<RadzenButton Size="ButtonSize.Medium" Click="reloadGrid" IsBusy="isLoading" Icon="refresh" Text="重置" ButtonStyle="ButtonStyle.Warning" />
</RadzenColumn>
</RadzenRow>
</RadzenStack>
<RadzenButton Size="ButtonSize.Medium" ButtonStyle="ButtonStyle.Success" Icon="add_circle_outline" Click="@InsertRow" Disabled="@(usersToInsert.Count() > 0)" Text="新增" />
</RadzenStack>
</RadzenFieldset>
</form>
</div>
<div class="col-12 mb-4">
<RadzenDataGrid @ref="grid"
LoadData="@LoadData"
IsLoading="@isLoading"
Count="@count"
EmptyText="无数据"
Data="@userList"
Page="@Reset"
EditMode="DataGridEditMode.Single"
AllowColumnResize="true" AllowAlternatingRows="false"
RowUpdate="@((Pojo.User u) => { OnUpdateRow(u); })" RowCreate="@((Pojo.User u) => { OnCreateRow(u); })"
SelectionMode="DataGridSelectionMode.Single"
AllowPaging="true" PageSize="10" PagerHorizontalAlign="HorizontalAlign.Left" ShowPagingSummary="true" PagingSummaryFormat="{0}/{1} 共{2}条数据">
<Columns>
<RadzenDataGridColumn Title="ID" Property="Id"></RadzenDataGridColumn>
<RadzenDataGridColumn Title="用户名" Property="NickName">
<EditTemplate Context="user">
<RadzenTextBox Name="NickName" @bind-Value="user.NickName" Style="width:100%; display: block;" />
<RadzenRequiredValidator Text="请填写用户名" Component="NickName" Popup="true" />
</EditTemplate>
</RadzenDataGridColumn>
<RadzenDataGridColumn Title="账号" Property="Username">
<EditTemplate Context="user">
<RadzenTextBox Name="Username" @bind-Value="user.Username" Style="width:100%; display: block;" />
<RadzenRequiredValidator Text="请填写账号" Component="Username" Popup="true" />
</EditTemplate>
</RadzenDataGridColumn>
<RadzenDataGridColumn Title="权限" Property="role.RoleName">
<EditTemplate Context="user">
<RadzenDropDown Name="RoleId" @bind-Value="user.RoleId" Data="@roles" TextProperty="RoleName" ValueProperty="Id" Style="width:100%; display: block;"
InputAttributes="@(new Dictionary<string,object>(){ { "aria-label", "Select customer" }})" />
<RadzenRequiredValidator Text="请选择角色" Component="RoleId" Popup="true" />
</EditTemplate>
</RadzenDataGridColumn>
<RadzenDataGridColumn Context="user" Filterable="false" Sortable="false" TextAlign="TextAlign.Right" Frozen="true" FrozenPosition="FrozenColumnPosition.Right">
<Template Context="user">
<RadzenButton Icon="edit" ButtonStyle="ButtonStyle.Light" Variant="Variant.Flat" Size="ButtonSize.Medium" Click="@(args => EditRow(user))" @onclick:stopPropagation="true">
</RadzenButton>
<RadzenButton Icon="edit_document" ButtonStyle="ButtonStyle.Warning" Variant="Variant.Flat" Shade="Shade.Lighter" Size="ButtonSize.Medium" Click="@(args => Signatrue(user))" @onclick:stopPropagation="true">
</RadzenButton>
<RadzenButton Icon="fingerprint" ButtonStyle="ButtonStyle.Info" Variant="Variant.Flat" Size="ButtonSize.Medium" class="my-1 ms-1" Click="@(args => Reg2ZWJ(user))" @onclick:stopPropagation="true">
</RadzenButton>
<RadzenButton ButtonStyle="ButtonStyle.Danger" Icon="delete" Variant="Variant.Flat" Shade="Shade.Lighter" Size="ButtonSize.Medium" class="my-1 ms-1" Click="@(args => DeleteRow(user))" @onclick:stopPropagation="true">
</RadzenButton>
<RadzenButton ButtonStyle="ButtonStyle.Danger" Icon="https" Variant="Variant.Flat" Shade="Shade.Lighter" Size="ButtonSize.Medium" class="my-1 ms-1" Click="@(args => ResetPasswordRow(user))" aria-label="ResetPassword">
</RadzenButton>
</Template>
<EditTemplate Context="user">
<RadzenButton Icon="check" ButtonStyle="ButtonStyle.Success" Variant="Variant.Flat" Size="ButtonSize.Medium" Click="@((args) => SaveRow(user))" aria-label="Save">
</RadzenButton>
<RadzenButton Icon="close" ButtonStyle="ButtonStyle.Light" Variant="Variant.Flat" Size="ButtonSize.Medium" class="my-1 ms-1" Click="@((args) => CancelEdit(user))" aria-label="Cancel">
</RadzenButton>
<RadzenButton ButtonStyle="ButtonStyle.Danger" Icon="delete" Variant="Variant.Flat" Shade="Shade.Lighter" Size="ButtonSize.Medium" class="my-1 ms-1" Click="@(args => DeleteRow(user))" aria-label="Delete">
</RadzenButton>
<RadzenButton ButtonStyle="ButtonStyle.Danger" Icon="https" Variant="Variant.Flat" Shade="Shade.Lighter" Size="ButtonSize.Medium" class="my-1 ms-1" Click="@(args => ResetPasswordRow(user))" aria-label="ResetPassword">
</RadzenButton>
</EditTemplate>
</RadzenDataGridColumn>
</Columns>
</RadzenDataGrid>
</div>
</div>
</div>
@code {
@inject IUserDao userDao;
@inject IRoleDao roleDao;
@inject DialogService dialogService;
@inject NotificationService _message
RadzenDataGrid<Pojo.User> grid;
bool isLoading;
int count;
private IEnumerable<Pojo.User>? userList;
string nickname;
DateTime OrderDate;
private readonly ILog logger = LogManager.GetLogger(typeof(Pages.User));
List<Pojo.Role> roles;
List<Pojo.User> usersToInsert = new List<Pojo.User>();
List<Pojo.User> usersToUpdate = new List<Pojo.User>();
protected override async Task OnInitializedAsync()
{
await base.OnInitializedAsync();
roles = await roleDao.GetAllRoles();
}
void Reset()
{
usersToInsert.Clear();
usersToUpdate.Clear();
}
async Task Reg2ZWJ(Pojo.User user)
{
await dialogService.OpenAsync<FingerRegDialog>(
$"录入指纹",
new Dictionary<string, object>() { { "userId", user.Id } },
new DialogOptions() { Width = "55vw", Resizable = true, Draggable = true, ShowClose = false }
);
}
async Task Signatrue(Pojo.User user)
{
var flag = await dialogService.OpenAsync<SignatureDialog>(
$"签名-{user.NickName}",
new Dictionary<string, object>() { { "user", user } },
new DialogOptions() { Width = "55vw", Resizable = true, Draggable = true, ShowClose = true }
);
if(flag != null && flag)
{
await reloadGrid();
}
}
void Reset(Pojo.User user)
{
usersToInsert.Remove(user);
usersToUpdate.Remove(user);
}
void OnCurrentDateChanged(DateTime args)
{
OrderDate = new DateTime(args.Year, args.Month, args.Day);
}
async Task LoadData(LoadDataArgs args)
{
isLoading = true;
var result = await userDao.GetAllByNickname(nickname, args.Top, args.Skip);
// Update the Data property
userList = result.Desserts;
// Update the count
count = result.TotalDesserts;
isLoading = false;
}
async Task reloadGrid()
{
nickname = "";
await grid.Reload();
}
async Task EditRow(Pojo.User user)
{
Reset();
usersToUpdate.Add(user);
await grid.EditRow(user);
}
void OnUpdateRow(Pojo.User user)
{
Reset(user);
// 数据库更新
userDao.UpdateUser(user);
if(user.role.Id != user.RoleId)
{
grid.Reload();
}
}
async Task SaveRow(Pojo.User user)
{
await grid.UpdateRow(user);
}
void CancelEdit(Pojo.User user)
{
Reset(user);
grid.CancelEditRow(user);
grid.Reload();
}
async Task DeleteRow(Pojo.User user)
{
Reset(user);
if (userList.Contains(user))
{
//弹出确认提示框
var b = await dialogService.OpenAsync<ConfirmDialo>(
$"删除确认",
new Dictionary<string, object>() { { "confirmInfo", "删除用户:"+user.Username } },
new DialogOptions() { Width = "45vw", Resizable = true, Draggable = true, ShowClose = false });
if (b)
{
// 数据库删除
userDao.DeleteeUser(user.Id);
}
await grid.Reload();
}
else
{
grid.CancelEditRow(user);
await grid.Reload();
}
}
//重置密码
async Task ResetPasswordRow(Pojo.User user)
{
Reset(user);
if (userList.Contains(user))
{
//弹出确认提示框
var b = await dialogService.OpenAsync<ConfirmDialo>(
$"密码重置确认",
new Dictionary<string, object>() { { "confirmInfo", "重置用户:" + user.Username+" 的密码" } },
new DialogOptions() { Width = "45vw", Resizable = true, Draggable = true, ShowClose = false });
if (b)
{
// 数据库重置密码
userDao.ResetPassword(user.Id);
//提示密码已重置,下次登录请使用重置后的密码
_message.Notify(new NotificationMessage { Severity = NotificationSeverity.Success, Summary = "提示", Detail = $"密码已重置,下次登录请使用重置后的密码", Duration = 4000 });
}
await grid.Reload();
}
else
{
grid.CancelEditRow(user);
await grid.Reload();
}
}
async Task InsertRow()
{
Reset();
var user = new Pojo.User()
{
RoleId = roles[0].Id,
};
usersToInsert.Add(user);
await grid.InsertRow(user);
}
void OnCreateRow(Pojo.User user)
{
// 数据库添加用户
userDao.InsertUser(user);
usersToInsert.Remove(user);
grid.Reload();
}
}

View File

@ -0,0 +1,113 @@
using LinqToDB.Mapping;
using MasaBlazorApp3.Pojo;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Principal;
using System.Text;
using System.Threading.Tasks;
namespace MasaBlazorApp3.Pojo
{
[Table("account_book")]
public class AccountBook
{
/// <summary>
/// 主键
///</summary>
[Column("id", IsPrimaryKey = true, IsIdentity = true)]
public int Id { get; set; }
/// <summary>
/// 设备id
///</summary>
[Column("machine_id")]
public string MachineId { get; set; }
/// <summary>
/// 药品id
///</summary>
[Column("drug_id")]
public string DrugId { get; set; }
[Association(ThisKey = nameof(DrugId), OtherKey = nameof(DrugInfo.DrugId))]
public DrugInfo Drug { get; set; }
/// <summary>
/// 数量
///</summary>
[Column("add_quantity")]
public int AddQuantity { get; set; }
[Column("out_quantity")]
public int OutQuantity { get; set; }
/// <summary>
/// 批号
///</summary>
[Column("manu_no")]
public string ManuNo { get; set; }
/// <summary>
/// 操作人id
///</summary>
[Column("operator")]
public int? Operator { get; set; }
[Association(ThisKey = nameof(Operator), OtherKey = nameof(User.Id))]
public User OperatorUser { get; set; }
/// <summary>
/// 审核人id
///</summary>
[Column("reviewer")]
public int? Reviewer { get; set; }
[Association(ThisKey = nameof(Reviewer), OtherKey = nameof(User.Id))]
public User ReviewerUser { get; set; }
/// <summary>
/// 操作时间
/// 默认值: CURRENT_TIMESTAMP
///</summary>
[Column("create_time")]
public DateTime OperationTime { get; set; }
/// <summary>
/// 效期
///</summary>
[Column("eff_date")]
public DateTime? EffDate { get; set; }
/// <summary>
/// 出库入库类型(1领入2发出3日结4日总结5转结)
///</summary>
[Column("type")]
public int Type { get; set; }
/// <summary>
/// 出入库调拨单id
///</summary>
[Column("invoice_id")]
public string InvoiceId { get; set; }
/// <summary>
/// 列号
///</summary>
[Column("yesterday_quantity")]
public int YesterdayQuantity { get; set; }
/// <summary>
/// 抽屉号
///</summary>
[Column("manu_stock")]
public int ManuStock { get; set; }
[Column("total_stock")]
public int TotalStock { get; set; }
/// <summary>
/// 取药科室
///</summary>
[Column("department")]
public string department { get; set; }
/// <summary>
/// 退药量
/// 默认值: 0
///</summary>
[Column("create_date")]
public string CreateDate { get; set; }
}
}

View File

@ -0,0 +1,48 @@
using LinqToDB.Mapping;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MasaBlazorApp3.Pojo
{
[Table("channel_list")]
public class ChannelList
{
[PrimaryKey]
[Column("chnguid")]
public string Id { get; set; }
[Column("machine_id")]
public string MachineId { get; set; }
[Column("row_no")]
public int DrawerNo { get; set; }
[Column("col_no")]
public int ColNo { get; set; }
[Column("drug_id")]
public string DrugId { get; set; }
[Column("chn_type")]
public int DrawerType { get; set; }
[Column("col_no1")]
public int IsBox { get; set; }
[Column("col_no2")]
public int IsWeight { get; set; }
[Association(ThisKey = nameof(Id), OtherKey = nameof(ChannelStock.ListId))]
public List<ChannelStock> ChannelStocks { get; set; } = new();
[Association(ThisKey = nameof(DrugId), OtherKey = nameof(DrugInfo.DrugId))]
public DrugInfo Drug { get; set; } = new();
}
}

View File

@ -0,0 +1,83 @@
using LinqToDB.Common.Internal.Cache;
using LinqToDB.Mapping;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MasaBlazorApp3.Pojo
{
[Table("channel_stock")]
public class ChannelStock
{
[PrimaryKey]
[Column("chsguid")]
public string Id { get; set; }
[Column("chnguid")]
public string ListId { get; set; }
[Column("machine_id")]
public string MachineId { get; set; }
[Column("row_no")]
public int DrawerNo { get; set; }
[Column("col_no")]
public int ColNo { get; set; }
[Column("drug_id")]
public string DrugId { get; set; }
[Column("quantity")]
public int Quantity { get; set; }
[Column("drawer_type")]
public int DrawerType { get; set; }
[Column("board_type")]
public int BoardType { get; set; }
[Column("manu_no")]
public string ManuNo { get; set; }
[Column("eff_date")]
public string EffDate { get; set; }
[Association(ThisKey = nameof(DrugId), OtherKey = nameof(DrugInfo.DrugId))]
public DrugInfo? Drug { get; set; }
[Column(IsColumn = false)]
public int TakeQuantity { get; set; } = 0;
[Column(IsColumn = false)]
public int AddQuantity { get; set; } = 0;
[Column(IsColumn = false)]
public int ReturnQuantity { get; set; }
[Column("dmnguid")]
public string Dmnguid { get; set; }
[Association(ThisKey = nameof(Dmnguid), OtherKey = nameof(DrugManuNo.Id))]
public DrugManuNo? drugManuNo { get; set; }
[Column(IsColumn =false)]
public string Location
{ get=>DrawerNo+ "-" + ColNo; }
[Column(IsColumn =false)]
public int CanReturnQuantity { get; set; }
[Column(IsColumn = false)]
public int CheckQuantity
{
get;
set;
}
}
}

View File

@ -0,0 +1,17 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MasaBlazorApp3.Pojo.Config
{
public class DrawerConfig
{
public int[] single { get; set; }
public int[] weigh { get; set; }
public int[] box { get; set; }
public int[] label { get; set; }
}
}

View File

@ -0,0 +1,15 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MasaBlazorApp3.Pojo.Config
{
public class FingerPojo
{
public string ip { get; set; }
public int port { get; set; }
public int type { get; set; }
}
}

View File

@ -0,0 +1,23 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MasaBlazorApp3.Pojo.Config
{
public class PortConfig
{
public string drawerPortPath { get; set; }
public int drawerProtocol { get; set; }
public string scanCodePortPath { get; set; }
public string canBusPortPath { get; set; }
public bool canBusExsit { get; set; }
public int doorAddr { get; set; }
public int storageBoxAddr { get; set; }
}
}

View File

@ -0,0 +1,19 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MasaBlazorApp3.Pojo.Config
{
public class SettingConfig
{
public string machineId { get; set; }
public string storage { get; set; }
public int loginMode { get; set; }
public bool opFirst { get; set; }
//自动退出登录时间,单位秒0不自动退出
public int autoOutLog { get; set; }
}
}

View File

@ -0,0 +1,62 @@
using LinqToDB.Mapping;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;
namespace MasaBlazorApp3.Pojo
{
[Table("drug_info")]
public class DrugInfo
{
[PrimaryKey]
[Column("drug_id")]
public string DrugId { get; set; }
[Column("drug_name")]
public string DrugName { get; set;}
[Column("drug_type")]
public string DrugType { get; set;}
[Column("drug_spec")]
public string DrugSpec { get; set;}
[Column("manufactory")]
public string Manufactory { get; set; }
[Column("pack_unit")]
public string PackUnit { get; set;}
[Association(ThisKey = nameof(DrugId), OtherKey = nameof(ChannelStock.DrugId))]
public List<ChannelStock> Stocks { get; set;} = new List<ChannelStock>();
[Association(ThisKey = nameof(DrugId), OtherKey = nameof(DrugManuNo.DrugId))]
public List<DrugManuNo> Manus { get; set; } = new List<DrugManuNo>();
[Column(IsColumn = false)]
public int StockQuantity
{
get { return Stocks.Aggregate(0, (current, next) => current + next.Quantity); ; }
}
public override bool Equals(object o)
{
var other = o as DrugInfo;
return other?.DrugId == DrugId;
}
public override string ToString()
{
return $"名称: {DrugName},规格:{DrugSpec}";
}
}
}

View File

@ -0,0 +1,40 @@
using LinqToDB.Mapping;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MasaBlazorApp3.Pojo
{
[Table("drug_manu_no")]
public class DrugManuNo
{
[Column("dmnguid", IsPrimaryKey = true)]
public string Id { get; set; }
[Column("drug_id")]
public string DrugId { get; set; }
[Column("manu_no")]
public string ManuNo { get; set; }
[Column("manu_date")]
public string ManuDate { get; set; }
[Column("eff_date")]
public DateTime? EffDate { get; set; }
public override bool Equals(object o)
{
var other = o as DrugManuNo;
return other?.DrugId == DrugId && other?.ManuNo == ManuNo;
}
}
}

View File

@ -0,0 +1,146 @@
using LinqToDB.Mapping;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MasaBlazorApp3.Pojo
{
[Table("in_out_invoice")]
public class InOutInvoice
{
/// <summary>
/// 主键(序号)
/// </summary>
[Column("id", IsPrimaryKey = true, IsIdentity =true)]
public int Id { get; set; }
[Column("in_pharmacy_id")]
public string InPharmacyId { get; set; }
[Column("out_pharmacy_id")]
public string OutPharmacyId { get; set; }
/// <summary>
/// 库存管理单位(入库单位代码)
/// </summary>
[Column("storage")]
public string storage { get; set; }
/// <summary>
/// 单据号
/// </summary>
[Column("invoice_no")]
public string InvoiceNo { get; set; }
[Column("invoice_date")]
public string InvoiceDate { get; set; }
/// <summary>
/// 药品id
/// </summary>
[Column("drug_id")]
public string DrugId { get; set; }
[Association(ThisKey = nameof(DrugId), OtherKey = nameof(DrugInfo.DrugId))]
public DrugInfo Drug { get; set; } = new();
/// <summary>
/// 药品规格
/// </summary>
[Column("drug_spec")]
public string DrugSpec { get; set; }
/// <summary>
/// 计算单位
/// </summary>
[Column("units")]
public string Units { get; set; }
/// <summary>
/// 厂商标识
/// </summary>
[Column("firm_id")]
public string FirmId { get; set; }
/// <summary>
/// 包装规格反映药品含量及包装信息如0.25g*30
/// </summary>
[Column("package_spec")]
public string PackageSpec { get; set; }
/// <summary>
/// 数量(以包装单位所计的数量)
/// </summary>
[Column("quantity")]
public int quantity { get; set; }
/// <summary>
/// 计量单位,可使用任一级管理上方便的包装
/// </summary>
[Column("package_units")]
public string PackageUnits { get; set; }
/// <summary>
/// 药品批次
/// </summary>
[Column("drug_manu_no")]
public string DrugManuNo { get; set; }
/// <summary>
/// 创建时间(入库日期)
/// </summary>
[Column("create_time")]
public DateTime CreateTime { get; set; }
/// <summary>
/// 2调拨出库1.调拨入库 0.调拨
/// </summary>
[Column("type")]
public int Type { get; set; }
/// <summary>
/// 类型描述
/// </summary>
[Column("type_describe")]
public string TypeDescribe { get; set; }
/// <summary>
/// 供货方
/// </summary>
[Column("supplier")]
public string Supplier { get; set; }
/// <summary>
/// 操作人
/// </summary>
[Column("operator")]
public string Operator { get; set; }
/// <summary>
/// 存放库房
/// </summary>
[Column("sub_storage")]
public string SubStorage { get; set; }
/// <summary>
/// 备注
/// </summary>
[Column("memos")]
public string Memos { get; set; }
[Column("status")]
public int Status { get; set; }
[Column("drug_eff_date")]
public string EffDate { get; set; }
[Column("cancel_flag")]
public int CancelFlag { get; set; }
}
}

View File

@ -0,0 +1,149 @@
using LinqToDB.Mapping;
using MasaBlazorApp3.Pojo;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Principal;
using System.Text;
using System.Threading.Tasks;
namespace MasaBlazorApp3.Pojo
{
[Table("dm_machine_record")]
public class MachineRecord
{
/// <summary>
/// 主键
///</summary>
[Column("id", IsPrimaryKey = true, IsIdentity = true)]
public int Id { get; set; }
/// <summary>
/// 设备id
///</summary>
[Column("machine_id")]
public string MachineId { get; set; }
/// <summary>
/// 药品id
///</summary>
[Column("drug_id")]
public string DrugId { get; set; }
[Association(ThisKey = nameof(DrugId), OtherKey = nameof(DrugInfo.DrugId))]
public DrugInfo Drug { get; set; }
/// <summary>
/// 数量
///</summary>
[Column("quantity")]
public int Quantity { get; set; }
/// <summary>
/// 批号
///</summary>
[Column("manu_no")]
public string ManuNo { get; set; }
/// <summary>
/// 操作人id
///</summary>
[Column("operator")]
public int? Operator { get; set; }
[Association(ThisKey = nameof(Operator), OtherKey = nameof(User.Id))]
public User OperatorUser { get; set; }
/// <summary>
/// 审核人id
///</summary>
[Column("reviewer")]
public int? Reviewer { get; set; }
[Association(ThisKey = nameof(Reviewer), OtherKey = nameof(User.Id))]
public User ReviewerUser { get; set; }
/// <summary>
/// 操作时间
/// 默认值: CURRENT_TIMESTAMP
///</summary>
[Column("operation_time")]
public DateTime OperationTime { get; set; }
/// <summary>
/// 效期
///</summary>
[Column("eff_date")]
public DateTime? EffDate { get; set; }
/// <summary>
/// 出库入库类型(1入库2出库31还药32还空瓶)
///</summary>
[Column("type")]
public int Type { get; set; }
/// <summary>
/// 出入库调拨单id
///</summary>
[Column("invoice_id")]
public string InvoiceId { get; set; }
/// <summary>
/// 列号
///</summary>
[Column("col_no")]
public int ColNo { get; set; }
/// <summary>
/// 抽屉号
///</summary>
[Column("drawer_no")]
public int DrawerNo { get; set; }
/// <summary>
/// 取药科室
///</summary>
[Column("department_id")]
public string DepartmentId { get; set; }
/// <summary>
/// 是否已经退药(0:没有1:还了部分2:完成)
/// 默认值: 0
///</summary>
[Column("status")]
public int Status { get; set; }
/// <summary>
/// 退药量
/// 默认值: 0
///</summary>
[Column("return_quantity1")]
public int ReturnQuantity1 { get; set; }
/// <summary>
/// 退空瓶量
/// 默认值: 0
///</summary>
[Column("return_quantity2")]
public int ReturnQuantity2 { get; set; }
[Column(IsColumn = false)]
public int CurrentReturnQuantity { get; set; }
/// <summary>
/// 取药记录id
///</summary>
[Column("get_id")]
public int? GetId { get; set; }
/// <summary>
/// 是否已经销毁
/// 默认值: 0
///</summary>
[Column("is_destroy")]
public int? IsDestroy { get; set; }
[Column(IsColumn = false)]
public int CanReturnQuantity
{
get => Quantity - ReturnQuantity1 - ReturnQuantity2;
}
//是否选中
[Column(IsColumn = false)]
public bool IsSelected { get; set; }
[Column(IsColumn =false)]
public string Location
{
get => DrawerNo + "-" + ColNo;
}
}
}

View File

@ -0,0 +1,133 @@
using LinqToDB.Mapping;
using System;
using System.Collections.Generic;
using System.Linq;
namespace MasaBlazorApp3.Pojo
{
/// <summary>
///
///</summary>
[Table("order_detail")]
public class OrderDetail
{
/// <summary>
///
///</summary>
///
[PrimaryKey]
[Column("id")]
public int Id { get; set; }
/// <summary>
///
/// 默认值: NULL
///</summary>
//[SugarColumn(ColumnName = "order_id")]
//public int? OrderId { get; set; }
/// <summary>
///
///</summary>
[Column("patient_id")]
public string PatientId { get; set; }
/// <summary>
///
///</summary>
[Column("order_no")]
public string OrderNo { get; set; }
/// <summary>
///
///</summary>
[Column("charge_date")]
public DateTime ChargeDate { get; set; }
/// <summary>
///
/// 默认值: NULL
///</summary>
//[SugarColumn(ColumnName = "serial_no")]
//public int? SerialNo { get; set; }
/// <summary>
///
///</summary>
[Column("drug_id")]
public string DrugId { get; set; }
[Association(ThisKey = nameof(DrugId), OtherKey = nameof(DrugInfo.DrugId))]
public DrugInfo Drug { get; set; } = new();
/// <summary>
///
///</summary>
[Column("quantity")]
public int Quantity { get; set; }
/// <summary>
///
/// 默认值: NULL
///</summary>
[Column("order_unit")]
public string OrderUnit { get; set; }
/// <summary>
///
/// 默认值: 1
///</summary>
[Column("unit_convercoef")]
public int? UnitConvercoef { get; set; }
/// <summary>
///
/// 默认值: NULL
///</summary>
[Column("set_manu_no")]
public string SetManuNo { get; set; }
/// <summary>
///
/// 默认值: NULL
///</summary>
[Column("set_eff_date")]
public string SetEffDate { get; set; }
/// <summary>
///
/// 默认值: NULL
///</summary>
//[SugarColumn(ColumnName = "price")]
//public string Price { get; set; }
/// <summary>
///
/// 默认值: NULL
///</summary>
//[SugarColumn(ColumnName = "total_price")]
//public string TotalPrice { get; set; }
/// <summary>
///
/// 默认值: NULL
///</summary>
[Column("use_discrip")]
public string UseDiscrip { get; set; }
/// <summary>
///
/// 默认值: NULL
///</summary>
[Column("use_frequ")]
public string UseFrequ { get; set; }
/// <summary>
///
/// 默认值: NULL
///</summary>
[Column("use_once")]
public string UseOnce { get; set; }
/// <summary>
///
/// 默认值: NULL
///</summary>
[Column("use_by")]
public string UseBy { get; set; }
/// <summary>
///
/// 默认值: '0'
///</summary>
[Column("use_self")]
public string UseSelf { get; set; }
/// <summary>
///
/// 默认值: NULL
///</summary>
[Column("use_dosage")]
public string UseDosage { get; set; }
}
}

View File

@ -0,0 +1,33 @@
using LinqToDB.Mapping;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MasaBlazorApp3.Pojo
{
[Table("hkc_order_finish")]
public class OrderFinish
{
[PrimaryKey]
[Column("id")]
public int Id { get; set; }
[Column("pharmacy")]
public string Pharmacy { get; set; }
[Column("patient_id")]
public string PatientId { get; set; }
[Column("order_no")]
public string OrderNo { get; set; }
[Column("state")]
public int State { get; set; }
[Column("operator")]
public string Operator { get; set; }
}
}

View File

@ -0,0 +1,159 @@
using LinqToDB.Mapping;
using System;
using System.Collections.Generic;
using System.Linq;
namespace MasaBlazorApp3.Pojo
{
/// <summary>
///
///</summary>
[Table("order_info")]
public class OrderInfo
{
/// <summary>
///
///</summary>
///
[PrimaryKey, Identity]
[Column("order_id")]
public int OrderId { get; set; }
/// <summary>
///
/// 默认值: NULL
///</summary>
[Column("pharmacy")]
public string Pharmacy { get; set; }
/// <summary>
///
///</summary>
[Column("order_no")]
public string OrderNo { get; set; }
/// <summary>
///
///</summary>
[Column("patient_id")]
public string PatientId { get; set; }
/// <summary>
///
///</summary>
[Column("p_name")]
public string PatientName { get; set; }
/// <summary>
///
/// 默认值: NULL
///</summary>
[Column("sex")]
public string Sex { get; set; }
/// <summary>
///
/// 默认值: NULL
///</summary>
[Column("age")]
public string Age { get; set; }
/// <summary>
///
/// 默认值: NULL
///</summary>
[Column("id_number")]
public string IdNumber { get; set; }
/// <summary>
///
/// 默认值: NULL
///</summary>
[Column("invoice_no")]
public string InvoiceNo { get; set; }
/// <summary>
///
/// 默认值: NULL
///</summary>
[Column("patient_no")]
public string PatientNo { get; set; }
/// <summary>
///
/// 默认值: NULL
///</summary>
[Column("doctor_name")]
public string DoctorName { get; set; }
/// <summary>
///
/// 默认值: NULL
///</summary>
[Column("order_date")]
public DateTime OrderDate { get; set; }
/// <summary>
///
///</summary>
[Column("charge_date")]
public DateTime ChargeDate { get; set; } = DateTime.Now;
/// <summary>
///
/// 默认值: NULL
///</summary>
[Column("recv_date")]
public DateTime RecvDate { get; set; }
/// <summary>
///
/// 默认值: NULL
///</summary>
[Column("dept_name")]
public string DeptName { get; set; }
/// <summary>
///
/// 默认值: NULL
///</summary>
[Column("disease")]
public string Disease { get; set; }
/// <summary>
///
/// 默认值: NULL
///</summary>
[Column("order_type")]
public string OrderType { get; set; }
/// <summary>
///
/// 默认值: NULL
///</summary>
[Column("charge_type")]
public string ChargeType { get; set; }
/// <summary>
///
///</summary>
[Column("dm_status")]
public int Status { get; set; }
/// <summary>
///
/// 默认值: 0
///</summary>
[Column("his_disp_flag")]
public int? HisDispFlag { get; set; }
/// <summary>
///
/// 默认值: 0
///</summary>
[Column("cancel_flag")]
public int? CancelFlag { get; set; }
/// <summary>
///
/// 默认值: 0
///</summary>
[Column("win_no")]
public int WinNo { get; set; } = 0;
/// <summary>
///
/// 默认值: 0
///</summary>
[Column("state")]
public int state { get; set; } = 0;
}
}

View File

@ -0,0 +1,207 @@
using Mysqlx.Crud;
namespace MasaBlazorApp3.Pojo
{
[Serializable]
public class Premission
{
public Premission Parent { get; set; } = null;
public void AddChild(Premission item)
{
item.Parent = this;
this.Items = this.Items.Concat(new Premission[] { item });
}
public int Id { get; set; }
public string PremissionName { get; set; }
/// <summary>
/// 菜单路径
/// <summary>
public string PremissionPath { get; set; }
public IEnumerable<Premission> Items { get; set; } = Enumerable.Empty<Premission>();
public List<Premission> getAdminPremission()
{
var list = new List<Premission>();
Premission q = new Premission
{
Id = 1,
PremissionName = "出库",
PremissionPath = "take"
};
q.AddChild(new Premission()
{
Id = 11,
PremissionName = "处方取药",
PremissionPath = "/take/order"
});
q.AddChild(new Premission()
{
Id = 12,
PremissionName = "调拨取药",
PremissionPath = "/take/invoice"
});
q.AddChild(new Premission()
{
Id = 13,
PremissionName = "抽屉取药",
PremissionPath = "/take/drawer"
});
q.AddChild(new Premission()
{
Id = 14,
PremissionName = "自选取药",
PremissionPath = "/take/self"
});
q.AddChild(new Premission()
{
Id = 15,
PremissionName = "取药记录",
PremissionPath = "/take/record/2"
});
Premission j = new Premission
{
Id = 2,
PremissionName = "入库",
PremissionPath = "add"
};
j.AddChild(new Premission()
{
Id = 21,
PremissionName = "调拨入库",
PremissionPath = "/add/invoice"
});
//j.AddChild(new Premission()
//{
// Id = 22,
// PremissionName = "请领入库",
// PremissionPath = "/add/apply"
//});
j.AddChild(new Premission()
{
Id = 23,
PremissionName = "抽屉入库",
PremissionPath = "/add/drawer"
});
j.AddChild(new Premission()
{
Id = 24,
PremissionName = "入库记录",
PremissionPath = "/add/record/1"
});
Premission h = new Premission
{
Id = 3,
PremissionName = "归还",
PremissionPath = "return"
};
h.AddChild(new Premission()
{
Id = 31,
PremissionName = "归还药品(处方)",
PremissionPath = "/return/order"
});
h.AddChild(new Premission()
{
Id = 32,
PremissionName = "归还药品(记录)",
PremissionPath = "/return/byRecord"
});
h.AddChild(new Premission()
{
Id = 33,
PremissionName = "归还空瓶",
PremissionPath = "/return/empty"
});
h.AddChild(new Premission()
{
Id = 34,
PremissionName = "归还记录(药品)",
PremissionPath = "/return/record1/31"
});
h.AddChild(new Premission()
{
Id = 35,
PremissionName = "归还记录(空瓶)",
PremissionPath = "/return/record2/32"
});
Premission k = new Premission
{
Id = 4,
PremissionName = "库存管理",
PremissionPath = "stock"
};
k.AddChild(new Premission()
{
Id = 41,
PremissionName = "库存列表",
PremissionPath = "/stock/list"
});
k.AddChild(new Premission()
{
Id = 42,
PremissionName = "库位绑定",
PremissionPath = "/stock/binding"
});
k.AddChild(new Premission()
{
Id = 43,
PremissionName = "库存盘点",
//PremissionName = "盘点交接",
PremissionPath = "/stock/check"
});
k.AddChild(new Premission()
{
Id = 44,
PremissionName = "盘点记录",
//PremissionPath = "/stock/checkRecord"
PremissionPath = "/stock/record/4"
});
k.AddChild(new Premission()
{
Id = 45,
PremissionName = "药品信息",
PremissionPath = "/stock/drug"
});
k.AddChild(new Premission()
{
Id = 46,
PremissionName = "药品标定",
PremissionPath = "/stock/biaoDing"
});
Premission x = new Premission
{
Id = 5,
PremissionName = "系统管理",
PremissionPath = "manage"
};
x.AddChild(new Premission()
{
Id = 51,
PremissionName = "用户管理",
PremissionPath = "/manage/user"
});
x.AddChild(new Premission()
{
Id = 52,
PremissionName = "权限管理",
PremissionPath = "/manage/role"
});
list.Add(q);
list.Add(j);
list.Add(h);
list.Add(k);
list.Add(x);
return list;
}
}
}

View File

@ -0,0 +1,50 @@
using LinqToDB.Mapping;
namespace MasaBlazorApp3.Pojo
{
[Table("role")]
public class Role
{
[PrimaryKey, Identity]
[Column("id")]
public int Id { get; set; }
[Column("role_name")]
public string RoleName { get; set; }
//[Column("role_des")]
//public string Description { get; set; }
[Column("machine_id")]
public string MachineId { get; set; }
[Column("permissions")]
public string permissions { get; set; }
[Column(IsColumn = false)]
public List<Premission> permissionList {
get
{
return null;
}
}
[Column(IsColumn = false)]
public IEnumerable<int> permissionIds
{
get
{
return !String.IsNullOrEmpty(permissions) ? permissions.Split(",").Select(s => Convert.ToInt32(s)): Enumerable.Empty<int>();
}
set
{
if (value == null)
{
permissions = "";
} else
{
permissions = string.Join(",", value);
}
}
}
}
}

View File

@ -0,0 +1,39 @@

using LinqToDB.Mapping;
namespace MasaBlazorApp3.Pojo
{
[Table("user_list")]
public class User
{
[Column("id")]
[PrimaryKey, Identity]
public int Id { get; set; }
[Column("user_id")]
public string Username { get; set; }
[Column("pass_word")]
public string Password { get; set; }
[Column("user_name")]
public string NickName { get; set; }
[Column("machine_id")]
public string MachineId { get; set; }
[Column("sign")]
public byte[] Sign { get; set; }
[Column("machine_role_id")]
public int RoleId { get; set; }
[Association(ThisKey = nameof(RoleId), OtherKey = nameof(Role.Id))]
public Role role { get; set; }
}
}

View File

@ -0,0 +1,34 @@
using Radzen.Blazor;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MasaBlazorApp3.Pojo.Vo
{
public class InvoiceVo
{
public DrugInfo Drug { get; set; }
public InOutInvoice Invoice { get; set; }
public List<ChannelStock> ChannelStocks { get; set; }
public int StockQuantity { get; set; }
public int Quantity { get; set; }
public int GetQuantity { get; set; } = 0;
public int Status { get; set; } = 0;
public int[] BeforeQuantity { get; set; } = new int[] { 0, 0, 0, 0, 0, 0, 0, 0, 0 };
public int[] AfterQuantity { get; set; } = new int[] { 0, 0, 0, 0, 0, 0, 0, 0, 0 };
public int AddQuantity { get; set; } = 0;
public RadzenDataGrid<ChannelStock> Grid { get; set; }
}
}

View File

@ -0,0 +1,37 @@
using Radzen.Blazor;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MasaBlazorApp3.Pojo.Vo
{
public class OperationVo<T>
{
public DrugInfo Drug { get; set; }
public T data { get; set; }
public List<ChannelStock> ChannelStocks { get; set; }
public int StockQuantity { get; set; }
public int Quantity { get; set; }
public int GetQuantity { get; set; } = 0;
public int Status { get; set; } = 0;
public int[] BeforeQuantity { get; set; } = new int[] { 0, 0, 0, 0, 0, 0, 0, 0, 0 };
public int[] AfterQuantity { get; set; } = new int[] { 0, 0, 0, 0, 0, 0, 0, 0, 0 };
public int AddQuantity { get; set; } = 0;
public int ReturnQuantity { get; set; } = 0;
public RadzenDataGrid<ChannelStock> Grid { get; set; }
}
}

View File

@ -0,0 +1,32 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MasaBlazorApp3.Pojo.Vo
{
public class OrderTakeVo
{
public DrugInfo Drug { get; set; }
public OrderDetail OrderDetail { get; set; }
public ChannelStock ChannelStock { get; set; }
public int StockQuantity { get; set; }
public int Quantity { get; set;}
public int GetQuantity { get; set; } = 0;
public int Status { get; set; } = 0;
public int[] BeforeQuantity { get; set; } = new int[] { 0,0,0,0,0,0,0,0,0 };
public int[] AfterQuantity { get; set; } = new int[] { 0, 0, 0, 0, 0, 0, 0, 0, 0 };
public int AddQuantity { get; set; } = 0;
}
}

View File

@ -0,0 +1,987 @@
using log4net;
using log4net.Repository.Hierarchy;
using System;
using System.Collections.Generic;
using System.ComponentModel.Design;
using System.Configuration;
using System.IO.Ports;
using System.Linq;
using System.Reflection.Metadata;
using System.Speech.Synthesis;
using System.Text;
using System.Threading.Channels;
using System.Threading.Tasks;
using System.Timers;
using System.Windows;
using System.Windows.Markup;
using System.Reflection;
using MasaBlazorApp3.Pojo.Config;
using Microsoft.Extensions.Options;
using LinqToDB.Common;
namespace MasaBlazorApp3.Port
{
public class PortUtil
{
private readonly ILog logger = LogManager.GetLogger(typeof(PortUtil));
// 抽屉串口
public SerialPort drawerSerial;
// can总线串口
public SerialPort canBusSerial;
// 条码枪串口
public SerialPort scanCodeSerial;
public bool Operate { get; set; }
public DateTime dateTime { get; set; } = DateTime.Now;
// 当前操作的抽屉号
public int DrawerNo { get; set; }
// 当前操作的库位号列表
public int[] ColNos { get; set; } = new int[] { };
// 当前操作查数的库位号列表
public List<int> ColNoLst { get; set; } = new List<int>();
// 当前操作开药盒的库位号
public int OpenBoxColNo { get; set; } = 0;
private readonly PortConfig _portConfig;
public PortUtil(IOptions<PortConfig> setting)
{
_portConfig = setting.Value;
try
{
string DrawerPortPath = _portConfig.drawerPortPath;
logger.Info($"打开抽屉串口【{DrawerPortPath}】");
drawerSerial = new SerialPort(DrawerPortPath, 9600, Parity.None, 8);
drawerSerial.Open();
logger.Info($"抽屉串口打开结果【{drawerSerial.IsOpen}】");
}
catch (Exception e)
{
logger.Error("抽屉串口打开错误" + e.Message);
}
try {
string ScanCodePortPath = _portConfig.scanCodePortPath;
logger.Info($"打开条码枪串口【{ScanCodePortPath}】");
scanCodeSerial = new SerialPort(ScanCodePortPath, 9600, Parity.None, 8);
scanCodeSerial.DataReceived += (object sender, System.IO.Ports.SerialDataReceivedEventArgs e) =>
{
string code = scanCodeSerial.ReadExisting();
};
scanCodeSerial.Open();
logger.Info($"条码枪串口打开结果【{scanCodeSerial.IsOpen}】");
}
catch (Exception e)
{
logger.Error("条码枪串口打开错误" + e.Message);
}
if (_portConfig.canBusExsit)
{
try
{
string CanBusPortPath = _portConfig.canBusPortPath;
logger.Info($"打开can总线串口【{CanBusPortPath}】");
canBusSerial = new SerialPort(CanBusPortPath, 57600, Parity.None, 8);
canBusSerial.Open();
logger.Info($"can总线串口打开结果【{canBusSerial.IsOpen}】");
}
catch (Exception e)
{
logger.Error("can总线串口打开错误" + e.Message);
}
}
}
private byte[] GetBufferByPort(SerialPort serialPort, int length, int timeout)
{
int _length = 0;
DateTime start = DateTime.Now;
DateTime end = DateTime.Now;
while(_length != length && end.Subtract(start).TotalMilliseconds < timeout)
{
_length = serialPort.BytesToRead;
end = DateTime.Now;
}
if(_length != length)
{
throw new TimeoutException($"串口【{serialPort.PortName}】交互超时");
}
byte[] buffer = new byte[length];
serialPort.Read(buffer, 0, length);
return buffer;
}
private Task<byte[]> GetBufferByPort(SerialPort serialPort, int length)
{
return Task.Run(() => GetBufferByPort(serialPort, length, 3000));
}
public static SpeechSynthesizer speechSynthesizer = new SpeechSynthesizer();
public void SpeakAsync(string textinfo)
{
speechSynthesizer.SpeakAsync(textinfo);
}
#region
// 打开抽屉
public async Task<byte[]> OpenDrawer(int DrawerNo)
{
drawerSerial.DiscardInBuffer();
byte[] buffer = new byte[] { 0xaa, 0x41, (byte)DrawerNo, 0xee };
if (_portConfig.drawerProtocol == 485)
{
if (DrawerNo > 8)
{
buffer = new byte[] { 0xaa, 0x21, (byte)(DrawerNo - 8), 0xee };
}
else
{
buffer = new byte[] { 0xaa, 0x11, (byte)DrawerNo, 0xee };
}
}
logger.Info($"打开抽屉,串口数据:{Convert.ToHexString(buffer)}");
drawerSerial.Write(buffer, 0, 4);
return await GetBufferByPort(drawerSerial, 11);
}
public async Task<bool> OpenDrawerStatus(int DrawerNo)
{
byte[] buffer = await OpenDrawer(DrawerNo);
int[] r = buffer.Select(it => Convert.ToInt32(it)).ToArray();
int index = DrawerNo > 8 ? DrawerNo - 7 : DrawerNo + 1;
return r[index] == 0;
}
// 查询抽屉状态
public async Task<byte[]> CheckDrawerStatus(int DrawerNo)
{
drawerSerial.DiscardInBuffer();
byte[] buffer = new byte[] { 0xaa, 0x42, 0xee };
if (_portConfig.drawerProtocol == 485)
{
if (DrawerNo > 8)
{
buffer = new byte[] { 0xaa, 0x22, 0xee };
}
else
{
buffer = new byte[] { 0xaa, 0x12, 0xee };
}
}
logger.Info($"查询抽屉状态,串口数据:{Convert.ToHexString(buffer)}");
drawerSerial.Write(buffer, 0, 3);
return await GetBufferByPort(drawerSerial, 11);
}
public async Task<bool> CheckDrawerStatus2(int DrawerNo)
{
byte[] buffer = await CheckDrawerStatus(DrawerNo);
int[] r = buffer.Select(it => Convert.ToInt32(it)).ToArray();
int index = DrawerNo > 8 ? DrawerNo - 7 : DrawerNo + 1;
return r[index] != 0;
}
#endregion
#region can总线串口操作
#region
// 后门状态
public async Task<byte[]> BackDoorState()
{
canBusSerial.DiscardInBuffer();
byte[] buffer = new byte[] { 0xaa, (byte)(_portConfig.doorAddr), 0x02, 0x00, 0x00, 0x00, 0x00, 0xee };
canBusSerial.Write(buffer, 0, 8);
return await GetBufferByPort(canBusSerial, 8);
}
// 打开电控门储物箱(有灯使能)
public async Task<byte[]> OpenStorage()
{
canBusSerial.DiscardInBuffer();
byte[] buffer = new byte[] { 0xaa, (byte)(_portConfig.doorAddr), 0x01, (byte)_portConfig.storageBoxAddr, 0x00, 0x00, 0x00, 0xee };
canBusSerial.Write(buffer, 0, 8);
return await GetBufferByPort(canBusSerial, 8);
}
// 关闭电控门储物箱(有灯失能)
public void CloseStorage()
{
byte[] buffer = new byte[] { 0xaa, (byte)(_portConfig.doorAddr), 0x04, 0x00, 0x00, 0x00, 0x00, 0xee };
canBusSerial.Write(buffer, 0, 8);
}
// 打开普通储物箱(无灯)
public void OpenStorageBox()
{
byte[] buffer = new byte[] { 0xaa, (byte)(_portConfig.storageBoxAddr), 0x03, 0x00, 0x00, 0x00, 0x00, 0xee };
canBusSerial.Write(buffer, 0, 8);
}
// 关闭普通储物箱(无灯)
public void CloseStorageBox()
{
byte[] buffer = new byte[] { 0xaa, (byte)(_portConfig.storageBoxAddr), 0x04, 0x00, 0x00, 0x00, 0x00, 0xee };
canBusSerial.Write(buffer, 0, 8);
}
private int[] CheckStorageStatus(int[] data)
{
int a = data[0];
int b = data[1];
int[] intA = Decimal2Chunks(a);
int[] intB = Decimal2Chunks(b);
int[] r = new int[intA.Length + intB.Length];
Array.Copy(intA, 0, r, 0, intA.Length);
Array.Copy(intB, 0, r, intA.Length, intB.Length);
return r;
}
private int[] Decimal2Chunks(int d)
{
string s = Convert.ToString(d, 2);
List<int> t = s.Split().Select(it => Convert.ToInt32(it)).Reverse().ToList();
while (t.Count < 8)
{
t.Add(0);
}
return t.ToArray();
}
#endregion
#region
// 以抽屉为单位获取抽屉内所有库位的药品数量
public async Task<byte[]> CheckQuantityByDrawer(int DrawerNo)
{
canBusSerial.DiscardInBuffer();
byte[] buffer = new byte[] { 0xaa, (byte)(0xf0 + DrawerNo), 0x01, 0x00, 0x00, 0x00, 0x00, 0xee };
logger.Info($"单支板发送库位数量查询【{string.Join(",", buffer)}】");
canBusSerial.Write(buffer, 0, 8);
return await GetBufferByPort(canBusSerial, 13);
}
// 获取单个单支板药品数量
public async Task<byte[]> CheckQuantityByCol(int DrawerNo, int colNo)
{
canBusSerial.DiscardInBuffer();
var channel = Convert.ToInt32((DrawerNo * 10 + colNo).ToString(), 16);
byte[] buffer = new byte[] { 0xaa, (byte)channel, 0x08, 0x00, 0x00, 0x00, 0x00, 0xee };
canBusSerial.Write(buffer, 0, 8);
return await GetBufferByPort(canBusSerial, 8);
}
// 以抽屉为单位有药位置亮灯
public void HasLightOnByDrawer(int DrawerNo)
{
byte[] buffer = new byte[] { 0xaa, (byte)(0xf0 + DrawerNo), 0x02, 0x00, 0x00, 0x00, 0x00, 0xee };
canBusSerial.Write(buffer, 0, 8);
}
// 以抽屉为单位无药位置亮灯
public void NoLightOnByDrawer(int DrawerNo)
{
byte[] buffer = new byte[] { 0xaa, (byte)(0xf0 + DrawerNo), 0x03, 0x00, 0x00, 0x00, 0x00, 0xee };
canBusSerial.Write(buffer, 0, 8);
}
// 以抽屉为单位灭灯
public void LightOffByDrawer(int DrawerNo)
{
byte[] buffer = new byte[] { 0xaa, (byte)(0xf0 + DrawerNo), 0x06, 0x00, 0x00, 0x00, 0x00, 0xee };
canBusSerial.Write(buffer, 0, 8);
}
// 以单支板为单位有药位置亮灯
public async Task HasLightOnByCol(int DrawerNo, int[] ColNos)
{
for (int i = 0; i < ColNos.Length; i++)
{
var channel = Convert.ToInt32((DrawerNo * 10 + ColNos[i]).ToString(), 16);
byte[] buffer = new byte[] { 0xaa, (byte)channel, 0x0a, 0x00, 0x00, 0x00, 0x00, 0xee };
canBusSerial.Write(buffer, 0, 8);
await Task.Delay(TimeSpan.FromMilliseconds(20));
}
}
// 以单支板为单位无药位置亮灯
public async Task NoLightOnByCol(int DrawerNo, int[] ColNos)
{
for (int i = 0; i < ColNos.Length; i++)
{
var channel = Convert.ToInt32((DrawerNo * 10 + ColNos[i]).ToString(), 16);
byte[] buffer = new byte[] { 0xaa, (byte)channel, 0x0b, 0x00, 0x00, 0x00, 0x00, 0xee };
canBusSerial.Write(buffer, 0, 8);
await Task.Delay(TimeSpan.FromMilliseconds(20));
}
}
// 广播灭灯
public void AllLightOff()
{
byte[] buffer = new byte[] { 0xaa, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0xee };
canBusSerial.Write(buffer, 0, 8);
}
#endregion
#region
// 指定药盒指示灯开启使能开锁
public async Task BoxLockLightOn(int DrawerNo, int[] ColNos)
{
for (int i = 0; i < ColNos.Length; i++)
{
var channel = Convert.ToInt32((DrawerNo * 10 + ColNos[i]).ToString(), 16);
byte[] buffer = new byte[] { 0xaa, (byte)channel, 0x03, 0x00, 0x00, 0x00, 0x00, 0xee };
canBusSerial.Write(buffer, 0, 8);
await Task.Delay(TimeSpan.FromMilliseconds(20));
}
}
// 指定药盒指示灯开启失能开锁
public async Task BoxLockLightOff(int DrawerNo, int[] ColNos)
{
for (int i = 0; i < ColNos.Length; i++)
{
var channel = Convert.ToInt32((DrawerNo * 10 + ColNos[i]).ToString(), 16);
byte[] buffer = new byte[] { 0xaa, (byte)channel, 0x04, 0x00, 0x00, 0x00, 0x00, 0xee };
canBusSerial.Write(buffer, 0, 8);
await Task.Delay(TimeSpan.FromMilliseconds(20));
}
}
// 指定药盒状态查询
public async Task<byte[]> BoxLockState(int DrawerNo, int ColNo)
{
canBusSerial.DiscardInBuffer();
var channel = Convert.ToInt32((DrawerNo * 10 + ColNo).ToString(), 16);
byte[] buffer = new byte[] { 0xaa, (byte)channel, 0x02, 0x00, 0x00, 0x00, 0x00, 0xee };
canBusSerial.Write(buffer, 0, 8);
return await GetBufferByPort(canBusSerial, 8);
}
// 以抽屉为单位药盒指示灯开启使能开锁
public async Task BoxLockLightOnByDrawer(int DrawerNo)
{
canBusSerial.DiscardInBuffer();
byte[] buffer = new byte[] { 0xaa, (byte)(0xf0 + DrawerNo), 0x04, 0x00, 0x00, 0x00, 0x00, 0xee };
canBusSerial.Write(buffer, 0, 8);
}
// 以抽屉为单位药盒指示灯开启失能开锁
public async Task BoxLockLightOffByDrawer(int DrawerNo)
{
canBusSerial.DiscardInBuffer();
byte[] buffer = new byte[] { 0xaa, (byte)(0xf0 + DrawerNo), 0x05, 0x00, 0x00, 0x00, 0x00, 0xee };
canBusSerial.Write(buffer, 0, 8);
}
/// <summary>
/// 开指定库位的药盒
/// </summary>
/// <param name="ColNo"></param>
/// <returns></returns>
public async Task<bool> OpenBoxByColNo(int colNo)
{
if (colNo > 0)
{
canBusSerial.DiscardInBuffer();
int ColNo = colNo;
int[] iNum = new int[] { 4, 2, 1 };
var colNo2 = ColNo % 3 > 0 ? (ColNo % 3) - 1 : 2;
var bColNo = iNum[colNo2];
decimal decolNO = (decimal)ColNo;
var channel = Convert.ToInt32((DrawerNo * 10 + Math.Ceiling(decolNO / 3)).ToString(), 16);
byte[] buffer = new byte[] { 0xaa, (byte)channel, 5, (byte)bColNo, 0x00, 0x00, 0x00, 0xee };
//byte[] buffer = new byte[] { 0xaa, 0x11, 0x05,0x01, 0x00,0x00,0x00,0xee};
logger.Info($"开药盒{ColNo}【{Convert.ToHexString(buffer)}】");
canBusSerial.Write(buffer, 0, 8);
byte[] retBuffer = await GetBufferByPort(canBusSerial, 8);
logger.Info($"开药盒返回{ColNo}【{Convert.ToHexString(retBuffer)}】");
int[] r = retBuffer.Select(it => Convert.ToInt32(it)).ToArray();
if (r[4] > 0)
{
return true;
}
else
{
return false;
}
}
return false;
}
/// <summary>
/// 打开药盒
/// </summary>
/// <param name="ColNo"></param>
/// <returns></returns>
public async Task OpenBox()
{
for (int i = 0; i < ColNos.Length; i++)
{
canBusSerial.DiscardInBuffer();
int ColNo = ColNos[i];
int[] iNum = new int[] { 4, 2, 1 };
var colNo2 = ColNo % 3 > 0 ? (ColNo % 3) - 1 : 2;
var bColNo = iNum[colNo2];
decimal decolNO = (decimal)ColNo;
var channel = Convert.ToInt32((DrawerNo * 10 + Math.Ceiling(decolNO / 3)).ToString(), 16);
byte[] buffer = new byte[] { 0xaa, (byte)channel, 5, (byte)bColNo, 0x00, 0x00, 0x00, 0xee };
//byte[] buffer = new byte[] { 0xaa, 0x11, 0x05,0x01, 0x00,0x00,0x00,0xee};
logger.Info($"{Convert.ToHexString(buffer)}");
canBusSerial.Write(buffer, 0, 8);
await Task.Delay(800);
}
}
// 以抽屉为单位药盒指示灯开启使能开锁
public async Task BoxLockLightOnByDrawer()
{
canBusSerial.DiscardInBuffer();
byte[] buffer = new byte[] { 0xaa, (byte)(0xf0 + DrawerNo), 0x04, 0x00, 0x00, 0x00, 0x00, 0xee };
canBusSerial.Write(buffer, 0, 8);
}
// 以抽屉为单位药盒指示灯开启失能开锁
public async Task BoxLockLightOffByDrawer()
{
canBusSerial.DiscardInBuffer();
byte[] buffer = new byte[] { 0xaa, (byte)(0xf0 + DrawerNo), 0x05, 0x00, 0x00, 0x00, 0x00, 0xee };
canBusSerial.Write(buffer, 0, 8);
}
#endregion
private string trim(string text)
{
//此处使用了转义字符如:\',\",\\,分别表示单引号,双引号,反斜杠
char[] TrimChar = { ' ', '-', '\'', '\"', '\\','(', ')','', '', '①', '②' };
return text.Trim(TrimChar);
}
#region 2.4
// 基础数据写入方法
public async void WriteChannelInfo(int type, string content, int drawerNo, int colNo)
{
canBusSerial.DiscardInBuffer();
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
byte[] contentBuf = Encoding.GetEncoding("gb2312").GetBytes(trim(content));
int channel = (drawerNo * 10 + colNo);
if (contentBuf.Length % 2 != 0)
{
Array.Resize(ref contentBuf, contentBuf.Length + 1);
}
byte[] buffer = new byte[] { 0xaa, (byte)channel, 1, (byte)type, 0, 0, 0, 0xee };
canBusSerial.Write(buffer, 0, 8);
await Task.Delay(20);
buffer[4] = 1;
for (int i = 0; i < contentBuf.Length; i += 2)
{
buffer[5] = contentBuf[i];
buffer[6] = contentBuf[i + 1];
canBusSerial.Write(buffer, 0, 8);
await Task.Delay(20);
}
buffer[4] = 2;
buffer[5] = 0;
buffer[6] = 0;
canBusSerial.Write(buffer, 0, 8);
await Task.Delay(20);
}
// 清除显示内容
public void ClearContent(int drawerNo, int colNo)
{
canBusSerial.DiscardInBuffer();
int channel = (drawerNo * 10 + colNo);
byte[] buffer = new byte[] { 0xaa, (byte)channel, 4, 0, 0, 0, 0, 0xee };
canBusSerial.Write(buffer, 0, 8);
}
// 刷新显示内容
public void ShowContent(int drawerNo, int colNo)
{
canBusSerial.DiscardInBuffer();
int channel = (drawerNo * 10 + colNo);
byte[] buffer = new byte[] { 0xaa, (byte)channel, 2, 0, 0, 0, 0, 0xee };
canBusSerial.Write(buffer, 0, 8);
}
// 取药或者加药亮灯
public void TakeQuantity(int drawerNo, int colNo, int quantity, int stock)
{
canBusSerial.DiscardInBuffer();
int channel = (drawerNo * 10 + colNo);
byte[] buffer = new byte[] { 0xaa, (byte)channel, 6, 0, 0, 0, 0, 0xee };
buffer[3] = (byte)(quantity >> 8);
buffer[4] = (byte)(quantity & 0xff);
buffer[5] = (byte)(stock >> 8);
buffer[6] = (byte)(stock & 0xff);
canBusSerial.Write(buffer, 0, 8);
}
// 写入数量
public void WriteQuantity(int drawerNo, int colNo, int quantity)
{
canBusSerial.DiscardInBuffer();
int channel = (drawerNo * 10 + colNo);
byte[] buffer = new byte[] { 0xaa, (byte)channel, 0x21, 0, 0, 0, 0, 0xee };
buffer[5] = (byte)(quantity >> 8);
buffer[6] = (byte)(quantity & 0xff);
canBusSerial.Write(buffer, 0, 8);
}
//清屏
public void ClearContentMethod(int drawerNo, int colNo)
{
decimal deColNo = colNo;
//var channel = drawerNo * 10 + Math.Ceiling(deColNo / 3);
int[] iNum = new int[] { 3, 2, 1 };
var colNo2 = colNo % 3 > 0 ? (colNo % 3) - 1 : 2;
var bColNo = Convert.ToInt32((iNum[colNo2] + 10).ToString(), 16);
//var index = Convert.ToInt32(((colNo % 3 == 0 ? 3 : colNo % 3)+10).ToString(),16);
int channel = Convert.ToInt32((drawerNo * 10 + Math.Ceiling((decimal)colNo / 3)).ToString(), 16);
byte[] buffer = new byte[] { 0xaa, (byte)channel, 0x09, (byte)bColNo, 0, 0, 0, 0xee };
canBusSerial.Write(buffer, 0, 8);
logger.Info($"清屏指令:{Convert.ToHexString(buffer)}");
}
//刷新内容
public async Task ShowContentMethod(int drawerNo, int colNo)
{
int channel = Convert.ToInt32((drawerNo * 10 + Math.Ceiling((decimal)colNo / 3)).ToString(), 16);
byte[] buffer = new byte[] { 0xaa, (byte)channel, 0x0c, 0x00, 0x00, 0x00, 0x00, 0xee };
logger.Info($"刷新内容指令:{Convert.ToHexString(buffer)}");
canBusSerial.Write(buffer, 0, 8);
}
// 基础数据写入方法
public async Task WriteChannelInfoMethod(int type, string content, int drawerNo, int colNo)
{
try
{
canBusSerial.DiscardInBuffer();
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
if (content.Length > 10)
{
content = content.Substring(0, 10);
}
byte[] contentBuf = Encoding.GetEncoding("gb2312").GetBytes(trim(content));
int channel = Convert.ToInt32((drawerNo * 10 + Math.Ceiling((decimal)colNo / 3)).ToString(), 16);
int[] iNum = new int[] { 3, 2, 1 };
var colNo2 = colNo % 3 > 0 ? (colNo % 3) - 1 : 2;
var bColNo = iNum[colNo2] + 160;
//var index = (colNo % 3 == 0 ? 3 : colNo % 3)+160;
if (contentBuf.Length % 2 != 0)
{
Array.Resize(ref contentBuf, contentBuf.Length + 1);
}
byte[] buffer = new byte[] { 0xaa, (byte)channel, (byte)bColNo, (byte)type, 0, 0, 0, 0xee };
canBusSerial.Write(buffer, 0, 8);
logger.Info($"开始写标签指令:{Convert.ToHexString(buffer)}");
Thread.Sleep(20);
buffer[4] = 1;
for (int i = 0; i < contentBuf.Length; i += 2)
{
buffer[5] = contentBuf[i];
buffer[6] = contentBuf[i + 1];
canBusSerial.Write(buffer, 0, 8);
logger.Info($"写标签指令:{Convert.ToHexString(buffer)}");
Thread.Sleep(50);
}
buffer[4] = 2;
buffer[5] = 0;
buffer[6] = 0;
canBusSerial.Write(buffer, 0, 8);
logger.Info($"结束写标签指令:{Convert.ToHexString(buffer)}");
Thread.Sleep(20);
}
catch (Exception ex)
{
logger.Info($"2.4寸汉显屏异常ex:{ex.Message}");
}
}
public async Task WriteQuantityMethod(int quantity, int drawerNo, int colNo)
{
try
{
logger.Info($"写数量:{drawerNo}-{colNo}{quantity}");
canBusSerial.DiscardInBuffer();
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
string strQuantity = quantity.ToString("X");
if (strQuantity.Length % 2 != 0)
{
strQuantity = "0" + strQuantity;
}
int channel = Convert.ToInt32((drawerNo * 10 + Math.Ceiling((decimal)colNo / 3)).ToString(), 16);
int[] iNum = new int[] { 3, 2, 1 };
var colNo2 = colNo % 3 > 0 ? (colNo % 3) - 1 : 2;
var bColNo = iNum[colNo2] + 160;
byte[] buffer = new byte[] { 0xaa, (byte)channel, (byte)bColNo, 0xf2, 01, 0, 0, 0xee };
if (strQuantity.Length >= 4)
{
buffer[5] = Convert.ToByte(strQuantity.Substring(0, 2), 16);
buffer[6] = Convert.ToByte(strQuantity.Substring(2, 2), 16);
}
else
{
buffer[6] = Convert.ToByte(strQuantity.Substring(0, 2), 16);
}
canBusSerial.Write(buffer, 0, 8);
logger.Info($"写标签指令:{Convert.ToHexString(buffer)}");
}
catch (Exception ex)
{
logger.Info($"写标签数量异常ex:{ex.Message}");
}
}
#endregion
#region
// 打开回收箱
public async Task<byte[]> OpenRecover()
{
canBusSerial.DiscardInBuffer();
byte[] buffer = new byte[] { 0xAA, 0x9A, 0x04, 0x00, 0x00, 0x00, 0x00, 0xEE };
canBusSerial.Write(buffer, 0, 8);
return await GetBufferByPort(canBusSerial, 8);
}
// 回收箱状态查询
public async Task<byte[]> CheckRecoverStatus()
{
canBusSerial.DiscardInBuffer();
byte[] buffer = new byte[] { 0xAA, 0x9A, 0x03, 0x00, 0x00, 0x00, 0x00, 0xEE };
canBusSerial.Write(buffer, 0, 8);
return await GetBufferByPort(canBusSerial, 8);
}
// 回收箱回收数量查询
public async Task<byte[]> CheckRecoverQuantity(int ColNo)
{
canBusSerial.DiscardInBuffer();
byte[] buffer = new byte[] { 0xAA, 0x9A, (byte)(ColNo > 3 ? 2 : 1), 0x00, 0x00, 0x00, 0x00, 0xEE };
canBusSerial.Write(buffer, 0, 8);
return await GetBufferByPort(canBusSerial, 8);
}
#endregion
#region
// 以板子为单位获取抽屉内所有库位的药品数量
public async Task<byte[]> CheckQuantityByAddr(int DrawerNo)
{
canBusSerial.DiscardInBuffer();
var channel = Convert.ToInt32((DrawerNo * 10 + 1).ToString(), 16);
byte[] buffer = new byte[] { 0xaa, (byte)(channel), 0x28, 0x00, 0x00, 0x00, 0x00, 0xee };
logger.Info($"称重发送库位数量查询1【{string.Join(",", buffer)}】");
canBusSerial.Write(buffer, 0, 8);
byte[] result1 = await GetBufferByPort(canBusSerial, 8);
var channel2 = Convert.ToInt32((DrawerNo * 10 + 2).ToString(), 16);
byte[] buffer2 = new byte[] { 0xaa, (byte)(channel2), 0x28, 0x00, 0x00, 0x00, 0x00, 0xee };
logger.Info($"称重发送库位数量查询2【{string.Join(",", buffer2)}】");
canBusSerial.Write(buffer2, 0, 8);
byte[] result2 = await GetBufferByPort(canBusSerial, 8);
byte[] res = new byte[6];
Array.Copy(result1, 3, res, 0, 3);
Array.Copy(result2, 3, res, 3, 3);
return res;
}
// 以板子为单位获取抽屉内所有库位的药品数量
public async Task<int[]> CheckQuantityByAddr2(int DrawerNo, int[] ColNos)
{
int[] res = new int[6];
for (int i = 0; i < ColNos.Length; i++)
{
canBusSerial.DiscardInBuffer();
var index = ColNos[i] > 3 ? 2 : 1;
var lock1 = ColNos[i] % 3 == 0 ? 3 : ColNos[i] % 3;
var channel = Convert.ToInt32((DrawerNo * 10 + index).ToString(), 16);
byte[] buffer = new byte[] { 0xaa, (byte)(channel), 0x27, (byte)lock1, 0x00, 0x00, 0x00, 0xee };
logger.Info($"称重发送库位数量查询1【{string.Join(",", buffer)}】");
canBusSerial.Write(buffer, 0, 8);
byte[] result = await GetBufferByPort(canBusSerial, 8);
logger.Info($"称重发送库位数量查询1返回结果【{string.Join(",", result)}】");
byte[] hl = result.Skip(3).Take(2).ToArray();
int quantity = BitConverter.ToInt16(hl.Reverse().ToArray(), 0);
res[ColNos[i] - 1] = quantity;
}
return res;
}
// 指定药盒指示灯开启使能开锁
public async Task BoxLockLightOn2(int DrawerNo, int[] ColNos)
{
for (int i = 0; i < ColNos.Length; i++)
{
var index = ColNos[i] > 3 ? 2 : 1;
var lock1 = ColNos[i] % 3 == 0 ? 3 : ColNos[i] % 3;
var channel = Convert.ToInt32((DrawerNo * 10 + index).ToString(), 16);
byte[] buffer = new byte[] { 0xaa, (byte)(channel), 0x03, (byte)lock1, 0x00, 0x00, 0x00, 0xee };
logger.Info($"称重发送药盒使能【{string.Join(",", buffer)}】");
canBusSerial.Write(buffer, 0, 8);
await Task.Delay(TimeSpan.FromMilliseconds(500));
}
}
// 指定药盒指示灯开启失能开锁
public async Task BoxLockLightOff2(int DrawerNo, int[] ColNos)
{
canBusSerial.DiscardInBuffer();
for (int i = 0; i < ColNos.Length; i++)
{
var index = ColNos[i] > 3 ? 2 : 1;
var lock1 = ColNos[i] % 3 == 0 ? 3 : ColNos[i] % 3;
var channel = Convert.ToInt32((DrawerNo * 10 + index).ToString(), 16);
byte[] buffer = new byte[] { 0xaa, (byte)(channel), 0x04, (byte)lock1, 0x00, 0x00, 0x00, 0xee };
logger.Info($"称重发送药盒失能【{string.Join(",", buffer)}】");
canBusSerial.Write(buffer, 0, 8);
await Task.Delay(TimeSpan.FromMilliseconds(50));
}
}
public async void ClearCount(int DrawerNo, int ColNo)
{
canBusSerial.DiscardInBuffer();
var index = ColNo > 3 ? 2 : 1;
var lock1 = ColNo % 3 == 0 ? 3 : ColNo % 3;
var channel = Convert.ToInt32((DrawerNo * 10 + index).ToString(), 16);
byte[] buffer = new byte[] { 0xaa, (byte)(channel), 0x25, (byte)lock1, 0x00, 0x00, 0x00, 0xee };
logger.Info($"称重发送清空计数【{string.Join(",", buffer)}】");
canBusSerial.Write(buffer, 0, 8);
}
public async void SetNumCount(int DrawerNo, int ColNo, int Quantity)
{
canBusSerial.DiscardInBuffer();
var index = ColNo > 3 ? 2 : 1;
var lock1 = ColNo % 3 == 0 ? 3 : ColNo % 3;
var channel = Convert.ToInt32((DrawerNo * 10 + index).ToString(), 16);
byte[] buffer = new byte[] { 0xaa, (byte)(channel), 0x26, (byte)lock1, 0x00, 0x00, 0x00, 0xee };
buffer[4] = (byte)(Quantity >> 8);
buffer[5] = (byte)(Quantity & 0xff);
logger.Info($"称重发送数量【{string.Join(",", buffer)}】");
canBusSerial.Write(buffer, 0, 8);
}
// 以板子为单位获取抽屉内所有库位的药品数量
public async Task<byte[]> CheckQuantityByAddr()
{
canBusSerial.DiscardInBuffer();
var channel = Convert.ToInt32((DrawerNo * 10 + 1).ToString(), 16);
byte[] buffer = new byte[] { 0xaa, (byte)(channel), 0x28, 0x00, 0x00, 0x00, 0x00, 0xee };
logger.Info($"称重发送库位数量查询1【{Convert.ToHexString(buffer)}】");
canBusSerial.Write(buffer, 0, 8);
byte[] result1 = await GetBufferByPort(canBusSerial, 8);
var channel2 = Convert.ToInt32((DrawerNo * 10 + 2).ToString(), 16);
byte[] buffer2 = new byte[] { 0xaa, (byte)(channel2), 0x28, 0x00, 0x00, 0x00, 0x00, 0xee };
logger.Info($"称重发送库位数量查询2【{Convert.ToHexString(buffer2)}】");
canBusSerial.Write(buffer2, 0, 8);
byte[] result2 = await GetBufferByPort(canBusSerial, 8);
byte[] res = new byte[6];
Array.Copy(result1, 3, res, 0, 3);
Array.Copy(result2, 3, res, 3, 3);
return res;
}
// 以板子为单位获取抽屉内所有库位的药品数量
public async Task<int[]> CheckQuantityByAddrForMulti()
{
int[] res = new int[9];
for (int i = 0; i < ColNoLst.Count; i++)
{
Thread.Sleep(200);
canBusSerial.DiscardInBuffer();
int colNo = ColNoLst[i];
int[] iNum = new int[] { 3, 2, 1 };
var colNo2 = colNo % 3 > 0 ? (colNo % 3) - 1 : 2;
var bColNo = iNum[colNo2];
decimal decolNO = (decimal)colNo;
var channel = Convert.ToInt32((DrawerNo * 10 + Math.Ceiling(decolNO / 3)).ToString(), 16);
byte[] buffer = new byte[] { 0xaa, (byte)(channel), 0x27, (byte)bColNo, 0x00, 0x00, 0x00, 0xee };
logger.Info($"称重发送库位数量查询{ColNoLst[i]}【{Convert.ToHexString(buffer)}】");
canBusSerial.Write(buffer, 0, 8);
byte[] result = await GetBufferByPort(canBusSerial, 8);
logger.Info($"称重发送库位数量查询返回结果【{Convert.ToHexString(result)}】");
byte[] hl = result.Skip(4).Take(2).ToArray();
var r = Convert.ToHexString(result).Substring(8, 1);
int quantity = 0;
if (r == "8")
{
hl[0] -= 0x80;
quantity = BitConverter.ToInt16(hl.Reverse().ToArray(), 0);
logger.Info($"获取值为负数{quantity}");
quantity = 0 - quantity;
}
else
{
quantity = BitConverter.ToInt16(hl.Reverse().ToArray(), 0);
logger.Info($"获取值为正数{quantity}");
}
res[ColNoLst[i] - 1] = quantity;
}
return res;
}
//获取单个称重药合的药品数量 --查数
public async Task<int> CheckQuantityForSingle(int colNo)
{
//await Task.Delay(300);
//canBusSerial.DiscardInBuffer();
//var index = colNo % 3 == 0 ? 3 : colNo % 3;
//var lock1 = colNo <= 3 ? 3 : colNo >= 7 ? 1 : 2;
//var channel = Convert.ToInt32((DrawerNo * 10 + index).ToString(), 16);
canBusSerial.DiscardInBuffer();
int[] iNum = new int[] { 3, 2, 1 };
var colNo2 = colNo % 3 > 0 ? (colNo % 3) - 1 : 2;
var bColNo = iNum[colNo2];
decimal decolNO = (decimal)colNo;
var channel = Convert.ToInt32((DrawerNo * 10 + Math.Ceiling(decolNO / 3)).ToString(), 16);
byte[] buffer = new byte[] { 0xaa, (byte)(channel), 0x27, (byte)bColNo, 0x00, 0x00, 0x00, 0xee };
logger.Info($"称重发送库位数量查询{colNo}【{Convert.ToHexString(buffer)}】");
canBusSerial.Write(buffer, 0, 8);
byte[] result = await GetBufferByPort(canBusSerial, 8);
byte[] hl = result.Skip(4).Take(2).ToArray();
var r = Convert.ToHexString(result).Substring(8, 1);
logger.Info($"称重发送库位数量查询返回结果【{Convert.ToHexString(result)}】");
if (r == "8")
{
hl[0] -= 0x80;
int quantity = BitConverter.ToInt16(hl.Reverse().ToArray(), 0);
logger.Info($"获取值为负数{quantity}");
return 0 - quantity;
}
else
{
int quantity = BitConverter.ToInt16(hl.Reverse().ToArray(), 0);
logger.Info($"获取值为正数{quantity}");
return quantity;
}
}
//获取单个称重药合的药品数量---标定标定查数与库位查数区别在于用不用忽略0x80
public async Task<int> CheckQuantityForBiaoDing(int colNo)
{
canBusSerial.DiscardInBuffer();
int[] iNum = new int[] { 3, 2, 1 };
var colNo2 = colNo % 3 > 0 ? (colNo % 3) - 1 : 2;
var bColNo = iNum[colNo2];
decimal decolNO = (decimal)colNo;
var channel = Convert.ToInt32((DrawerNo * 10 + Math.Ceiling(decolNO / 3)).ToString(), 16);
byte[] buffer = new byte[] { 0xaa, (byte)(channel), 0x27, (byte)bColNo, 0x00, 0x00, 0x00, 0xee };
logger.Info($"称重发送库位数量查询{colNo}【{Convert.ToHexString(buffer)}】");
canBusSerial.Write(buffer, 0, 8);
byte[] result = await GetBufferByPort(canBusSerial, 8);
logger.Info($"称重发送库位数量查询返回结果【{Convert.ToHexString(result)}】");
byte[] hl = result.Skip(4).Take(2).ToArray();
int quantity = BitConverter.ToInt16(hl.Reverse().ToArray(), 0);
return quantity;
}
// 以板子为单位获取抽屉内所有库位的药品数量
public async Task<int[]> CheckQuantityByAddr2()
{
int[] res = new int[9];
for (int i = 0; i < ColNos.Length; i++)
{
await Task.Delay(300);
canBusSerial.DiscardInBuffer();
int colNo = ColNos[i];
int[] iNum = new int[] { 3, 2, 1 };
var colNo2 = colNo % 3 > 0 ? (colNo % 3) - 1 : 2;
var bColNo = iNum[colNo2];
decimal decolNO = (decimal)colNo;
var channel = Convert.ToInt32((DrawerNo * 10 + Math.Ceiling(decolNO / 3)).ToString(), 16);
byte[] buffer = new byte[] { 0xaa, (byte)(channel), 0x27, (byte)bColNo, 0x00, 0x00, 0x00, 0xee };
logger.Info($"称重发送库位数量查询{ColNos[i]}【{Convert.ToHexString(buffer)}】");
canBusSerial.Write(buffer, 0, 8);
byte[] result = await GetBufferByPort(canBusSerial, 8);
logger.Info($"称重发送库位数量查询返回结果【{Convert.ToHexString(result)}】");
byte[] hl = result.Skip(4).Take(2).ToArray();
//int quantity = BitConverter.ToInt16(hl.Reverse().ToArray(), 0);
var r = Convert.ToHexString(result).Substring(8, 1);
int quantity = 0;
if (r == "8")
{
hl[0] -= 0x80;
quantity = BitConverter.ToInt16(hl.Reverse().ToArray(), 0);
logger.Info($"获取值为负数{quantity}");
quantity = 0 - quantity;
}
else
{
quantity = BitConverter.ToInt16(hl.Reverse().ToArray(), 0);
logger.Info($"获取值为正数{quantity}");
}
res[ColNos[i] - 1] = quantity;
}
return res;
}
#endregion
#endregion
}
}

View File

@ -0,0 +1,171 @@
using log4net;
using MasaBlazorApp3.Pojo;
using SuperSimpleTcp;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Channels;
using System.Threading.Tasks;
using System.Windows.Markup;
namespace MasaBlazorApp3.Port
{
public class ScreenUtil
{
private readonly ILog logger = LogManager.GetLogger(typeof(ScreenUtil));
SimpleTcpServer server = new SimpleTcpServer("0.0.0.0:8888");
string ipport { get; set; } = "";
public ScreenUtil()
{
server.Events.ClientConnected += (object sender, ConnectionEventArgs e) =>
{
ipport = e.IpPort;
logger.Info($"[{e.IpPort}] client connected");
};
server.Events.ClientDisconnected += (object sender, ConnectionEventArgs e) =>
{
logger.Info($"[{e.IpPort}] client disconnected: {e.Reason}");
};
server.Events.DataReceived += (object sender, DataReceivedEventArgs e) =>
{
logger.Info($"[{e.IpPort}]: {e.Data.Array}");
};
// let's go!
server.Start();
}
private byte[] head = new byte[] { 0xee, 0xb1, 0x12 };
private byte[] end = new byte[] { 0xFF, 0xFC, 0xFF, 0xFF };
public void SetStockInfo(ChannelStock channel, int screenId)
{
// 添加画面id
byte[] a = Copy2NewArr(head, HighLow(screenId));
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
//if (channel.DrugInfo.DrugName != null)
//{
byte[] content = Encoding.GetEncoding("gb2312").GetBytes(channel.Drug?.DrugName??"");
a = WriteInfo(a, content, channel.ColNo * 10 + 1);
//}
//if (channel.DrugInfo.Manufactory != null)
//{
byte[] content1 = Encoding.GetEncoding("gb2312").GetBytes(channel.Drug?.Manufactory?? "");
a = WriteInfo(a, content1, channel.ColNo * 10 + 2);
//}
//if (channel.DrugInfo.DrugSpec != null)
//{
byte[] content2 = Encoding.GetEncoding("gb2312").GetBytes(channel.Drug?.DrugSpec ?? "");
a = WriteInfo(a, content2, channel.ColNo * 10 + 3);
//}
//if (channel.ManuNo != null)
//{
byte[] content3 = Encoding.GetEncoding("gb2312").GetBytes(channel.ManuNo);
a = WriteInfo(a, content3, channel.ColNo * 10 + 4);
//}
//if (channel.EffDate != null)
//{
byte[] content4 = Encoding.GetEncoding("gb2312").GetBytes(channel.EffDate);
a = WriteInfo(a, content4, channel.ColNo * 10 + 5);
//}
//if (channel.Quantity != null)
//{
byte[] content5 = Encoding.GetEncoding("gb2312").GetBytes(channel.Quantity.ToString());
a = WriteInfo(a, content5, channel.ColNo * 10 + 6);
//}
// 添加结束块
byte[] b = Copy2NewArr(a, end);
server.Send(ipport, b);
}
public void TellChange(int d)
{
byte[] buffer = new byte[] { 0xee, 0xb5, 0x01, 0x00, 0xFF, 0xFC, 0xFF, 0xFF };
}
public void SetStockInfo(List<ChannelStock> channels, int screenId)
{
// 添加画面id
byte[] a = Copy2NewArr(head, HighLow(screenId));
for (int i = 0; i < channels.Count; i++)
{
ChannelStock channel = channels[i];
if (channel.Drug.DrugName != null)
{
byte[] content = Encoding.ASCII.GetBytes(channel.Drug.DrugName);
a = WriteInfo(a, content, channels[0].DrawerNo * 10 + 1);
}
if (channel.Drug.Manufactory != null)
{
byte[] content = Encoding.ASCII.GetBytes(channel.Drug.Manufactory);
a = WriteInfo(a, content, channels[0].DrawerNo * 10 + 2);
}
if (channel.Drug.DrugSpec != null)
{
byte[] content = Encoding.ASCII.GetBytes(channel.Drug.DrugSpec);
a = WriteInfo(a, content, channels[0].DrawerNo * 10 + 3);
}
if (channel.ManuNo != null)
{
byte[] content = Encoding.ASCII.GetBytes(channel.ManuNo);
a = WriteInfo(a, content, channels[0].DrawerNo * 10 + 4);
}
if (channel.EffDate != null)
{
byte[] content = Encoding.ASCII.GetBytes(channel.EffDate);
a = WriteInfo(a, content, channels[0].DrawerNo * 10 + 5);
}
if (channel.Quantity != null)
{
byte[] content = Encoding.ASCII.GetBytes(channel.Quantity.ToString());
a = WriteInfo(a, content, channels[0].DrawerNo * 10 + 6);
}
}
// 添加结束块
byte[] b = Copy2NewArr(a, end);
server.Send(ipport, b);
}
public byte[] WriteInfo(byte[] a, byte[] content, int id)
{
// 添加控件id
byte[] b = Copy2NewArr(a, HighLow(id));
// 添加需要向控件内写入的字节长度
byte[] c = Copy2NewArr(b, HighLow(content.Length));
// 写入内容
return Copy2NewArr(c, content);
}
public byte[] HighLow(int data)
{
byte high = Convert.ToByte((data >> 8) & 0x00ff); //位运算右移8位
byte low = Convert.ToByte(data & 0x00ff); //去掉高位
return new byte[] {high, low};
}
public byte[] Copy2NewArr(byte[] source1, byte[] source2)
{
byte[] target = new byte[source1.Length + source2.Length];
Buffer.BlockCopy(source1, 0, target, 0, source1.Length);
Buffer.BlockCopy(source2, 0, target, source1.Length, source2.Length);
return target;
}
}
}

92
MasaBlazorApp3/Program.cs Normal file
View File

@ -0,0 +1,92 @@
using log4net.Config;
using MasaBlazorApp3;
using MasaBlazorApp3.DataAccess.Dao;
using MasaBlazorApp3.DataAccess.Impl;
using MasaBlazorApp3.DataAccess;
using MasaBlazorApp3.Finger;
using Microsoft.Extensions.DependencyInjection;
using Photino.Blazor;
using LinqToDB.AspNet;
using LinqToDB;
using Microsoft.Extensions.Configuration;
using LinqToDB.AspNet.Logging;
using Radzen;
using MasaBlazorApp3.Pojo.Config;
using MasaBlazorApp3.Port;
internal class Program
{
[STAThread]
private static void Main(string[] args)
{
var appBuilder = PhotinoBlazorAppBuilder.CreateDefault(args);
appBuilder.RootComponents.Add<App>("#app");
appBuilder.Services.AddRadzenComponents();
// 指纹机工具类
appBuilder.Services.AddSingleton<FingerprintUtil>();
// 串口工具类
appBuilder.Services.AddSingleton<PortUtil>();
// 登录用户全局存放
appBuilder.Services.AddSingleton<GlobalStateService>();
// 框架自带通知服务注入
appBuilder.Services.AddScoped<NotificationService>();
appBuilder.Services.AddScoped<TooltipService>();
appBuilder.Services.AddScoped<DialogService>();
// 注入log
XmlConfigurator.ConfigureAndWatch(new System.IO.FileInfo(AppDomain.CurrentDomain.BaseDirectory + "log4net.config"));
//设置配置文件
var config = new ConfigurationBuilder()
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.Build();
// 注入配置
appBuilder.Services.Configure<FingerPojo>(config.GetSection("finger"));
appBuilder.Services.Configure<SettingConfig>(config.GetSection("setting"));
appBuilder.Services.Configure<PortConfig>(config.GetSection("port"));
appBuilder.Services.Configure<DrawerConfig>(config.GetSection("drawer"));
// i18n
//appBuilder.Services.AddI18nText();
// 数据库
appBuilder.Services.AddLinqToDBContext<AppDataConnection>((provider, options) =>
options.UseMySql(config.GetValue<String>("connectionStrings"))
.UseDefaultLogging(provider));
// dao层数据库操作
appBuilder.Services.AddScoped<IUserDao, UserDao>();
appBuilder.Services.AddScoped<IRoleDao, RoleDao>();
appBuilder.Services.AddScoped<IChannelListDao, ChannelListDao>();
appBuilder.Services.AddScoped<IOrderInfoDao, OrderInfoDao>();
appBuilder.Services.AddScoped<IDrugInfoDao, DrugInfoDao>();
appBuilder.Services.AddScoped<IMachineRecordDao, MachineRecordDao>();
appBuilder.Services.AddScoped<IInOutInvoiceDao, InOutInvoiceDao>();
//自选取药
appBuilder.Services.AddScoped<ISelfTakeDao, SelfTakeDao>();
//药品批次
appBuilder.Services.AddScoped<IDrugManuNoDao, DrugManuNoDao>();
var app = appBuilder.Build();
app.MainWindow
.SetHeight(768)
.SetWidth(1024)
.SetIconFile("favicon.ico")
.SetContextMenuEnabled(false)
#if DEBUG
.SetFullScreen(false)
#else
.SetChromeless(true)
.SetFullScreen(true)
#endif
;
AppDomain.CurrentDomain.UnhandledException += (sender, error) =>
{
};
app.Run();
}
}

View File

@ -0,0 +1,38 @@
using gregn6Lib;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Configuration;
namespace MasaBlazorApp3.Report
{
public class GridReportUtil
{
// 定义Grid++Report报表主对象
public static GridppReport Report = new GridppReport();
/**
*
* tempname:
* data:
*/
public static void PrintReport(string tempname, object data)
{
// 定义Grid++Report报表主对象
// 加载模板文件
Report.LoadFromFile(new FileInfo(AppDomain.CurrentDomain.BaseDirectory) + "ReportTemp//" + tempname);
string s = JsonConvert.SerializeObject(data);
// 加载数据
Report.LoadDataFromXML(JsonConvert.SerializeObject(data));
Report.PrintPreview(true);
}
}
}

View File

@ -0,0 +1,612 @@
{
"Version":"6.8.5.2",
"Font":{
"Name":"宋体",
"Size":105000,
"Weight":400,
"Charset":134
},
"Printer":{
"Oriention":"Landscape",
"LeftMargin":1,
"TopMargin":1.42875,
"RightMargin":1,
"BottomMargin":1.8
},
"DetailGrid":{
"CenterView":true,
"AppendBlankRow":true,
"Recordset":{
"ConnectionString":"MYSQL;\r\nDatabase=hkcdb;\r\nPassword=qq1223;\r\nPort=3307;\r\nServer=127.0.0.1;\r\nUser=root;",
"QuerySQL":"SELECT \r\n mr.`stock_quantity` AS `stockQuantity`,\r\n IF(mr.`type` IN (1, 31), mr.`quantity`, IF(mr.`type` = 4 AND mr.`quantity` > 0, mr.`quantity`, 0)) AS `inQuantity`,\r\n IF(mr.`type` = 2, mr.`quantity`, IF(mr.`type` = 4 AND mr.`quantity` < 0, (0 - mr.`quantity`), 0)) AS `outQuantity`,\r\n mr.`operation_time` AS `operationTime`,\r\n mr.`invoice_id` AS `invoiceId`,\r\n di.`drug_name` AS `drugName`,\r\n di.`drug_id` AS `drugId`,\r\n di.`drug_spec` AS `drugSpec`,\r\n di.`pack_unit` AS `packUnit`,\r\n di.`dosage` AS `dosage`,\r\n di.`manufactory` AS `manufactory`,\r\n mr.`manu_no` AS `manuNo`,\r\n mr.`eff_date` AS `effDate`,\r\n u1.`user_name` AS `operatorName`,\r\n u2.`user_name` AS `reviewerName`\r\nFROM\r\n dm_machine_record mr \r\n LEFT JOIN drug_info di ON mr.`drug_id` = di.`drug_id` \r\n LEFT JOIN user_list u1 ON mr.`operator` = u1.`id`\r\n LEFT JOIN user_list u2 ON mr.`reviewer` = u2.`id`\r\n ORDER BY mr.`drug_id`, mr.`operation_time`, mr.`id`",
"Field":[
{
"Name":"日期",
"Type":"DateTime",
"Format":"M/d",
"DBFieldName":"operationTime"
},
{
"Name":"操作类型",
"DBFieldName":"type"
},
{
"Name":"批号",
"DBFieldName":"manuNo"
},
{
"Name":"上次批次结存",
"Type":"Integer",
"DBFieldName":"beforeManuQuan"
},
{
"Name":"入库数量",
"Type":"Integer",
"DBFieldName":"inQuantity"
},
{
"Name":"出库数量",
"Type":"Integer",
"DBFieldName":"outQuantity"
},
{
"Name":"批号结存",
"Type":"Integer",
"DBFieldName":"manuQuantity"
},
{
"Name":"总结存",
"Type":"Integer",
"DBFieldName":"stockQuantity"
},
{
"Name":"收/发药人",
"DBFieldName":"operatorName"
},
{
"Name":"复核人",
"DBFieldName":"reviewName"
},
{
"Name":"药品名称",
"DBFieldName":"drugName"
},
{
"Name":"规格",
"DBFieldName":"drugSpec"
},
{
"Name":"单位",
"DBFieldName":"packUnit"
},
{
"Name":"剂型",
"DBFieldName":"dosage"
},
{
"Name":"厂家",
"DBFieldName":"manuFactory"
},
{
"Name":"有效期",
"Type":"DateTime",
"Format":"yy/M/d",
"DBFieldName":"effDate"
},
{
"Name":"sign1",
"Type":"Binary"
},
{
"Name":"sign2",
"Type":"Binary"
},
{
"Name":"drugId"
}
]
},
"Column":[
{
"Name":"日期",
"Width":1.77271
},
{
"Name":"操作类型",
"Width":2.19604
},
{
"Name":"批号",
"Width":3.99521
},
{
"Name":"有效期",
"Width":2.43417
},
{
"Name":"入库数量",
"Width":1.79917
},
{
"Name":"出库数量",
"Width":1.79917
},
{
"Name":"Column4",
"Width":1.98438
},
{
"Name":"收/发药人",
"Width":2.80458
},
{
"Name":"复核人",
"Width":2.80458
},
{
"Name":"Column2",
"Width":2.35479
},
{
"Name":"Column3",
"Width":2.38125
}
],
"ColumnContent":{
"Height":0.85,
"ColumnContentCell":[
{
"Column":"日期",
"TextAlign":"MiddleCenter",
"DataField":"日期"
},
{
"Column":"操作类型",
"FreeCell":true,
"Control":[
{
"Type":"StaticBox",
"Name":"StaticBox10",
"Dock":"Fill",
"TextAlign":"MiddleCenter"
}
]
},
{
"Column":"批号",
"TextAlign":"MiddleCenter",
"DataField":"批号"
},
{
"Column":"有效期",
"TextAlign":"MiddleCenter",
"DataField":"有效期"
},
{
"Column":"入库数量",
"TextAlign":"MiddleCenter",
"DataField":"入库数量"
},
{
"Column":"出库数量",
"TextAlign":"MiddleCenter",
"DataField":"出库数量"
},
{
"Column":"Column4",
"TextAlign":"MiddleCenter",
"DataField":"总结存"
},
{
"Column":"收/发药人",
"FreeCell":true,
"Control":[
{
"Type":"FieldBox",
"Name":"FieldBox12",
"Dock":"Fill",
"TextAlign":"MiddleCenter",
"DataField":"收/发药人"
}
]
},
{
"Column":"复核人",
"FreeCell":true,
"Control":[
{
"Type":"FieldBox",
"Name":"FieldBox13",
"Dock":"Fill",
"TextAlign":"MiddleCenter",
"DataField":"复核人"
}
]
},
{
"Column":"Column2",
"FreeCell":true,
"Control":[
{
"Type":"StaticBox",
"Name":"StaticBox6",
"Dock":"Fill",
"TextAlign":"MiddleCenter",
"Text":"药库"
}
]
},
{
"Column":"Column3",
"FreeCell":true,
"Control":[
{
"Type":"StaticBox",
"Name":"StaticBox7",
"Dock":"Fill",
"TextAlign":"MiddleCenter",
"Text":"门诊药房"
}
]
}
]
},
"ColumnTitle":{
"Height":1.19063,
"RepeatStyle":"OnGroupHeaderPage",
"ColumnTitleCell":[
{
"GroupTitle":false,
"Column":"日期",
"Font":{
"Name":"宋体",
"Size":105000,
"Bold":true,
"Charset":134
},
"TextAlign":"MiddleCenter",
"Text":"日期"
},
{
"GroupTitle":false,
"Column":"操作类型",
"Font":{
"Name":"宋体",
"Size":105000,
"Bold":true,
"Charset":134
},
"TextAlign":"MiddleCenter",
"Text":"凭证号"
},
{
"GroupTitle":false,
"Column":"批号",
"Font":{
"Name":"宋体",
"Size":105000,
"Bold":true,
"Charset":134
},
"TextAlign":"MiddleCenter",
"Text":"批号"
},
{
"GroupTitle":false,
"Column":"有效期",
"Font":{
"Name":"宋体",
"Size":105000,
"Bold":true,
"Charset":134
},
"TextAlign":"MiddleCenter",
"Text":"有效\r\n期"
},
{
"GroupTitle":false,
"Column":"入库数量",
"Font":{
"Name":"宋体",
"Size":105000,
"Bold":true,
"Charset":134
},
"TextAlign":"MiddleCenter",
"Text":"借入\r\n数量"
},
{
"GroupTitle":false,
"Column":"出库数量",
"Font":{
"Name":"宋体",
"Size":105000,
"Bold":true,
"Charset":134
},
"TextAlign":"MiddleCenter",
"Text":"发出\r\n数量"
},
{
"GroupTitle":false,
"Column":"Column4",
"Font":{
"Name":"宋体",
"Size":105000,
"Bold":true,
"Charset":134
},
"TextAlign":"MiddleCenter",
"Text":"总结存"
},
{
"GroupTitle":false,
"Column":"收/发药人",
"Font":{
"Name":"宋体",
"Size":105000,
"Bold":true,
"Charset":134
},
"TextAlign":"MiddleCenter",
"Text":"发药人"
},
{
"GroupTitle":false,
"Column":"复核人",
"Font":{
"Name":"宋体",
"Size":105000,
"Bold":true,
"Charset":134
},
"TextAlign":"MiddleCenter",
"Text":"复核人"
},
{
"GroupTitle":false,
"Column":"Column2",
"Font":{
"Name":"宋体",
"Size":105000,
"Bold":true,
"Charset":134
},
"TextAlign":"MiddleCenter",
"Text":"供应单位"
},
{
"GroupTitle":false,
"Column":"Column3",
"Font":{
"Name":"宋体",
"Size":105000,
"Bold":true,
"Charset":134
},
"TextAlign":"MiddleCenter",
"Text":"领用部门"
}
]
},
"Group":[
{
"Name":"Group1",
"ByFields":"drugId",
"GroupHeader":{
"PrintGridBorder":false,
"RepeatOnPage":true,
"Control":[
{
"Type":"StaticBox",
"Name":"StaticBox15",
"Left":28.3898,
"Top":0.238125,
"Width":2.01083,
"Height":0.79375,
"Text":"生产厂家:"
},
{
"Type":"MemoBox",
"Name":"MemoBox11",
"Left":30.3742,
"Top":0.211667,
"Width":5.3975,
"Height":0.79375,
"Text":"[#manuFactory#]"
},
{
"Type":"StaticBox",
"Name":"StaticBox16",
"Top":0.0529167,
"Width":1.19063,
"Height":0.978958,
"Font":{
"Name":"宋体",
"Size":105000,
"Bold":true,
"Charset":134
},
"Text":"品名:"
},
{
"Type":"FieldBox",
"Name":"FieldBox7",
"Left":1.16417,
"Top":0.0529167,
"Width":5.63563,
"Height":0.978958,
"Font":{
"Name":"宋体",
"Size":105000,
"Bold":true,
"Charset":134
},
"DataField":"药品名称"
},
{
"Type":"StaticBox",
"Name":"StaticBox17",
"Left":6.93208,
"Top":0.0529167,
"Width":1.11125,
"Height":0.978958,
"Font":{
"Name":"宋体",
"Size":105000,
"Bold":true,
"Charset":134
},
"Text":"规格:"
},
{
"Type":"FieldBox",
"Name":"FieldBox8",
"Left":8.01688,
"Top":0.0529167,
"Width":3.175,
"Height":0.978958,
"Font":{
"Name":"宋体",
"Size":105000,
"Bold":true,
"Charset":134
},
"DataField":"规格"
},
{
"Type":"StaticBox",
"Name":"StaticBox18",
"Left":11.5888,
"Top":0.0529167,
"Width":1.21708,
"Height":0.978958,
"Font":{
"Name":"宋体",
"Size":105000,
"Bold":true,
"Charset":134
},
"Text":"单位:"
},
{
"Type":"FieldBox",
"Name":"FieldBox9",
"Left":12.7794,
"Top":0.0529167,
"Width":1.87854,
"Height":0.978958,
"Font":{
"Name":"宋体",
"Size":105000,
"Bold":true,
"Charset":134
},
"DataField":"单位"
},
{
"Type":"StaticBox",
"Name":"StaticBox19",
"Left":15.3988,
"Top":0.0529167,
"Width":1.16417,
"Height":0.978958,
"Font":{
"Name":"宋体",
"Size":105000,
"Bold":true,
"Charset":134
},
"Text":"剂型:"
},
{
"Type":"FieldBox",
"Name":"FieldBox10",
"Left":16.5365,
"Top":0.0529167,
"Width":2.83104,
"Height":0.978958,
"Font":{
"Name":"宋体",
"Size":105000,
"Bold":true,
"Charset":134
},
"DataField":"剂型"
},
{
"Type":"StaticBox",
"Name":"StaticBox20",
"Left":19.7379,
"Top":0.0529167,
"Width":2.01083,
"Height":0.978958,
"Font":{
"Name":"宋体",
"Size":105000,
"Bold":true,
"Charset":134
},
"Text":"生产厂家:"
},
{
"Type":"FieldBox",
"Name":"FieldBox11",
"Left":21.7223,
"Top":0.05,
"Width":5.92667,
"Height":0.978958,
"Font":{
"Name":"宋体",
"Size":105000,
"Bold":true,
"Charset":134
},
"DataField":"厂家"
}
],
"NewPageColumn":"Before"
},
"GroupFooter":{
"Visible":false
}
}
]
},
"Parameter":[
{
"Name":"machine_id"
},
{
"Name":"startDate",
"DataType":"DateTime"
},
{
"Name":"endDate",
"DataType":"DateTime"
}
],
"ReportHeader":[
{
"Name":"ReportHeader1",
"Height":1.79917,
"Control":[
{
"Type":"MemoBox",
"Name":"MemoBox1",
"Dock":"Fill",
"Center":"Both",
"Font":{
"Name":"宋体",
"Size":262500,
"Bold":true,
"Charset":134
},
"TextAlign":"MiddleCenter",
"Text":"麻醉、精神药品逐笔专用账册"
}
],
"RepeatOnPage":true
}
]
}

View File

@ -0,0 +1,284 @@
{
"Version":"6.8.5.2",
"Font":{
"Name":"宋体",
"Size":105000,
"Weight":400,
"Charset":134
},
"Printer":{
"LeftMargin":0.3175,
"TopMargin":0.899583,
"RightMargin":0.396875
},
"DetailGrid":{
"CenterView":true,
"AppendBlankRow":true,
"Recordset":{
"ConnectionString":"MYSQL;\r\nDatabase=hkcdb;\r\nPassword=qq1223;\r\nPort=3307;\r\nServer=127.0.0.1;\r\nUser=root;",
"QuerySQL":"SELECT \r\n dmr.`drawer_no` AS drawerNo,\r\n dmr.`col_no` AS colNo,\r\n dmr.`type` AS `type`,\r\n dmr.`quantity` AS quantity,\r\n dmr.`manu_no` AS manuNo,\r\n dmr.`eff_date` AS effDate,\r\n dmr.`operation_time` AS operationTime,\r\n di.`drug_name` AS drugName,\r\n di.`drug_spec` AS drugSpec,\r\n di.`pack_unit` AS packUnit,\r\n di.`manufactory` AS manuFactory,\r\n di.`max_stock` AS baseQuantity,\r\n dmr.`drug_id` AS drugId,\r\n ul.`user_name` AS nickname\r\nFROM\r\n dm_machine_record dmr\r\nLEFT JOIN drug_info di ON di.`drug_id` = dmr.`drug_id`\r\nLEFT JOIN user_list ul ON ul.`id` = dmr.`Operator`\r\nWHERE dmr.`type` = 1 \r\n AND dmr.`machine_id` = :machine_id\r\n AND dmr.`operation_time` > :startDate\r\n AND dmr.`operation_time` < :endDate",
"Field":[
{
"Name":"操作人",
"DBFieldName":"Nickname"
},
{
"Name":"时间",
"Type":"DateTime",
"Format":"yyyy/MM/dd HH:mm:ss",
"DBFieldName":"operationTime"
},
{
"Name":"药品名称",
"DBFieldName":"DrugName"
},
{
"Name":"数量",
"DBFieldName":"quantity"
},
{
"Name":"批次",
"DBFieldName":"manuNo"
},
{
"Name":"效期",
"Type":"DateTime",
"Format":"yyyy/MM/dd",
"DBFieldName":"effDate"
},
{
"Name":"库位",
"DBFieldName":"drawerNo"
},
{
"Name":"colNo"
},
{
"Name":"type2",
"Type":"Integer",
"DBFieldName":"type"
}
]
},
"Column":[
{
"Name":"操作人",
"Width":2.38125
},
{
"Name":"时间",
"Width":3.78354
},
{
"Name":"药品名称",
"Width":4.63021
},
{
"Name":"数量",
"Width":1.98438
},
{
"Name":"批次",
"Width":2.61938
},
{
"Name":"效期",
"Width":2.38125
},
{
"Name":"库位",
"Width":2.59292
}
],
"ColumnContent":{
"Height":1.00542,
"ColumnContentCell":[
{
"Column":"操作人",
"TextAlign":"MiddleCenter",
"DataField":"操作人"
},
{
"Column":"时间",
"TextAlign":"MiddleCenter",
"DataField":"时间"
},
{
"Column":"药品名称",
"TextAlign":"MiddleCenter",
"DataField":"药品名称"
},
{
"Column":"数量",
"TextAlign":"MiddleCenter",
"DataField":"数量"
},
{
"Column":"批次",
"TextAlign":"MiddleCenter",
"DataField":"批次"
},
{
"Column":"效期",
"TextAlign":"MiddleCenter",
"DataField":"效期"
},
{
"Column":"库位",
"FreeCell":true,
"Control":[
{
"Type":"FieldBox",
"Name":"FieldBox1",
"Left":9.60438,
"Top":-2.16958,
"Width":2.80458,
"Height":0.661458
},
{
"Type":"MemoBox",
"Name":"MemoBox1",
"Dock":"Fill",
"Center":"Both",
"TextAlign":"MiddleCenter",
"Text":"[#库位#] - [#colNo#]"
}
]
}
]
},
"ColumnTitle":{
"Height":1.40229,
"RepeatStyle":"OnPage",
"ColumnTitleCell":[
{
"GroupTitle":false,
"Column":"操作人",
"Font":{
"Name":"宋体",
"Size":120000,
"Bold":true,
"Charset":134
},
"TextAlign":"MiddleCenter",
"Text":"操作人"
},
{
"GroupTitle":false,
"Column":"时间",
"Font":{
"Name":"宋体",
"Size":120000,
"Bold":true,
"Charset":134
},
"TextAlign":"MiddleCenter",
"Text":"时间"
},
{
"GroupTitle":false,
"Column":"药品名称",
"Font":{
"Name":"宋体",
"Size":120000,
"Bold":true,
"Charset":134
},
"TextAlign":"MiddleCenter",
"Text":"药品名称"
},
{
"GroupTitle":false,
"Column":"数量",
"Font":{
"Name":"宋体",
"Size":120000,
"Bold":true,
"Charset":134
},
"TextAlign":"MiddleCenter",
"Text":"数量"
},
{
"GroupTitle":false,
"Column":"批次",
"Font":{
"Name":"宋体",
"Size":120000,
"Bold":true,
"Charset":134
},
"TextAlign":"MiddleCenter",
"Text":"批次"
},
{
"GroupTitle":false,
"Column":"效期",
"Font":{
"Name":"宋体",
"Size":120000,
"Bold":true,
"Charset":134
},
"TextAlign":"MiddleCenter",
"Text":"效期"
},
{
"GroupTitle":false,
"Column":"库位",
"Font":{
"Name":"宋体",
"Size":120000,
"Bold":true,
"Charset":134
},
"TextAlign":"MiddleCenter",
"Text":"库位"
}
]
}
},
"Parameter":[
{
"Name":"startDate",
"DataType":"DateTime",
"Format":"yyyy-MM-dd hh:mm:ss",
"Value":"2023/1/1"
},
{
"Name":"endDate",
"DataType":"DateTime",
"Format":"yyyy-MM-dd hh:mm:ss",
"Value":"2023/4/28 23:59:59"
},
{
"Name":"machine_id",
"Value":"DM1"
}
],
"ReportHeader":[
{
"Name":"ReportHeader1",
"Height":1.79917,
"Control":[
{
"Type":"MemoBox",
"Name":"MemoBox2",
"Left":7.59354,
"Top":0.211667,
"Width":5.60917,
"Height":1.19063,
"Font":{
"Name":"宋体",
"Size":217500,
"Bold":true,
"Charset":134
},
"TextAlign":"MiddleCenter",
"Text":"入库记录"
}
],
"RepeatOnPage":true
}
]
}

View File

@ -0,0 +1,284 @@
{
"Version":"6.8.5.2",
"Font":{
"Name":"宋体",
"Size":105000,
"Weight":400,
"Charset":134
},
"Printer":{
"LeftMargin":0.3175,
"TopMargin":0.899583,
"RightMargin":0.396875
},
"DetailGrid":{
"CenterView":true,
"AppendBlankRow":true,
"Recordset":{
"ConnectionString":"MYSQL;\r\nDatabase=hkcdb;\r\nPassword=qq1223;\r\nPort=3307;\r\nServer=127.0.0.1;\r\nUser=root;",
"QuerySQL":"SELECT \r\n dmr.`drawer_no` AS drawerNo,\r\n dmr.`col_no` AS colNo,\r\n dmr.`type` AS `type`,\r\n dmr.`quantity` AS quantity,\r\n dmr.`manu_no` AS manuNo,\r\n dmr.`eff_date` AS effDate,\r\n dmr.`operation_time` AS operationTime,\r\n di.`drug_name` AS drugName,\r\n di.`drug_spec` AS drugSpec,\r\n di.`pack_unit` AS packUnit,\r\n di.`manufactory` AS manuFactory,\r\n di.`max_stock` AS baseQuantity,\r\n dmr.`drug_id` AS drugId,\r\n ul.`user_name` AS nickname\r\nFROM\r\n dm_machine_record dmr\r\nLEFT JOIN drug_info di ON di.`drug_id` = dmr.`drug_id`\r\nLEFT JOIN user_list ul ON ul.`id` = dmr.`Operator`\r\nWHERE dmr.`type` = 4 \r\n AND dmr.`machine_id` = :machine_id\r\n AND dmr.`operation_time` > :startDate\r\n AND dmr.`operation_time` < :endDate",
"Field":[
{
"Name":"操作人",
"DBFieldName":"Nickname"
},
{
"Name":"时间",
"Type":"DateTime",
"Format":"yyyy/MM/dd HH:mm:ss",
"DBFieldName":"operationTime"
},
{
"Name":"药品名称",
"DBFieldName":"DrugName"
},
{
"Name":"数量",
"DBFieldName":"quantity"
},
{
"Name":"批次",
"DBFieldName":"manuNo"
},
{
"Name":"效期",
"Type":"DateTime",
"Format":"yyyy/MM/dd",
"DBFieldName":"effDate"
},
{
"Name":"库位",
"DBFieldName":"drawerNo"
},
{
"Name":"colNo"
},
{
"Name":"type2",
"Type":"Integer",
"DBFieldName":"type"
}
]
},
"Column":[
{
"Name":"操作人",
"Width":2.38125
},
{
"Name":"时间",
"Width":3.78354
},
{
"Name":"药品名称",
"Width":4.63021
},
{
"Name":"数量",
"Width":1.98438
},
{
"Name":"批次",
"Width":2.61938
},
{
"Name":"效期",
"Width":2.38125
},
{
"Name":"库位",
"Width":2.59292
}
],
"ColumnContent":{
"Height":1.00542,
"ColumnContentCell":[
{
"Column":"操作人",
"TextAlign":"MiddleCenter",
"DataField":"操作人"
},
{
"Column":"时间",
"TextAlign":"MiddleCenter",
"DataField":"时间"
},
{
"Column":"药品名称",
"TextAlign":"MiddleCenter",
"DataField":"药品名称"
},
{
"Column":"数量",
"TextAlign":"MiddleCenter",
"DataField":"数量"
},
{
"Column":"批次",
"TextAlign":"MiddleCenter",
"DataField":"批次"
},
{
"Column":"效期",
"TextAlign":"MiddleCenter",
"DataField":"效期"
},
{
"Column":"库位",
"FreeCell":true,
"Control":[
{
"Type":"FieldBox",
"Name":"FieldBox1",
"Left":9.60438,
"Top":-2.16958,
"Width":2.80458,
"Height":0.661458
},
{
"Type":"MemoBox",
"Name":"MemoBox1",
"Dock":"Fill",
"Center":"Both",
"TextAlign":"MiddleCenter",
"Text":"[#库位#] - [#colNo#]"
}
]
}
]
},
"ColumnTitle":{
"Height":1.40229,
"RepeatStyle":"OnPage",
"ColumnTitleCell":[
{
"GroupTitle":false,
"Column":"操作人",
"Font":{
"Name":"宋体",
"Size":120000,
"Bold":true,
"Charset":134
},
"TextAlign":"MiddleCenter",
"Text":"操作人"
},
{
"GroupTitle":false,
"Column":"时间",
"Font":{
"Name":"宋体",
"Size":120000,
"Bold":true,
"Charset":134
},
"TextAlign":"MiddleCenter",
"Text":"时间"
},
{
"GroupTitle":false,
"Column":"药品名称",
"Font":{
"Name":"宋体",
"Size":120000,
"Bold":true,
"Charset":134
},
"TextAlign":"MiddleCenter",
"Text":"药品名称"
},
{
"GroupTitle":false,
"Column":"数量",
"Font":{
"Name":"宋体",
"Size":120000,
"Bold":true,
"Charset":134
},
"TextAlign":"MiddleCenter",
"Text":"数量"
},
{
"GroupTitle":false,
"Column":"批次",
"Font":{
"Name":"宋体",
"Size":120000,
"Bold":true,
"Charset":134
},
"TextAlign":"MiddleCenter",
"Text":"批次"
},
{
"GroupTitle":false,
"Column":"效期",
"Font":{
"Name":"宋体",
"Size":120000,
"Bold":true,
"Charset":134
},
"TextAlign":"MiddleCenter",
"Text":"效期"
},
{
"GroupTitle":false,
"Column":"库位",
"Font":{
"Name":"宋体",
"Size":120000,
"Bold":true,
"Charset":134
},
"TextAlign":"MiddleCenter",
"Text":"库位"
}
]
}
},
"Parameter":[
{
"Name":"startDate",
"DataType":"DateTime",
"Format":"yyyy-MM-dd hh:mm:ss",
"Value":"2023/1/1"
},
{
"Name":"endDate",
"DataType":"DateTime",
"Format":"yyyy-MM-dd hh:mm:ss",
"Value":"2023/4/28 23:59:59"
},
{
"Name":"machine_id",
"Value":"DM1"
}
],
"ReportHeader":[
{
"Name":"ReportHeader1",
"Height":1.79917,
"Control":[
{
"Type":"MemoBox",
"Name":"MemoBox2",
"Left":7.59354,
"Top":0.211667,
"Width":5.60917,
"Height":1.19063,
"Font":{
"Name":"宋体",
"Size":217500,
"Bold":true,
"Charset":134
},
"TextAlign":"MiddleCenter",
"Text":"盘点记录"
}
],
"RepeatOnPage":true
}
]
}

View File

@ -0,0 +1,284 @@
{
"Version":"6.8.5.2",
"Font":{
"Name":"宋体",
"Size":105000,
"Weight":400,
"Charset":134
},
"Printer":{
"LeftMargin":0.3175,
"TopMargin":0.899583,
"RightMargin":0.396875
},
"DetailGrid":{
"CenterView":true,
"AppendBlankRow":true,
"Recordset":{
"ConnectionString":"MYSQL;\r\nDatabase=hkcdb;\r\nPassword=qq1223;\r\nPort=3307;\r\nServer=127.0.0.1;\r\nUser=root;",
"QuerySQL":"SELECT \r\n dmr.`drawer_no` AS drawerNo,\r\n dmr.`col_no` AS colNo,\r\n dmr.`type` AS `type`,\r\n CONCAT(dmr.`quantity`,IF(dmr.`type`=32,\"(空瓶)\",\"\")) AS quantity,\r\n dmr.`manu_no` AS manuNo,\r\n dmr.`eff_date` AS effDate,\r\n dmr.`operation_time` AS operationTime,\r\n di.`drug_name` AS drugName,\r\n di.`drug_spec` AS drugSpec,\r\n di.`pack_unit` AS packUnit,\r\n di.`manufactory` AS manuFactory,\r\n di.`max_stock` AS baseQuantity,\r\n dmr.`drug_id` AS drugId,\r\n ul.`user_name` AS nickname\r\nFROM\r\n dm_machine_record dmr\r\nLEFT JOIN drug_info di ON di.`drug_id` = dmr.`drug_id`\r\nLEFT JOIN user_list ul ON ul.`id` = dmr.`Operator`\r\nWHERE dmr.`type` in (31, 32)\r\n AND dmr.`machine_id` = :machine_id\r\n AND dmr.`operation_time` > :startDate\r\n AND dmr.`operation_time` < :endDate",
"Field":[
{
"Name":"操作人",
"DBFieldName":"Nickname"
},
{
"Name":"时间",
"Type":"DateTime",
"Format":"yyyy/MM/dd HH:mm:ss",
"DBFieldName":"operationTime"
},
{
"Name":"药品名称",
"DBFieldName":"DrugName"
},
{
"Name":"数量",
"DBFieldName":"quantity"
},
{
"Name":"批次",
"DBFieldName":"manuNo"
},
{
"Name":"效期",
"Type":"DateTime",
"Format":"yyyy/MM/dd",
"DBFieldName":"effDate"
},
{
"Name":"库位",
"DBFieldName":"drawerNo"
},
{
"Name":"colNo"
},
{
"Name":"type2",
"Type":"Integer",
"DBFieldName":"type"
}
]
},
"Column":[
{
"Name":"操作人",
"Width":2.38125
},
{
"Name":"时间",
"Width":3.78354
},
{
"Name":"药品名称",
"Width":4.63021
},
{
"Name":"数量",
"Width":1.98438
},
{
"Name":"批次",
"Width":2.61938
},
{
"Name":"效期",
"Width":2.38125
},
{
"Name":"库位",
"Width":2.59292
}
],
"ColumnContent":{
"Height":1.00542,
"ColumnContentCell":[
{
"Column":"操作人",
"TextAlign":"MiddleCenter",
"DataField":"操作人"
},
{
"Column":"时间",
"TextAlign":"MiddleCenter",
"DataField":"时间"
},
{
"Column":"药品名称",
"TextAlign":"MiddleCenter",
"DataField":"药品名称"
},
{
"Column":"数量",
"TextAlign":"MiddleCenter",
"DataField":"数量"
},
{
"Column":"批次",
"TextAlign":"MiddleCenter",
"DataField":"批次"
},
{
"Column":"效期",
"TextAlign":"MiddleCenter",
"DataField":"效期"
},
{
"Column":"库位",
"FreeCell":true,
"Control":[
{
"Type":"FieldBox",
"Name":"FieldBox1",
"Left":9.60438,
"Top":-2.16958,
"Width":2.80458,
"Height":0.661458
},
{
"Type":"MemoBox",
"Name":"MemoBox1",
"Dock":"Fill",
"Center":"Both",
"TextAlign":"MiddleCenter",
"Text":"[#库位#] - [#colNo#]"
}
]
}
]
},
"ColumnTitle":{
"Height":1.40229,
"RepeatStyle":"OnPage",
"ColumnTitleCell":[
{
"GroupTitle":false,
"Column":"操作人",
"Font":{
"Name":"宋体",
"Size":120000,
"Bold":true,
"Charset":134
},
"TextAlign":"MiddleCenter",
"Text":"操作人"
},
{
"GroupTitle":false,
"Column":"时间",
"Font":{
"Name":"宋体",
"Size":120000,
"Bold":true,
"Charset":134
},
"TextAlign":"MiddleCenter",
"Text":"时间"
},
{
"GroupTitle":false,
"Column":"药品名称",
"Font":{
"Name":"宋体",
"Size":120000,
"Bold":true,
"Charset":134
},
"TextAlign":"MiddleCenter",
"Text":"药品名称"
},
{
"GroupTitle":false,
"Column":"数量",
"Font":{
"Name":"宋体",
"Size":120000,
"Bold":true,
"Charset":134
},
"TextAlign":"MiddleCenter",
"Text":"数量"
},
{
"GroupTitle":false,
"Column":"批次",
"Font":{
"Name":"宋体",
"Size":120000,
"Bold":true,
"Charset":134
},
"TextAlign":"MiddleCenter",
"Text":"批次"
},
{
"GroupTitle":false,
"Column":"效期",
"Font":{
"Name":"宋体",
"Size":120000,
"Bold":true,
"Charset":134
},
"TextAlign":"MiddleCenter",
"Text":"效期"
},
{
"GroupTitle":false,
"Column":"库位",
"Font":{
"Name":"宋体",
"Size":120000,
"Bold":true,
"Charset":134
},
"TextAlign":"MiddleCenter",
"Text":"库位"
}
]
}
},
"Parameter":[
{
"Name":"startDate",
"DataType":"DateTime",
"Format":"yyyy-MM-dd hh:mm:ss",
"Value":"2023/1/1"
},
{
"Name":"endDate",
"DataType":"DateTime",
"Format":"yyyy-MM-dd hh:mm:ss",
"Value":"2023/4/28 23:59:59"
},
{
"Name":"machine_id",
"Value":"DM1"
}
],
"ReportHeader":[
{
"Name":"ReportHeader1",
"Height":1.79917,
"Control":[
{
"Type":"MemoBox",
"Name":"MemoBox2",
"Left":7.59354,
"Top":0.211667,
"Width":5.60917,
"Height":1.19063,
"Font":{
"Name":"宋体",
"Size":217500,
"Bold":true,
"Charset":134
},
"TextAlign":"MiddleCenter",
"Text":"归还记录"
}
],
"RepeatOnPage":true
}
]
}

View File

@ -0,0 +1,284 @@
{
"Version":"6.8.5.2",
"Font":{
"Name":"宋体",
"Size":105000,
"Weight":400,
"Charset":134
},
"Printer":{
"LeftMargin":0.3175,
"TopMargin":0.899583,
"RightMargin":0.396875
},
"DetailGrid":{
"CenterView":true,
"AppendBlankRow":true,
"Recordset":{
"ConnectionString":"MYSQL;\r\nDatabase=hkcdb;\r\nPassword=qq1223;\r\nPort=3307;\r\nServer=127.0.0.1;\r\nUser=root;",
"QuerySQL":"SELECT \r\n dmr.`drawer_no` AS drawerNo,\r\n dmr.`col_no` AS colNo,\r\n dmr.`type` AS `type`,\r\n dmr.`quantity` AS quantity,\r\n dmr.`manu_no` AS manuNo,\r\n dmr.`eff_date` AS effDate,\r\n dmr.`operation_time` AS operationTime,\r\n di.`drug_name` AS drugName,\r\n di.`drug_spec` AS drugSpec,\r\n di.`pack_unit` AS packUnit,\r\n di.`manufactory` AS manuFactory,\r\n di.`max_stock` AS baseQuantity,\r\n dmr.`drug_id` AS drugId,\r\n ul.`user_name` AS nickname\r\nFROM\r\n dm_machine_record dmr\r\nLEFT JOIN drug_info di ON di.`drug_id` = dmr.`drug_id`\r\nLEFT JOIN user_list ul ON ul.`id` = dmr.`Operator`\r\nWHERE dmr.`type` = 2 \r\n AND dmr.`machine_id` = :machine_id\r\n AND dmr.`operation_time` > :startDate\r\n AND dmr.`operation_time` < :endDate",
"Field":[
{
"Name":"操作人",
"DBFieldName":"Nickname"
},
{
"Name":"时间",
"Type":"DateTime",
"Format":"yyyy/MM/dd HH:mm:ss",
"DBFieldName":"operationTime"
},
{
"Name":"药品名称",
"DBFieldName":"DrugName"
},
{
"Name":"数量",
"DBFieldName":"quantity"
},
{
"Name":"批次",
"DBFieldName":"manuNo"
},
{
"Name":"效期",
"Type":"DateTime",
"Format":"yyyy/MM/dd",
"DBFieldName":"effDate"
},
{
"Name":"库位",
"DBFieldName":"drawerNo"
},
{
"Name":"colNo"
},
{
"Name":"type2",
"Type":"Integer",
"DBFieldName":"type"
}
]
},
"Column":[
{
"Name":"操作人",
"Width":2.38125
},
{
"Name":"时间",
"Width":3.78354
},
{
"Name":"药品名称",
"Width":4.63021
},
{
"Name":"数量",
"Width":1.98438
},
{
"Name":"批次",
"Width":2.61938
},
{
"Name":"效期",
"Width":2.38125
},
{
"Name":"库位",
"Width":2.59292
}
],
"ColumnContent":{
"Height":1.00542,
"ColumnContentCell":[
{
"Column":"操作人",
"TextAlign":"MiddleCenter",
"DataField":"操作人"
},
{
"Column":"时间",
"TextAlign":"MiddleCenter",
"DataField":"时间"
},
{
"Column":"药品名称",
"TextAlign":"MiddleCenter",
"DataField":"药品名称"
},
{
"Column":"数量",
"TextAlign":"MiddleCenter",
"DataField":"数量"
},
{
"Column":"批次",
"TextAlign":"MiddleCenter",
"DataField":"批次"
},
{
"Column":"效期",
"TextAlign":"MiddleCenter",
"DataField":"效期"
},
{
"Column":"库位",
"FreeCell":true,
"Control":[
{
"Type":"FieldBox",
"Name":"FieldBox1",
"Left":9.60438,
"Top":-2.16958,
"Width":2.80458,
"Height":0.661458
},
{
"Type":"MemoBox",
"Name":"MemoBox1",
"Dock":"Fill",
"Center":"Both",
"TextAlign":"MiddleCenter",
"Text":"[#库位#] - [#colNo#]"
}
]
}
]
},
"ColumnTitle":{
"Height":1.40229,
"RepeatStyle":"OnPage",
"ColumnTitleCell":[
{
"GroupTitle":false,
"Column":"操作人",
"Font":{
"Name":"宋体",
"Size":120000,
"Bold":true,
"Charset":134
},
"TextAlign":"MiddleCenter",
"Text":"操作人"
},
{
"GroupTitle":false,
"Column":"时间",
"Font":{
"Name":"宋体",
"Size":120000,
"Bold":true,
"Charset":134
},
"TextAlign":"MiddleCenter",
"Text":"时间"
},
{
"GroupTitle":false,
"Column":"药品名称",
"Font":{
"Name":"宋体",
"Size":120000,
"Bold":true,
"Charset":134
},
"TextAlign":"MiddleCenter",
"Text":"药品名称"
},
{
"GroupTitle":false,
"Column":"数量",
"Font":{
"Name":"宋体",
"Size":120000,
"Bold":true,
"Charset":134
},
"TextAlign":"MiddleCenter",
"Text":"数量"
},
{
"GroupTitle":false,
"Column":"批次",
"Font":{
"Name":"宋体",
"Size":120000,
"Bold":true,
"Charset":134
},
"TextAlign":"MiddleCenter",
"Text":"批次"
},
{
"GroupTitle":false,
"Column":"效期",
"Font":{
"Name":"宋体",
"Size":120000,
"Bold":true,
"Charset":134
},
"TextAlign":"MiddleCenter",
"Text":"效期"
},
{
"GroupTitle":false,
"Column":"库位",
"Font":{
"Name":"宋体",
"Size":120000,
"Bold":true,
"Charset":134
},
"TextAlign":"MiddleCenter",
"Text":"库位"
}
]
}
},
"Parameter":[
{
"Name":"startDate",
"DataType":"DateTime",
"Format":"yyyy-MM-dd hh:mm:ss",
"Value":"2023/1/1"
},
{
"Name":"endDate",
"DataType":"DateTime",
"Format":"yyyy-MM-dd hh:mm:ss",
"Value":"2023/4/28 23:59:59"
},
{
"Name":"machine_id",
"Value":"DM1"
}
],
"ReportHeader":[
{
"Name":"ReportHeader1",
"Height":1.79917,
"Control":[
{
"Type":"MemoBox",
"Name":"MemoBox2",
"Left":7.59354,
"Top":0.211667,
"Width":5.60917,
"Height":1.19063,
"Font":{
"Name":"宋体",
"Size":217500,
"Bold":true,
"Charset":134
},
"TextAlign":"MiddleCenter",
"Text":"出库记录"
}
],
"RepeatOnPage":true
}
]
}

View File

@ -0,0 +1,348 @@
{
"Version":"6.8.5.2",
"Font":{
"Name":"宋体",
"Size":105000,
"Weight":400,
"Charset":134
},
"Printer":{
"Oriention":"Landscape"
},
"DetailGrid":{
"CenterView":true,
"PrintAdaptMethod":"ResizeToFit",
"AppendBlankRow":true,
"Recordset":{
"ConnectionString":"MYSQL;\r\nDatabase=hkcdb;\r\nPassword=qq1223;\r\nPort=3307;\r\nServer=127.0.0.1;\r\nUser=root;",
"QuerySQL":"SELECT \r\n cl.`row_no` AS drawerNo,\r\n cl.`col_no` AS colNo,\r\n cl.`quantity` AS quantity,\r\n cl.`manu_no` AS manuNo,\r\n cl.`eff_date` AS effDate,\r\n di.`drug_name` AS drugName,\r\n di.`drug_spec` AS drugSpec,\r\n di.`pack_unit` AS packUnit,\r\n di.`manufactory` AS manuFactory,\r\n di.`max_stock` AS baseQuantity,\r\n cl.`drug_id` AS drugId\r\nFROM\r\n channel_stock cl\r\nINNER JOIN drug_info di ON di.`drug_id` = cl.`drug_id`\r\nWHERE cl.`machine_id` = :machine_id\r\n AND cl.`drawer_type` = 1\r\n ORDER BY cl.`drug_id`",
"Field":[
{
"Name":"drugName"
},
{
"Name":"drugSpec"
},
{
"Name":"manuFactory"
},
{
"Name":"quantityCount"
},
{
"Name":"manuNo"
},
{
"Name":"effDate"
},
{
"Name":"quantity",
"Type":"Integer",
"Format":"0"
},
{
"Name":"drawerNo"
},
{
"Name":"drugId"
},
{
"Name":"baseQuantity",
"Type":"Integer"
}
]
},
"Column":[
{
"Name":"drugName",
"Width":5.37104
},
{
"Name":"drugSpec"
},
{
"Name":"manuFactory",
"Width":4.60375
},
{
"Name":"Column1"
},
{
"Name":"quantityCount",
"Width":2.59292
},
{
"Name":"manuNo"
},
{
"Name":"effDate"
},
{
"Name":"quantity",
"Width":2.43417
}
],
"ColumnContent":{
"Height":0.79375,
"ColumnContentCell":[
{
"Column":"drugName",
"TextAlign":"MiddleCenter",
"DataField":"drugName"
},
{
"Column":"drugSpec",
"TextAlign":"MiddleCenter",
"DataField":"drugSpec"
},
{
"Column":"manuFactory",
"TextAlign":"MiddleCenter",
"DataField":"manuFactory"
},
{
"Column":"Column1",
"FreeCell":true
},
{
"Column":"quantityCount",
"FreeCell":true
},
{
"Column":"manuNo",
"TextAlign":"MiddleCenter",
"DataField":"manuNo"
},
{
"Column":"effDate",
"TextAlign":"MiddleCenter",
"DataField":"effDate"
},
{
"Column":"quantity",
"TextAlign":"MiddleCenter",
"DataField":"quantity"
}
]
},
"ColumnTitle":{
"Height":1.19063,
"RepeatStyle":"OnPage",
"BeforeHeaders":true,
"ColumnTitleCell":[
{
"GroupTitle":false,
"Column":"drugName",
"Font":{
"Name":"宋体",
"Size":142500,
"Bold":true,
"Charset":134
},
"TextAlign":"MiddleCenter",
"Text":"药品名称"
},
{
"GroupTitle":false,
"Column":"drugSpec",
"Font":{
"Name":"宋体",
"Size":142500,
"Bold":true,
"Charset":134
},
"TextAlign":"MiddleCenter",
"Text":"规格"
},
{
"GroupTitle":false,
"Column":"manuFactory",
"Font":{
"Name":"宋体",
"Size":142500,
"Bold":true,
"Charset":134
},
"TextAlign":"MiddleCenter",
"Text":"厂家"
},
{
"GroupTitle":false,
"Column":"Column1",
"Font":{
"Name":"宋体",
"Size":142500,
"Bold":true,
"Charset":134
},
"TextAlign":"MiddleCenter",
"Text":"基数"
},
{
"GroupTitle":false,
"Column":"quantityCount",
"Font":{
"Name":"宋体",
"Size":142500,
"Bold":true,
"Charset":134
},
"TextAlign":"MiddleCenter",
"Text":"总库存"
},
{
"GroupTitle":false,
"Column":"manuNo",
"Font":{
"Name":"宋体",
"Size":142500,
"Bold":true,
"Charset":134
},
"TextAlign":"MiddleCenter",
"Text":"批次"
},
{
"GroupTitle":false,
"Column":"effDate",
"Font":{
"Name":"宋体",
"Size":142500,
"Bold":true,
"Charset":134
},
"TextAlign":"MiddleCenter",
"Text":"效期"
},
{
"GroupTitle":false,
"Column":"quantity",
"Font":{
"Name":"宋体",
"Size":142500,
"Bold":true,
"Charset":134
},
"TextAlign":"MiddleCenter",
"Text":"数量"
}
]
},
"Group":[
{
"Name":"drugId",
"ByFields":"drugId",
"GroupHeader":{
"Visible":false,
"Height":0.79375,
"RepeatOnPage":true,
"OccupyColumn":true,
"IncludeFooter":true,
"OccupiedColumns":"drugName;drugSpec;manuFactory;quantityCount;Column1",
"VAlign":"Middle"
},
"GroupFooter":{
"Visible":false,
"Height":0.396875
}
},
{
"Name":"Group1",
"ByFields":"drugId",
"GroupHeader":{
"Control":[
{
"Type":"MemoBox",
"Name":"MemoBox3",
"AlignColumn":"drugName",
"Width":5.34458,
"Height":1.19063,
"TextAlign":"MiddleCenter",
"Text":"[#drugName#]"
},
{
"Type":"MemoBox",
"Name":"MemoBox4",
"AlignColumn":"drugSpec",
"Left":5.37104,
"Width":2.96333,
"Height":1.19063,
"TextAlign":"MiddleCenter",
"Text":"[#drugSpec#]"
},
{
"Type":"MemoBox",
"Name":"MemoBox5",
"AlignColumn":"manuFactory",
"Left":8.36083,
"Width":4.57729,
"Height":1.19063,
"TextAlign":"MiddleCenter",
"Text":"[#manuFactory#]"
},
{
"Type":"MemoBox",
"Name":"MemoBox6",
"AlignColumn":"Column1",
"Left":12.9646,
"Width":2.96333,
"Height":1.19063,
"TextAlign":"MiddleCenter",
"Text":"[#baseQuantity#]"
},
{
"Type":"SummaryBox",
"Name":"SummaryBox1",
"AlignColumn":"quantityCount",
"Left":15.9544,
"Width":2.56646,
"Height":1.19063,
"TextAlign":"MiddleCenter",
"DataField":"quantity",
"Format":"0"
}
],
"OccupyColumn":true,
"SameAsColumn":false,
"OccupiedColumns":"Column1;drugName;drugSpec;manuFactory;quantityCount",
"VAlign":"Middle"
},
"GroupFooter":{
"Visible":false
}
}
]
},
"Parameter":[
{
"Name":"machine_id",
"Value":"DM1"
}
],
"ReportHeader":[
{
"Name":"ReportHeader1",
"Height":2.40771,
"Control":[
{
"Type":"StaticBox",
"Name":"StaticBox1",
"Center":"Horizontal",
"Left":7.77875,
"Top":0.608542,
"Width":9.18104,
"Height":1.21708,
"Font":{
"Name":"宋体",
"Size":217500,
"Bold":true,
"Charset":134
},
"TextAlign":"MiddleCenter",
"Text":"毒麻药品库存信息"
}
],
"RepeatOnPage":true
}
]
}

View File

@ -0,0 +1,6 @@
@inherits LayoutComponentBase
<div style="width:100vw;height:100vh">
@Body
</div>
<RadzenNotification />

View File

@ -0,0 +1,154 @@
@namespace MasaBlazorApp3
@using MasaBlazorApp3.Pojo.Config
@using MasaBlazorApp3.Util
@using log4net
@inherits LayoutComponentBase
<style>
.my-tab-menu{
padding: 10px 20px;
}
.my-tab-menu:hover{
box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.7); /* 阴影效果 */
text-decoration: none !important;
background: #255dd6;
border-radius: 20px;
}
a.active {
background: #255dd4;
border-radius: 20px;
}
</style>
<RadzenLayout>
<RadzenHeader Style="height: 75px;">
<RadzenRow JustifyContent="JustifyContent.Start" AlignItems="AlignItems.Center" Style="height: 100%;">
<RadzenColumn Size="2">
<RadzenStack Orientation="Orientation.Horizontal" AlignItems="AlignItems.Center">
<RadzenIcon Icon="chevron_left" Style="font-size:3rem;cursor: pointer;padding: 0 10px;" @onclick="@(() => { backHome(); })" />
</RadzenStack>
</RadzenColumn>
<RadzenColumn Size="8" Orientation="Orientation.Horizontal" AlignItems="AlignItems.Center" JustifyContent="JustifyContent.End">
<RadzenStack Orientation="Orientation.Horizontal" JustifyContent="JustifyContent.Center" AlignItems="AlignItems.Center">
@foreach (Premission p in children)
{
if (childrenIds.Any(id => id == p.Id))
{
<RadzenLink Match="NavLinkMatch.All" class="my-tab-menu" Path="@p.PremissionPath">@p.PremissionName</RadzenLink>
}
}
</RadzenStack>
</RadzenColumn>
<RadzenColumn Size="2">
<RadzenStack Orientation="Orientation.Horizontal" AlignItems="AlignItems.Center" JustifyContent="JustifyContent.Center">
@* <RadzenText TextAlign="TextAlign.Center" class="rz-color-white">退出</RadzenText> *@
<RadzenIcon Icon="exit_to_app" Style="font-size:2rem;cursor: pointer;" class="rz-ripple" IconColor="white" @onclick="@(() => { logout(); })" />
</RadzenStack>
</RadzenColumn>
</RadzenRow>
</RadzenHeader>
<RadzenBody>
<div class="container-fluid rz-p-1">
<RadzenCard>
@Body
</RadzenCard>
</div>
</RadzenBody>
<RadzenNotification />
<RadzenComponents />
</RadzenLayout>
@code
{
@inject GlobalStateService globalStateService;
@inject NavigationManager na;
int selectedIndex = 0;
Pojo.User Operator;
List<int> childrenIds;
List<Premission> children;
@inject Microsoft.Extensions.Options.IOptions<Pojo.Config.SettingConfig> setting;
@inject PortUtil _portUtil;
private readonly ILog logger = LogManager.GetLogger(typeof(MainLayout));
bool currentPage = true;
protected override void OnInitialized()
{
string Uri = na.Uri;
string[] s = Uri.Split("/");
Operator = globalStateService.Operator;
Premission parent = new Premission().getAdminPremission().Find(p => p.PremissionPath == s[3]);
childrenIds = Operator.role.permissionIds.Where(id => id - (parent .Id* 10) < 10).ToList();
children = parent.Items.ToList();
if(setting.Value.autoOutLog>0)
{
// 是否需要自动退出
var promiseUtil = new PromiseUtil<object>();
promiseUtil.taskAsyncLoop(500, null, async (data, next, stop) =>
{
if (globalStateService.Operator == null||!currentPage)
{
logger.Info($"MainLayout页自动退出循环停止{globalStateService.Operator==null},{!currentPage}");
stop();
}
else
{
try
{
//没有在操作抽屉
if(!_portUtil.Operate)
{
// 无人操作鼠标键盘
if((DateTime.Now - _portUtil.dateTime).TotalSeconds > setting.Value.autoOutLog && CheckComputerFreeState.GetLastInputTime() > setting.Value.autoOutLog)
{
logger.Info($"设备{setting.Value.autoOutLog}内无人操作,用户【{Operator?.NickName}】自动退出登录,_portUtil.Operate:{_portUtil.Operate},totalSecond:{(DateTime.Now - _portUtil.dateTime).TotalSeconds},lastInputTime:{CheckComputerFreeState.GetLastInputTime()},autoOutLog:{setting.Value.autoOutLog}");
globalStateService.Operator = null;
globalStateService.Reviewer = null;
na.NavigateTo("");
stop();
}
else
{
next();
}
}
else
{
next();
}
}
catch (Exception ex)
{
logger.Info($"检查是否自动退出循环异常:{ex.Message}");
next();
}
}
});
}
base.OnInitialized();
}
void backHome()
{
currentPage = false;
na.NavigateTo("/home");
}
void logout()
{
globalStateService.Operator = null;
globalStateService.Reviewer = null;
na.NavigateTo("");
}
}
@code
{
}

View File

@ -0,0 +1,53 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
namespace MasaBlazorApp3.Util
{
public class CheckComputerFreeState
{
/// <summary>
/// 创建结构体用于返回捕获时间
/// </summary>
[StructLayout(LayoutKind.Sequential)]
struct LASTINPUTINFO
{
/// <summary>
/// 设置结构体块容量
/// </summary>
[MarshalAs(UnmanagedType.U4)]
public int cbSize;
/// <summary>
/// 抓获的时间
/// </summary>
[MarshalAs(UnmanagedType.U4)]
public uint dwTime;
}
[DllImport("user32.dll")]
private static extern bool GetLastInputInfo(ref LASTINPUTINFO plii);
/// <summary>
/// 获取键盘和鼠标没有操作的时间
/// </summary>
/// <returns>用户上次使用系统到现在的时间间隔,单位为秒</returns>
public static long GetLastInputTime()
{
LASTINPUTINFO vLastInputInfo = new LASTINPUTINFO();
vLastInputInfo.cbSize = Marshal.SizeOf(vLastInputInfo);
if (!GetLastInputInfo(ref vLastInputInfo))
{
return 0;
}
else
{
var count = (Environment.TickCount & Int32.MaxValue) - (long)vLastInputInfo.dwTime;
var icount = count / 1000;
return icount;
}
}
}
}

View File

@ -0,0 +1,30 @@
using System.Text;
using System.Security.Cryptography;
namespace MasaBlazorApp3.Util
{
public class MD5
{
public static string GetMD5Hash(string password)
{
//就是比string往后一直加要好的优化容器
StringBuilder sb = new StringBuilder();
using (MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider())
{
//将输入字符串转换为字节数组并计算哈希。
byte[] data = md5.ComputeHash(Encoding.UTF8.GetBytes(password));
//X为 十六进制 X都是大写 x都为小写
//2为 每次都是两位数
//假设有两个数10和26正常情况十六进制显示0xA、0x1A这样看起来不整齐为了好看可以指定"X2"这样显示出来就是0x0A、0x1A。
//遍历哈希数据的每个字节
//并将每个字符串格式化为十六进制字符串。
int length = data.Length;
for (int i = 0; i < length; i++)
sb.Append(data[i].ToString("x2"));
}
return sb.ToString();
}
}
}

View File

@ -0,0 +1,44 @@
using SharpPromise;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static LinqToDB.Reflection.Methods.LinqToDB.Insert;
namespace MasaBlazorApp3.Util
{
public class PromiseUtil<T>
{
public int _delay { get; set; }
public T? _data { get; set; }
public async Task taskAsyncLoop(int delay, T data, Action<PromiseUtil<T>, Action, Action> action)
{
_data = data;
_delay = 0;
while (_delay >= 0)
{
await new Promise(async (Action onResolve, Action onReject) =>
{
await Task.Delay(_delay);
try
{
await Task.Run(() => action(this, onResolve, onReject));
} catch (Exception ex)
{
onReject();
}
}).Then(() =>
{
_delay = delay;
}).Catch((Exception e) =>
{
_delay = -1;
});
}
}
}
}

View File

@ -0,0 +1,342 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Management;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Threading;
namespace MasaBlazorApp3.Util
{
public class VirtualKeyboardHelper
{
private const uint WS_VISIBLE = 0x10000000;
private const int GWL_STYLE = -16;
private const int WM_SYSCOMMAND = 0x0112;
private const uint SC_CLOSE = 0xF060;
private const int WS_DISABLED = 0x08000000;
private const int DWMWA_CLOAKED = 14;
private const string ApplicationFrameHostClassName = "ApplicationFrameWindow";
private const string CoreWindowClassName = "Windows.UI.Core.CoreWindow";
private const string TextInputApplicationCaption = "Microsoft Text Input Application";
/// <summary>
/// win10 虚拟键盘路径
/// </summary>
private const string Win10TabTipPath = @"C:\Program Files\Common Files\microsoft shared\ink\TabTip.exe";
/// <summary>
/// win7 虚拟键盘路径
/// </summary>
private const string Win7OskPath = @"C:\WINDOWS\system32\osk.exe";
/// <summary>
/// 虚拟键盘 窗口名称
/// </summary>
private const string TabTipWindowClassName = "IPTIP_Main_Window";
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
private static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
[DllImport("user32.dll", EntryPoint = "FindWindowEx")]
private static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass,
string lpszWindow);
[DllImport("user32.dll", EntryPoint = "GetWindowLong")]
private static extern int GetWindowLong(IntPtr hWnd, int nIndex);
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
private static extern bool PostMessage(IntPtr hWnd, int msg, uint wParam, uint lParam);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool Wow64DisableWow64FsRedirection(ref IntPtr ptr);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool Wow64RevertWow64FsRedirection(IntPtr ptr);
[DllImport("user32.dll", EntryPoint = "GetDesktopWindow", SetLastError = false)]
private static extern IntPtr GetDesktopWindow();
[DllImport("dwmapi.dll", EntryPoint = "DwmGetWindowAttribute")]
private static extern int DwmGetWindowAttribute(IntPtr intPtr, int dwAttribute, out int pvAttribute,
uint cbAttribute);
/// <summary>
/// 判断键盘是否连接
/// </summary>
/// <returns></returns>
public static bool IsKeyboardAttached()
{
try
{
ManagementObjectSearcher searcher =
new ManagementObjectSearcher("root\\CIMV2", "SELECT * FROM Win32_Keyboard");
int devCount = 0;
foreach (ManagementObject obj in searcher.Get())
{
if (obj["Status"].ToString().Contains("OK")) // if device is ready
{
//surface测试时发现HID设备不是键盘比较特殊
if (!obj["Description"].ToString().Contains("HID Keyboard Device"))
{
devCount++;
}
}
}
return devCount > 0;
}
catch (Exception)
{
return false;
}
}
/// <summary>
/// 打开虚拟键盘目前支持win7 64位win10 64位exe编译为x86。
/// </summary>
public static void ShowVirtualKeyboard()
{
//+------------------------------------------------------------------------------+
//| | PlatformID | Major version | Minor version |
//+------------------------------------------------------------------------------+
//| Windows 95 | Win32Windows | 4 | 0 |
//| Windows 98 | Win32Windows | 4 | 10 |
//| Windows Me | Win32Windows | 4 | 90 |
//| Windows NT 4.0 | Win32NT | 4 | 0 |
//| Windows 2000 | Win32NT | 5 | 0 |
//| Windows XP | Win32NT | 5 | 1 |
//| Windows 2003 | Win32NT | 5 | 2 |
//| Windows Vista | Win32NT | 6 | 0 |
//| Windows 2008 | Win32NT | 6 | 0 |
//| Windows 7 | Win32NT | 6 | 1 |
//| Windows 2008 R2 | Win32NT | 6 | 1 |
//| Windows 8 | Win32NT | 6 | 2 |
//| Windows 8.1 | Win32NT | 6 | 3 |
//+------------------------------------------------------------------------------+
//| Windows 10 | Win32NT | 10 | 0 |
try
{
var isWin7 = Environment.OSVersion.Version.Major == 6 && Environment.OSVersion.Version.Minor == 1;
var isWin8OrWin10 =
Environment.OSVersion.Version.Major == 6 && Environment.OSVersion.Version.Minor == 2;
var isWin10 = Environment.OSVersion.Version.Major == 10 && Environment.OSVersion.Version.Minor == 0;
if (isWin7)
{
//win7
ShowWin7VirtualKeyboard();
}
else if (isWin8OrWin10 || isWin10)
{
//win10
ShowWin10VirtualKeyboard();
}
}
catch (Exception)
{
// ignored
}
}
/// <summary>
/// 关闭虚拟键盘
/// </summary>
public void CloseVirtualKeyboard()
{
var touchhWnd = FindWindow("IPTip_Main_Window", null);
if (touchhWnd == IntPtr.Zero)
{
return;
}
PostMessage(touchhWnd, WM_SYSCOMMAND, SC_CLOSE, 0);
}
private static void ShowWin7VirtualKeyboard()
{
if (!Environment.Is64BitProcess && Environment.Is64BitOperatingSystem)
{
//32位程序 运行在64位系统上打开32位程序需要禁用文件重定向
var ptr = new IntPtr();
var isWow64FsRedirectionDisabled = Wow64DisableWow64FsRedirection(ref ptr);
Process.Start(Win7OskPath);
if (isWow64FsRedirectionDisabled)
{
Wow64RevertWow64FsRedirection(ptr);
}
}
else if (Environment.Is64BitProcess && Environment.Is64BitOperatingSystem)
{
Process.Start(Win7OskPath);
}
}
private static void ShowWin10VirtualKeyboard()
{
if (!IsTabTipProcessPresent())
{
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.FileName = Win10TabTipPath;
startInfo.UseShellExecute = true;
startInfo.Verb = "runas";
Process.Start(startInfo);
while (!IsValidHandle(FindWindow("IPTIP_Main_Window", "")))
{
Thread.Sleep(100);
}
}
//判断可见性
if (!IsWin10OnScreenKeyboardVisible())
{
ShowByCom();
}
}
private static bool IsWin10OnScreenKeyboardVisible()
{
var handle = FindWindow(TabTipWindowClassName, "");
if (!IsValidHandle(handle))
{
return false;
}
var isVisible = IsWindowVisibleByHandle(handle);
if (isVisible.HasValue)
{
return isVisible.Value;
}
// hard way
var textInputHandle = FindTextInputWindow();
return IsValidHandle(textInputHandle);
}
private static IntPtr FindTextInputWindow()
{
var lastProbed = IntPtr.Zero;
do
{
lastProbed = FindWindowEx(IntPtr.Zero, lastProbed, ApplicationFrameHostClassName, null);
if (IsValidHandle(lastProbed))
{
var textInput = FindWindowEx(lastProbed, IntPtr.Zero, CoreWindowClassName,
TextInputApplicationCaption);
return textInput;
}
} while (IsValidHandle(lastProbed));
return IntPtr.Zero;
}
private static bool? IsWindowVisibleByHandle(IntPtr handle)
{
var style = GetWindowLong(handle, GWL_STYLE);
//Console.WriteLine( "Style {0:X8}", style );
// if is disabled - not visible
if ((style & WS_DISABLED) != 0)
{
return false;
}
// if has visible style - visible :)
if ((style & WS_VISIBLE) != 0)
{
return true;
}
// DWM Window can be cloaked
// see https://social.msdn.microsoft.com/Forums/vstudio/en-US/f8341376-6015-4796-8273-31e0be91da62/difference-between-actually-visible-and-not-visiblewhich-are-there-but-we-cant-see-windows-of?forum=vcgeneral
if (DwmGetWindowAttribute(handle, DWMWA_CLOAKED, out var cloaked, 4) == 0)
{
if (cloaked != 0)
{
return false;
}
}
// undefined
return null;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static bool IsValidHandle(IntPtr handle)
{
// if (?:) will be eliminated by jit
return IntPtr.Size == 4
? handle.ToInt32() > 0
: handle.ToInt64() > 0;
}
private static bool IsTabTipProcessPresent()
{
var handle = FindWindow(TabTipWindowClassName, "");
return IntPtr.Size == 4
? handle.ToInt32() > 0
: handle.ToInt64() > 0;
}
private static void ShowByCom()
{
ITipInvocation instance = null;
try
{
instance = (ITipInvocation)Activator.CreateInstance(ComTypes.TipInvocationType);
instance.Toggle(GetDesktopWindow());
}
finally
{
if (!ReferenceEquals(instance, null))
{
Marshal.ReleaseComObject(instance);
}
}
}
}
[ComImport]
[Guid("37c994e7-432b-4834-a2f7-dce1f13b834b")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
internal interface ITipInvocation
{
void Toggle(IntPtr hwnd);
}
internal static class ComTypes
{
internal static readonly Guid ImmersiveShellBrokerGuid;
internal static readonly Type ImmersiveShellBrokerType;
internal static readonly Guid TipInvocationGuid;
internal static readonly Type TipInvocationType;
static ComTypes()
{
TipInvocationGuid = Guid.Parse("4ce576fa-83dc-4F88-951c-9d0782b4e376");
TipInvocationType = Type.GetTypeFromCLSID(TipInvocationGuid);
ImmersiveShellBrokerGuid = new Guid("228826af-02e1-4226-a9e0-99a855e455a6");
ImmersiveShellBrokerType = Type.GetTypeFromCLSID(ImmersiveShellBrokerGuid);
}
}
}

View File

@ -0,0 +1,22 @@
using FluentValidation;
using MasaBlazorApp3.Pojo;
namespace MasaBlazorApp3.Validator
{
public class LoginModelValidator : AbstractValidator<User>
{
public LoginModelValidator()
{
RuleFor(u => u.Username).NotEmpty().WithMessage("用户名不能为空");
RuleFor(u => u.Password).NotEmpty();
}
public Func<object, string, Task<IEnumerable<string>>> ValidateValue => async (model, propertyName) =>
{
var result = await ValidateAsync(ValidationContext<User>.CreateWithOptions((User)model, x => x.IncludeProperties(propertyName)));
if (result.IsValid)
return Array.Empty<string>();
return result.Errors.Select(e => e.ErrorMessage);
};
}
}

View File

@ -0,0 +1,24 @@
@using System.Net.Http
@using Microsoft.AspNetCore.Components.Forms
@using Microsoft.AspNetCore.Components.Routing
@using Microsoft.AspNetCore.Components.Web
@using Microsoft.AspNetCore.Components.Web.Virtualization
@using Microsoft.JSInterop
@using Radzen
@using Radzen.Blazor
@using MasaBlazorApp3.Shared;
@using System.Net.Http.Json
@using System.IO;
@using System.Text.Json;
@using MasaBlazorApp3.Pojo
@using MasaBlazorApp3.Validator
@using MasaBlazorApp3.Finger
@using MasaBlazorApp3.Port
@using MasaBlazorApp3.DataAccess.Impl;
@using MasaBlazorApp3.DataAccess.Dao;
@using MasaBlazorApp3.DataAccess;
@using MasaBlazorApp3;

View File

@ -0,0 +1,32 @@
{
"connectionStrings": "server=127.0.0.1;port=3306;database=hkcdb;userid=root;password=root;Charset=utf8mb4;",
"finger": {
"ip": "192.168.50.201",
"port": 4370,
"type": 2
},
"setting": {
"machineId": "DM1",
"storage": null,
"loginMode": 1,
"opFirst": true,
//退,0退
"autoOutLog": 0
},
"port": {
"drawerPortPath": "COM1",
"drawerProtocol": 485,
"scanCodePortPath": "COM8",
"canBusPortPath": "COM5",
"canBusExsit": true,
"doorAddr": 0,
"storageBoxAddr": 0
},
"drawer": {
"single": [ 3 ],
"weigh": [1],
"box": [],
"label": []
}
}

BIN
MasaBlazorApp3/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 264 KiB

View File

@ -0,0 +1,4 @@
{
"login": "LOGIN",
"exit": "EXIT"
}

View File

@ -0,0 +1,4 @@
{
"login": "登录",
"exit": "退出"
}

Some files were not shown because too many files have changed in this diff Show More