@@ -8,7 +8,7 @@ | |||
<ItemGroup> | |||
<PackageReference Include="BPA.ApolloClient" Version="1.0.12" /> | |||
<PackageReference Include="BPA.Message" Version="1.0.41" /> | |||
<PackageReference Include="BPA.Message" Version="1.0.43" /> | |||
<PackageReference Include="Microsoft.Extensions.Configuration" Version="6.0.1" /> | |||
<PackageReference Include="Microsoft.Extensions.Configuration.FileExtensions" Version="6.0.0" /> | |||
<PackageReference Include="System.Configuration.ConfigurationManager" Version="6.0.0" /> | |||
@@ -229,7 +229,7 @@ | |||
</ItemGroup> | |||
<ItemGroup> | |||
<PackageReference Include="BPA.Message" Version="1.0.41" /> | |||
<PackageReference Include="BPA.Message" Version="1.0.43" /> | |||
</ItemGroup> | |||
<ItemGroup> | |||
@@ -0,0 +1,45 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Globalization; | |||
using System.Linq; | |||
using System.Text; | |||
using System.Threading.Tasks; | |||
using System.Windows.Data; | |||
using System.Windows.Media; | |||
namespace BPASmartClient.CustomResource.Converters | |||
{ | |||
public class StatusConverter : IValueConverter | |||
{ | |||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture) | |||
{ | |||
SolidColorBrush returnValue = new SolidColorBrush(Color.FromArgb(255, 0, 204, 255)); | |||
if (value != null && value is ushort statusValue) | |||
{ | |||
switch (statusValue) | |||
{ | |||
case 0: | |||
returnValue = new SolidColorBrush(Color.FromArgb(255, 0, 204, 255)); | |||
break; | |||
case 1: | |||
returnValue = new SolidColorBrush(Color.FromArgb(255, 0, 255, 127)); | |||
break; | |||
case 2: | |||
returnValue = new SolidColorBrush(Color.FromArgb(255, 255, 215, 00)); | |||
break; | |||
case 3: | |||
returnValue = new SolidColorBrush(Color.FromArgb(255, 255, 0, 0)); | |||
break; | |||
default: | |||
break; | |||
} | |||
} | |||
return returnValue; | |||
} | |||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) | |||
{ | |||
throw new NotImplementedException(); | |||
} | |||
} | |||
} |
@@ -7,7 +7,7 @@ | |||
</PropertyGroup> | |||
<ItemGroup> | |||
<PackageReference Include="BPA.Message" Version="1.0.41" /> | |||
<PackageReference Include="BPA.Message" Version="1.0.43" /> | |||
</ItemGroup> | |||
<ItemGroup> | |||
@@ -49,11 +49,11 @@ namespace BPASmartClient.Modbus | |||
Port = port; | |||
modbusFactory = new ModbusFactory(); | |||
Connect(); | |||
master.Transport.ReadTimeout = 2000;//读取超时时间 | |||
master.Transport.WriteTimeout = 2000;//写入超时时间 | |||
master.Transport.Retries = 10;//重试次数 | |||
if (Connected) | |||
{ | |||
master.Transport.ReadTimeout = 2000;//读取超时时间 | |||
master.Transport.WriteTimeout = 2000;//写入超时时间 | |||
master.Transport.Retries = 10;//重试次数 | |||
ConnectOk?.Invoke(); | |||
MessageLog.GetInstance.Show($"设备【{ip}:{port}】连接成功"); | |||
} | |||
@@ -17,7 +17,7 @@ | |||
</ItemGroup> | |||
<ItemGroup> | |||
<PackageReference Include="BPA.Message" Version="1.0.41" /> | |||
<PackageReference Include="BPA.Message" Version="1.0.43" /> | |||
<PackageReference Include="Microsoft.Toolkit.Mvvm" Version="7.1.2" /> | |||
</ItemGroup> | |||
@@ -23,6 +23,7 @@ | |||
<con:ColorConverter x:Key="ColorConverter" /> | |||
<con:TextConverter x:Key="TextConverter" /> | |||
<con:VisibleTypeConverter x:Key="VisibleTypeConverter" /> | |||
<con:StatusConverter x:Key="StatusConverter" /> | |||
</ResourceDictionary> | |||
<ResourceDictionary> | |||
@@ -14,7 +14,7 @@ | |||
</ItemGroup> | |||
<ItemGroup> | |||
<PackageReference Include="BPA.Message" Version="1.0.39" /> | |||
<PackageReference Include="BPA.Message" Version="1.0.43" /> | |||
<PackageReference Include="Microsoft.Toolkit.Mvvm" Version="7.1.2" /> | |||
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" /> | |||
</ItemGroup> | |||
@@ -14,16 +14,15 @@ namespace DosingSystem.Model | |||
{ | |||
public class DeviceInquire | |||
{ | |||
private volatile static DeviceInquire _Instance; | |||
public static DeviceInquire GetInstance => _Instance ?? (_Instance = new DeviceInquire()); | |||
private DeviceInquire() { } | |||
string IPSegment = "192.168.1."; | |||
string NameAddress = "VW5000"; | |||
string NameAddress = "VW0"; | |||
int count = 0; | |||
private static readonly object _lock = new object(); | |||
ConcurrentDictionary<string, ModbusTcp> modbusTcps = new ConcurrentDictionary<string, ModbusTcp>(); | |||
ConcurrentDictionary<string, DeviceStatus> DeviceLists = new ConcurrentDictionary<string, DeviceStatus>(); | |||
List<string> InvalidIP = new List<string>(); | |||
public void Init() | |||
@@ -36,10 +35,14 @@ namespace DosingSystem.Model | |||
}), "配料机设备上线监听", true); | |||
} | |||
public ModbusTcp GetModbusTcp(string ip) | |||
public DeviceStatus GetDevice(string deviceName) | |||
{ | |||
if (modbusTcps.ContainsKey(ip)) return modbusTcps[ip]; | |||
else return default; | |||
if (deviceName != null) | |||
{ | |||
var res = DeviceLists.Values.FirstOrDefault(p => p.DeviceName == deviceName); | |||
if (res != null) return res; | |||
} | |||
return default; | |||
} | |||
private void IpAddressLines() | |||
@@ -48,8 +51,7 @@ namespace DosingSystem.Model | |||
{ | |||
if (!InvalidIP.Contains($"{IPSegment}{i}")) | |||
{ | |||
Ping myPing; | |||
myPing = new Ping(); | |||
Ping myPing = new Ping(); | |||
myPing.PingCompleted += new PingCompletedEventHandler(_myPing_PingCompleted); | |||
string pingIP = $"{IPSegment}{i}"; | |||
myPing.SendAsync(pingIP, 1000, null); | |||
@@ -69,17 +71,23 @@ namespace DosingSystem.Model | |||
if (e.Reply.Status == IPStatus.Success) | |||
{ | |||
string ip = e.Reply.Address.ToString(); | |||
if (!modbusTcps.ContainsKey(ip)) | |||
if (!DeviceLists.ContainsKey(ip)) | |||
{ | |||
modbusTcps.TryAdd(ip, new ModbusTcp()); | |||
modbusTcps[ip].IsReconnect = false; | |||
Task.Run(new Action(() => { modbusTcps[ip].ModbusTcpConnect(ip); })); | |||
modbusTcps[ip].ConnectOk = new Action(() => | |||
DeviceStatus DS = new DeviceStatus(); | |||
//DeviceLists.TryAdd(ip, new DeviceStatus()); | |||
//DeviceLists[ip].modbusTcp.IsReconnect = false; | |||
//Task.Run(new Action(() => { DeviceLists[ip].modbusTcp.ModbusTcpConnect(ip, 508); })); | |||
DS.modbusTcp.IsReconnect = false; | |||
Task.Run(new Action(() => { DS.modbusTcp.ModbusTcpConnect(ip, 508); })); | |||
DS.modbusTcp.ConnectOk = new Action(() => | |||
{ | |||
string DeviceName = modbusTcps[ip].GetString(NameAddress, 10); | |||
//string DeviceName = DeviceLists[ip].modbusTcp.GetString(NameAddress, 20); | |||
string DeviceName = DS.modbusTcp.GetString(NameAddress, 20); | |||
if (DeviceName.Length > 0) | |||
{ | |||
DeviceLists.TryAdd(ip, DS); | |||
DeviceLists[ip].Init(DeviceName); | |||
DeviceLists[ip].modbusTcp.IsReconnect = true; | |||
App.Current.Dispatcher.Invoke(new Action(() => | |||
{ | |||
DeviceListViewModel.devices.Add(new Devices() | |||
@@ -87,6 +95,9 @@ namespace DosingSystem.Model | |||
DeviceName = DeviceName, | |||
IpAddress = ip | |||
}); | |||
if (!NewRecipeViewModel.RawMaterialNames.Contains(DeviceName)) | |||
NewRecipeViewModel.RawMaterialNames.Add(DeviceName); | |||
})); | |||
} | |||
else | |||
@@ -95,23 +106,71 @@ namespace DosingSystem.Model | |||
} | |||
}); | |||
modbusTcps[ip].ConnectFail = new Action(() => | |||
DS.modbusTcp.ConnectFail = new Action(() => | |||
{ | |||
if (!InvalidIP.Contains(ip)) InvalidIP.Add(ip); | |||
}); | |||
modbusTcps[ip].Disconnect = new Action(() => | |||
DS.modbusTcp.Disconnect = new Action(() => | |||
{ | |||
if (InvalidIP.Contains(ip)) InvalidIP.Remove(ip); | |||
var res = DeviceListViewModel.devices.FirstOrDefault(P => P.IpAddress == ip); | |||
if (res != null && DeviceListViewModel.devices.Contains(res)) | |||
App.Current.Dispatcher.Invoke(new Action(() => { DeviceListViewModel.devices.Remove(res); })); | |||
App.Current.Dispatcher.Invoke(new Action(() => | |||
{ | |||
DeviceListViewModel.devices.Remove(res); | |||
if (!NewRecipeViewModel.RawMaterialNames.Contains(res.DeviceName)) | |||
NewRecipeViewModel.RawMaterialNames.Remove(res.DeviceName); | |||
})); | |||
//DeviceLists[ip].Dispose(); | |||
DS.Dispose(); | |||
}); | |||
} | |||
} | |||
CompleteCount(); | |||
} | |||
} | |||
public class DeviceStatus | |||
{ | |||
public string DeviceName = String.Empty; | |||
public ModbusTcp modbusTcp = new ModbusTcp(); | |||
public void Init(string DeviceName) | |||
{ | |||
this.DeviceName = DeviceName; | |||
if (modbusTcp.Connected) | |||
{ | |||
ThreadManage.GetInstance().StartLong(new Action(() => | |||
{ | |||
var res = this.modbusTcp.Read("VW100"); | |||
if (res is ushort ushortValue) | |||
{ | |||
RunStatus = ushortValue; | |||
} | |||
Thread.Sleep(100); | |||
}), $"{DeviceName} 开始监听", true); | |||
} | |||
} | |||
public void Dispose() | |||
{ | |||
ThreadManage.GetInstance().StopTask($"{DeviceName} 开始监听"); | |||
} | |||
public bool IsConnected => modbusTcp.Connected; | |||
/// <summary> | |||
/// 配料系统运行状态 | |||
/// </summary> | |||
public ushort RunStatus { get; private set; } | |||
public void Start(float Value) | |||
{ | |||
if (modbusTcp.Connected) | |||
{ | |||
modbusTcp.SetReal("VW40", Value);//写入配方量 | |||
modbusTcp.Write("M0.0", true);//设备启动写入 | |||
} | |||
} | |||
} | |||
} |
@@ -4,6 +4,7 @@ using System.Linq; | |||
using System.Text; | |||
using System.Threading.Tasks; | |||
using System.Collections.ObjectModel; | |||
using DosingSystem.ViewModel; | |||
namespace DosingSystem.Model | |||
{ | |||
@@ -0,0 +1,48 @@ | |||
using Microsoft.Toolkit.Mvvm.ComponentModel; | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Linq; | |||
using System.Text; | |||
using System.Threading.Tasks; | |||
namespace DosingSystem.Model | |||
{ | |||
/// <summary> | |||
/// 原料模块 | |||
/// </summary> | |||
public class RawMaterialModel : ObservableObject | |||
{ | |||
/// <summary> | |||
/// 原料名称 | |||
/// </summary> | |||
public string RawMaterialName { get { return _mRawMaterialName; } set { _mRawMaterialName = value; OnPropertyChanged(); } } | |||
private string _mRawMaterialName; | |||
/// <summary> | |||
/// 原料设备IP | |||
/// </summary> | |||
public string DeviceIp { get; set; } | |||
/// <summary> | |||
/// 原料重量 | |||
/// </summary> | |||
public float RawMaterialWeight { get { return _mRawMaterialWeight; } set { _mRawMaterialWeight = value; OnPropertyChanged(); } } | |||
private float _mRawMaterialWeight; | |||
/// <summary> | |||
/// 原料ID | |||
/// </summary> | |||
public string RawMaterialId { get { return _mRawMaterialId; } set { _mRawMaterialId = value; OnPropertyChanged(); } } | |||
private string _mRawMaterialId; | |||
/// <summary> | |||
/// 原料设备执行状态 | |||
/// 1:等待下料 | |||
/// 2:下料中 | |||
/// 3:下料完成 | |||
/// </summary> | |||
public int RecipeStatus { get { return _mRecipeStatus; } set { _mRecipeStatus = value; OnPropertyChanged(); } } | |||
private int _mRecipeStatus; | |||
} | |||
} |
@@ -9,8 +9,13 @@ using Microsoft.Toolkit.Mvvm.ComponentModel; | |||
namespace DosingSystem.Model | |||
{ | |||
/// <summary> | |||
/// 配方模块 | |||
/// </summary> | |||
public class RecipeModel : ObservableObject | |||
{ | |||
public bool IsEnable { get { return _mIsEnable; } set { _mIsEnable = value; OnPropertyChanged(); } } | |||
private bool _mIsEnable = true; | |||
/// <summary> | |||
/// 序号 | |||
@@ -30,7 +35,11 @@ namespace DosingSystem.Model | |||
public string RecipCode { get { return _mRecipCode; } set { _mRecipCode = value; OnPropertyChanged(); } } | |||
private string _mRecipCode; | |||
public ObservableCollection<RawMaterial> RawMaterials { get; set; } = new ObservableCollection<RawMaterial>(); | |||
/// <summary> | |||
/// 原料集合 | |||
/// </summary> | |||
public ObservableCollection<RawMaterialModel> RawMaterials { get; set; } = new ObservableCollection<RawMaterialModel>(); | |||
} | |||
@@ -2,26 +2,187 @@ | |||
x:Class="DosingSystem.View.RecipeControlView" | |||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" | |||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" | |||
xmlns:control="clr-namespace:BPASmartClient.CustomResource.UserControls;assembly=BPASmartClient.CustomResource" | |||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" | |||
xmlns:control="clr-namespace:BPASmartClient.CustomResource.UserControls;assembly=BPASmartClient.CustomResource" | |||
xmlns:pry="clr-namespace:BPASmartClient.CustomResource.UserControls;assembly=BPASmartClient.CustomResource" | |||
xmlns:vm="clr-namespace:DosingSystem.ViewModel" | |||
xmlns:local="clr-namespace:DosingSystem.View" | |||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" | |||
xmlns:pry="clr-namespace:BPASmartClient.CustomResource.UserControls;assembly=BPASmartClient.CustomResource" | |||
xmlns:vm="clr-namespace:DosingSystem.ViewModel" | |||
d:DesignHeight="450" | |||
d:DesignWidth="800" | |||
mc:Ignorable="d"> | |||
<UserControl.DataContext> | |||
<vm:RecipeControlViewModel/> | |||
<vm:RecipeControlViewModel /> | |||
</UserControl.DataContext> | |||
<UserControl.Resources> | |||
<Style x:Key="UserItemContainerStyle" TargetType="ListBoxItem"> | |||
<Style.Resources> | |||
<!-- SelectedItem with focus --> | |||
<SolidColorBrush | |||
x:Key="{x:Static SystemColors.HighlightBrushKey}" | |||
Opacity=".4" | |||
Color="White" /> | |||
<!-- SelectedItem without focus --> | |||
<SolidColorBrush | |||
x:Key="{x:Static SystemColors.ControlBrushKey}" | |||
Opacity=".4" | |||
Color="White" /> | |||
</Style.Resources> | |||
<!-- 设置触发器 --> | |||
<Style.Triggers> | |||
<Trigger Property="IsMouseOver" Value="true"> | |||
<Setter Property="Background" Value="White" /> | |||
<Setter Property="Foreground" Value="White" /> | |||
</Trigger> | |||
<Trigger Property="IsFocused" Value="true"> | |||
<Setter Property="Background" Value="White" /> | |||
<Setter Property="Foreground" Value="White" /> | |||
</Trigger> | |||
</Style.Triggers> | |||
</Style> | |||
</UserControl.Resources> | |||
<Grid> | |||
<TextBlock | |||
HorizontalAlignment="Center" | |||
VerticalAlignment="Center" | |||
FontSize="40" | |||
Foreground="Wheat" | |||
Text="配方控制" /> | |||
<ScrollViewer> | |||
<ItemsControl ItemsSource="{Binding Recipes}"> | |||
<ItemsControl.ItemTemplate> | |||
<DataTemplate> | |||
<Grid Height="150" VerticalAlignment="Top"> | |||
<Border | |||
Name="ShadowElement" | |||
Height="150" | |||
VerticalAlignment="Top" | |||
BorderBrush="#00BEFA" | |||
BorderThickness="2" | |||
ClipToBounds="True" | |||
CornerRadius="8"> | |||
<Border.Effect> | |||
<DropShadowEffect | |||
BlurRadius="18" | |||
ShadowDepth="0" | |||
Color="#00BEFA" /> | |||
</Border.Effect> | |||
</Border> | |||
<Grid> | |||
<Grid.ColumnDefinitions> | |||
<ColumnDefinition Width="auto" /> | |||
<ColumnDefinition /> | |||
<ColumnDefinition Width="auto" /> | |||
</Grid.ColumnDefinitions> | |||
<Grid Margin="20,0,0,0"> | |||
<Grid.RowDefinitions> | |||
<RowDefinition /> | |||
<RowDefinition /> | |||
</Grid.RowDefinitions> | |||
<TextBlock | |||
FontSize="40" | |||
Foreground="White" | |||
Text="{Binding RecipeName}" /> | |||
<Button | |||
Grid.Row="1" | |||
Width="80" | |||
Height="30" | |||
HorizontalAlignment="Left" | |||
Command="{Binding DataContext.StartCommand, RelativeSource={RelativeSource AncestorType=ItemsControl, Mode=FindAncestor}}" | |||
CommandParameter="{Binding RecipeName}" | |||
Content="配方下发" | |||
IsEnabled="{Binding IsEnable}" /> | |||
</Grid> | |||
<ListView | |||
Grid.Column="1" | |||
Margin="10" | |||
Background="Transparent" | |||
BorderBrush="#00BEFA" | |||
BorderThickness="2,0,2,0" | |||
ItemsSource="{Binding RawMaterials}" | |||
ScrollViewer.HorizontalScrollBarVisibility="Disabled"> | |||
<ListView.ItemsPanel> | |||
<ItemsPanelTemplate> | |||
<UniformGrid | |||
HorizontalAlignment="Left" | |||
VerticalAlignment="Top" | |||
Columns="4" /> | |||
</ItemsPanelTemplate> | |||
</ListView.ItemsPanel> | |||
<ListView.ItemTemplate> | |||
<DataTemplate> | |||
<StackPanel | |||
Grid.Column="1" | |||
Height="20" | |||
Margin="20,0,0,0" | |||
VerticalAlignment="Top" | |||
Orientation="Horizontal"> | |||
<Ellipse | |||
Width="{Binding ElementName=n, Path=ActualHeight}" | |||
Margin="0,0,5,0" | |||
Fill="{Binding RecipeStatus, Converter={StaticResource StatusConverter}}" /> | |||
<TextBlock | |||
Name="n" | |||
FontSize="16" | |||
Foreground="White" | |||
Text="{Binding RawMaterialName}" /> | |||
</StackPanel> | |||
</DataTemplate> | |||
</ListView.ItemTemplate> | |||
</ListView> | |||
<StackPanel | |||
Grid.Column="2" | |||
Margin="5,0" | |||
VerticalAlignment="Center"> | |||
<StackPanel Margin="0,0,0,5" Orientation="Horizontal"> | |||
<Ellipse | |||
Width="{Binding ElementName=tb, Path=ActualHeight}" | |||
Margin="0,0,5,0" | |||
Fill="Green" /> | |||
<TextBlock | |||
Name="tb" | |||
Foreground="#ddd" | |||
Text="等待下料" /> | |||
</StackPanel> | |||
<StackPanel Margin="0,0,0,5" Orientation="Horizontal"> | |||
<Ellipse | |||
Width="{Binding ElementName=tb, Path=ActualHeight}" | |||
Margin="0,0,5,0" | |||
Fill="Yellow" /> | |||
<TextBlock | |||
Name="tb1" | |||
Foreground="#ddd" | |||
Text="下料中" /> | |||
</StackPanel> | |||
<StackPanel Margin="0,0,0,5" Orientation="Horizontal"> | |||
<Ellipse | |||
Width="{Binding ElementName=tb, Path=ActualHeight}" | |||
Margin="0,0,5,0" | |||
Fill="Aqua" /> | |||
<TextBlock | |||
Name="tb2" | |||
Foreground="#ddd" | |||
Text="下料完成" /> | |||
</StackPanel> | |||
<StackPanel Margin="0,0,0,5" Orientation="Horizontal"> | |||
<Ellipse | |||
Width="{Binding ElementName=tb, Path=ActualHeight}" | |||
Margin="0,0,5,0" | |||
Fill="Red" /> | |||
<TextBlock | |||
Name="tb3" | |||
Foreground="#ddd" | |||
Text="原料设备异常" /> | |||
</StackPanel> | |||
</StackPanel> | |||
</Grid> | |||
</Grid> | |||
</DataTemplate> | |||
</ItemsControl.ItemTemplate> | |||
</ItemsControl> | |||
</ScrollViewer> | |||
</Grid> | |||
</UserControl> |
@@ -185,7 +185,6 @@ | |||
Foreground="#ff00ccff" | |||
Style="{StaticResource TextBlockStyle}" | |||
Text="{Binding RecipeName}" /> | |||
<!--<Border BorderBrush="{StaticResource BorderSolid}" BorderThickness="1,0,1,0" />--> | |||
</Grid> | |||
@@ -195,24 +194,22 @@ | |||
Style="{StaticResource TextBlockStyle}" | |||
Text="{Binding RecipCode}" /> | |||
<Grid Grid.Column="3"> | |||
<!--<Grid Grid.Column="3"> | |||
<Button | |||
Command="{Binding DataContext.EditCommand, RelativeSource={RelativeSource AncestorType=ItemsControl, Mode=FindAncestor}}" | |||
CommandParameter="{Binding RecipCode}" | |||
Content="编辑" | |||
Style="{StaticResource buttonStyle}" /> | |||
<!--<Border BorderBrush="{StaticResource BorderSolid}" BorderThickness="1,0,1,0" />--> | |||
</Grid> | |||
</Grid>--> | |||
<Grid Grid.Column="5"> | |||
<Button | |||
Command="{Binding DataContext.LookCommand, RelativeSource={RelativeSource AncestorType=ItemsControl, Mode=FindAncestor}}" | |||
Command="{Binding DataContext.DetailsCommand, RelativeSource={RelativeSource AncestorType=ItemsControl, Mode=FindAncestor}}" | |||
CommandParameter="{Binding RecipCode}" | |||
Content="查看" | |||
Content="详情" | |||
Style="{StaticResource buttonStyle}" /> | |||
<!--<Border BorderBrush="{StaticResource BorderSolid}" BorderThickness="0,0,1,0" />--> | |||
</Grid> | |||
<Grid Grid.Column="6"> | |||
@@ -221,14 +218,8 @@ | |||
CommandParameter="{Binding RecipCode}" | |||
Content="删除" | |||
Style="{StaticResource buttonStyle}" /> | |||
<!--<Border BorderBrush="{StaticResource BorderSolid}" BorderThickness="0,0,1,0" />--> | |||
</Grid> | |||
<!--<Border | |||
Grid.ColumnSpan="8" | |||
BorderBrush="{StaticResource BorderSolid}" | |||
BorderThickness="1,1,1,1" />--> | |||
</Grid> | |||
<ControlTemplate.Triggers> | |||
@@ -16,10 +16,7 @@ namespace DosingSystem.ViewModel | |||
{ | |||
public DeviceListViewModel() | |||
{ | |||
for (int i = 0; i < 10; i++) | |||
{ | |||
devices.Add(new Devices() { IpAddress = $"192.168.1.{i + 10}", DeviceName = $"Device_{i}" }); | |||
} | |||
} | |||
public static ObservableCollection<Devices> devices { get; set; } = new ObservableCollection<Devices>(); | |||
@@ -55,7 +55,7 @@ namespace DosingSystem.ViewModel | |||
MenuInit(); | |||
permission = Permission.管理员; | |||
if (Menus.Count > 0) DoNavChanged(Menus.ElementAt(0).CommandParameter); | |||
DeviceInquire.GetInstance.Init(); | |||
} | |||
@@ -15,11 +15,18 @@ namespace DosingSystem.ViewModel | |||
{ | |||
public NewRecipeViewModel() | |||
{ | |||
RawMaterialNames.Clear(); | |||
for (int i = 0; i < 10; i++) | |||
ActionManage.GetInstance.Register(new Action<object>((o) => | |||
{ | |||
RawMaterialNames.Add($"原料{i}"); | |||
} | |||
if (o != null && o is RecipeModel rm) | |||
{ | |||
RecipeName = rm.RecipeName; | |||
foreach (var item in rm.RawMaterials) | |||
{ | |||
RawMaterials.Add(item); | |||
} | |||
RecipCode = rm.RecipCode; | |||
} | |||
}), "Details"); | |||
AddCommand = new RelayCommand(() => | |||
{ | |||
@@ -27,7 +34,7 @@ namespace DosingSystem.ViewModel | |||
string guid = Guid.NewGuid().ToString(); | |||
if (RawMaterials.FirstOrDefault(p => p.RawMaterialId == guid) == null) | |||
{ | |||
RawMaterials.Add(new RawMaterial() | |||
RawMaterials.Add(new RawMaterialModel() | |||
{ | |||
RawMaterialId = guid | |||
}); | |||
@@ -46,66 +53,72 @@ namespace DosingSystem.ViewModel | |||
SaveCommand = new RelayCommand(() => | |||
{ | |||
var res = Array.FindIndex(Json<LocaPar>.Data.Recipes.ToArray(), p => p.RecipeName == RecipeName); | |||
if (res >= 0 && res < Json<LocaPar>.Data.Recipes.Count) | |||
if (RecipCode.Length <= 0) | |||
{ | |||
Json<LocaPar>.Data.Recipes.ElementAt(res).RecipeName = RecipeName; | |||
Json<LocaPar>.Data.Recipes.ElementAt(res).RawMaterials = RawMaterials; | |||
var res = Array.FindIndex(Json<LocaPar>.Data.Recipes.ToArray(), p => p.RecipeName == RecipeName); | |||
if (res >= 0 && res < Json<LocaPar>.Data.Recipes.Count) | |||
{ | |||
ErrorInfo = "该配方已存在,请重新输入"; | |||
} | |||
else | |||
{ | |||
AddRecipes(); | |||
} | |||
} | |||
else | |||
{ | |||
string date = DateTime.Now.ToString("yyyy-MM-dd-HH-mm-ss"); | |||
var dates = date.Split("-").ToList(); | |||
StringBuilder sb = new StringBuilder(); | |||
dates?.ForEach((item) => { sb.Append(item); }); | |||
Json<LocaPar>.Data.Recipes.Add(new RecipeModel() | |||
var res = Array.FindIndex(Json<LocaPar>.Data.Recipes.ToArray(), p => p.RecipCode == RecipCode); | |||
if (res >= 0 && res < Json<LocaPar>.Data.Recipes.Count) | |||
{ | |||
SerialNum = Json<LocaPar>.Data.Recipes.Count + 1, | |||
RawMaterials = RawMaterials, | |||
RecipCode = sb.ToString(), | |||
RecipeName = RecipeName | |||
}); | |||
Json<LocaPar>.Data.Recipes.ElementAt(res).RecipeName = RecipeName; | |||
foreach (var item in RawMaterials) | |||
{ | |||
Json<LocaPar>.Data.Recipes.ElementAt(res).RawMaterials.Add(item); | |||
} | |||
} | |||
} | |||
ActionManage.GetInstance.Send("CloseNewRecipeView"); | |||
}); | |||
} | |||
private void AddRecipes() | |||
{ | |||
string date = DateTime.Now.ToString("yyyy-MM-dd-HH-mm-ss"); | |||
var dates = date.Split("-").ToList(); | |||
StringBuilder sb = new StringBuilder(); | |||
dates?.ForEach((item) => { sb.Append(item); }); | |||
Json<LocaPar>.Data.Recipes.Add(new RecipeModel() | |||
{ | |||
SerialNum = Json<LocaPar>.Data.Recipes.Count + 1, | |||
RawMaterials = RawMaterials, | |||
RecipCode = sb.ToString(), | |||
RecipeName = RecipeName | |||
}); | |||
} | |||
static NewRecipeViewModel() | |||
{ | |||
RawMaterialNames.Clear(); | |||
} | |||
private string RecipCode = string.Empty; | |||
public string RecipeName { get { return _mRecipeName; } set { _mRecipeName = value; OnPropertyChanged(); } } | |||
private string _mRecipeName; | |||
public string ErrorInfo { get { return _mErrorInfo; } set { _mErrorInfo = value; OnPropertyChanged(); } } | |||
private string _mErrorInfo; | |||
public RelayCommand AddCommand { get; set; } | |||
public RelayCommand<object> RemoveCommand { get; set; } | |||
public RelayCommand SaveCommand { get; set; } | |||
public ObservableCollection<RawMaterial> RawMaterials { get; set; } = new ObservableCollection<RawMaterial>(); | |||
public ObservableCollection<string> RawMaterialNames { get; set; } = new ObservableCollection<string>(); | |||
} | |||
public class RawMaterial : ObservableObject | |||
{ | |||
/// <summary> | |||
/// 原料名称 | |||
/// </summary> | |||
public string RawMaterialName { get { return _mRawMaterialName; } set { _mRawMaterialName = value; OnPropertyChanged(); } } | |||
private string _mRawMaterialName; | |||
/// <summary> | |||
/// 原料重量 | |||
/// </summary> | |||
public float RawMaterialWeight { get { return _mRawMaterialWeight; } set { _mRawMaterialWeight = value; OnPropertyChanged(); } } | |||
private float _mRawMaterialWeight; | |||
/// <summary> | |||
/// 原料ID | |||
/// </summary> | |||
public string RawMaterialId { get { return _mRawMaterialId; } set { _mRawMaterialId = value; OnPropertyChanged(); } } | |||
private string _mRawMaterialId; | |||
public ObservableCollection<RawMaterialModel> RawMaterials { get; set; } = new ObservableCollection<RawMaterialModel>(); | |||
public static ObservableCollection<string> RawMaterialNames { get; set; } = new ObservableCollection<string>(); | |||
} | |||
} |
@@ -9,10 +9,35 @@ using System.Collections.ObjectModel; | |||
using System.Windows; | |||
using BPASmartClient.Helper; | |||
using Microsoft.Toolkit.Mvvm.Input; | |||
using DosingSystem.Model; | |||
namespace DosingSystem.ViewModel | |||
{ | |||
public class RecipeControlViewModel : ObservableObject | |||
{ | |||
public RecipeControlViewModel() | |||
{ | |||
Recipes = Json<LocaPar>.Data.Recipes; | |||
StartCommand = new RelayCommand<object>((o) => | |||
{ | |||
if (o != null && o is string deviceName) | |||
{ | |||
Task.Run(new Action(() => | |||
{ | |||
int index = Array.FindIndex(Recipes.ToArray(), p => p.RecipeName == deviceName); | |||
if (index >= 0 && index < Recipes.Count) | |||
{ | |||
Recipes.ElementAt(index).IsEnable = false; | |||
foreach (var item in Recipes.ElementAt(index).RawMaterials) | |||
{ | |||
DeviceInquire.GetInstance.GetDevice(item.RawMaterialName)?.Start(item.RawMaterialWeight);//启动写入 | |||
} | |||
} | |||
})); | |||
} | |||
}); | |||
} | |||
public RelayCommand<object> StartCommand { get; set; } | |||
public ObservableCollection<RecipeModel> Recipes { get; set; } | |||
} | |||
} |
@@ -26,14 +26,38 @@ namespace DosingSystem.ViewModel | |||
nrv.ShowDialog(); | |||
}); | |||
SaveRecipe = new Action(() => { Json<LocaPar>.Save(); }); | |||
RemoveCommand = new RelayCommand<object>((o) => | |||
{ | |||
if (o is string str) | |||
{ | |||
var res = Json<LocaPar>.Data.Recipes.FirstOrDefault(p => p.RecipCode == str); | |||
if (res != null) Json<LocaPar>.Data.Recipes.Remove(res); | |||
} | |||
}); | |||
DetailsCommand = new RelayCommand<object>((o) => | |||
{ | |||
if (o != null && o is string str) | |||
{ | |||
ActionManage.GetInstance.CancelRegister("Details"); | |||
NewRecipeView nrv = new NewRecipeView(); | |||
ActionManage.GetInstance.Send("Details", Json<LocaPar>.Data.Recipes.FirstOrDefault(p => p.RecipCode == str)); | |||
nrv.ShowDialog(); | |||
} | |||
}); | |||
} | |||
public Action NewRecipe { get; set; } | |||
public Action SaveRecipe { get; set; } | |||
public RelayCommand<object> EditCommand { get; set; } | |||
public RelayCommand<object> LookCommand { get; set; } | |||
public RelayCommand<object> DetailsCommand { get; set; } | |||
public RelayCommand<object> RemoveCommand { get; set; } | |||
public ObservableCollection<RecipeModel> Recipes { get; set; } | |||
} | |||
} |