添加项目文件。

This commit is contained in:
2026-04-30 11:34:41 +08:00
parent a8539ccaac
commit 80635aa46e
181 changed files with 16378 additions and 0 deletions

View File

@@ -0,0 +1,75 @@
using System.Collections.Concurrent;
using System.Collections.Generic;
namespace SamplePre.Common
{
public class ConcurrentQueueExt<T>
{
private readonly ConcurrentQueue<T> queue = new ConcurrentQueue<T>();
public void Enqueue(T msgData)
{
if (msgData != null)
{
queue.Enqueue(msgData);
}
}
//public void Enqueue(List<T> msgDatas)
//{
// if (msgDatas.IsNullOrEmpty()) return;
// foreach (var msgData in msgDatas)
// {
// queue.Enqueue(msgData);
// }
//}
public T GetOne()
{
if (queue.TryDequeue(out T result))
{
return result;
}
else
{
return default;
}
}
public List<T> GetAll()
{
List<T> result = new List<T>();
int count = queue.Count;
if (count > 0)
{
for (int i = 0; i < count; i++)
{
if (queue.TryDequeue(out T t))
{
result.Add(t);
}
}
}
return result;
}
public void Clear()
{
while (!queue.IsEmpty)
{
queue.TryDequeue(out _);
}
}
public int Count
{
get
{
return queue.Count;
}
}
}
}

View File

@@ -0,0 +1,91 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
namespace SamplePre.Common.Helper
{
/// <summary>
/// 实体对象复制工具类(反射实现)
/// 适配.NET Framework 4.8,支持同实体/不同实体间同名字段值复制(浅拷贝)
/// </summary>
public static class ObjectCopyHelper
{
/// <summary>
/// 核心方法:将源对象的同名字段值复制到目标对象
/// </summary>
/// <typeparam name="TSource">源对象类型</typeparam>
/// <typeparam name="TTarget">目标对象类型</typeparam>
/// <param name="source">源对象(提供值)</param>
/// <param name="target">目标对象(接收值,需提前实例化)</param>
/// <param name="ignoreCase">是否忽略属性名大小写默认trueName和name视为同一个</param>
/// <param name="ignoreNull">是否忽略源对象的null值默认false源null会覆盖目标值</param>
public static void CopyProperties<TSource, TTarget>(this TSource source, TTarget target,
bool ignoreCase = true, bool ignoreNull = false)
where TSource : class // 源对象不能为空引用类型
where TTarget : class // 目标对象不能为空引用类型
{
// 空值校验
if (source == null) throw new ArgumentNullException(nameof(source), "源对象不能为null");
if (target == null) throw new ArgumentNullException(nameof(target), "目标对象不能为null");
// 获取源对象和目标对象的属性信息(仅获取公共可读写属性)
PropertyInfo[] sourceProps = typeof(TSource).GetProperties(BindingFlags.Public | BindingFlags.Instance);
PropertyInfo[] targetProps = typeof(TTarget).GetProperties(BindingFlags.Public | BindingFlags.Instance);
// 遍历源对象的所有属性,匹配目标对象的同名字段
foreach (PropertyInfo sourceProp in sourceProps)
{
// 跳过源对象中不可读的属性无getter
if (!sourceProp.CanRead) continue;
// 获取源对象当前属性的值
object sourceValue = sourceProp.GetValue(source, null);
// 忽略源对象的null值若开启该配置
if (ignoreNull && sourceValue == null) continue;
// 在目标对象中查找同名字段(支持忽略大小写)
PropertyInfo targetProp = Array.Find(targetProps, p =>
string.Equals(p.Name, sourceProp.Name, ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal));
// 目标对象无该属性/目标属性不可写/类型不匹配 → 跳过
if (targetProp == null || !targetProp.CanWrite
|| !sourceProp.PropertyType.IsAssignableFrom(targetProp.PropertyType))
{
continue;
}
// 给目标对象的属性赋值
targetProp.SetValue(target, sourceValue, null);
}
}
/// <summary>
/// 重载方法快速复制默认忽略大小写、不忽略null
/// </summary>
public static void CopyProperties<TSource, TTarget>(this TSource source, TTarget target)
where TSource : class
where TTarget : class
{
CopyProperties(source, target, true, false);
}
/// <summary>
/// 便捷方法:创建目标对象并完成复制(一步到位,无需提前实例化目标对象)
/// </summary>
public static TTarget CopyToNew<TSource, TTarget>(this TSource source,
bool ignoreCase = true, bool ignoreNull = false)
where TSource : class
where TTarget : class, new() // 目标对象必须有无参构造函数
{
if (source == null) throw new ArgumentNullException(nameof(source));
// 实例化目标对象并赋值
TTarget target = new TTarget();
source.CopyProperties(target, ignoreCase, ignoreNull);
return target;
}
}
}

View File

@@ -0,0 +1,46 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
namespace SamplePre.Common
{
public class ReflectionCommHelper
{
/// <summary>
/// 根据属性名获取对象的属性值(支持公共/非公共属性)
/// </summary>
/// <param name="obj">目标对象不能为null</param>
/// <param name="propertyName">属性名(大小写敏感)</param>
/// <param name="ignoreCase">是否忽略大小写默认false</param>
/// <returns>属性值不存在返回null</returns>
public static object GetPropertyValue(object obj, string propertyName, bool ignoreCase = false)
{
// 空值校验
if (obj == null)
throw new ArgumentNullException(nameof(obj), "目标对象不能为null");
if (string.IsNullOrEmpty(propertyName))
throw new ArgumentNullException(nameof(propertyName), "属性名不能为空");
// 获取对象类型
Type type = obj.GetType();
// 获取属性信息BindingFlags控制是否查找非公共/实例成员)
PropertyInfo propInfo = type.GetProperty(
propertyName,
BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance |
(ignoreCase ? BindingFlags.IgnoreCase : BindingFlags.Default)
);
// 属性不存在返回null
if (propInfo == null)
return null;
// 获取属性值
return propInfo.GetValue(obj);
}
}
}

View File

@@ -0,0 +1,74 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Serialization;
namespace SamplePre.Common.Helper
{
/// <summary>
/// XML序列化/反序列化工具类(强类型读取)
/// </summary>
public static class XmlSerializerHelper
{
/// <summary>
/// 从XML文件反序列化为指定类型的对象
/// </summary>
/// <typeparam name="T">目标实体类型</typeparam>
/// <param name="filePath">XML文件路径</param>
/// <returns>实体对象</returns>
public static T DeserializeFromXml<T>(string filePath) where T : class, new()
{
// 检查文件是否存在
if (!File.Exists(filePath))
{
throw new FileNotFoundException("XML配置文件不存在", filePath);
}
try
{
// 初始化序列化器
XmlSerializer serializer = new XmlSerializer(typeof(T));
// 读取文件并反序列化
using (FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read))
{
return serializer.Deserialize(fs) as T;
}
}
catch (Exception ex)
{
throw new Exception("XML反序列化失败检查XML格式和实体类是否匹配", ex);
}
}
/// <summary>
/// 将对象序列化为XML并保存到文件
/// </summary>
/// <typeparam name="T">实体类型</typeparam>
/// <param name="obj">实体对象</param>
/// <param name="filePath">保存路径</param>
public static void SerializeToXml<T>(T obj, string filePath) where T : class
{
if (obj == null)
{
throw new ArgumentNullException(nameof(obj), "序列化对象不能为null");
}
try
{
XmlSerializer serializer = new XmlSerializer(typeof(T));
// 写入文件UTF8编码避免中文乱码
using (StreamWriter sw = new StreamWriter(filePath, false, System.Text.Encoding.UTF8))
{
serializer.Serialize(sw, obj);
}
}
catch (Exception ex)
{
throw new Exception("XML序列化失败", ex);
}
}
}
}

View File

@@ -0,0 +1,100 @@
using NLog;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SamplePre.Common
{
/// <summary>
/// nLog使用帮助类
/// </summary>
public class LoggerHelper
{
/// <summary>
/// 实例化nLog即为获取配置文件相关信息(获取以当前正在初始化的类命名的记录器)
/// </summary>
private readonly NLog.Logger _logger = LogManager.GetCurrentClassLogger();
private static LoggerHelper _obj;
public static LoggerHelper Logger
{
get => _obj ?? (new LoggerHelper());
set => _obj = value;
}
#region Debug
public void Debug(string msg)
{
_logger.Debug(msg);
}
public void Debug(string msg, Exception err)
{
_logger.Debug(err, msg);
}
#endregion
#region Info
public void Info(string msg)
{
_logger.Info(msg);
}
public void Info(string msg, Exception err)
{
_logger.Info(err, msg);
}
#endregion
#region Warn
public void Warn(string msg)
{
_logger.Warn(msg);
}
public void Warn(string msg, Exception err)
{
_logger.Warn(err, msg);
}
#endregion
#region Trace
public void Trace(string msg)
{
_logger.Trace(msg);
}
public void Trace(string msg, Exception err)
{
_logger.Trace(err, msg);
}
#endregion
#region Error
public void Error(string msg)
{
_logger.Error(msg);
}
public void Error(string msg, Exception err)
{
_logger.Error(err, msg);
}
#endregion
#region Fatal,
public void Fatal(string msg)
{
_logger.Fatal(msg);
}
public void Fatal(string msg, Exception err)
{
_logger.Fatal(err, msg);
}
#endregion
}
}

View File

@@ -0,0 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="NLog" Version="5.2.5" />
<PackageReference Include="S7netplus" Version="0.20.0" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,43 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SamplePre.Communication
{
/// <summary>
/// 通讯协议类型枚举
/// </summary>
public enum CommProtocolType
{
S7 = 0,
ModbusTcp = 1,
ModbusRtu = 2
}
/// <summary>
/// 通讯状态枚举
/// </summary>
public enum CommunicationState
{
Disconnected = 0,
Connected = 1,
Connecting = 2,
Error = 3
}
/// <summary>
/// 通讯数据类型枚举
/// </summary>
public enum CommDataType
{
Bit, // 位
Byte, // 字节
Int16, // 16位整数
Int32, // 32位整数
Float // 浮点型
}
}

View File

@@ -0,0 +1,40 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SamplePre.Communication
{
public interface ICommunication
{
/// <summary>
/// 下发下位机指令
/// </summary>
/// <param name="Dbno"></param>
/// <param name="start"></param>
/// <param name="bytes"></param>
/// <returns></returns>
bool WriteArraysBtye<T>(int Dbno, int start, T[] bytes);
/// <summary>
/// 读取监控数据,读取数组
/// </summary>
/// <returns></returns>
ushort[] ReadArraysShort(int Dbno, int start, int lenth);
/// <summary>
/// 写入数据
/// </summary>
/// <param name="address">地址(如"M0.0", "DB1.DBW2"</param>
/// <param name="value">要写入的值</param>
/// <returns>是否写入成功</returns>
public bool WriteSingleData(string address, object value);
}
}

View File

@@ -0,0 +1,236 @@
using Modbus.Device;
using S7.Net;
using SamplePre.Common;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
namespace SamplePre.Communication.Communication
{
public class ModbusTcpCommunicator : ICommunication, IDisposable
{
IModbusMaster _modbusMaster = null;
TcpClient _tcpClient = null;
private readonly string _ipAddress;
private readonly int _port;
/// <summary>
/// 是否连接
/// </summary>
private bool _isConnected = false;
/// <summary>
/// 是否连接
/// </summary>
public bool IsConnected
{
get => _isConnected;
set
{
if (_isConnected != value)
{
_isConnected = value;
ConnectionStatusChanged?.Invoke(value);
}
}
}
/// <summary>
/// 连接状态变化事件
/// </summary>
public event Action<bool> ConnectionStatusChanged;
/// <summary>
/// 构造函数
/// </summary>
/// <param name="ipAddress">IP地址</param>
/// <param name="port">端口号</param>
public ModbusTcpCommunicator(string ipAddress, int port=502)
{
try
{
_ipAddress = ipAddress;
_port = port;
_tcpClient = new TcpClient(ipAddress, port);//Modbus主设备
_modbusMaster = ModbusIpMaster.CreateIp(_tcpClient);
_modbusMaster.Transport.ReadTimeout = 2000;
_modbusMaster.Transport.Retries = 3;
IsConnected = true;
}
catch (Exception ex)
{
LoggerHelper.Logger.Error("初始化ModbusTcpCommunicator失败" + ex.Message);
}
}
/// <summary>
/// 连接PLC
/// </summary>
/// <returns>是否连接成功</returns>
public bool Connect()
{
try
{
if (IsConnected)
{
LoggerHelper.Logger.Info("已经处于连接状态!");
return true;
}
// 如果之前的连接对象已释放,创建新的
if (_modbusMaster == null)
{
_tcpClient = new TcpClient(_ipAddress, _port);//Modbus主设备
_modbusMaster = ModbusIpMaster.CreateIp(_tcpClient);
_modbusMaster.Transport.ReadTimeout = 2000; //
_modbusMaster.Transport.Retries = 3;
}
LoggerHelper.Logger.Info("PLC连接成功");
IsConnected = true;
return IsConnected;
}
catch (Exception ex)
{
LoggerHelper.Logger.Info($"连接PLC失败: {ex.Message}");
IsConnected = false;
return false;
}
}
/// <summary>
/// 断开连接
/// </summary>
public void Disconnect()
{
try
{
if (IsConnected)
{
_modbusMaster.Dispose();
_tcpClient.Close();
IsConnected = false;
LoggerHelper.Logger.Info("PLC连接已断开");
}
}
catch (Exception ex)
{
LoggerHelper.Logger.Info($"断开PLC连接失败: {ex.Message}");
}
}
/// <summary>
/// 写入数组数据
/// </summary>
/// <param name="Dbno"></param>
/// <param name="start"></param>
/// <param name="bytes"></param>
/// <returns></returns>
public bool WriteArraysBtye<T>(int Dbno, int start, T[] data)
{
try
{
if (!IsConnected && !Connect())
{
return false;
}
ushort[] ushorts = data.Cast<ushort>().ToArray();
_modbusMaster.WriteMultipleRegisters((byte)Dbno, (ushort)start, ushorts);
return true;
}
catch (Exception ex)
{
LoggerHelper.Logger.Info($"写入数组失败: {ex.Message}");
return false;
}
}
/// <summary>
/// 读取数组
/// </summary>
/// <returns></returns>
public ushort[] ReadArraysShort(int Dbno, int start, int lenth)
{
//try
//{
// if (!IsConnected && !Connect())
// {
// return null;
// }
// //public object? Read(DataType dataType, int db, int startByteAdr, VarType varType, int varCount, byte bitAdr = 0)
// ushort[] datas = _plc.Read(DataType.DataBlock, Dbno, start, VarType.Word, lenth) as ushort[];
// return datas;
//}
//catch (Exception ex)
//{
// LoggerHelper.Logger.Info($"读取数组失败: {ex.Message}");
// return null;
//}
return null;
}
/// <summary>
/// 释放资源
/// </summary>
public void Dispose()
{
// 释放托管资源
Disconnect();
}
public bool WriteSingleData(string address, object value)
{
throw new NotImplementedException();
}
~ModbusTcpCommunicator()
{
Dispose();
}
}
}

View File

@@ -0,0 +1,236 @@
using S7.Net;
using S7.Net.Types;
using SamplePre.Common;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
namespace SamplePre.Communication
{
public class S7PlcCommunicator : ICommunication, IDisposable
{
public Plc _plc;
private readonly string _ipAddress;
private readonly int _rack;
private readonly int _slot;
private readonly CpuType _cpuType;
/// <summary>
/// 是否连接
/// </summary>
private bool _isConnected = false;
/// <summary>
/// 是否连接
/// </summary>
public bool IsConnected
{
get => _isConnected;
set
{
if (_isConnected != value)
{
_isConnected = value;
ConnectionStatusChanged?.Invoke(value);
}
}
}
/// <summary>
/// 连接状态变化事件
/// </summary>
public event Action<bool> ConnectionStatusChanged;
/// <summary>
/// 构造函数
/// </summary>
/// <param name="cpuType">PLC型号</param>
/// <param name="ipAddress">IP地址</param>
/// <param name="rack">机架号</param>
/// <param name="slot">插槽号</param>
public S7PlcCommunicator(CpuType cpuType, string ipAddress, int rack = 0, int slot = 1)
{
_cpuType = cpuType;
_ipAddress = ipAddress;
_rack = rack;
_slot = slot;
_plc = new Plc(cpuType, ipAddress, (short)rack, (short)slot);
}
/// <summary>
/// 连接PLC
/// </summary>
/// <returns>是否连接成功</returns>
public bool Connect()
{
try
{
if (IsConnected)
{
LoggerHelper.Logger.Info("已经处于连接状态!");
return true;
}
// 如果之前的连接对象已释放,创建新的
if (_plc == null)
{
_plc = new Plc(_cpuType, _ipAddress, (short)_rack, (short)_slot);
}
_plc.Open();
bool connected = _plc.IsConnected;
LoggerHelper.Logger.Info(connected ? "PLC连接成功" : "PLC连接失败");
IsConnected = connected;
return connected;
}
catch (Exception ex)
{
LoggerHelper.Logger.Info($"连接PLC失败: {ex.Message}");
IsConnected = false;
return false;
}
}
/// <summary>
/// 断开连接
/// </summary>
public void Disconnect()
{
try
{
if (IsConnected)
{
_plc.Close();
IsConnected = false;
LoggerHelper.Logger.Info("PLC连接已断开");
}
}
catch (Exception ex)
{
LoggerHelper.Logger.Info($"断开PLC连接失败: {ex.Message}");
}
}
/// <summary>
/// 写入数组数据
/// </summary>
/// <param name="Dbno"></param>
/// <param name="start"></param>
/// <param name="bytes"></param>
/// <returns></returns>
public bool WriteArraysBtye<T>(int Dbno, int start, T[] bytes)
{
try
{
if (!IsConnected && !Connect())
{
return false;
}
byte[] data = bytes.Cast<byte>().ToArray();
_plc.WriteBytes(DataType.DataBlock, Dbno, start, data);
return true;
}
catch (Exception ex)
{
LoggerHelper.Logger.Info($"写入数组失败: {ex.Message}");
return false;
}
}
/// <summary>
/// 读取数组
/// </summary>
/// <returns></returns>
public ushort[] ReadArraysShort(int Dbno,int start,int lenth)
{
try
{
if (!IsConnected && !Connect())
{
return null;
}
//public object? Read(DataType dataType, int db, int startByteAdr, VarType varType, int varCount, byte bitAdr = 0)
ushort[] datas = _plc.Read(DataType.DataBlock, Dbno, start, VarType.Word, lenth) as ushort[];
return datas;
}
catch (Exception ex)
{
LoggerHelper.Logger.Info($"读取数组失败: {ex.Message}");
return null;
}
}
/// <summary>
/// 写入数据
/// </summary>
/// <param name="address">地址(如"M0.0", "DB1.DBW2"</param>
/// <param name="value">要写入的值</param>
/// <returns>是否写入成功</returns>
public bool WriteSingleData(string address, object value)
{
try
{
if (!IsConnected && !Connect())
{
return false;
}
_plc.Write(address, value);
Console.WriteLine($"写入 {address} 成功: {value}");
return true;
}
catch (Exception ex)
{
Console.WriteLine($"写入 {address} 失败: {ex.Message}");
return false;
}
}
/// <summary>
/// 释放资源
/// </summary>
public void Dispose()
{
// 释放托管资源
Disconnect();
//_plc?.Dispose();
_plc = null;
}
~S7PlcCommunicator()
{
Dispose();
}
}
}

View File

@@ -0,0 +1,424 @@
using S7.Net;
using S7.Net.Types;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
namespace SamplePre.Communication
{
public class S7PlcCommunicatorBack : IDisposable
{
public Plc _plc;
private readonly string _ipAddress;
private readonly int _rack;
private readonly int _slot;
private readonly CpuType _cpuType;
/// <summary>
/// 是否连接
/// </summary>
public bool IsConnected => _plc?.IsConnected ?? false;
/// <summary>
/// 连接状态变化事件
/// </summary>
public event Action<bool> ConnectionStatusChanged;
/// <summary>
/// 构造函数
/// </summary>
/// <param name="cpuType">PLC型号</param>
/// <param name="ipAddress">IP地址</param>
/// <param name="rack">机架号</param>
/// <param name="slot">插槽号</param>
public S7PlcCommunicatorBack(CpuType cpuType, string ipAddress, int rack = 0, int slot = 1)
{
_cpuType = cpuType;
_ipAddress = ipAddress;
_rack = rack;
_slot = slot;
_plc = new Plc(cpuType, ipAddress, (short)rack, (short)slot);
}
/// <summary>
/// 连接PLC
/// </summary>
/// <returns>是否连接成功</returns>
public bool Connect()
{
try
{
if (IsConnected)
{
Console.WriteLine("已经处于连接状态");
return true;
}
// 如果之前的连接对象已释放,创建新的
if (_plc == null)
{
_plc = new Plc(_cpuType, _ipAddress, (short)_rack, (short)_slot);
}
_plc.Open();
bool connected = _plc.IsConnected;
Console.WriteLine(connected ? "PLC连接成功" : "PLC连接失败");
ConnectionStatusChanged?.Invoke(connected);
return connected;
}
catch (Exception ex)
{
Console.WriteLine($"连接PLC失败: {ex.Message}");
ConnectionStatusChanged?.Invoke(false);
return false;
}
}
/// <summary>
/// 断开连接
/// </summary>
public void Disconnect()
{
try
{
if (IsConnected)
{
_plc.Close();
Console.WriteLine("PLC连接已断开");
ConnectionStatusChanged?.Invoke(false);
}
}
catch (Exception ex)
{
Console.WriteLine($"断开PLC连接失败: {ex.Message}");
}
}
/// <summary>
/// 读取数据
/// </summary>
/// <param name="address">地址(如"M0.0", "DB1.DBW2"</param>
/// <returns>读取的值</returns>
public object ReadData(string address)
{
try
{
if (!IsConnected && !Connect())
{
return null;
}
object value = _plc.Read(address);
Console.WriteLine($"a读取 {address} 成功: {value}");
return value;
}
catch (Exception ex)
{
Console.WriteLine($"读取 {address} 失败: {ex.Message}");
return null;
}
}
/// <summary>
/// 写入数据
/// </summary>
/// <param name="address">地址(如"M0.0", "DB1.DBW2"</param>
/// <param name="value">要写入的值</param>
/// <returns>是否写入成功</returns>
public bool WriteData(string address, object value)
{
try
{
if (!IsConnected && !Connect())
{
return false;
}
_plc.Write(address, value);
Console.WriteLine($"写入 {address} 成功: {value}");
return true;
}
catch (Exception ex)
{
Console.WriteLine($"写入 {address} 失败: {ex.Message}");
return false;
}
}
/// <summary>
/// 批量读取数据
/// </summary>
/// <param name="addresses">地址数组</param>
/// <returns>值数组,与地址数组顺序对应</returns>
public object[] ReadMultipleData(string[] addresses)
{
if (addresses == null || addresses.Length == 0)
return new object[0];
try
{
if (!IsConnected && !Connect())
{
return null;
}
var values = new object[addresses.Length];
for (int i = 0; i < addresses.Length; i++)
{
values[i] = _plc.Read(addresses[i]);
}
Console.WriteLine($"批量读取 {addresses.Length} 个地址成功");
return values;
}
catch (Exception ex)
{
Console.WriteLine($"批量读取失败: {ex.Message}");
return null;
}
}
/// <summary>
/// 写入数组数据
/// </summary>
/// <param name="Dbno"></param>
/// <param name="start"></param>
/// <param name="bytes"></param>
/// <returns></returns>
public bool WriteArraysBtye(int Dbno, int start, byte[] bytes)
{
try
{
if (!IsConnected && !Connect())
{
return false;
}
_plc.WriteBytes(DataType.DataBlock, Dbno, start, bytes);
return true;
}
catch (Exception ex)
{
Console.WriteLine($"写入数组: {ex.Message}");
return false;
}
}
/// <summary>
/// 读取数组
/// </summary>
/// <returns></returns>
public ushort[] ReadArraysShort(int Dbno,int start,int lenth)
{
try
{
if (!IsConnected && !Connect())
{
return null;
}
//public object? Read(DataType dataType, int db, int startByteAdr, VarType varType, int varCount, byte bitAdr = 0)
ushort[] datas = _plc.Read(DataType.DataBlock, Dbno, start, VarType.Word, lenth) as ushort[];
return datas;
}
catch (Exception ex)
{
Console.WriteLine($"读取数组: {ex.Message}");
return null;
}
}
/// <summary>
/// 读结构体
/// </summary>
public T ReadStruct<T>(int dbno, int start)
{
T t;
try
{
if (!IsConnected && !Connect())
{
return default(T);
}
t = (T)_plc.ReadStruct(typeof(T), dbno, start);
return t;
}
catch (Exception)
{
Console.WriteLine($"读结构体失败!");
return default(T);
}
}
/// <summary>
/// 写结构体
/// </summary>
public bool WriteStruct<T>(T t,int dbno,int start)
{
try
{
if (!IsConnected && !Connect())
{
return false;
}
_plc.WriteStruct(t, dbno, start);
return true;
}
catch (Exception)
{
Console.WriteLine($"写入失败!");
return false;
}
}
/// <summary>
/// 读取字符串
/// </summary>
/// <param name="DBno"></param>
/// <param name="startNo"></param>
/// <returns></returns>
public string ReadString(int DBno, int startNo)
{
try
{
if (!IsConnected && !Connect())
{
return "";
}
int totalLenth = (byte)_plc.Read(S7.Net.DataType.DataBlock, DBno, startNo, VarType.Byte, 1);
int len = (byte)_plc.Read(S7.Net.DataType.DataBlock, DBno, startNo + 1, VarType.Byte, 1);
byte[] bytes = _plc.ReadBytes(S7.Net.DataType.DataBlock, DBno, startNo + 2, len);
string mesg = Encoding.ASCII.GetString(bytes);
return mesg;
}
catch (Exception ex)
{
Console.WriteLine($"读取字符串失败!");
return "";
}
}
/// <summary>
/// 写入字符串
/// </summary>
/// <param name="DBno"></param>
/// <param name="startNo"></param>
/// <param name="contextStr"></param>
/// <returns></returns>
public bool WriteString(int DBno,int startNo, string contextStr)
{
try
{
if (!IsConnected && !Connect())
{
return false;
}
_plc.Write(S7.Net.DataType.DataBlock, DBno, startNo + 1, (byte)contextStr.Length);
_plc.Write(S7.Net.DataType.DataBlock, DBno, startNo + 2, contextStr);
Console.WriteLine($"写入字符串成功!");
return true;
}
catch (Exception ex)
{
Console.WriteLine($"写入字符串失败!");
return false;
}
}
/// <summary>
/// 写入bool
/// </summary>
/// <param name="DBno"></param>
/// <param name="startNo"></param>
/// <param name="contextStr"></param>
/// <returns></returns>
public bool WriteBoolen(int DBno, int startByteAdr, int bitAdr, bool val)
{
try
{
if (!IsConnected && !Connect())
{
return false;
}
_plc.WriteBit(DataType.DataBlock, DBno, startByteAdr, bitAdr, val);
Console.WriteLine($"写入成功!");
return true;
}
catch (Exception ex)
{
Console.WriteLine($"写入失败!");
return false;
}
}
/// <summary>
/// 释放资源
/// </summary>
public void Dispose()
{
Disconnect();
//_plc?.Dispose();
_plc = null;
}
}
struct TestA
{
public ushort value1;
public ushort value2;
}
}

View File

@@ -0,0 +1,98 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
namespace SamplePre.Communication.Communication
{
public class SocketClient
{
// 服务端 IP 和端口(和你服务端一致)
private const string ServerIp = "127.0.0.1";
private const int ServerPort = 8888;
private Socket _clientSocket;
public Action<string> ReceiveMsgAction;
//static async Task Main(string[] args)
//{
// var client = new SocketClient();
// await client.StartClientAsync();
//}
/// <summary>
/// 启动客户端
/// </summary>
public async Task StartClientAsync()
{
try
{
// 创建客户端 Socket
_clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
ReceiveMsgAction?.Invoke("正在连接服务端...");
// 连接服务端
await _clientSocket.ConnectAsync(IPAddress.Parse(ServerIp), ServerPort);
ReceiveMsgAction?.Invoke("✅ 连接服务端成功!");
// 启动接收消息任务(后台异步监听)
_ = Task.Run(ReceiveMsgAsync);
}
catch (Exception ex)
{
ReceiveMsgAction?.Invoke($"连接失败:{ex.Message}");
}
}
public void CloseConnect()
{
_clientSocket.Close();
ReceiveMsgAction?.Invoke("客户端已断开");
}
/// <summary>
/// 发送消息
/// </summary>
public async Task SendMsgAsync(string msg)
{
if (string.IsNullOrEmpty(msg)) return;
byte[] data = Encoding.UTF8.GetBytes(msg);
await _clientSocket.SendAsync(data, SocketFlags.None);
}
/// <summary>
/// 接收服务端消息
/// </summary>
private async Task ReceiveMsgAsync()
{
byte[] buffer = new byte[1024];
while (true)
{
try
{
int len = await _clientSocket.ReceiveAsync(buffer, SocketFlags.None);
if (len == 0) break;
string recMsg = Encoding.UTF8.GetString(buffer, 0, len);
//回调函数
ReceiveMsgAction?.Invoke($"\n📩 服务端回复:{recMsg}");
}
catch
{
break;
}
}
}
}
}

View File

@@ -0,0 +1,64 @@
using S7.Net;
using SamplePre.Communication.Communication;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
namespace SamplePre.Communication
{
public class CommunicationFactory
{
/// <summary>
/// 创建通讯实例
/// </summary>
/// <param name="protocolType">协议类型</param>
/// <param name="connectionParams">连接参数</param>
/// <returns></returns>
/// <exception cref="NotSupportedException"></exception>
public static ICommunication CreateCommunication(CommProtocolType protocolType, string connectionParams)
{
ICommunication comm = null;
switch (protocolType)
{
case CommProtocolType.S7:
comm = CreateS7(connectionParams);
break;
case CommProtocolType.ModbusTcp:
comm = CreateModbusTcp(connectionParams);
break;
case CommProtocolType.ModbusRtu:
break;
default:
break;
}
return comm;
}
public static ICommunication CreateS7(string connectionParams)
{
string[] params1 = connectionParams.Split(':');
if(params1 == null || params1.Length < 3) return null;
//ICommunication comm = new S7PlcCommunicator(CpuType.S71500, "192.168.10.2", 0, 1);
ICommunication comm = new S7PlcCommunicator(CpuType.S71500, params1[0], int.Parse( params1[1]), int.Parse( params1[2]));
return comm;
}
public static ICommunication CreateModbusTcp(string connectionParams)
{
string[] params1 = connectionParams.Split(':');
if (params1 == null || params1.Length < 2) return null;
ICommunication comm = new ModbusTcpCommunicator(params1[0], int.Parse(params1[1]));
return comm;
}
}
}

View File

@@ -0,0 +1,19 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="NModbus4" Version="2.1.0" />
<PackageReference Include="S7netplus" Version="0.20.0" />
<PackageReference Include="System.IO.Ports" Version="10.0.5" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\SamplePre.Common\SamplePre.Common.csproj" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,96 @@
using Dapper;
using Models.Models;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
//using System.Windows.Documents;
namespace DataDAL.DBContext
{
public class LogDal
{
public LogDal()
{
}
/// <summary>
/// 保存日志
/// </summary>
/// <param name="entity"></param>
/// <param name="sysDict"></param>
/// <returns></returns>
public int SaveLog(run_log_info runLogInfo)
{
//using (IDbConnection dbConnection = new DapperDBContext().Connection)
//{
// dbConnection.Open();
// string insertSql = @"insert into run_log_info ( id,run_date
// ,log_level
// ,log_content,log_type
// )
// values(@id,@run_date
// ,@log_level
// ,@log_content ,@log_type
// )";
// var item = dbConnection.QueryFirstOrDefault<run_log_info>(insertSql, runLogInfo);
return 1;
//}
}
/// <summary>
/// 查询日志信息
/// </summary>
public List<run_log_info> QueryLogByDate(DateTime dt1,DateTime dt2)
{
using (IDbConnection dbConnection = new DapperDBContext().Connection)
{
dbConnection.Open();
string querySql = "select * from run_log_info where run_date >= @dt1 and run_date <= @dt2";
List<run_log_info> data = dbConnection.Query<run_log_info>(querySql, new { dt1 = dt1,dt2 = dt2 }).ToList();
return data;
}
}
///// <summary>
///// 查询二维码开始编号
///// </summary>
//public string QueryQrcode()
//{
// using (IDbConnection dbConnection = new BaseDBContext().Connection)
// {
// dbConnection.Open();
// string qrcode = "";
// List<sys_dict> data = dbConnection.Query<sys_dict>("select * from sys_dict where data_type='二维码编号'").ToList();
// if (data.Count > 0)
// {
// qrcode = (int.Parse(data[0].data_value) + 1).ToString("0000");
// }
// return qrcode;
// }
//}
}
}

View File

@@ -0,0 +1,72 @@
using Dapper;
using DataDAL.DBContext;
using Models.Models;
using SamplePre.Common;
using SamplePre.DAL.DBContext;
using SamplePre.Models.Ext;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static Dapper.SqlMapper;
namespace SamplePre.DAL
{
public class SOPDal
{
/// <summary>
/// 获取标准下的动作,动作中包含参数
/// </summary>
/// <param name="standId"></param>
/// <returns></returns>
public List<sys_standard_action_ext> QueryStandardProcessByStandardId(string standId)
{
using (IDbConnection dbConnection = new DapperDBContext().Connection)
{
dbConnection.Open();
string querySql = @"
SELECT
a.*,
b.action_name,
b.action_unit,
e.data_value AS action_unit_name,
b.remark,
c.all_param
FROM
sys_standard_action a
LEFT JOIN sys_action b ON a.process_id = b.id
LEFT JOIN sys_dict e ON b.action_unit = e.id
LEFT JOIN (
SELECT
x.action_id,
x.action_seqno,
GROUP_CONCAT( CONCAT( y.title, '', x.data_value, y.unit ) SEPARATOR '' ) AS all_param
FROM
sys_standard_action_parm x
LEFT JOIN sys_parm y ON x.parm_id = y.id
WHERE
x.standard_id = @standId
GROUP BY
x.action_id,
x.action_seqno
) c ON a.process_id = c.action_id
AND a.process_no = c.action_seqno
WHERE
a.standard_id = @standId
ORDER BY a.process_no
";
List<sys_standard_action_ext> data = dbConnection.Query<sys_standard_action_ext>(querySql, new { standId = standId }).ToList();
return data;
}
}
}
}

View File

@@ -0,0 +1,24 @@
using Dapper;
using DataDAL.DBContext;
using Models.Models;
using SamplePre.Common;
using SamplePre.DAL.DBContext;
using SamplePre.Models.Ext;
using SamplePre.Models.Models;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static Dapper.SqlMapper;
namespace SamplePre.DAL
{
public class SampleSequenceDal
{
}
}

View File

@@ -0,0 +1,59 @@
using Dapper;
using DataDAL.DBContext;
using Models.Models;
using SamplePre.DAL.DBContext;
using SamplePre.Models.Ext;
using SamplePre.Models.Models;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SamplePre.DAL
{
public class SystemDal
{
/// <summary>
/// 获取用户数据
/// </summary>
/// <param name="standId"></param>
/// <returns></returns>
public List<config_user_ext> QueryUserData()
{
using (IDbConnection dbConnection = new DapperDBContext().Connection)
{
dbConnection.Open();
string querySql = @"
SELECT a.*,b.all_role_names from config_user a
LEFT JOIN (
SELECT
x.user_id,
GROUP_CONCAT(x.role_id SEPARATOR ',') AS all_role_ids,
GROUP_CONCAT(y.`name` SEPARATOR ',') AS all_role_names
FROM
config_user_role x
LEFT JOIN config_role y ON x.role_id = y.id
GROUP BY
x.user_id
) b on a.id = b.user_id
";
List<config_user_ext> data = dbConnection.Query<config_user_ext>(querySql).ToList();
return data;
}
}
}
}

View File

@@ -0,0 +1,108 @@
using Models.Const;
using SamplePre.Common;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SamplePre.DAL.DBContext
{
public class DBFactory
{
#region
private static readonly Lazy<SqlSugarClient> _lazySqlSugarClient = new Lazy<SqlSugarClient>(() =>
{
return CreateSqlSugarClient();
});
/// <summary>
/// 获取默认数据库的SqlSugarClient单例实例
/// </summary>
public static SqlSugarClient Instance => _lazySqlSugarClient.Value;
#endregion
#region App.config读取的配置项
private static readonly string _connStr; // 数据库连接字符串
private static readonly bool _isAutoCloseConn; // 是否自动关闭连接
/// <summary>
/// 静态构造函数读取App.config配置初始化全局参数
/// </summary>
static DBFactory()
{
try
{
// 1. 读取数据库连接字符串MySQL
_connStr = SystemConst.SysConfigInfo.DbConfig.MySql.ConnStr;//"Data Source=localhost;Database=fanghuayuan;AllowLoadLocalInfile=true;User ID=root;Password=123;allowPublicKeyRetrieval=true;pooling=true;port=3306;";
// 2. 读取SqlSugar全局配置AppSettings节点
_isAutoCloseConn = true;//Convert.ToBoolean(ConfigurationManager.AppSettings["SqlSugar_IsAutoCloseConnection"]);
}
catch (Exception ex)
{
throw new Exception("SqlSugar工厂类配置读取失败" + ex.Message);
}
}
#endregion
#region SqlSugarClient并配置全局参数
/// <summary>
/// 封装SqlSugarClient的创建、数据库配置、全局AOP
/// </summary>
/// <returns>配置完成的SqlSugarClient实例</returns>
private static SqlSugarClient CreateSqlSugarClient()
{
// 1. 数据库连接核心配置按需修改DbType对应连接字符串
var connectionConfig = new ConnectionConfig
{
ConnectionString = _connStr, // 连接字符串
DbType = SqlSugar.DbType.MySql, // 数据库类型:
IsAutoCloseConnection = _isAutoCloseConn, // 自动关闭连接(必开,避免连接泄漏)
InitKeyType = InitKeyType.Attribute, // 从实体类特性读取主键/自增配置(核心)
};
// 2. 创建SqlSugarClient实例
var db = new SqlSugarClient(connectionConfig);
db.Aop.OnError = (ex) =>
{
string errorLog = $@"【SQL执行异常】{DateTime.Now:yyyy-MM-dd HH:mm:ss.fff}
【异常信息】{ex.Message}
【SQL语句】{ex.Sql}";
// 异常日志写入本地文件
LoggerHelper.Logger.Error(errorLog);
};
return db;
}
#endregion
#region 退
/// <summary>
/// 手动释放SqlSugarClient资源仅特殊场景使用
/// </summary>
public static void DisposeInstance()
{
if (_lazySqlSugarClient.IsValueCreated)
{
Instance.Dispose();
}
}
#endregion
}
}

View File

@@ -0,0 +1,27 @@
using Models.Const;
using MySql.Data.MySqlClient;
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace DataDAL.DBContext
{
public class DapperDBContext
{
public IDbConnection Connection { get; set; }
//string connectionString = "Data Source=localhost;Database=fanghuayuan;AllowLoadLocalInfile=true;User ID=root;Password=123;allowPublicKeyRetrieval=true;pooling=true;port=3306;"; //"Data Source=DESKTOP-T4SGEQ7;Initial Catalog=防化院毒素;Integrated Security=True;TrustServerCertificate=True";
public DapperDBContext()
{
Connection = new MySqlConnection(SystemConst.SysConfigInfo.DbConfig.MySql.ConnStr);
}
}
}

View File

@@ -0,0 +1,22 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Dapper" Version="2.0.151" />
<PackageReference Include="MySql.Data" Version="9.5.0" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
<PackageReference Include="SqlSugar" Version="5.1.4.207" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\SamplePre.Common\SamplePre.Common.csproj" />
<ProjectReference Include="..\SamplePre.Communication\SamplePre.Communication.csproj" />
<ProjectReference Include="..\SamplePre.Models\SamplePre.Models.csproj" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,67 @@
using Models.Models;
using SamplePre.Common;
using SamplePre.Communication;
using SamplePre.Models.Ext;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Models.Const
{
public class SystemConst
{
/// <summary>
/// 运行、成功色-绿色
/// </summary>
public static Color SuccessColor = Color.FromArgb(40, 167, 69); // 运行、成功色-绿色
/// <summary>
/// 待机-浅绿色
/// </summary>
public static Color AwaitColor = Color.FromArgb(66, 202, 171); // 待机-浅绿色
/// <summary>
/// 结束
/// </summary>
public static Color FinishColor = Color.FromArgb(22, 167, 169); // 运行、成功色-绿色
/// <summary>
/// 警告色-黄色
/// </summary>
public static Color WarningColor = Color.FromArgb(255, 193, 7); // 停止、警告色-黄色
/// <summary>
/// 危险色-红色
/// </summary>
public static Color DangerColor = Color.FromArgb(220, 53, 69); // 危险色-红色
/// <summary>
/// 主PLC对象
/// </summary>
public static ICommunication MasterPLC;
/// <summary>
/// 字典数据
/// </summary>
public static List<sys_dict> dictDatas = new List<sys_dict>();
public static SysConfigData SysConfigInfo = new SysConfigData();
/// <summary>
/// 当前通信协议类型
/// </summary>
public static CommProtocolType ProtocolType = CommProtocolType.ModbusTcp;
/// <summary>
/// 当前登录用户信息
/// </summary>
public static LoginUserInfo loginUserInfo = new LoginUserInfo();
}
}

View File

@@ -0,0 +1,26 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Models
{
public enum LiXinJiEnum
{
//待机
Wait = 0,
//运行
Run = 1,
//故障
Err = 2
}
}

View File

@@ -0,0 +1,19 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Models.Ext
{
public class LogQuery
{
public string runDate { get; set; }
public string errType { get; set; }
public string errlevel { get; set; }
public string content { get; set; }
}
}

View File

@@ -0,0 +1,23 @@
using SamplePre.Models.Tables;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SamplePre.Models.Ext
{
public class LoginUserInfo
{
/// <summary>
/// 用户信息
/// </summary>
public config_user user { get; set; }
/// <summary>
/// 功能权限
/// </summary>
public List<config_function> functions { get; set; }
}
}

View File

@@ -0,0 +1,26 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Models.Ext
{
public class MenuNode
{
public string Id { get; set; }
public string Name { get; set; }
public string Icon { get; set; }
public List<MenuNode> Children { get; set; }
//public MenuNode(string id, string name, List<MenuNode> children = null)
//{
// Id = id;
// Name = name;
// Children = children ?? new List<MenuNode>();
//}
}
}

View File

@@ -0,0 +1,17 @@
using SamplePre.Models.Tables;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SamplePre.Models.Ext
{
public class config_function_ext : config_function
{
public bool IsChecked { get; set; }
}
}

View File

@@ -0,0 +1,16 @@
using SamplePre.Models.Tables;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SamplePre.Models.Ext
{
public class config_role_ext : config_role
{
public bool IsSelected { get; set; }
}
}

View File

@@ -0,0 +1,16 @@
using SamplePre.Models.Tables;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SamplePre.Models.Ext
{
public class config_user_ext : config_user
{
public string all_role_names { get; set; }
}
}

View File

@@ -0,0 +1,25 @@
using SamplePre.Models.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SamplePre.Models.Ext
{
public class sample_exec_detail_ext : sample_exec_detail
{
public string exec_state { get; set; }
public string item_name { get; set; }
public string standrad_id { get; set; }
public string standrad { get; set; }
public DateTime input_date { get; set; }
public string input_user { get; set; }
public string tube_type_name { get; set; }
}
}

View File

@@ -0,0 +1,17 @@
using SamplePre.Models.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SamplePre.Models.Ext
{
public class sample_exec_ext : sample_exec
{
public string standradName { get; set; }
public List<sample_exec_detail> sampleExecDetails { get; set; }
}
}

View File

@@ -0,0 +1,15 @@
using Models.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SamplePre.Models.Ext
{
public class sys_action_ext : sys_action
{
public string action_unitname { 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 Models.Ext
{
public class sys_action_parm_map_ext
{
public int id { get; set; }
public string process_id { get; set; }
public string parm_id { get; set; }
public string process_name { get; set; }
public string title { get; set; }
public string unit { get; set; }
public string data_type { get; set; }
public string data_value { get; set; }
public string plc_type { get; set; }
}
}

View File

@@ -0,0 +1,27 @@
using Models.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SamplePre.Models.Ext
{
public class sys_standard_action_ext : sys_standard_action
{
public string action_name { get; set; }
public string remark { get; set; }
public string all_param { get; set; }
public string action_unit { get; set; }
public string action_unit_name { set; get; }
public int new_action_seqno { set; get; }
/// <summary>
/// 执行完成标识
/// </summary>
public bool ExecFinishFlag { set; get; } = false;
}
}

View File

@@ -0,0 +1,21 @@
using Models.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SamplePre.Models.Ext
{
public class sys_standard_action_parm_ext : sys_standard_action_parm
{
public string action_name { get; set; }
public string title { get; set; }
public string unit { get; set; }
public string data_type { get; set; }
public string plc_type { get; set; }
public string actionAndseqno { get; set; }
}
}

View File

@@ -0,0 +1,38 @@
using Models.Models;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
namespace SamplePre.Models.Ext
{
public class sys_standard_ext : sys_standard ,INotifyPropertyChanged
{
//public bool IsSelected { get; set; }
private bool _isSelected;
public bool IsSelected
{
get { return _isSelected; }
set { _isSelected = value;
OnPropertyChanged();
}
}
protected void OnPropertyChanged([CallerMemberName] string? propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
public event PropertyChangedEventHandler? PropertyChanged;
}
}

View File

@@ -0,0 +1,40 @@
using Models.Models;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
namespace SamplePre.Models.Ext
{
public class tube_input_ext : tube_input,INotifyPropertyChanged
{
//public bool isChecked { get; set; } = false;
public string tube_type_name { get; set; }
private bool isSelected = false;
public event PropertyChangedEventHandler? PropertyChanged;
public bool IsSelected
{
get { return isSelected; }
set
{
isSelected = value;
OnPropertyChanged();
}
}
protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
}

View File

@@ -0,0 +1,26 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SamplePre.Models
{
public class ComboBoxListItem : Object
{
public string Text { get; set; }
public object Value { get; set; }
public ComboBoxListItem(string text, object value)
{
this.Text = text;
this.Value = value;
}
public override string ToString()
{
return this.Text;
}
}
}

View File

@@ -0,0 +1,18 @@
using Models.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SamplePre.Models
{
public class SopDataInfo
{
public sys_standard sysStandard { get; set; } = new sys_standard();
public List<sys_standard_action> sysStandActions { get; set; } = new List<sys_standard_action>();
public List<sys_standard_action_parm> sysStandardActionParms { get; set; } = new List<sys_standard_action_parm>();
}
}

View File

@@ -0,0 +1,84 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Models
{
using System.Xml.Serialization;
/// <summary>
/// 系统配置根实体类对应XML根节点SystemConfig
/// </summary>
[XmlRoot("SystemConfig")]
public class SysConfigData
{
/// <summary>
/// 数据库配置对应DbConfig节点
/// </summary>
[XmlElement("DbConfig")]
public DbConfigModel DbConfig { get; set; }
/// <summary>
/// 应用配置对应AppConfig节点
/// </summary>
[XmlElement("AppConfig")]
public AppConfigModel AppConfig { get; set; }
}
/// <summary>
/// 数据库配置实体对应DbConfig节点
/// </summary>
public class DbConfigModel
{
/// <summary>
/// SQL Server配置对应SqlServer节点含属性
/// </summary>
[XmlElement("SqlServer")]
public DbItemModel SqlServer { get; set; }
/// <summary>
/// MySQL配置对应MySql节点含属性
/// </summary>
[XmlElement("MySql")]
public DbItemModel MySql { get; set; }
}
/// <summary>
/// 数据库子项配置对应SqlServer/MySql节点含属性
/// </summary>
public class DbItemModel
{
/// <summary>
/// 连接串对应ConnStr属性
/// </summary>
[XmlAttribute("ConnStr")]
public string ConnStr { get; set; }
/// <summary>
/// 超时时间对应TimeOut属性
/// </summary>
[XmlAttribute("TimeOut")]
public int TimeOut { get; set; }
}
/// <summary>
/// 应用配置实体对应AppConfig节点
/// </summary>
public class AppConfigModel
{
[XmlElement("AppName")]
public string AppName { get; set; }
[XmlElement("Version")]
public string Version { get; set; }
[XmlElement("MaxLoginCount")]
public int MaxLoginCount { get; set; }
[XmlElement("IsDebug")]
public bool IsDebug { get; set; }
}
}

View File

@@ -0,0 +1,20 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SamplePre.Models
{
// 定义树节点数据模型
public class TreeListItem
{
// 节点唯一ID主键
public string ID { get; set; }
// 父节点ID根节点的ParentID为0子节点对应父节点的ID
public string ParentID { get; set; }
// 节点显示的文本
public string DisplayText { get; set; }
}
}

View File

@@ -0,0 +1,22 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="SqlSugar" Version="5.1.4.207" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\SamplePre.Common\SamplePre.Common.csproj" />
<ProjectReference Include="..\SamplePre.Communication\SamplePre.Communication.csproj" />
</ItemGroup>
<ItemGroup>
<Folder Include="Properties\" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,25 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Models.Models
{
public class QRcode
{
public string code { get; set; }
public string checkItem { get; set; } //检测项目
public string jizhi { get; set; } // 基质
public string sqno { get; set; } // 序号
public string position { get; set; } // 试管位置
public string stand { get; set; } // 标准
public string user { get; set; } //录入人员
public string inputDate { get; set; } //录入日期
}
}

View File

@@ -0,0 +1,18 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SamplePre.Models.Tables
{
public class config_function
{
public int id { get; set; } // 功能ID
public string name { get; set; } // 功能名称(如:用户管理、角色新增)
public string code { get; set; } // 功能编码唯一标识User_Manage
public int parent_id { get; set; } // 父功能编码(用于构建菜单层级)
public string description { get; set; } // 功能描述
}
}

View File

@@ -0,0 +1,21 @@
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SamplePre.Models.Tables
{
public class config_role
{
[SugarColumn(IsPrimaryKey = true, IsIdentity = false)]
public string id { get; set; } // 角色ID
public string name { get; set; } // 角色名称(如:管理员、普通用户)
public string description { get; set; } // 角色描述
}
}

View File

@@ -0,0 +1,20 @@
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SamplePre.Models.Tables
{
public class config_role_permisson
{
[SugarColumn(IsPrimaryKey = true, IsIdentity = false)]
public int id { get; set; }
public string role_id { get; set; }
public int function_id { get; set; }
}
}

View File

@@ -0,0 +1,25 @@
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SamplePre.Models.Tables
{
public class config_user
{
[SugarColumn(IsPrimaryKey = true, IsIdentity = false)]
public string id { get; set; } // 用户ID
public string username { get; set; } // 用户名
public string password { get; set; } // 密码(实际项目需加密存储)
public bool is_enabled { get; set; } // 是否启用
}
}

View File

@@ -0,0 +1,20 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SamplePre.Models.Tables
{
public class config_user_role
{
public int id { get; set; }
public string user_id { get; set; }
public string role_id { get; set; }
}
}

View File

@@ -0,0 +1,30 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Models.Models
{
public class run_log_info
{
public string id { get; set; }
public DateTime run_date { get; set; }
/// <summary>
/// 信息,警告,故障
/// </summary>
public string log_level { get; set; }
public string log_content { get; set; }
public string log_type { get; set; }
/// <summary>
/// 运行时间
/// </summary>
public string run_time { get; set; }
}
}

View File

@@ -0,0 +1,22 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SamplePre.Models.Models
{
public class sample_exec
{
public string id { get; set; }
public string standrad_id { get; set; }
public string cmd_content { get; set; }
public string cmd_content2 { get; set; }
public string qrcodes { get; set; }
public int sample_count { get; set; }
public string exec_state { get; set; }
public DateTime exec_date { get; set; }
}
}

View File

@@ -0,0 +1,18 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SamplePre.Models.Models
{
public class sample_exec_detail
{
public int id { get; set; }
public string master_id { get; set; }
public string qrcode { get; set; }
}
}

View File

@@ -0,0 +1,26 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Models.Models
{
/// <summary>
/// 样本记录
/// </summary>
public class sample_record
{
public int id { get; set; }
public string qrcode { get; set; }
public string check_item { get; set; }
public string jizhi { get; set; }
public string xuhao { get; set; }
public string standard_id { get; set; }
public string input_user { get; set; }
public DateTime inpu_date { get; set; }
public string weight { get; set; }
}
}

View File

@@ -0,0 +1,22 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Models.Models
{
public class sys_action
{
public string id { get; set; }
public string action_name { get; set; }
public string action_unit { get; set; }
public string action_adress { get; set; }
public string plc_type { get; set; }
public string remark { get; set; }
}
}

View File

@@ -0,0 +1,21 @@
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Models.Models
{
public class sys_action_parm_map
{
[SugarColumn(IsPrimaryKey = true, IsIdentity = true)]
public int id { get; set; }
public string process_id { get; set; }
public string parm_id { get; set; }
//public string parm_name { 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 Models.Models
{
public class sys_dict
{
public string id { get; set; }
public string data_type { get; set; }
public string data_value { get; set; }
public int class_id { get;set; }
public string remark { get; set; }
}
}

View File

@@ -0,0 +1,18 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SamplePre.Models.Models
{
public class sys_dict_class
{
public int id { get; set; }
public string dict_type { get; set; }
public string remark { get; set; }
}
}

View File

@@ -0,0 +1,25 @@
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Models.Models
{
public class sys_parm
{
[SugarColumn(IsPrimaryKey = true)]
//[SugarColumn(IsPrimaryKey = true, IsIdentity = true)]
public string id { get; set; }
public string title { get; set; }
public string unit { get; set; }
public string data_type { get; set; }
public string data_value { get; set; }
public string plc_type { get; set; }
public string param_type { 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 Models.Models
{
public class sys_standard
{
public string id { get; set; }
public string sample_id { get; set; }
//public string sample_name { get; set; }
public string standard_name { get; set; }
}
}

View File

@@ -0,0 +1,20 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Models.Models
{
public class sys_standard_action
{
public string id { get; set; }
public string standard_id { get; set; }
public string process_id { get; set; }
//public string process_name { get; set; }
public int process_no { get; set; }
}
}

View File

@@ -0,0 +1,31 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Models.Models
{
public class sys_standard_action_parm
{
//[SugarColum(IsPrimaryKey = true)]
public string id { get; set; }
public string standard_id { get; set; }
public string action_id { get; set; }
public int action_seqno { get; set; }
public string parm_id { get; set; }
public int parm_seqno { get; set; }
public int standard_process_id { get; set; }
public string data_value { get; set; }
}
}

View File

@@ -0,0 +1,24 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Models.Models
{
public class tube_input
{
public string qrcode { get; set; }
public string item_name { get; set; }
public string tube_type { get; set; }
public string standrad_id { get; set; }
public string standrad { get; set; }
public string input_user { get; set; }
public DateTime input_date { get; set; }
public string weight { get; set; }
public int tube_count { get; set; }
public string bach_no { get; set; }
}
}

View File

@@ -0,0 +1,178 @@
using DataDAL;
using Models.Ext;
using Models.Models;
using SamplePre.Common;
using SamplePre.DAL.DBContext;
using SamplePre.Models.Ext;
using System;
using System.Collections.Generic;
using System.Data.Common;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SamplePre.ProcessBll.BLL
{
public class ActionMangerBll
{
public int DelProcessParmMap(int id)
{
int val = DBFactory.Instance.Deleteable<sys_action_parm_map>().Where(p=>p.id == id).ExecuteCommand();
return val;
}
public int DelSysActionData(string actionId)
{
var _db = DBFactory.Instance;
try
{
_db.BeginTran();
int val = _db.Deleteable<sys_action>().Where(p => p.id == actionId).ExecuteCommand();
int val2 = _db.Deleteable<sys_action_parm_map>().Where(p => p.process_id == actionId).ExecuteCommand();
_db.CommitTran();
}
catch (Exception ex)
{
_db.RollbackTran();
LoggerHelper.Logger.Error(ex.Message);
return -1;
}
return 1;
}
public List<sys_action_parm_map_ext> GetProcess_parm_mapByProcessId(string processId)
{
var result = DBFactory.Instance.Queryable<sys_action_parm_map>()
.LeftJoin<sys_parm>((a, b) => a.parm_id == b.id)
.Where((a, b) => a.process_id == processId && b.title != null)
.Select((a, b) => new sys_action_parm_map_ext
{
id = a.id,
process_id = a.process_id,
parm_id = a.parm_id,
title = b.title,
unit = b.unit,
data_type = b.data_type,
data_value = b.data_value,
plc_type = b.plc_type
})
.ToList();
return result;//standardDal.GetProcess_parm_mapByProcessId(processId);
}
/// <summary>
/// 获取系统动作字典
/// </summary>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
public List<sys_action_ext> GetTreeListSysAction()
{
List<sys_action_ext> treeListItems = new List<sys_action_ext>();
//获取动作
List<sys_action_ext> actions = QuerySysAction();
//拼装组
var groups = actions.GroupBy(p => new { p.action_unitname, p.action_unit }).ToList();
foreach (var item in groups)
{
treeListItems.Add(new sys_action_ext()
{
id = item.Key.action_unit,
action_name = item.Key.action_unitname,
action_unit = "0"
});
}
//组织数据
foreach (var item in actions)
{
treeListItems.Add(item);
}
return treeListItems;
}
public bool IsExtisPlCcode(string text)
{
var val = DBFactory.Instance.Queryable<sys_action>().Where(p=>p.plc_type == text).ToList();
if(val.Count > 0) return true;
return false;
}
public List<sys_action_ext> QuerySysAction()
{
var result = DBFactory.Instance.Queryable<sys_action>()
.LeftJoin<sys_dict>((a, s) => a.action_unit == s.id)
.Where((a, s) => s.class_id == 2)
.Select((a, s) => new sys_action_ext
{
id = a.id,
action_name = a.action_name,
action_unit = a.action_unit,
action_adress = a.action_adress,
plc_type = a.plc_type,
remark = a.remark,
action_unitname = s.data_value
})
.ToList();
return result;
}
/// <summary>
/// 查询系统动作参数
/// </summary>
/// <exception cref="NotImplementedException"></exception>
public List<sys_parm> QuerySysParm()
{
//string querySql = "select * from sys_parm ";
List<sys_parm> data = DBFactory.Instance.Queryable<sys_parm>().ToList();
return data;
}
/// <summary>
/// 保存动作中的参数
/// </summary>
/// <param name="actionParams"></param>
public int SaveActionParm(List<sys_action_parm_map> actionParams)
{
int val = DBFactory.Instance.Insertable(actionParams).ExecuteCommand();
return val;
}
public int SaveSysAction(sys_action process)
{
int val = DBFactory.Instance.Insertable(process).ExecuteCommand();
return val;
}
}
}

View File

@@ -0,0 +1,80 @@
using Models.Const;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SamplePre.ProcessBll.BLL
{
public class CommunicationBll
{
/// <summary>
/// 读取PLC状态数据-数组
/// </summary>
/// <param name="Dbno"></param>
/// <param name="start"></param>
/// <param name="lenth"></param>
/// <returns></returns>
public ushort[] ReadSateData(int Dbno, int start, int lenth)
{
if (SystemConst.ProtocolType == Communication.CommProtocolType.S7)
{
//读取下位机状态
ushort[] data1 = SystemConst.MasterPLC.ReadArraysShort(Dbno, start, lenth);
return data1;
}
//这里应该增加一个协议数据解析层解析后的格式返回给UI后续完善
///
return null;
}
/// <summary>
/// 写入plc指令,字节数组
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="Dbno"></param>
/// <param name="start"></param>
/// <param name="bytes"></param>
/// <returns></returns>
public bool WritePlcData<T>(int Dbno, int start, T[] bytes)
{
bool val = false;
//if (SystemConst.ProtocolType == Communication.CommProtocolType.S7)
//{
//写入PLC
val = SystemConst.MasterPLC.WriteArraysBtye(Dbno, start, bytes);
//}
//else if (SystemConst.ProtocolType == Communication.CommProtocolType.ModbusTcp)
//{
// //写入PLC
// val = SystemConst.MasterPLC.WriteArraysBtye(Dbno, start, bytes);
//}
return val;
}
/// <summary>
/// 写plc数据单数据
/// </summary>
/// <param name="Dbno"></param>
/// <param name="obj"></param>
/// <returns></returns>
public bool WriteSingleData(string Dbno, object obj)
{
//写入PLC
var val = SystemConst.MasterPLC.WriteSingleData(Dbno, obj);
return val;
}
}
}

View File

@@ -0,0 +1,50 @@
using DataDAL;
using DataDAL.DBContext;
using Models.Const;
using Models.Models;
using Org.BouncyCastle.Utilities;
using SamplePre.Common;
using SamplePre.Communication;
using SamplePre.DAL;
using SamplePre.DAL.DBContext;
using SamplePre.Models.Ext;
using SamplePre.Models.Models;
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Data.Odbc;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SamplePre.ProcessBll.SampleSequence
{
/// <summary>
/// 样本序列管理业务逻辑
/// </summary>
public class MonitorBll
{
SampleSequenceDal sampleSequenceDal = new SampleSequenceDal();
SOPDal sopDal = new SOPDal();
public List<sys_dict> GetSampleType()
{
List<sys_dict> data = DBFactory.Instance.Queryable<sys_dict>().Where(p => p.class_id == 3).ToList();
return data;
}
}
}

View File

@@ -0,0 +1,518 @@
using DataDAL;
using Models.Const;
using Models.Ext;
using Models.Models;
using Newtonsoft.Json;
using SamplePre.Common;
using SamplePre.DAL;
using SamplePre.DAL.DBContext;
using SamplePre.Models;
using SamplePre.Models.Ext;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Data.Common;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
using static System.Collections.Specialized.BitVector32;
namespace SamplePre.ProcessBll.BLL
{
public class SOPManagerBll
{
SOPDal sopDal = new SOPDal();
public List<sys_action_parm_map_ext> GetActionParmById(string actionID)
{
var result = DBFactory.Instance.Queryable<sys_action_parm_map>()
.LeftJoin<sys_parm>((a, b) => a.parm_id == b.id)
.Where((a, b) => a.process_id == actionID && b.title != null)
.Select((a, b) => new sys_action_parm_map_ext
{
id = a.id,
process_id = a.process_id,
parm_id = a.parm_id,
title = b.title,
unit = b.unit,
data_type = b.data_type,
data_value = b.data_value,
plc_type = b.plc_type
})
.ToList();
//List<sys_action_parm_map_ext> paramsList = standardDal.GetProcess_parm_mapByProcessId(actionID);
return result;//paramsList;
}
public List<sys_standard_action_parm_ext> GetStrandActionParamByStrandId(string standId)
{
var result = DBFactory.Instance.Queryable<sys_standard_action_parm>()
.LeftJoin< sys_action >((a,b)=>a.action_id == b.id)
.LeftJoin< sys_parm >((a,b,c)=>a.parm_id == c.id)
.Where((a,b,c)=>a.standard_id == standId)
.OrderBy((a,b,c)=>a.action_seqno)
.Select((a,b,c)=> new sys_standard_action_parm_ext {
id = a.id,
standard_id = a.standard_id,
action_id = a.action_id,
action_seqno = a.action_seqno,
parm_id = a.parm_id,
parm_seqno = a.parm_seqno,
standard_process_id = a.standard_process_id,
data_value = a.data_value,
action_name = b.action_name,
title = c.title,
unit = c.unit,
data_type = c.data_type,
plc_type = c.plc_type
})
.ToList();
//List<sys_standard_action_parm_ext> paramsList = sopDal.GetStrandActionParamByStrandId(standId);
return result; //paramsList;
}
/// <summary>
/// 删除动作下的参数配置
/// </summary>
/// <param name="standId"></param>
/// <param name="actionId"></param>
/// <param name="seqno"></param>
public int removeActionParmByActionId(string standId, string actionId, int seqno)
{
var val = DBFactory.Instance.Deleteable<sys_standard_action_parm>(p => p.standard_id == standId && p.action_id == actionId && p.action_seqno == seqno)
.ExecuteCommand();
return val;
//sopDal.removeActionParmByActionId(standId, actionId, seqno);
}
/// <summary>
/// 删除动作下的参数配置byid
/// </summary>
/// <param name="standId"></param>
/// <param name="actionId"></param>
/// <param name="seqno"></param>
public int removeActionParmByParamId(string standId, string actionId, int seqno,string paramId)
{
var val = DBFactory.Instance.Deleteable<sys_standard_action_parm>(p => p.standard_id == standId && p.action_id == actionId && p.action_seqno == seqno && p.parm_id == paramId)
.ExecuteCommand();
return val;
//sopDal.removeActionParmByActionId(standId, actionId, seqno);
}
public int updateStandardActionParm(sys_standard_action_parm item)
{
//sopDal.updateStandardActionParm(item);
int val = DBFactory.Instance.Updateable<sys_standard_action_parm>()
.SetColumns(p=> new sys_standard_action_parm() { data_value = item.data_value })
.Where(p=>p.id == item.id)
.ExecuteCommand();
return val;
}
public bool IsExisAction(string actionId)
{
List<sys_standard_action_parm> data = DBFactory.Instance.Queryable<sys_standard_action_parm>().Where(p => p.action_id == actionId).ToList();
return data.Count() > 0 ? true : false;
}
public List<sys_standard_action_ext> QueryStandardActionByStandardId(string standId)
{
var result = DBFactory.Instance.Queryable<sys_standard_action>().
LeftJoin<sys_action>((a, b) => a.process_id == b.id).
Where((a, b) => a.standard_id == standId).
Select((a, b) => new sys_standard_action_ext {
id = a.id,
standard_id = a.standard_id,
process_id = a.process_id,
process_no = a.process_no,
action_name = b.action_name,
remark = b.remark
}).ToList();
return result;//standardDal.QueryStandardActionByStandardId(standId);
}
/// <summary>
/// 更新动作序号
/// </summary>
/// <param name="action"></param>
/// <returns></returns>
public int UpdateActionSeqno(sys_standard_action_ext action)
{
// return sopDal.UpdateActionSeqno(action);
var _db = DBFactory.Instance;
try
{
_db.BeginTran();
var val = _db.Updateable<sys_standard_action>()
.SetColumns(it => new sys_standard_action() { process_no = action.new_action_seqno })
.Where(p => p.standard_id == action.standard_id && p.process_id == action.process_id && p.process_no == action.process_no)
.ExecuteCommand();
////参数里的动作顺序
var val2 = _db.Updateable<sys_standard_action_parm>()
.SetColumns(it => new sys_standard_action_parm() { action_seqno = action.new_action_seqno })
.Where(p => p.standard_id == action.standard_id && p.action_id == action.process_id && p.action_seqno == action.process_no)
.ExecuteCommand();
_db.CommitTran();
}
catch (Exception ex)
{
_db.RollbackTran();
LoggerHelper.Logger.Error(ex.Message);
return -1;
}
return 1;
}
/// <summary>
/// 删除标准,及标准下的所有配置
/// </summary>
/// <param name="iD"></param>
/// <exception cref="NotImplementedException"></exception>
public int DelStandardActionParamByStandId(string standardId)
{
var _db = DBFactory.Instance;
try
{
_db.BeginTran();
_db.Deleteable<sys_standard>().Where(p => p.id == standardId).ExecuteCommand();
_db.Deleteable<sys_standard_action>().Where(p => p.standard_id == standardId).ExecuteCommand();
_db.Deleteable<sys_standard_action_parm>().Where(p => p.standard_id == standardId).ExecuteCommand();
_db.CommitTran();
}
catch (Exception ex)
{
_db.RollbackTran();
LoggerHelper.Logger.Error(ex.Message);
return -1;
}
return 1;
//return sopDal.DelStandardActionParamByStandId(iD);
}
/// <summary>
/// 获取标准下的动作,动作中包含参数的预览
/// </summary>
/// <param name="standID"></param>
/// <returns></returns>
public List<sys_standard_action_ext> QueryStandardProcessByStandardId(string standID)
{
return sopDal.QueryStandardProcessByStandardId(standID);
}
/// <summary>
/// 保存标准动作表、动作参数表
/// </summary>
/// <param name="action"></param>
/// <returns></returns>
public int SaveStandardAction_param(sys_standard_action action)
{
//return standardDal.Save_standard_process_map(procemodel);
var _db = DBFactory.Instance;
try
{
_db.BeginTran();
//保存标准动作
_db.Insertable<sys_standard_action>(action).ExecuteCommand();
//保存标准动作参数表
//获取动作下的参数
List<sys_action_parm_map_ext> paramList = GetActionParmById(action.process_id);
List<sys_standard_action_parm> new_parms = new List<sys_standard_action_parm>();
foreach (var item in paramList)
{
//保存标准动作参数表
sys_standard_action_parm parmmodel = new sys_standard_action_parm()
{
id = Guid.NewGuid().ToString(),
standard_id = action.standard_id,
action_id = action.process_id,
action_seqno = action.process_no,
parm_id = item.parm_id,
data_value = item.data_value,
parm_seqno = item.id
};
new_parms.Add(parmmodel);
}
_db.Insertable<sys_standard_action_parm>(new_parms).ExecuteCommand();
_db.CommitTran();
}
catch (Exception ex)
{
_db.RollbackTran();
LoggerHelper.Logger.Error(ex.Message);
return -1;
}
return 1;
}
/// <summary>
/// sop导出
/// </summary>
/// <param name="sysStandardId"></param>
public void ExprotSop(string sysStandardId ,string filePath)
{
//标准信息
sys_standard sysStandard = DBFactory.Instance.Queryable<sys_standard>().Where(p=>p.id == sysStandardId).Single();
//标准动作信息
List<sys_standard_action> standardActions = DBFactory.Instance.Queryable<sys_standard_action>().Where(p => p.standard_id == sysStandardId).ToList();
//标准动作信息
List<sys_standard_action_parm> standardActionsParams = DBFactory.Instance.Queryable<sys_standard_action_parm>().Where(p => p.standard_id == sysStandardId).ToList();
SopDataInfo sopDataInfo = new SopDataInfo();
sopDataInfo.sysStandard = sysStandard;
sopDataInfo.sysStandActions = standardActions;
sopDataInfo.sysStandardActionParms = standardActionsParams;
// 2. 序列化:格式化易读、保留中文
string jsonStr = JsonConvert.SerializeObject(sopDataInfo);
// 3. 写入TXT文件
File.WriteAllText(filePath, jsonStr);
}
/// <summary>
/// 导入SOP
/// </summary>
/// <param name="selectFilePath"></param>
/// <exception cref="NotImplementedException"></exception>
public bool ImportSop(string selectFilePath)
{
string fileContent = File.ReadAllText(selectFilePath, System.Text.Encoding.UTF8);
SopDataInfo sopDataInfo = JsonConvert.DeserializeObject<SopDataInfo>(fileContent);
var _db = DBFactory.Instance;
try
{
//开始事务
_db.BeginTran();
//标准
sopDataInfo.sysStandard.id = Guid.NewGuid().ToString();
sopDataInfo.sysStandard.standard_name = sopDataInfo.sysStandard.standard_name + "_imp";
DBFactory.Instance.Insertable<sys_standard>(sopDataInfo.sysStandard).ExecuteCommand();
//标准动作
foreach (var item in sopDataInfo.sysStandActions)
{
item.id = Guid.NewGuid().ToString();
item.standard_id = sopDataInfo.sysStandard.id;
}
DBFactory.Instance.Insertable<sys_standard_action>(sopDataInfo.sysStandActions).ExecuteCommand();
//标准动作参数
foreach (var item in sopDataInfo.sysStandardActionParms)
{
item.id = Guid.NewGuid().ToString();
item.standard_id = sopDataInfo.sysStandard.id;
}
DBFactory.Instance.Insertable<sys_standard_action_parm>(sopDataInfo.sysStandardActionParms).ExecuteCommand();
//提交事务
_db.CommitTran();
}
catch (Exception ex)
{
_db.RollbackTran();
LoggerHelper.Logger.Error(ex.Message);
return false;
}
return true;
}
/// <summary>
/// 获取左侧标准树
/// </summary>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
public List<TreeListItem> GetStandardData()
{
List<TreeListItem> treeListItems = new List<TreeListItem>();
//获取样本
List<sys_dict> yangbens = SystemConst.dictDatas.Where(p => p.class_id == 3).ToList(); //sopBll.QueryGyData(); //standardDal.QueryGyData();
foreach (var item in yangbens)
{
treeListItems.Add(new TreeListItem() { ID = item.id, DisplayText = item.data_value, ParentID = "0" });
}
//获取标准
List<sys_standard> SopList = QueryAllGyStandards(); //standardDal.QueryAllGyStandards();
foreach (var item in SopList)
{
treeListItems.Add(new TreeListItem() { ID = item.id, DisplayText = item.standard_name, ParentID = item.sample_id });
}
return treeListItems;
}
/// <summary>
/// 获取所有标准
/// </summary>
/// <returns></returns>
public List<sys_standard> QueryAllGyStandards()
{
List<sys_standard> data = DBFactory.Instance.Queryable<sys_standard>().ToList();
return data;
}
/// <summary>
/// 获取动作字典
/// </summary>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
public List<sys_action_ext> QuerySysAction()
{
var result = DBFactory.Instance.Queryable<sys_action>()
.LeftJoin<sys_dict>((a, s) => a.action_unit == s.id)
.Where((a, s) => s.class_id == 2)
.Select((a, s) => new sys_action_ext
{
id = a.id,
action_name = a.action_name,
action_unit = a.action_unit,
action_adress = a.action_adress,
plc_type = a.plc_type,
remark = a.remark,
action_unitname = s.data_value
})
.ToList();
return result;
}
/// <summary>
/// 移除标准的动作
/// </summary>
/// <param name="id"></param>
public void removeStandAction(sys_standard_action_ext sysStandardAction)
{
//移除动作
var _db = DBFactory.Instance;
try
{
_db.BeginTran();
var va11 = _db.Deleteable<sys_standard_action>(p => p.id == sysStandardAction.id).ExecuteCommand();
//移除动作下的参数配置
var val2 = _db.Deleteable<sys_standard_action_parm>(p => p.standard_id == sysStandardAction.standard_id
&& p.action_id == sysStandardAction.process_id
&& p.action_seqno == sysStandardAction.process_no).ExecuteCommand();
_db.CommitTran();
}
catch (Exception ex)
{
_db.RollbackTran();
LoggerHelper.Logger.Error(ex.Message);
}
}
/// <summary>
/// 保存动作参数配置
/// </summary>
/// <param name="actionParms"></param>
/// <returns></returns>
public int SaveStandardActionParam(List<sys_standard_action_parm> actionParms)
{
int val = DBFactory.Instance.Insertable<sys_standard_action_parm>(actionParms).ExecuteCommand();
return val;
}
public int SaveStandardCopy(sys_standard new_sysStandard, List<sys_standard_action> newStandActions, List<sys_standard_action_parm> sysStandardActionParms)
{
var _db = DBFactory.Instance;
try
{
_db.BeginTran();
_db.Insertable<sys_standard>(new_sysStandard).ExecuteCommand();
_db.Insertable<sys_standard_action>(newStandActions).ExecuteCommand();
_db.Insertable<sys_standard_action_parm>(sysStandardActionParms).ExecuteCommand();
_db.CommitTran();
}
catch (Exception ex)
{
_db.RollbackTran();
LoggerHelper.Logger.Error(ex.Message);
return -1;
}
return 1;
}
}
}

View File

@@ -0,0 +1,539 @@
using DataDAL;
using DataDAL.DBContext;
using Models.Models;
using SamplePre.Common;
using SamplePre.DAL;
using SamplePre.DAL.DBContext;
using SamplePre.Models.Ext;
using SamplePre.Models.Models;
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Data.Odbc;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SamplePre.ProcessBll.SampleSequence
{
/// <summary>
/// 样本序列管理业务逻辑
/// </summary>
public class SampleSequenceBll
{
SampleSequenceDal sampleSequenceDal = new SampleSequenceDal();
SOPDal sopDal = new SOPDal();
public List<sys_dict> GetSampleType()
{
List<sys_dict> data = DBFactory.Instance.Queryable<sys_dict>().Where(p => p.class_id == 3).ToList();
return data;
}
/// <summary>
/// 获取标准动作参数
/// </summary>
/// <param name="standId"></param>
/// <returns></returns>
public List<sys_standard_action_parm_ext> GetStrandActionParamByStrandId(string standId)
{
var result = DBFactory.Instance.Queryable<sys_standard_action_parm>()
.LeftJoin<sys_action>((a, b) => a.action_id == b.id)
.LeftJoin<sys_parm>((a, b, c) => a.parm_id == c.id)
.LeftJoin<sys_standard>((a, b, c,d) => a.standard_id == d.id)
.Where((a, b, c, d) => a.standard_id == standId)
.OrderBy((a, b, c, d) => a.action_seqno)
.Select((a, b, c, d) => new sys_standard_action_parm_ext
{
id = a.id,
standard_id = a.standard_id,
action_id = a.action_id,
action_seqno = a.action_seqno,
parm_id = a.parm_id,
parm_seqno = a.parm_seqno,
standard_process_id = a.standard_process_id,
data_value = a.data_value,
action_name = b.action_name,
title = c.title,
unit = c.unit,
data_type = c.data_type,
plc_type = c.plc_type,
actionAndseqno = $"{d.standard_name}: {a.action_seqno}{b.action_name}"
})
.ToList();
//List<sys_standard_action_parm_ext> datas = sopDal.GetStrandActionParamByStrandId(standId);
return result;
}
public List<sys_action_ext> QuerySysAction()
{
var result = DBFactory.Instance.Queryable<sys_action>()
.LeftJoin<sys_dict>((a, s) => a.action_unit == s.id)
.Where((a, s) => s.class_id == 2)
.Select((a, s) => new sys_action_ext
{
id = a.id,
action_name = a.action_name,
action_unit = a.action_unit,
action_adress = a.action_adress,
plc_type = a.plc_type,
remark = a.remark,
action_unitname = s.data_value
})
.ToList();
//List<sys_action_ext> sysActions = standardDal.QuerySysAction();
return result;
}
public int DelTubeInputByCode(string code)
{
int val = DBFactory.Instance.Deleteable<tube_input>().Where(p => p.qrcode == code).ExecuteCommand();
return val;
}
/// <summary>
/// 保存下发命令记录
/// </summary>
/// <param name="cmdExec"></param>
/// <exception cref="NotImplementedException"></exception>
public int SaveCmdExec(sample_exec_ext cmdExec)
{
var _db = DBFactory.Instance;
try
{
_db.BeginTran();
//主记录
int val = _db.Insertable<sample_exec>(cmdExec).ExecuteCommand();
//明细
int val2 = _db.Insertable<sample_exec_detail>(cmdExec.sampleExecDetails).ExecuteCommand();
_db.CommitTran();
}
catch (Exception ex)
{
_db.RollbackTran();
LoggerHelper.Logger.Error(ex.Message);
return -1;
}
return 1;
}
public List<sys_standard> QuerySysStandards(string sampleId)
{
List<sys_standard> data = DBFactory.Instance.Queryable<sys_standard>().Where(p => p.sample_id == sampleId).ToList();
return data;
}
public string QueryQrcode()
{
string qrcode = "";
List<sys_dict> data = DBFactory.Instance.Queryable<sys_dict>().Where(p => p.class_id == 1).ToList();
if (data.Count > 0)
{
qrcode = (int.Parse(data[0].data_value) + 1).ToString("0000");
}
return qrcode;
}
public int SaveDataAndQrcode(tube_input qRcode, sys_dict sys_Dict)
{
var _db = DBFactory.Instance;
try
{
_db.BeginTran();
//保存样品记录
_db.Insertable<tube_input>(qRcode).ExecuteCommand();
//更新二维码
int val = _db.Updateable<sys_dict>()
.SetColumns(p => new sys_dict() { data_value = sys_Dict.data_value })
.Where(p => p.class_id == 1)
.ExecuteCommand();
_db.CommitTran();
}
catch (Exception ex)
{
_db.RollbackTran();
LoggerHelper.Logger.Error(ex.Message);
return -1;
}
return 1;
}
public List<tube_input> GetTubeData(DateTime dt1, DateTime dt2)
{
List<tube_input> data = DBFactory.Instance.Queryable<tube_input>().Where(p => p.input_date >= dt1 && p.input_date <= dt2).ToList();
return data;;
}
/// <summary>
/// 生成指令字节数组byte
/// </summary>
/// <param name="sysAction"></param>
/// <param name="standardProcessParms"></param>
/// <returns></returns>
public List<byte> CreateCmdBytes(List<sys_action_ext> sysAction, List<string> sopIds, List<sys_standard_action_parm_ext> standardProcessParms)
{
string cmdReamrk = "";
List<byte> sop = new List<byte>();
try
{
//起始位
sop.Insert(0, 0xCC);
cmdReamrk += $"【0 开始:{sop[0]}】 ";
//插入总字节数-占位
sop.Insert(1, 0);
//cmdReamrk += $"【1 总字节数:{Convert.ToByte(seq + 1)}】 ";
//插入总动作数
sop.Insert(2, 0);
//cmdReamrk += $"【2 总动作数0】 ";
int seq = 3;
//总动作数
int actionCount = 0;
//===============
foreach (string standrad_id in sopIds)
{
//查询标准下的动作
var standardActions = GetStrandActionByStrandId(standrad_id);
//动作排序
standardActions = standardActions.OrderBy(p => p.process_no).ToList();
actionCount += standardActions.Count();
foreach (var actionItem in standardActions)
{
//int start = seq; //记录起始位置
//转换PLC映射名称
string action_plc = sysAction.FirstOrDefault(p => p.id == actionItem.process_id)?.plc_type;
//动作类型(如:离心)
byte action_byte = Convert.ToByte(action_plc);
sop.Insert(seq, action_byte);
cmdReamrk += $"【{seq} 动作:{sop[seq]}】 ";
seq++;
//查询动作下的参数
var paramData = standardProcessParms.Where(p => p.action_id == actionItem.process_id && p.action_seqno == actionItem.process_no && p.standard_id == standrad_id).ToList();
//插入动作字节长度
int actionLenth = (int)(paramData.Count() * 5 + 2);
sop.Insert(seq, (byte)actionLenth);
cmdReamrk += $"【{seq} 动作字节长度:{sop[seq]}】 ";
seq++;
foreach (var item in paramData)
{
//转换plc参数类型
string param_plc = item.plc_type;//parms.FirstOrDefault(p => p.title == item.title).plc_type;
//参数类型(如:时间)
byte parm_byte = Convert.ToByte(param_plc);
sop.Insert(seq, parm_byte);
cmdReamrk += $"【{seq} 参数类型:{sop[seq]}】 ";
seq++;
sys_standard_action_parm_ext actionParm = standardProcessParms.FirstOrDefault(p => p.title == item.title);
string param_val = actionParm.data_value;
if (actionParm.unit.ToUpper() == "ML") //都转换成最小单位ul
{
param_val = (float.Parse(param_val) * 1000).ToString();
}
//参数值
float paramval = 0;
paramval = float.Parse(param_val);
cmdReamrk += $"【{seq} 参数值float{paramval}】 ";
byte[] paramval_bytes = BitConverter.GetBytes(paramval);
sop.Insert(seq, paramval_bytes[0]);
cmdReamrk += $"【{seq} 参数值byte{sop[seq]}-";
seq++;
sop.Insert(seq, paramval_bytes[1]);
cmdReamrk += $"{sop[seq]}-";
seq++;
sop.Insert(seq, paramval_bytes[2]);
cmdReamrk += $"{sop[seq]}-";
seq++;
sop.Insert(seq, paramval_bytes[3]);
cmdReamrk += $"{sop[seq]}】 ";
seq++;
}
}
}
//=================
//结束
sop.Insert(seq, 0xEE);
cmdReamrk += $"【{seq} 结束:{sop[seq]}-";
seq++;
sop.Insert(seq, 0xEE);
cmdReamrk += $"{sop[seq]}】 ";
seq++;
//修改总字节数
sop[1] = (byte)sop.Count;
cmdReamrk += $"【1 总字节数:{sop[1]}】 ";
//修改总动作数据
sop[2] = (byte)actionCount;
cmdReamrk += $"【2 总动作数:{sop[2]}】 ";
LoggerHelper.Logger.Info($"{cmdReamrk}");
return sop;
}
catch (Exception ex)
{
LoggerHelper.Logger.Error(ex.StackTrace);
return null;
}
}
/// <summary>
/// 生成指令字节数组ushort
/// </summary>
/// <param name="sysAction"></param>
/// <param name="standardProcessParms"></param>
/// <returns></returns>
public List<ushort> CreateCmdUshorts(List<sys_action_ext> sysAction, List<sys_standard_action_ext> standardActions, List<sys_standard_action_parm_ext> standardProcessParms)
{
string cmdReamrk = "";
List<ushort> sop = new List<ushort>();
try
{
//起始位
sop.Insert(0, 0xCC);
cmdReamrk += $"【0 开始:{sop[0]}】 ";
//插入总字节数
sop.Insert(1, 0);
//cmdReamrk += $"【1 总字节数:{0}】 ";
//插入总动作数
sop.Insert(2, Convert.ToByte(standardActions.Count()));
cmdReamrk += $"【2 总动作数:{Convert.ToByte(standardActions.Count())}】 ";
int seq = 3;
foreach (var actionItem in standardActions)
{
int start = seq; //记录起始位置
//转换PLC映射名称
string action_plc = sysAction.FirstOrDefault(p => p.id == actionItem.process_id)?.plc_type;
//动作类型(如:离心)
ushort action_byte = Convert.ToUInt16(action_plc);
sop.Insert(seq, action_byte);
cmdReamrk += $"【{seq} 动作:{sop[seq]}】 ";
seq++;
//查询动作下的参数
var paramData = standardProcessParms.Where(p => p.action_id == actionItem.process_id && p.action_seqno == actionItem.process_no).ToList();
//插入动作寄存器长度
int actionLenth = (int)(paramData.Count() * 3 + 2);
sop.Insert(seq, (byte)actionLenth);
cmdReamrk += $"【{seq} 动作长度:{sop[seq]}】 ";
seq++;
foreach (var item in paramData)
{
//转换plc参数类型
string param_plc = item.plc_type;//parms.FirstOrDefault(p => p.title == item.title).plc_type;
//参数类型(如:时间)
ushort parm_byte = Convert.ToUInt16(param_plc);
sop.Insert(seq, parm_byte);
cmdReamrk += $"【{seq} 参数类型:{sop[seq]}】 ";
seq++;
sys_standard_action_parm_ext actionParm = standardProcessParms.FirstOrDefault(p => p.title == item.title);
string param_val = actionParm.data_value;
if (actionParm.unit.ToUpper() == "ML") //都转换成最小单位ul
{
param_val = (float.Parse(param_val) * 1000).ToString();
}
//参数值
float paramval = 0;
paramval = float.Parse(param_val);
cmdReamrk += $"【{seq} 参数值float{paramval}】 ";
//===float转ushort数组
byte[] bytes = BitConverter.GetBytes(paramval);
var a = BitConverter.ToUInt16(new byte[] { bytes[0], bytes[1] }, 0);
var b = BitConverter.ToUInt16(new byte[] { bytes[2], bytes[3] }, 0);
ushort[] ushorts = { b, a };
sop.Insert(seq, ushorts[0]);
cmdReamrk += $"【{seq} 参数值ushort{sop[seq]}-";
seq++;
sop.Insert(seq, ushorts[1]);
cmdReamrk += $"{sop[seq]}】 ";
seq++;
//============
}
}
//结束
sop.Insert(seq, 0xEE);
cmdReamrk += $"【{seq} 结束:{sop[seq]}-";
seq++;
sop.Insert(seq, 0xEE);
cmdReamrk += $"{sop[seq]}】 ";
seq++;
//修改总寄存器数量
sop[1] = (ushort)sop.Count;
cmdReamrk += $"【1 总寄存器数:{sop[1]}】 ";
LoggerHelper.Logger.Info($"{cmdReamrk}");
return sop;
}
catch (Exception ex)
{
LoggerHelper.Logger.Error(ex.StackTrace);
return null;
}
}
public List<sample_exec_detail_ext> GetSampleExecDetails()
{
var result = DBFactory.Instance.Queryable<sample_exec_detail>()
.LeftJoin<sample_exec>((a, b) => a.master_id == b.id)
.LeftJoin<tube_input>((a, b, c) => a.qrcode == c.qrcode)
.Where((a, b, c) => b.exec_state == "执行中")
.Select((a, b, c) => new sample_exec_detail_ext {
id = a.id,
master_id = a.master_id,
qrcode = a.qrcode,
exec_state = b.exec_state,
item_name= c.item_name,
standrad_id = c.standrad_id,
standrad = c.standrad,
input_date = c.input_date,
input_user = c.input_user
})
.ToList();
return result;// sampleSequenceDal.GetSampleExecDetails();
}
public List<tube_input> QueryTubeInputByBachNo(string bachNo)
{
return DBFactory.Instance.Queryable<tube_input>().Where(p => p.bach_no == bachNo).ToList();
}
public List<sys_standard_action_ext> GetStrandActionByStrandId(string standrad_id)
{
List<sys_standard_action_ext> data = DBFactory.Instance.Queryable<sys_standard_action>()
.LeftJoin<sys_action>((a, b) => a.process_id == b.id)
.Where((a, b) => a.standard_id == standrad_id)
.Select((a, b) => new sys_standard_action_ext
{
id = a.id,
standard_id = a.standard_id,
process_id = a.process_id,
process_no = a.process_no,
action_name = b.action_name,
remark = b.remark
})
.ToList();
return data;
}
}
}

View File

@@ -0,0 +1,86 @@
using Models.Models;
using SamplePre.DAL;
using SamplePre.DAL.DBContext;
using SamplePre.Models.Ext;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SamplePre.ProcessBll.BLL
{
public class SysParamBll
{
public int DelSysParm(string id)
{
int val = DBFactory.Instance.Deleteable<sys_parm>().Where(p => p.id == id).ExecuteCommand();
return val;
}
/// <summary>
/// 判断该参数是否被使用,已使用不能删除
/// </summary>
/// <param name="parmId"></param>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
public bool IsExtisActionParam(string parmId)
{
//动作参数
List<sys_action_parm_map> data = DBFactory.Instance.Queryable<sys_action_parm_map>()
.Where(p=>p.parm_id == parmId).ToList();
if(data.Count > 0) return true;
//标准动作参数配置表
List<sys_standard_action_parm> data2 = DBFactory.Instance.Queryable<sys_standard_action_parm>()
.Where(p => p.parm_id == parmId).ToList();
if (data2.Count > 0) return true;
return false;
}
/// <summary>
/// 判断plc编码是否存在
/// </summary>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
public bool IsExtisPlCcode(string plcCode)
{
List<sys_parm> data2 = DBFactory.Instance.Queryable<sys_parm>()
.Where(p => p.plc_type == plcCode).ToList();
if (data2.Count > 0) return true;
return false;
}
public List<sys_parm> QuerySysParm()
{
List<sys_parm> data = DBFactory.Instance.Queryable<sys_parm>().ToList();
return data;
}
public int SaveSysParm(sys_parm parm)
{
int val = DBFactory.Instance.Insertable<sys_parm>(parm).ExecuteCommand();
return val;
}
/// <summary>
/// 更新参数数据
/// </summary>
/// <param name="parm"></param>
/// <exception cref="NotImplementedException"></exception>
public int UpdateSysParm(sys_parm parm)
{
int val = DBFactory.Instance.Updateable<sys_parm>(parm).ExecuteCommand();
return val;
}
}
}

View File

@@ -0,0 +1,107 @@
using DataDAL;
using Models.Ext;
using Models.Models;
using S7.Net.Types;
using SamplePre.DAL;
using SamplePre.DAL.DBContext;
using SamplePre.Models.Ext;
using SamplePre.Models.Models;
using SamplePre.Models.Tables;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SamplePre.ProcessBll.BLL
{
public class SystemBll
{
SystemDal systemDal = new SystemDal();
public int DelDictClassById(int classid)
{
var val = DBFactory.Instance.Deleteable<sys_dict_class>(p => p.id == classid).ExecuteCommand();
return val;
}
public int DelSysDictByid(sys_dict sys_Dict)
{
var val = DBFactory.Instance.Deleteable<sys_dict>(p => p.id == sys_Dict.id).ExecuteCommand();
return val;
}
/// <summary>
/// 根据分类id查询字典明细
/// </summary>
/// <param name="classid"></param>
/// <returns></returns>
public List<sys_dict> QueryDictByClassId(int classid)
{
List<sys_dict> data = DBFactory.Instance.Queryable<sys_dict>().Where(p => p.class_id == classid).ToList();
return data;
}
/// <summary>
/// 查询字典分类
/// </summary>
/// <returns></returns>
public List<sys_dict_class> QueryDictClassData()
{
List<sys_dict_class> data = DBFactory.Instance.Queryable<sys_dict_class>().ToList();
return data;
}
public List<sys_dict> QueryDictData()
{
List<sys_dict> data = DBFactory.Instance.Queryable<sys_dict>().ToList();
return data;
}
public int SaveSysDict(sys_dict sysDict)
{
var val = DBFactory.Instance.Insertable<sys_dict>(sysDict).ExecuteCommand();
return val;
}
public int SaveSysDictClass(sys_dict_class sysDictClass)
{
var val = DBFactory.Instance.Insertable<sys_dict_class>(sysDictClass).ExecuteCommand();
return val;
}
/// <summary>
/// 查询系统功能
/// </summary>
/// <param name="classid"></param>
/// <returns></returns>
public List<config_function> QueryFunctionList()
{
List<config_function> data = DBFactory.Instance.Queryable<config_function>().ToList();
List<config_function> newData = new List<config_function>();
foreach (var item in data.Where(p=>p.parent_id == 0))
{
foreach(var newItem in data.Where(p => p.parent_id == item.id).ToList())
{
newItem.description = item.name;
newData.Add(newItem);
}
}
return newData;
}
}
}

View File

@@ -0,0 +1,159 @@
using DataDAL;
using Models.Const;
using Models.Ext;
using Models.Models;
using SamplePre.Common;
using SamplePre.Common.Helper;
using SamplePre.DAL;
using SamplePre.DAL.DBContext;
using SamplePre.Models;
using SamplePre.Models.Ext;
using SamplePre.Models.Tables;
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static System.Collections.Specialized.BitVector32;
namespace SamplePre.ProcessBll.BLL
{
public class RolesBll
{
/// <summary>
/// 删除角色
/// </summary>
/// <param name="user"></param>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
public int DeleteRole(config_role role)
{
var _db = DBFactory.Instance;
try
{
_db.BeginTran();
var val = _db.Deleteable<config_role>(role)
.Where(p => p.id == role.id)
.ExecuteCommand();
////
//删除角色权限
_db.Deleteable<config_role_permisson>().Where(p => p.role_id == role.id).ExecuteCommand();
_db.CommitTran();
}
catch (Exception ex)
{
_db.RollbackTran();
LoggerHelper.Logger.Error(ex.Message);
return -1;
}
return 1;
}
/// <summary>
/// 获取功能树
/// </summary>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
public List<config_function_ext> GetFuncDataTree()
{
List<config_function> funcList = DBFactory.Instance.Queryable<config_function>().ToList();
List<config_function_ext> funcList2 = new List<config_function_ext>();
foreach(var item in funcList)
{
config_function_ext ext = new config_function_ext();
ext.code = item.code;
ext.id = item.id;
ext.name = item.name;
ext.description = item.description;
ext.IsChecked = false;
ext.parent_id = item.parent_id;
funcList2.Add(ext);
}
return funcList2;
}
/// <summary>
/// 获取角色的权限id集合
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
public List<int> GetPermission(string id)
{
var list = DBFactory.Instance.Queryable<config_role_permisson>()
.Where(p => p.role_id == id)
.Select(p => p.function_id)
.ToList();
return list;
}
public List<config_role> GetRoles()
{
List<config_role> roles = DBFactory.Instance.Queryable<config_role>().ToList();
return roles;
}
public int SavePermission(List<config_role_permisson> rolePermissonList)
{
var _db = DBFactory.Instance;
try
{
_db.BeginTran();
//先删除
var val = _db.Deleteable<config_role_permisson>()
.Where(p => p.role_id == rolePermissonList[0].role_id)
.ExecuteCommand();
///保存权限
DBFactory.Instance.Insertable<config_role_permisson>(rolePermissonList).ExecuteCommand();
_db.CommitTran();
}
catch (Exception ex)
{
_db.RollbackTran();
LoggerHelper.Logger.Error(ex.Message);
return -1;
}
return 1;
}
public int SaveRoleData(config_role configRole)
{
var val = DBFactory.Instance.Insertable<config_role>(configRole).ExecuteCommand();
return val;
}
public int UpdateRoleData(config_role configRole)
{
var val = DBFactory.Instance.Updateable<config_role>(configRole).ExecuteCommand();
return val;
}
}
}

View File

@@ -0,0 +1,176 @@
using DataDAL;
using Models.Const;
using Models.Ext;
using Models.Models;
using SamplePre.Common;
using SamplePre.DAL;
using SamplePre.DAL.DBContext;
using SamplePre.Models.Ext;
using SamplePre.Models.Tables;
using System;
using System.Collections.Generic;
using System.Data.Common;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static System.Collections.Specialized.BitVector32;
namespace SamplePre.ProcessBll.BLL
{
public class UsersBll
{
SystemDal systemDal = new SystemDal();
/// <summary>
/// 获取用户数据
/// </summary>
/// <returns></returns>
public List<config_user_ext> GetUsers()
{
//List<config_user> users = DBFactory.Instance.Queryable<config_user>().ToList();
var users = systemDal.QueryUserData();
return users;
}
public List<config_role> GetRoles()
{
List<config_role> roles = DBFactory.Instance.Queryable<config_role>()
.ToList();
return roles;
}
public int SaveUserData(config_user configUser, List<config_user_role> roles)
{
//throw new NotImplementedException();
var _db = DBFactory.Instance;
try
{
_db.BeginTran();
var val = _db.Insertable<config_user>(configUser).ExecuteCommand();
var val2 = _db.Insertable<config_user_role>(roles).ExecuteCommand();
_db.CommitTran();
}
catch (Exception ex)
{
_db.RollbackTran();
LoggerHelper.Logger.Error(ex.Message);
return -1;
}
return 1;
}
public int UpdateUserData(config_user configUser, List<config_user_role> roles)
{
var _db = DBFactory.Instance;
try
{
_db.BeginTran();
var val = _db.Updateable<config_user>()
.SetColumns(it => new config_user() { username = configUser.username
,password = configUser.password
,is_enabled = configUser.is_enabled })
.Where(p => p.id == configUser.id)
.ExecuteCommand();
////用户角色
//先删除,后插入
_db.Deleteable<config_user_role>().Where(p => p.user_id == configUser.id).ExecuteCommand();
var val2 = _db.Insertable<config_user_role>(roles).ExecuteCommand();
_db.CommitTran();
}
catch (Exception ex)
{
_db.RollbackTran();
LoggerHelper.Logger.Error(ex.Message);
return -1;
}
return 1;
}
public int DeleteUser(config_user user)
{
var _db = DBFactory.Instance;
try
{
_db.BeginTran();
var val = _db.Deleteable<config_user>(user)
.Where(p => p.id == user.id)
.ExecuteCommand();
////
//先删除用户角色
_db.Deleteable<config_user_role>().Where(p => p.user_id == user.id).ExecuteCommand();
_db.CommitTran();
}
catch (Exception ex)
{
_db.RollbackTran();
LoggerHelper.Logger.Error(ex.Message);
return -1;
}
return 1;
}
public List<config_user_role> GetUserRoles(string userId)
{
var result = DBFactory.Instance.Queryable<config_user_role>()
.Where(a=> a.user_id == userId)
.ToList();
return result;
}
public bool CheckUser(string userName, string pwd)
{
var users = DBFactory.Instance.Queryable<config_user>().Where(p => p.username == userName && p.password == pwd).Single();
if(users == null || string.IsNullOrEmpty(users.username)) return false;
SystemConst.loginUserInfo.user = users;
//查询用户权限
var result = DBFactory.Instance.Queryable<config_user_role>()
.RightJoin<config_role_permisson>((a, b) => a.role_id == b.role_id)
.LeftJoin<config_function>((a, b, c) => b.function_id == c.id)
.Where((a, b, c) => a.user_id == users.id)
.Select((a, b, c) => new config_function
{
id = c.id,
name = c.name,
code = c.code,
parent_id = c.parent_id,
description = c.description
})
.ToList();
SystemConst.loginUserInfo.functions = result;
return true;
}
}
}

View File

@@ -0,0 +1,22 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
<PackageReference Include="S7netplus" Version="0.20.0" />
<PackageReference Include="SqlSugar" Version="5.1.4.207" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\SamplePre.Common\SamplePre.Common.csproj" />
<ProjectReference Include="..\SamplePre.Communication\SamplePre.Communication.csproj" />
<ProjectReference Include="..\SamplePre.DAL\SamplePre.DAL.csproj" />
<ProjectReference Include="..\SamplePre.Models\SamplePre.Models.csproj" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,7 @@
namespace SamplePre.ViewModel
{
public class Class1
{
}
}

View File

@@ -0,0 +1,9 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
</Project>

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 905 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 160 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 955 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 955 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

@@ -0,0 +1,156 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
namespace SamplePre.UIWpf.BaseWindows
{
public class BaseWindow : Window
{
public BaseWindow()
{
//InitializeStyle();
//this.Loaded += delegate
//{
// InitializeEvent();
//};
InitializeStyle();
// 一定要在 Loaded 里执行,确保模板已加载
Loaded += (s, e) => InitializeEvent();
}
private void InitializeEvent()
{
// ✅ 关键:从可视化树查找模板内的元素
Button btnMin = FindChild<Button>(this, "btnMin");
Button btnMax = FindChild<Button>(this, "btnMax");
Button btnClose = FindChild<Button>(this, "btnClose");
Border borderTitle = FindChild<Border>(this, "borderTitle");
// 最小化
if (btnMin != null)
btnMin.Click += (s, e) => WindowState = WindowState.Minimized;
// 最大化/还原
if (btnMax != null)
btnMax.Click += (s, e) =>
WindowState = WindowState == WindowState.Normal ? WindowState.Maximized : WindowState.Normal;
// 关闭
if (btnClose != null)
btnClose.Click += (s, e) => Close();
// 拖动窗口
if (borderTitle != null)
{
borderTitle.MouseMove += (s, e) =>
{
if (e.LeftButton == MouseButtonState.Pressed)
DragMove();
};
// 双击标题最大化
borderTitle.MouseLeftButtonDown += (s, e) =>
{
if (e.ClickCount >= 2)
WindowState = WindowState == WindowState.Normal ? WindowState.Maximized : WindowState.Normal;
};
}
}
#region
/// <summary>
/// 在可视化树中查找指定名称的子元素
/// </summary>
public static T FindChild<T>(DependencyObject parent, string childName) where T : DependencyObject
{
if (parent == null) return null;
T foundChild = null;
int childrenCount = VisualTreeHelper.GetChildrenCount(parent);
for (int i = 0; i < childrenCount; i++)
{
var child = VisualTreeHelper.GetChild(parent, i);
if (child is T tChild && child is FrameworkElement element && element.Name == childName)
{
foundChild = tChild;
break;
}
foundChild = FindChild<T>(child, childName);
if (foundChild != null) break;
}
return foundChild;
}
#endregion
private void InitializeStyle()
{
Style = (Style)Application.Current.Resources["BaseWindowStyle"];
}
////==================================================
//private void InitializeEvent()
//{
// ControlTemplate baseWindowTemplate = (ControlTemplate)App.Current.Resources["BaseWindowControlTemplate"];
// //Button minBtn = (Button)baseWindowTemplate.FindName("btnMin", this);
// //minBtn.Click += delegate
// //{
// // this.WindowState = WindowState.Minimized;
// //};
// //Button maxBtn = (Button)baseWindowTemplate.FindName("btnMax", this);
// //maxBtn.Click += delegate
// //{
// // this.WindowState = (this.WindowState == WindowState.Normal ? WindowState.Maximized : WindowState.Normal);
// //};
// //Button closeBtn = this.FindName("btnClose") as Button;
// Button closeBtn = (Button)baseWindowTemplate.FindName("btnClose", this);
// closeBtn.Click += delegate
// {
// this.Close();
// };
// Border borderTitle = (Border)baseWindowTemplate.FindName("borderTitle", this);
// borderTitle.MouseMove += delegate (object sender, MouseEventArgs e)
// {
// if (e.LeftButton == MouseButtonState.Pressed)
// {
// this.DragMove();
// }
// };
// borderTitle.MouseLeftButtonDown += delegate (object sender, MouseButtonEventArgs e)
// {
// if (e.ClickCount >= 2)
// {
// //maxBtn.RaiseEvent(new RoutedEventArgs(Button.ClickEvent));
// }
// };
//}
//private void InitializeStyle()
//{
// this.Style = (Style)App.Current.Resources["BaseWindowStyle"];
//}
}
}

View File

@@ -0,0 +1,86 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
namespace SamplePreSystem.UI.BaseControls
{
public class PasswordAttaExt
{
public static string GetCustomPwd(DependencyObject obj)
{
return (string)obj.GetValue(CustomPwdProperty);
}
public static void SetCustomPwd(DependencyObject obj, string value)
{
obj.SetValue(CustomPwdProperty, value);
}
// Using a DependencyProperty as the backing store for CustomPwd. This enables animation, styling, binding, etc...
public static readonly DependencyProperty CustomPwdProperty =
DependencyProperty.RegisterAttached("CustomPwd", typeof(string), typeof(PasswordAttaExt), new PropertyMetadata("", OnPropertyChangeBack));
private static void OnPropertyChangeBack(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
PasswordBox pb = d as PasswordBox;
if (pb != null)
{
if (e.NewValue.ToString() != pb.Password)
{
pb.Password = e.NewValue.ToString();
}
}
}
#region
public static bool GetIsOpenPwdBading(DependencyObject obj)
{
return (bool)obj.GetValue(IsOpenPwdBadingProperty);
}
public static void SetIsOpenPwdBading(DependencyObject obj, bool value)
{
obj.SetValue(IsOpenPwdBadingProperty, value);
}
// Using a DependencyProperty as the backing store for IsOpenPwdBading. This enables animation, styling, binding, etc...
public static readonly DependencyProperty IsOpenPwdBadingProperty =
DependencyProperty.RegisterAttached("IsOpenPwdBading", typeof(bool), typeof(PasswordAttaExt), new PropertyMetadata(false, OnValEventChangeBack));
private static void OnValEventChangeBack(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
PasswordBox pd = d as PasswordBox;
if (pd != null)
{
pd.PasswordChanged -= Pd_PasswordChanged;
pd.PasswordChanged += Pd_PasswordChanged;
}
}
private static void Pd_PasswordChanged(object sender, RoutedEventArgs e)
{
PasswordBox pb = sender as PasswordBox;
if (pb != null)
{
SetCustomPwd((DependencyObject)sender, pb.Password);
}
}
#endregion
}
}

View File

@@ -0,0 +1,117 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Media;
namespace SamplePreSystem.UI.BaseControls
{
public class RingProgressBar : FrameworkElement
{
/// <summary>
/// 声明并注册一个依赖属性 Progress用于控制进度条显示的百分比0 ~ 100
/// </summary>
public static readonly DependencyProperty ProgressProperty =
DependencyProperty.Register(
nameof(Progress), // 属性名称
typeof(double), // 属性类型
typeof(RingProgressBar), // 所属类型
new FrameworkPropertyMetadata(
0.0, // 默认值
FrameworkPropertyMetadataOptions.AffectsRender // 当值变化时自动触发重绘
));
/// <summary>
/// Progress 属性包装器,提供进度值的获取和设置。
/// 设置时自动裁剪到 0~100 范围。
/// </summary>
public double Progress
{
get => (double)GetValue(ProgressProperty);
set => SetValue(ProgressProperty, Math.Max(0, Math.Min(100, value)));
}
/// <summary>
/// 重写 OnRender 方法,使用 DrawingContext 绘制控件外观。
/// </summary>
protected override void OnRender(DrawingContext dc)
{
double width = ActualWidth;
double height = ActualHeight;
// 根据控件尺寸计算圆环半径,保留 5 像素边距
double radius = Math.Min(width, height) / 2 - 5;
// 圆心位置
Point center = new Point(width / 2, height / 2);
// 1. 绘制背景圆环(灰色圆环)
dc.DrawEllipse(
null, // 无填充
new Pen(Brushes.LightGray, 30), // 使用浅灰色画笔宽度10
center, // 圆心
radius, radius // 水平半径 & 垂直半径
);
// 2. 计算进度角度(转换为 0~360
double angle = Progress / 100 * 360;
// 3. 将角度转换为弧度,-90 是为了从正上方开始绘制
double radians = (angle - 90) * Math.PI / 180;
// 4. 圆环起点:圆顶部
Point startPoint = new Point(center.X, center.Y - radius);
// 5. 计算终点:根据弧度计算 X/Y
Point endPoint = new Point(
center.X + radius * Math.Cos(radians),
center.Y + radius * Math.Sin(radians)
);
// 6. 判断是否需要绘制大角度弧超过180度
bool isLargeArc = angle > 180;
// 7. 创建一个弧线段,从 startPoint 到 endPoint构成圆环的一部分
PathFigure figure = new PathFigure(
startPoint, // 弧线起点
new[]
{
new ArcSegment(
endPoint, // 弧线终点
new Size(radius, radius), // 弧线的X/Y半径
0, // 旋转角度
isLargeArc, // 是否为大角度弧线
SweepDirection.Clockwise, // 顺时针方向
true // 弧线是否可见(用于裁剪,一般设为 true
)
},
false // 图形是否闭合(环形不闭合)
);
// 8. 创建 PathGeometry 对象用于绘制
PathGeometry geometry = new PathGeometry();
geometry.Figures.Add(figure);
// 9. 绘制进度圆环(蓝色)
dc.DrawGeometry(
null, // 无填充
new Pen(Brushes.SteelBlue, 30), // 钢蓝色画笔宽度10
geometry // 绘制路径
);
}
/// <summary>
/// Measure 阶段:建议大小为 100x100。
/// </summary>
protected override Size MeasureOverride(Size availableSize) => new Size(100, 100);
/// <summary>
/// Arrange 阶段:直接接受布局系统给予的最终大小。
/// </summary>
protected override Size ArrangeOverride(Size finalSize) => finalSize;
}
}

View File

@@ -0,0 +1,35 @@
using Microsoft.Xaml.Behaviors;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
namespace SamplePreSystem.UI.Behaviors
{
public class BorderMouseMoveBehavior :Behavior<Border>
{
protected override void OnAttached()
{
//base.OnAttached();
AssociatedObject.MouseMove += AssociatedObject_MouseMove;
}
private void AssociatedObject_MouseMove(object sender, System.Windows.Input.MouseEventArgs e)
{
if (e.LeftButton == MouseButtonState.Pressed)
{
// 获取窗口并执行拖拽
if (Window.GetWindow(AssociatedObject) is Window window)
{
window.DragMove();
}
}
}
}
}

View File

@@ -0,0 +1,90 @@
using Microsoft.Xaml.Behaviors;
using SamplePre.Models;
using SamplePreSystem.UI.ViewModel.SopManager;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
namespace SamplePreSystem.UI.Behaviors
{
public class DataGridDragBehavior :Behavior<DataGrid>
{
protected override void OnAttached()
{
//拖拽进入
AssociatedObject.DragEnter += AssociatedObject_DragEnter;
AssociatedObject.Drop += AssociatedObject_Drop;
}
public ICommand DropCompletedCommand
{
get { return (ICommand)GetValue(DropCompletedCommandProperty); }
set { SetValue(DropCompletedCommandProperty, value); }
}
// Using a DependencyProperty as the backing store for DropCompletedCommand. This enables animation, styling, binding, etc...
public static readonly DependencyProperty DropCompletedCommandProperty =
DependencyProperty.Register("DropCompletedCommand", typeof(ICommand), typeof(DataGridDragBehavior), new PropertyMetadata(null));
//// 可选:传递参数(比如拖拽后的数据源、拖拽前后索引)
//public static readonly DependencyProperty DropCommandParameterProperty =
// DependencyProperty.Register(
// nameof(DropCommandParameter),
// typeof(object),
// typeof(DataGridDragBehavior));
//public object DropCommandParameter
//{
// get => GetValue(DropCommandParameterProperty);
// set => SetValue(DropCommandParameterProperty, value);
//}
private void AssociatedObject_Drop(object sender, DragEventArgs e)
{
// 获取拖拽的数据
if (e.Data.GetData(typeof(TreeListItem)) is TreeListItem dropItem)
{
if (dropItem == null) return;
//var dataContext = this.DataContext as SopMangerViewModel;
//dataContext.AddDragSopAction(dropItem);
if (DropCompletedCommand != null && DropCompletedCommand.CanExecute(dropItem))
{
DropCompletedCommand.Execute(dropItem);
}
}
}
private void AssociatedObject_DragEnter(object sender, System.Windows.DragEventArgs e)
{
// 验证拖拽数据类型是否是我们需要的TreeItemModel
if (!e.Data.GetDataPresent(typeof(TreeListItem)))
{
e.Effects = DragDropEffects.None;
}
}
}
}

View File

@@ -0,0 +1,85 @@
using Microsoft.Xaml.Behaviors;
using SamplePre.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
namespace SamplePreSystem.UI.Behaviors
{
public class TreeViewDragBehavior :Behavior<TreeView>
{
// 拖拽起始点(用于判断是否是有效拖拽)
private Point _dragStartPoint;
protected override void OnAttached()
{
//记录鼠标按下时的坐标
AssociatedObject.PreviewMouseLeftButtonDown += AssociatedObject_PreviewMouseLeftButtonDown;
//处理TreeView的鼠标移动事件触发拖拽
AssociatedObject.PreviewMouseMove += AssociatedObject_PreviewMouseMove;
}
/// <summary>
/// 处理TreeView的鼠标移动事件触发拖拽
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
/// <exception cref="NotImplementedException"></exception>
private void AssociatedObject_PreviewMouseMove(object sender, System.Windows.Input.MouseEventArgs e)
{
// 获取当前鼠标位置
Point currentPoint = e.GetPosition(null);
// 计算鼠标移动的距离(过滤掉微小移动,避免误触发拖拽)
Vector dragVector = _dragStartPoint - currentPoint;
// 如果鼠标左键按下,且移动距离超过阈值(系统默认的拖拽阈值),则开始拖拽
if (e.LeftButton == MouseButtonState.Pressed &&
(Math.Abs(dragVector.X) > SystemParameters.MinimumHorizontalDragDistance ||
Math.Abs(dragVector.Y) > SystemParameters.MinimumVerticalDragDistance))
{
// 获取当前鼠标下的TreeViewItem
var treeViewItem = FindVisualParent<TreeViewItem>(e.OriginalSource as DependencyObject);
if (treeViewItem != null && treeViewItem.DataContext is TreeListItem dragItem)
{
// 开始拖拽,设置拖拽数据和拖拽效果
DragDrop.DoDragDrop(treeViewItem, dragItem, DragDropEffects.Copy);
}
}
}
/// <summary>
/// 查找可视化树中的父级控件(通用方法)
/// </summary>
private T FindVisualParent<T>(DependencyObject child) where T : DependencyObject
{
DependencyObject parentObject = VisualTreeHelper.GetParent(child);
if (parentObject == null) return null;
if (parentObject is T parent)
return parent;
else
return FindVisualParent<T>(parentObject);
}
private void AssociatedObject_PreviewMouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
// 记录鼠标按下时的坐标
_dragStartPoint = e.GetPosition(null);
}
}
}

View File

@@ -0,0 +1,77 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0-windows</TargetFramework>
<Nullable>enable</Nullable>
<UseWPF>true</UseWPF>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
<ItemGroup>
<None Remove="Assets\app.ico" />
<None Remove="Assets\App.png" />
<None Remove="Assets\login.png" />
<None Remove="Assets\progressBar.png" />
<None Remove="Assets\Warning.png" />
<None Remove="Assets\分液1.png" />
<None Remove="Assets\加液1.png" />
<None Remove="Assets\固相萃取1.png" />
<None Remove="Assets\机器人1.png" />
<None Remove="Assets\样品管理.png" />
<None Remove="Assets\氮吹1.png" />
<None Remove="Assets\离心机1.png" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.4.2" />
<PackageReference Include="HandyControl" Version="3.5.1" />
<PackageReference Include="MaterialDesignColors" Version="5.3.1" />
<PackageReference Include="MaterialDesignThemes" Version="5.3.1" />
<PackageReference Include="Microsoft.Xaml.Behaviors.Wpf" Version="1.1.142" />
<PackageReference Include="EPPlus" Version="7.0.10" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\SamplePre.Common\SamplePre.Common.csproj" />
<ProjectReference Include="..\SamplePre.Communication\SamplePre.Communication.csproj" />
<ProjectReference Include="..\SamplePre.Models\SamplePre.Models.csproj" />
<ProjectReference Include="..\SamplePre.ProcessBll\SamplePre.ProcessBll.csproj" />
</ItemGroup>
<ItemGroup>
<Resource Include="Assets\App.png">
<CopyToOutputDirectory>Never</CopyToOutputDirectory>
</Resource>
<Resource Include="Assets\login.png">
<CopyToOutputDirectory>Never</CopyToOutputDirectory>
</Resource>
<Resource Include="Assets\progressBar.png">
<CopyToOutputDirectory>Never</CopyToOutputDirectory>
</Resource>
<Resource Include="Assets\Warning.png">
<CopyToOutputDirectory>Never</CopyToOutputDirectory>
</Resource>
<Resource Include="Assets\分液1.png">
<CopyToOutputDirectory>Never</CopyToOutputDirectory>
</Resource>
<Resource Include="Assets\加液1.png">
<CopyToOutputDirectory>Never</CopyToOutputDirectory>
</Resource>
<Resource Include="Assets\固相萃取1.png">
<CopyToOutputDirectory>Never</CopyToOutputDirectory>
</Resource>
<Resource Include="Assets\机器人1.png">
<CopyToOutputDirectory>Never</CopyToOutputDirectory>
</Resource>
<Resource Include="Assets\样品管理.png">
<CopyToOutputDirectory>Never</CopyToOutputDirectory>
</Resource>
<Resource Include="Assets\氮吹1.png">
<CopyToOutputDirectory>Never</CopyToOutputDirectory>
</Resource>
<Resource Include="Assets\离心机1.png">
<CopyToOutputDirectory>Never</CopyToOutputDirectory>
</Resource>
</ItemGroup>
</Project>

View File

@@ -0,0 +1,59 @@
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes">
<!--<Style TargetType="Button">
<Setter Property="Background" Value="#106EBE"/>
<Setter Property="Foreground" Value="White"/>
-->
<!--<Setter Property="FontSize" Value="16"/>-->
<!--<Setter Property="FontFamily" Value="Assets/font/#iconfont"/>-->
<!--
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border Background="{TemplateBinding Background }">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="LightBlue"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>-->
<!-- ===================== MaterialDesign 图标+文字按钮 ===================== -->
<Style
x:Key="IconTextButtonStyle"
BasedOn="{StaticResource MaterialDesignRaisedButton}"
TargetType="Button">
<Setter Property="Width" Value="120" />
<Setter Property="Height" Value="30" />
<Setter Property="ContentTemplate">
<Setter.Value>
<!-- 关键:用 DataTemplate不破坏按钮样式 -->
<DataTemplate>
<StackPanel
HorizontalAlignment="Center"
VerticalAlignment="Center"
Orientation="Horizontal">
<materialDesign:PackIcon
Width="20"
Height="20"
Kind="{Binding RelativeSource={RelativeSource AncestorType=Button}, Path=Tag}" />
<TextBlock
Margin="5,0"
VerticalAlignment="Center"
Text="{Binding}" />
</StackPanel>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>

View File

@@ -0,0 +1,23 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Style x:Key="XBaseDataGrid" TargetType="DataGrid">
<!-- 表头样式:增加内边距 -->
<Setter Property="ColumnHeaderStyle">
<Setter.Value>
<Style TargetType="DataGridColumnHeader">
<!-- 表头背景色 -->
<Setter Property="Background" Value="#F5F5F5" />
<!-- 表头文字颜色 -->
<!--
<Setter Property="Foreground" Value="#2C7DBD"/>-->
<!-- 表头高度 -->
<Setter Property="Height" Value="35" />
<!-- 表头文字居中 -->
<Setter Property="HorizontalContentAlignment" Value="Left" />
</Style>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>

View File

@@ -0,0 +1,13 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<!-- 仅针对字体、间距的TreeView极简美化样式 -->
<Style TargetType="TreeView">
<!-- TreeView整体内边距避免控件紧贴窗口 -->
<Setter Property="Padding" Value="8" />
<!-- 整体背景:白色更清爽 -->
<Setter Property="Background" Value="White" />
<!-- 滚动条优化:避免文字被遮挡 -->
<Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Auto" />
</Style>
</ResourceDictionary>

View File

@@ -0,0 +1,277 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<ControlTemplate x:Key="WindowTemplateKey" TargetType="{x:Type Window}">
<Border
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<Grid>
<AdornerDecorator>
<ContentPresenter />
</AdornerDecorator>
<ResizeGrip
x:Name="WindowResizeGrip"
HorizontalAlignment="Right"
VerticalAlignment="Bottom"
IsTabStop="false"
Visibility="Collapsed" />
</Grid>
</Border>
<ControlTemplate.Triggers>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="ResizeMode" Value="CanResizeWithGrip" />
<Condition Property="WindowState" Value="Normal" />
</MultiTrigger.Conditions>
<Setter TargetName="WindowResizeGrip" Property="Visibility" Value="Visible" />
</MultiTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
<ControlTemplate x:Key="BaseWindowControlTemplate" TargetType="{x:Type Window}">
<DockPanel LastChildFill="True">
<!-- 外边框 -->
<Border
x:Name="borderTitle"
Width="Auto"
Height="Auto"
Background="#0170cc"
CornerRadius="0,0,0,0"
DockPanel.Dock="Top">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<TextBlock
Name="Title"
Grid.Column="0"
Margin="20,0,2,2"
VerticalAlignment="Center"
FontSize="16"
Foreground="White"
Text="{TemplateBinding Title}" />
<StackPanel
Grid.Column="1"
HorizontalAlignment="Right"
Orientation="Horizontal">
<!-- 最小化按钮 -->
<!--
<Button
x:Name="btnMin"
Margin="2,2,2,2"
Content="M"
Style="{DynamicResource MinButtonStyle}" />
-->
<!-- 最大化按钮 -->
<!--
<Button
x:Name="btnMax"
Margin="2,2,2,2"
Content="M"
Style="{DynamicResource MaxButtonStyle}" />-->
<!-- 关闭按钮 -->
<Button
x:Name="btnClose"
Margin="2,2,2,2"
Content="🗙"
Style="{DynamicResource CloseButtonStyle2}" />
</StackPanel>
</Grid>
</Border>
<Border
Width="Auto"
Height="Auto"
Background="{TemplateBinding Background}"
BorderBrush="LightGray"
BorderThickness="2"
CornerRadius="0,0,4,4"
DockPanel.Dock="Top">
<AdornerDecorator>
<ContentPresenter />
</AdornerDecorator>
</Border>
</DockPanel>
</ControlTemplate>
<Style x:Key="BaseWindowStyle" TargetType="{x:Type Window}">
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.WindowTextBrushKey}}" />
<Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.WindowBrushKey}}" />
<Setter Property="Template" Value="{StaticResource BaseWindowControlTemplate}" />
<Setter Property="AllowsTransparency" Value="True" />
<Setter Property="WindowStyle" Value="None" />
<Setter Property="BorderBrush" Value="#FF7097D0" />
<Setter Property="BorderThickness" Value="4,4,4,4" />
<Style.Triggers>
<Trigger Property="ResizeMode" Value="CanResizeWithGrip">
<Setter Property="Template" Value="{StaticResource WindowTemplateKey}" />
</Trigger>
</Style.Triggers>
</Style>
<!-- 最小化按钮 -->
<Style x:Key="MinButtonStyle" TargetType="{x:Type Button}">
<Setter Property="Foreground" Value="Black" />
<!-- 修改模板属性 -->
<Setter Property="Template">
<Setter.Value>
<!-- 控件模板 -->
<ControlTemplate TargetType="Button">
<!-- 背景色 -->
<Border
x:Name="back"
Margin="1"
Padding="2,0,0,0"
Background="#FFFFE9C9"
BorderBrush="#FFCDA05F"
BorderThickness="1"
CornerRadius="0"
Opacity="0.8">
<!-- 按钮内容 -->
<Path
x:Name="cp"
Width="12"
Height="12"
Fill="Black"
Stroke="#FFCEA15F"
StrokeThickness="3">
<Path.Data>
<PathGeometry Figures="M 0,6 H 6,6 " />
</Path.Data>
</Path>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="back" Property="Background" Value="#FFD4BD9B" />
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter TargetName="back" Property="Background" Value="#FFCDA05F" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!-- 最大化按钮 -->
<Style x:Key="MaxButtonStyle" TargetType="{x:Type Button}">
<Setter Property="Foreground" Value="Black" />
<!-- 修改模板属性 -->
<Setter Property="Template">
<Setter.Value>
<!-- 控件模板 -->
<ControlTemplate TargetType="Button">
<!-- 背景色 -->
<Border
x:Name="back"
Margin="1"
Padding="2,0,0,0"
Background="#FFFFE9C9"
BorderBrush="#FFCDA05F"
BorderThickness="1"
CornerRadius="0"
Opacity="0.8">
<!-- 按钮内容 -->
<Path
x:Name="cp"
Width="12"
Height="12"
Stroke="#FFCEA15F"
StrokeThickness="3">
<Path.Data>
<PathGeometry Figures="M 0,0 L 0,12 12,12 12,0 0,0" />
</Path.Data>
</Path>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="back" Property="Background" Value="#FFD4BD9B" />
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter TargetName="back" Property="Background" Value="#FFCDA05F" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!-- 关闭按钮 -->
<Style x:Key="CloseButtonStyle" TargetType="{x:Type Button}">
<Setter Property="Foreground" Value="Black" />
<!-- 修改模板属性 -->
<Setter Property="Template">
<Setter.Value>
<!-- 控件模板 -->
<ControlTemplate TargetType="Button">
<!-- 背景色 -->
<Border
x:Name="back"
Width="30"
Height="30"
Margin="0,0"
Padding="0,0,0,0"
BorderThickness="1"
CornerRadius="0">
<!-- 按钮内容 -->
<Path
x:Name="cp"
Width="12"
Height="12"
Stroke="White"
StrokeThickness="2">
<Path.Data>
<PathGeometry Figures="M 0,0 L 12,12 M 0,12 L 12,0" />
</Path.Data>
</Path>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="back" Property="Background" Value="DarkRed" />
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter TargetName="back" Property="Background" Value="DarkRed" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style
x:Key="CloseButtonStyle2"
BasedOn="{StaticResource MaterialDesignFlatMidBgButton}"
TargetType="Button">
<Setter Property="Width" Value="32" />
<Setter Property="Height" Value="32" />
<Setter Property="Padding" Value="0" />
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="DarkRed" />
<Setter Property="Foreground" Value="White" />
<Setter Property="Cursor" Value="Hand" />
</Trigger>
</Style.Triggers>
</Style>
</ResourceDictionary>

View File

@@ -0,0 +1,211 @@
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using Models.Models;
using SamplePre.Models.Ext;
using SamplePre.ProcessBll.SampleSequence;
using SamplePreSystem.UI.ViewModel.SampleManager;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using static MaterialDesignThemes.Wpf.Theme;
namespace SamplePreSystem.UI.ViewModel.Child
{
public partial class ImportSampleViewModel: ObservableObject
{
SampleSequenceBll sampleSequenceBll = new SampleSequenceBll();
SampleExecViewModel sampleExecViewModel;
// 关闭窗口的委托
public Action<bool> CloseAction { get; set; }
public ImportSampleViewModel(SampleExecViewModel _sampleExecViewModel)
{
GetData();
sampleExecViewModel = _sampleExecViewModel;
}
private DateTime _startDate = DateTime.Parse(DateTime.Now.ToString("yyyy-MM-dd") + " 00:00:00");
public DateTime StartDate
{
get { return _startDate; }
set
{
SetProperty(ref _startDate, value);
}
}
private DateTime _endDate = DateTime.Parse(DateTime.Now.ToString("yyyy-MM-dd") + " 00:00:00");
public DateTime EndDate
{
get { return _endDate; }
set
{
SetProperty(ref _endDate, value);
}
}
private List<tube_input_ext> _sampleList = new List<tube_input_ext>();
public List<tube_input_ext> SampleList
{
get { return _sampleList; }
set {
SetProperty(ref _sampleList, value);
}
}
public void GetData()
{
//DateTime dt1 = DateTime.Parse(dt_start.DateTime.ToString("yyyy-MM-dd") + " 00:00:00");
//DateTime dt2 = DateTime.Parse(dt_end.DateTime.ToString("yyyy-MM-dd") + " 23:00:00");
var templist = sampleSequenceBll.GetTubeData(StartDate, EndDate); ///
List<tube_input_ext> samples = new List<tube_input_ext>();
foreach(var item in templist)
{
item.bach_no = $"批号:{item.bach_no}";
tube_input_ext model = new tube_input_ext();
model.qrcode = item.qrcode;
model.item_name = item.item_name;
model.tube_type = item.tube_type;
model.standrad_id = item.standrad_id;
model.standrad = item.standrad;
model.input_user = item.input_user;
model.input_date = item.input_date;
model.weight = item.weight;
model.tube_count = item.tube_count;
model.bach_no = $"批号:{item.bach_no}";
model.IsSelected = false;
samples.Add(model);
}
SampleList = samples;
}
public bool? IsAllItems1Selected
{
get
{
var selected = SampleList.Select(item => item.IsSelected).Distinct().ToList();
return selected.Count == 1 ? selected.Single() : false;
}
set
{
if (value.HasValue)
{
SelectAll(value.Value, SampleList);
OnPropertyChanged();
}
}
}
/// <summary>
/// 选择所有
/// </summary>
/// <param name="select"></param>
/// <param name="models"></param>
private static void SelectAll(bool select, IEnumerable<tube_input_ext> models)
{
foreach (var model in models)
{
model.IsSelected = select;
}
}
/// <summary>
/// 选择组内数据
/// </summary>
/// <param name="bachCode"></param>
/// <param name="isSelect"></param>
public void SelectGroupData(string bachCode, bool isSelect)
{
foreach (var item in SampleList.Where(p => p.bach_no == bachCode))
{
item.IsSelected = isSelect;
}
}
[RelayCommand]
public void FindClick()
{
GetData();
ListCollectionView view = (ListCollectionView)CollectionViewSource.GetDefaultView(SampleList);//获取数据视图
//分组
view.GroupDescriptions.Add(new PropertyGroupDescription("bach_no"));
}
[RelayCommand]
public void ImportClick()
{
List<tube_input> samples = new List<tube_input>();
foreach (var tube in SampleList)
{
if (tube.IsSelected)
{
samples.Add(tube);
}
}
this.sampleExecViewModel.TubeInputs = samples;
CloseAction?.Invoke(true);
}
/// <summary>
/// 选中导入项
/// </summary>
[RelayCommand]
public void CheckBoxClick(object groupName)
{
System.Windows.Controls.CheckBox checkBox = groupName as System.Windows.Controls.CheckBox;
if (checkBox != null)
{
bool select = (bool)checkBox.IsChecked;
string code = checkBox.Content.ToString();
SelectGroupData(code, select);
}
}
}
}

View File

@@ -0,0 +1,120 @@
using Models.Const;
using Models.Models;
using SamplePre.Models;
using SamplePre.ProcessBll.BLL;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
namespace SamplePreSystem.UI.ViewModel.Child
{
public class NewActionViewModel: INotifyPropertyChanged
{
ActionMangerBll actionMangerBll = new ActionMangerBll();
public NewActionViewModel()
{
BindingUnit();
}
public void BindingUnit()
{
ActionUnits = SystemConst.dictDatas.Where(p => p.class_id == 2).ToList();
}
private List<sys_dict> actionUnits;
public event PropertyChangedEventHandler PropertyChanged;
public List<sys_dict> ActionUnits
{
get { return actionUnits; }
set { actionUnits = value;
OnPropertyChanged();
}
}
/// <summary>
/// 选择的动作单元
/// </summary>
private sys_dict _selectSysDict;
public sys_dict SelectSysDict
{
get { return _selectSysDict; }
set { _selectSysDict = value;
OnPropertyChanged();
}
}
protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
private sys_action sysAction = new sys_action();
public sys_action SysAction
{
get { return sysAction; }
set { sysAction = value;
OnPropertyChanged();
}
}
public int SaveNewData()
{
if (string.IsNullOrEmpty(SysAction.action_name))
{
MessageBox.Show("内容不能为空");
return -1;
}
//判断plc编码是否重复
if (actionMangerBll.IsExtisPlCcode(SysAction.plc_type))
{
MessageBox.Show("存在相同plc编码不能保存");
return -1;
}
sys_action process = new sys_action();
process.id = Guid.NewGuid().ToString();
process.action_name = SysAction.action_name;
process.plc_type = SysAction.plc_type;
process.remark = SysAction.remark;
//var selectItem = cmbActionUnit.SelectedItem as ComboBoxListItem;
process.action_unit = SelectSysDict.id;
//process.action_adress = actionAdress.Text;
int val = actionMangerBll.SaveSysAction(process);
return val;
}
}
}

View File

@@ -0,0 +1,218 @@
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using Models.Models;
using SamplePre.Models.Ext;
using SamplePre.ProcessBll.BLL;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
namespace SamplePreSystem.UI.ViewModel.Child
{
public partial class SelectParmListViewModel : ObservableObject
{
ActionMangerBll actionMangerBll = new ActionMangerBll();
SOPManagerBll sopBll = new SOPManagerBll();
sys_standard_action_ext sysStandardAction = null;
sys_action_ext sysAction = null;
// 关闭窗口的委托
public Action<bool> CloseAction { get; set; }
public SelectParmListViewModel(sys_standard_action_ext _sysStandardAction)
{
sysStandardAction = _sysStandardAction;
GetData();
FilterData(FilterType);
}
public SelectParmListViewModel(sys_action_ext _sysAction)
{
sysAction = _sysAction;
GetData();
FilterData(FilterType);
}
/// <summary>
/// 参数类型
/// </summary>
[ObservableProperty]
public List<string> dataTypes = new List<string> { "通用", "耗材", "液体" };
/// <summary>
/// 所有参数列表
/// </summary>
private List<sys_parm> allSysParams = new List<sys_parm>();
/// <summary>
/// 过滤参数列表
/// </summary>
[ObservableProperty]
public List<sys_parm> parms = new List<sys_parm>();
/// <summary>
/// 选中的参数列表
/// </summary>
[ObservableProperty]
public sys_parm selectParm = new sys_parm();
public void GetData()
{
if (Parms.Count <= 0)
{
//parms = standardDal.QuerySysParm();
allSysParams = actionMangerBll.QuerySysParm();
}
}
private string filterType = "通用";
/// <summary>
/// 类型过滤属性
/// </summary>
public string FilterType
{
get { return filterType; }
set {
SetProperty(ref filterType, value);
FilterData(value);
}
}
public void FilterData(string dataType)
{
if (string.IsNullOrEmpty(dataType))
{
Parms = allSysParams;
return;
}
Parms = allSysParams.Where(p => p.param_type == dataType).ToList();
}
public int SaveData(List<sys_parm> selectParam)
{
int val = -1;
if (sysStandardAction != null)
{
val = SavaDataSop(selectParam);
}
else if(sysAction != null)
{
val = SavaDataActionParam(selectParam);
}
return val;
}
private int SavaDataActionParam(List<sys_parm> selectParam)
{
//保存
List<sys_action_parm_map> actionParams = new List<sys_action_parm_map>();
foreach (var item in selectParam)
{
sys_action_parm_map map = new sys_action_parm_map();
map.process_id = sysAction.id;
map.parm_id = item.id;
//standardDal.Save_process_parm_map(map);
actionParams.Add(map);
}
int val = actionMangerBll.SaveActionParm(actionParams);
return val;
}
private int SavaDataSop(List<sys_parm> selectParam)
{
//保存
List<sys_standard_action_parm> actionParms = new List<sys_standard_action_parm>();
foreach (var item in selectParam)
{
//保存标准动作参数表
sys_standard_action_parm parmmodel = new sys_standard_action_parm()
{
id = Guid.NewGuid().ToString(),
standard_id = sysStandardAction.standard_id,
action_id = sysStandardAction.process_id,
action_seqno = sysStandardAction.process_no,
parm_id = item.id,
data_value = item.data_value,
parm_seqno = 0
};
actionParms.Add(parmmodel);
}
int val = sopBll.SaveStandardActionParam(actionParms);
return val;
}
/// <summary>
/// 确定命令
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
[RelayCommand]
public void BtnOKClick()
{
if (SelectParm != null)
{
List<sys_parm> selectParams = new List<sys_parm>();
selectParams.Add(SelectParm);
if (selectParams.Count > 0)
{
if (SaveData(selectParams) > 0)
{
CloseAction?.Invoke(true);
}
}
}
}
/// <summary>
/// 取消命令
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
[RelayCommand]
public void BtnCancelClick()
{
CloseAction?.Invoke(false);
}
}
}

View File

@@ -0,0 +1,171 @@
using SamplePre.Models.Ext;
using SamplePre.Models.Tables;
using SamplePre.ProcessBll.BLL;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
namespace SamplePreSystem.UI.ViewModel.ConfigManager
{
public class PermissionViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
RolesBll rolesBll = new RolesBll();
config_role configRole;
public PermissionViewModel(RoleViewModel vm)
{
configRole = vm.ConfigRole;
RoleName = configRole.name;
GetData();
}
protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
private string _roleName;
public string RoleName
{
get { return _roleName; }
set { _roleName = value; }
}
private List<TreeItemModel> _funList = new List<TreeItemModel>();
public List<TreeItemModel> FunList
{
get { return _funList; }
set { _funList = value;
OnPropertyChanged();
}
}
public void GetData()
{
var FunListTemp = rolesBll.GetFuncDataTree();
foreach (var item in FunListTemp.Where(p=>p.parent_id == 0))
{
// 根节点1
var root1 = new TreeItemModel { Id = item.id, Name = item.name };
foreach(var child in FunListTemp.Where(p => p.parent_id == item.id))
{
root1.Children.Add(new TreeItemModel { Id = child.id, Name = child.name, Parent = root1 });
}
FunList.Add(root1);
}
//选择中角色已有权限
List<int> ids = rolesBll.GetPermission(configRole.id);
LoadRolePermissions(ids);
}
/// <summary>
/// 加载指定角色已分配的权限(用于编辑角色权限)
/// </summary>
/// <param name="roleFunctionIds">角色已拥有的功能ID列表</param>
public void LoadRolePermissions(List<int> roleFunctionIds)
{
if (roleFunctionIds == null || roleFunctionIds.Count == 0) return;
foreach (var item in FunList)
{
bool isAll = true;
foreach (var fuc in item.Children)
{
if (roleFunctionIds.Contains(fuc.Id))
{
fuc.IsChecked = true;
//item.IsChecked = true;
}
else
{
isAll = false;
}
}
if(isAll)
{
item.IsChecked = true;
}
}
}
public bool SavePermission()
{
// 获取选中的功能ID列表
List<int> selectedIds = GetSelectedFunctionIds();
if (selectedIds.Count == 0)
{
MessageBox.Show("请至少选择一个功能权限!", "提示");
return false;
}
List<config_role_permisson> rolePermissonList = new List<config_role_permisson>();
foreach (int item in selectedIds)
{
config_role_permisson rolePermisson = new config_role_permisson();
rolePermisson.function_id = item;
rolePermisson.role_id = configRole.id;
rolePermissonList.Add(rolePermisson);
}
if (rolesBll.SavePermission(rolePermissonList) < 0)
{
MessageBox.Show("保存失败!");
return false;
}
return true;
}
private List<int> GetSelectedFunctionIds()
{
List<int> selectedIds = new List<int>();
foreach (var item in FunList)
{
foreach(var fuc in item.Children)
{
if(fuc.IsChecked)
{
//添加父节点功能id
if(!selectedIds.Contains(item.Id))
{
selectedIds.Add(item.Id);
}
selectedIds.Add(fuc.Id);
}
}
}
return selectedIds;
}
}
}

View File

@@ -0,0 +1,154 @@
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using SamplePre.Models.Tables;
using SamplePre.ProcessBll.BLL;
using SamplePre.UIWpf.ConfigManager.chirld;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
namespace SamplePreSystem.UI.ViewModel.ConfigManager
{
public partial class RoleViewModel : ObservableObject
{
RolesBll roleBll = new RolesBll();
public RoleViewModel()
{
GetData();
}
[ObservableProperty]
private List<config_role> rolesList;
[ObservableProperty]
private config_role configRole = new config_role();
public void GetData()
{
RolesList = roleBll.GetRoles();
}
/// <summary>
/// 保存角色
/// </summary>
public bool SaveRole()
{
if(string.IsNullOrEmpty(ConfigRole.name.Trim()))
{
MessageBox.Show("角色名称不能为空!");
return false;
}
if (string.IsNullOrEmpty(ConfigRole.id))
{
//new
ConfigRole.id = Guid.NewGuid().ToString();
if (roleBll.SaveRoleData(ConfigRole) < 0)
{
return false;
}
}
else
{
if (roleBll.UpdateRoleData(ConfigRole) < 0)
{
return false;
}
}
return true;
}
public bool DeleteRole()
{
if(!string.IsNullOrEmpty( ConfigRole.id ))
{
if (MessageBox.Show($"确定删除:{ConfigRole.name}", "提示",MessageBoxButton.OKCancel) == MessageBoxResult.OK)
{
if (roleBll.DeleteRole(ConfigRole) < 0)
{
MessageBox.Show("用户删除失败!");
return false;
}
//刷新用户
GetData();
return true;
}
}
return false;
}
/// <summary>
/// 添加角色
/// </summary>
[RelayCommand]
public void BtnAddClick()
{
ConfigRole = new config_role();
NewRoleWindow frm = new NewRoleWindow(this);
if (frm.ShowDialog() == true)
{
GetData();
}
}
/// <summary>
/// 编辑角色
/// </summary>
[RelayCommand]
public void BtnEditClick()
{
NewRoleWindow frm = new NewRoleWindow(this);
if (frm.ShowDialog() == true)
{
GetData();
}
}
/// <summary>
/// 删除角色
/// </summary>
[RelayCommand]
public void BtnDeleClick()
{
DeleteRole();
}
[RelayCommand]
public void BtnPermissonClick()
{
if (string.IsNullOrEmpty(ConfigRole.id)) return;
PermissionWindow frm = new PermissionWindow(this);
frm.ShowDialog();
}
}
}

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