Browse Source

user

样式分支
NXX 2 years ago
parent
commit
939f98b785
65 changed files with 1220 additions and 301 deletions
  1. +2
    -0
      BPASmart.ConfigurationSoftware/App.xaml.cs
  2. +3
    -8
      BPASmart.ConfigurationSoftware/BPASmart.ConfigurationSoftware.csproj
  3. +15
    -15
      BPASmart.ConfigurationSoftware/BasicInformation.cs
  4. +76
    -76
      BPASmart.ConfigurationSoftware/FileHelper.cs
  5. +0
    -0
      BPASmart.ConfigurationSoftware/Images/fyf.ico
  6. +14
    -1
      BPASmart.ConfigurationSoftware/Servers/ServiceCenter.cs
  7. +0
    -0
      BPASmart.ConfigurationSoftware/View/MainWindow.xaml
  8. +0
    -0
      BPASmart.ConfigurationSoftware/View/MainWindow.xaml.cs
  9. +0
    -0
      BPASmart.ConfigurationSoftware/View/NewPageView.xaml
  10. +0
    -0
      BPASmart.ConfigurationSoftware/View/NewPageView.xaml.cs
  11. +0
    -0
      BPASmart.ConfigurationSoftware/View/NewProjectView.xaml
  12. +0
    -0
      BPASmart.ConfigurationSoftware/View/NewProjectView.xaml.cs
  13. +0
    -0
      BPASmart.ConfigurationSoftware/ViewModel/MainWindowViewModel.cs
  14. +4
    -4
      BPASmart.ConfigurationSoftware/ViewModel/NewProjectViewModel.cs
  15. +1
    -0
      BPASmart.Model/BPASmart.Model.csproj
  16. +0
    -0
      BPASmart.Model/Config/BinConfigFile.cs
  17. +0
    -0
      BPASmart.Model/Config/FileConfigModel.cs
  18. +0
    -0
      BPASmart.Model/Config/GlobalVar.cs
  19. +0
    -0
      BPASmart.Model/Config/LocalPar.cs
  20. +0
    -0
      BPASmart.Model/Config/ProjectModel.cs
  21. +19
    -0
      BPASmart.Model/ExpandMethod.cs
  22. +19
    -0
      BPASmart.Model/IRecipeMaterials.cs
  23. +12
    -0
      BPASmart.Model/Interfaces/IMessage.cs
  24. +1
    -1
      BPASmart.Model/MQTT/PublishInfo.cs
  25. +1
    -1
      BPASmart.Model/用户/LocalUser.cs
  26. +1
    -1
      BPASmart.Model/用户/UserManager.cs
  27. +1
    -1
      BPASmart.Model/配方/LocalMaterails.cs
  28. +3
    -3
      BPASmart.Model/配方/LocalRecipes.cs
  29. +2
    -2
      BPASmart.Model/配方/Order.cs
  30. +2
    -2
      BPASmart.Model/配方/Property.cs
  31. +8
    -5
      BPASmart.Model/配方/RecipeMaterials.cs
  32. +4
    -4
      BPASmart.Model/配方/Recipes.cs
  33. +3
    -3
      BPASmart.Model/配方/TechnologyProcessModel.cs
  34. +1
    -1
      BPASmart.PageLoad/BPASmart.PageLoad.csproj
  35. +3
    -3
      BPASmart.RecipeManagement/Globle/GlobleData.cs
  36. +8
    -8
      BPASmart.RecipeManagement/ViewModel/CreateOrderViewModel.cs
  37. +2
    -2
      BPASmart.RecipeManagement/ViewModel/MainWindowViewModel.cs
  38. +19
    -19
      BPASmart.RecipeManagement/ViewModel/MaterialConfigureViewModel.cs
  39. +7
    -7
      BPASmart.RecipeManagement/ViewModel/MaterialManagerViewModel.cs
  40. +2
    -2
      BPASmart.RecipeManagement/ViewModel/OrderManagerViewModel.cs
  41. +4
    -4
      BPASmart.RecipeManagement/ViewModel/PowerManagerViewModel.cs
  42. +5
    -5
      BPASmart.RecipeManagement/ViewModel/PropertySettingViewModel.cs
  43. +6
    -6
      BPASmart.RecipeManagement/ViewModel/RecipeManagerViewModel.cs
  44. +16
    -16
      BPASmart.RecipeManagement/ViewModel/RecipesConfigureViewModel.cs
  45. +9
    -9
      BPASmart.RecipeManagement/ViewModel/TechnologyProcessViewModel.cs
  46. +2
    -1
      BPASmart.Server/BPASmart.Server.csproj
  47. +21
    -10
      BPASmart.Server/CommunicationServer.cs
  48. +72
    -0
      BPASmart.Server/SqliteContext.cs
  49. +1
    -1
      BPASmart.VariableManager/BPASmart.VariableManager.csproj
  50. +32
    -5
      BPASmart.VariableManager/ViewModels/VariableConfigViewModel.cs
  51. +13
    -5
      BPASmart.VariableManager/Views/VariableConfig.xaml
  52. +167
    -0
      BPASmartClient.SCADAControl/Converters/HoneycombPanel.cs
  53. +37
    -32
      BPASmartClient.SCADAControl/CustomerControls/Silos.xaml
  54. +21
    -0
      BPASmartClient.SCADAControl/CustomerControls/TheEllipse.xaml
  55. +144
    -0
      BPASmartClient.SCADAControl/CustomerControls/TheEllipse.xaml.cs
  56. +22
    -0
      BPASmartClient.SCADAControl/CustomerControls/TheRectangle.xaml
  57. +142
    -0
      BPASmartClient.SCADAControl/CustomerControls/TheRectangle.xaml.cs
  58. +87
    -0
      BPASmartClient.SCADAControl/CustomerControls/TheWuLiaoControl.xaml
  59. +119
    -0
      BPASmartClient.SCADAControl/CustomerControls/TheWuLiaoControl.xaml.cs
  60. +2
    -0
      BPASmartClient.SCADAControl/Themes/Generic.xaml
  61. +1
    -1
      BeDesignerSCADA/Common/PropertyHelper.cs
  62. +43
    -35
      BeDesignerSCADA/Controls/MainCanvasPanel.xaml
  63. +5
    -1
      BeDesignerSCADA/Controls/MainCanvasPanel.xaml.cs
  64. +15
    -0
      BeDesignerSCADA/Themes/Styles.xaml
  65. +1
    -1
      ComputerTestDemo/ComputerTestDemo.csproj

+ 2
- 0
BPASmart.ConfigurationSoftware/App.xaml.cs View File

@@ -21,6 +21,7 @@ namespace BPASmart.ConfigurationSoftware
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
Json<LocalPar>.Read();
if (e.Args != null && e.Args.Length == 1)
{
var res = e.Args[0];
@@ -34,6 +35,7 @@ namespace BPASmart.ConfigurationSoftware
protected override void OnExit(ExitEventArgs e)
{
base.OnExit(e);
Json<LocalPar>.Save();
}
}
}

+ 3
- 8
BPASmart.ConfigurationSoftware/BPASmart.ConfigurationSoftware.csproj View File

@@ -6,7 +6,7 @@
<Nullable>enable</Nullable>
<UseWPF>true</UseWPF>
<UseWindowsForms>true</UseWindowsForms>
<ApplicationIcon>fyf.ico</ApplicationIcon>
<ApplicationIcon>Images\fyf.ico</ApplicationIcon>
</PropertyGroup>

<ItemGroup>
@@ -14,13 +14,13 @@
</ItemGroup>

<ItemGroup>
<Content Include="fyf.ico">
<Content Include="Images\fyf.ico">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>

<ItemGroup>
<PackageReference Include="BPA.Helper" Version="1.0.11" />
<PackageReference Include="BPA.Helper" Version="1.0.15" />
</ItemGroup>

<ItemGroup>
@@ -32,11 +32,6 @@
<ProjectReference Include="..\BPASmart.VariableManager\BPASmart.VariableManager.csproj" />
</ItemGroup>

<ItemGroup>
<Folder Include="ViewModel\" />
<Folder Include="View\" />
</ItemGroup>

<ItemGroup>
<Reference Include="Interop.IWshRuntimeLibrary">
<HintPath>..\BPASmartClient.Helper\obj\Debug\net6.0\Interop.IWshRuntimeLibrary.dll</HintPath>


+ 15
- 15
BPASmart.ConfigurationSoftware/BasicInformation.cs View File

@@ -1,18 +1,18 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
//using System;
//using System.Collections.Generic;
//using System.Linq;
//using System.Text;
//using System.Threading.Tasks;

namespace BPASmart.ConfigurationSoftware
{
public class BasicInformation
{
/// <summary>
/// 项目上次保存的目录
/// </summary>
public string ProjectDefaultPath { get; set; } = string.Empty;
//namespace BPASmart.ConfigurationSoftware
//{
// public class BasicInformation
// {
// /// <summary>
// /// 项目上次保存的目录
// /// </summary>
// public string ProjectDefaultPath { get; set; } = string.Empty;


}
}
// }
//}

+ 76
- 76
BPASmart.ConfigurationSoftware/FileHelper.cs View File

@@ -1,89 +1,89 @@
using BPA.Helper;
using BPASmart.Model;
using Microsoft.Win32;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
//using BPA.Helper;
//using BPASmart.Model;
//using Microsoft.Win32;
//using System;
//using System.Collections.Generic;
//using System.IO;
//using System.Linq;
//using System.Runtime.InteropServices;
//using System.Text;
//using System.Threading.Tasks;
//using System.Windows.Forms;

namespace BPASmart.ConfigurationSoftware
{
public class FileHelper
{
//namespace BPASmart.ConfigurationSoftware
//{
// public class FileHelper
// {

private volatile static FileHelper _Instance;
public static FileHelper GetInstance => _Instance ?? (_Instance = new FileHelper());
private FileHelper() { }
// private volatile static FileHelper _Instance;
// public static FileHelper GetInstance => _Instance ?? (_Instance = new FileHelper());
// private FileHelper() { }

public void RegisterOpenFileType()
{
string icoFile = System.Windows.Forms.Application.StartupPath + $"\\fyf.ico";
string DirectoryPath = $"{Json<ProjectModel>.Data.ProjectPath}\\Images";
Directory.CreateDirectory(DirectoryPath);
File.Copy(icoFile, $"{DirectoryPath}\\fyf.ico");
RegisterFileType(".project", "HBL", ".project", System.Windows.Forms.Application.ExecutablePath, $"{DirectoryPath}\\fyf.ico");
}
// public void RegisterOpenFileType()
// {
// string icoFile = System.Windows.Forms.Application.StartupPath + $"\\Images\\fyf.ico";
// string DirectoryPath = $"{Json<ProjectModel>.Data.ProjectPath}\\Images";
// Directory.CreateDirectory(DirectoryPath);
// File.Copy(icoFile, $"{DirectoryPath}\\fyf.ico");
// RegisterFileType(".project", "HBL", ".project", System.Windows.Forms.Application.ExecutablePath, $"{DirectoryPath}\\fyf.ico");
// }

private void RegisterFileType(string typeName, string fileType, string fileContent, string app, string ico)
{
string toolPath = app;//工具启动路径
string extension = typeName;//fileType = "自定义文件类型";
// private void RegisterFileType(string typeName, string fileType, string fileContent, string app, string ico)
// {
// string toolPath = app;//工具启动路径
// string extension = typeName;//fileType = "自定义文件类型";

//fileContent = "AAAA";
//获取信息
RegistryKey registryKey = Registry.ClassesRoot.OpenSubKey(extension);
if (registryKey != null)
{
try
{
RegistryKey _Regkey = Registry.ClassesRoot.OpenSubKey("", true);
// //fileContent = "AAAA";
// //获取信息
// RegistryKey registryKey = Registry.ClassesRoot.OpenSubKey(extension);
// if (registryKey != null)
// {
// try
// {
// RegistryKey _Regkey = Registry.ClassesRoot.OpenSubKey("", true);

RegistryKey _VRPkey = _Regkey.OpenSubKey(extension);
if (_VRPkey != null) _Regkey.DeleteSubKeyTree(extension, true);
if (_VRPkey != null) _Regkey.DeleteSubKeyTree("Exec");
}
catch (Exception e)
{
// RegistryKey _VRPkey = _Regkey.OpenSubKey(extension);
// if (_VRPkey != null) _Regkey.DeleteSubKeyTree(extension, false);
// if (_VRPkey != null) _Regkey.DeleteSubKeyTree("Exec");
// }
// catch (Exception e)
// {

}
}
// }
// }

if (registryKey != null && registryKey.OpenSubKey("shell") != null && registryKey.OpenSubKey("shell").OpenSubKey("open") != null &&
registryKey.OpenSubKey("shell").OpenSubKey("open").OpenSubKey("command") != null)
{
var varSub = registryKey.OpenSubKey("shell").OpenSubKey("open").OpenSubKey("command");
var varValue = varSub.GetValue("");
// if (registryKey != null && registryKey.OpenSubKey("shell") != null && registryKey.OpenSubKey("shell").OpenSubKey("open") != null &&
// registryKey.OpenSubKey("shell").OpenSubKey("open").OpenSubKey("command") != null)
// {
// var varSub = registryKey.OpenSubKey("shell").OpenSubKey("open").OpenSubKey("command");
// var varValue = varSub.GetValue("");

if (Equals(varValue, toolPath + " \"%1\""))
{
return;
}
}
// if (Equals(varValue, toolPath + " \"%1\""))
// {
// return;
// }
// }

//文件注册
registryKey = Registry.ClassesRoot.CreateSubKey(extension);
registryKey.SetValue("", fileType);
registryKey.SetValue("Content Type", fileContent);
//设置默认图标
RegistryKey iconKey = registryKey.CreateSubKey("DefaultIcon");
//iconKey.SetValue("", Application.StartupPath + $"\\{ico}.ico");
iconKey.SetValue("", ico);
iconKey.Close();
//设置默认打开程序路径
registryKey = registryKey.CreateSubKey("shell\\open\\command");
registryKey.SetValue("", toolPath + " \"%1\"");
//关闭
registryKey.Close();
SHChangeNotify(0x8000000, 0, IntPtr.Zero, IntPtr.Zero);
}
// //文件注册
// registryKey = Registry.ClassesRoot.CreateSubKey(extension);
// registryKey.SetValue("", fileType);
// registryKey.SetValue("Content Type", fileContent);
// //设置默认图标
// RegistryKey iconKey = registryKey.CreateSubKey("DefaultIcon");
// //iconKey.SetValue("", Application.StartupPath + $"\\{ico}.ico");
// iconKey.SetValue("", ico);
// iconKey.Close();
// //设置默认打开程序路径
// registryKey = registryKey.CreateSubKey("shell\\open\\command");
// registryKey.SetValue("", toolPath + " \"%1\"");
// //关闭
// registryKey.Close();
// SHChangeNotify(0x8000000, 0, IntPtr.Zero, IntPtr.Zero);
// }

[DllImport("shell32.dll")]
public static extern void SHChangeNotify(uint wEventId, uint uFlags, IntPtr dwItem1, IntPtr dwItem2);
}
// [DllImport("shell32.dll")]
// public static extern void SHChangeNotify(uint wEventId, uint uFlags, IntPtr dwItem1, IntPtr dwItem2);
// }

}
//}


BPASmart.ConfigurationSoftware/fyf.ico → BPASmart.ConfigurationSoftware/Images/fyf.ico View File


BPASmart.ConfigurationSoftware/ServiceCenter.cs → BPASmart.ConfigurationSoftware/Servers/ServiceCenter.cs View File

@@ -167,11 +167,24 @@ namespace BPASmart.ConfigurationSoftware
ProjectNameChange?.Invoke(objModel.ProjectName);
FileConfigModel.ConstPath = $"{path}";
Save();
FileHelper.GetInstance.RegisterOpenFileType();
//FileHelper.GetInstance.RegisterOpenFileType();
RegisterOpenFileType();
}
}
}

/// <summary>
/// 注册使用默认应用程序打开自定义文件
/// </summary>
private void RegisterOpenFileType()
{
string icoFile = System.Windows.Forms.Application.StartupPath + $"\\Images\\fyf.ico";
string DirectoryPath = $"{Json<ProjectModel>.Data.ProjectPath}\\Images";
Directory.CreateDirectory(DirectoryPath);
File.Copy(icoFile, $"{DirectoryPath}\\fyf.ico");
SystemHelper.GetInstance.RegisterOpenFileType("project", "HBL", System.Windows.Forms.Application.ExecutablePath, $"{DirectoryPath}\\fyf.ico");
}

/// <summary>
/// 打开新建页面弹窗
/// </summary>

BPASmart.ConfigurationSoftware/MainWindow.xaml → BPASmart.ConfigurationSoftware/View/MainWindow.xaml View File


BPASmart.ConfigurationSoftware/MainWindow.xaml.cs → BPASmart.ConfigurationSoftware/View/MainWindow.xaml.cs View File


BPASmart.ConfigurationSoftware/NewPageView.xaml → BPASmart.ConfigurationSoftware/View/NewPageView.xaml View File


BPASmart.ConfigurationSoftware/NewPageView.xaml.cs → BPASmart.ConfigurationSoftware/View/NewPageView.xaml.cs View File


BPASmart.ConfigurationSoftware/NewProjectView.xaml → BPASmart.ConfigurationSoftware/View/NewProjectView.xaml View File


BPASmart.ConfigurationSoftware/NewProjectView.xaml.cs → BPASmart.ConfigurationSoftware/View/NewProjectView.xaml.cs View File


BPASmart.ConfigurationSoftware/MainWindowViewModel.cs → BPASmart.ConfigurationSoftware/ViewModel/MainWindowViewModel.cs View File


BPASmart.ConfigurationSoftware/NewProjectViewModel.cs → BPASmart.ConfigurationSoftware/ViewModel/NewProjectViewModel.cs View File

@@ -16,16 +16,16 @@ namespace BPASmart.ConfigurationSoftware
{
public NewProjectViewModel()
{
Json<BasicInformation>.Read();
NewData.ProjectPath = Json<BasicInformation>.Data.ProjectDefaultPath;
//Json<BasicInformation>.Read();
NewData.ProjectPath = Json<LocalPar>.Data.ProjectDefaultPath;
OpenBrowserDialogCommand = new RelayCommand(() =>
{
FolderBrowserDialog folderBrowserDialog = new FolderBrowserDialog();
if (folderBrowserDialog.ShowDialog() == DialogResult.OK)
{
NewData.ProjectPath = folderBrowserDialog.SelectedPath;
Json<BasicInformation>.Data.ProjectDefaultPath = NewData.ProjectPath;
Json<BasicInformation>.Save();
Json<LocalPar>.Data.ProjectDefaultPath = NewData.ProjectPath;
//Json<LocalPar>.Save();
}
});


+ 1
- 0
BPASmart.Model/BPASmart.Model.csproj View File

@@ -7,6 +7,7 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="6.0.9" />
<PackageReference Include="Microsoft.Toolkit.Mvvm" Version="7.1.2" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
<PackageReference Include="System.IO.Ports" Version="6.0.0" />


BPASmart.Model/BinConfigFile.cs → BPASmart.Model/Config/BinConfigFile.cs View File


BPASmart.Model/FileConfigModel.cs → BPASmart.Model/Config/FileConfigModel.cs View File


BPASmart.Model/GlobalVar.cs → BPASmart.Model/Config/GlobalVar.cs View File


BPASmart.Model/LocalPar.cs → BPASmart.Model/Config/LocalPar.cs View File


BPASmart.Model/ProjectModel.cs → BPASmart.Model/Config/ProjectModel.cs View File


+ 19
- 0
BPASmart.Model/ExpandMethod.cs View File

@@ -37,6 +37,25 @@ namespace BPASmart.Model
return 1;
}

public static string ToSystemData(this EDataType eData)
{
switch (eData)
{
case EDataType.Bool: return "bool";
case EDataType.Byte: return "byte";
case EDataType.Int: return "short";
case EDataType.Word: return "ushort";
case EDataType.Dint: return "int";
case EDataType.Dword: return "uint";
case EDataType.Float: return "float";
case EDataType.Double: return "double";
case EDataType.String: return "string";
default:
break;
}
return default;
}

/// <summary>
/// 获取Modbus Tcp 连续变量数据的组对象
/// </summary>


+ 19
- 0
BPASmart.Model/IRecipeMaterials.cs View File

@@ -0,0 +1,19 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using BPASmart.Model;

namespace BPASmart.Model
{
public interface IRecipeMaterials
{
Task<bool> AddAsync(RecipeMaterials recipeMaterials);
Task<bool> AddRangeAsync(RecipeMaterials[] recipeMaterials);
Task<bool> UpdateAsync(RecipeMaterials recipeMaterials);
Task<bool> DeleteAsync(string ID);
Task<List<RecipeMaterials>> GetData();
}
}

+ 12
- 0
BPASmart.Model/Interfaces/IMessage.cs View File

@@ -0,0 +1,12 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace BPASmart.Model
{
public interface IMessage
{
}
}

+ 1
- 1
BPASmart.Model/MQTT/PublishInfo.cs View File

@@ -6,7 +6,7 @@ using System.Threading.Tasks;

namespace BPASmart.Model
{
public class PublishInfo
public class PublishInfo : IMessage
{
public List<PublishModel> PublishModels { get; set; } = new List<PublishModel>();
}


+ 1
- 1
BPASmart.Model/用户/LocalUser.cs View File

@@ -5,7 +5,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace BPASmart.Model.用户
namespace BPASmart.Model
{
public class LocalUser
{


+ 1
- 1
BPASmart.Model/用户/UserManager.cs View File

@@ -5,7 +5,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace BPASmart.Model.用户
namespace BPASmart.Model
{
public class UserManager
{


+ 1
- 1
BPASmart.Model/配方/LocalMaterails.cs View File

@@ -5,7 +5,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace BPASmart.Model.配方
namespace BPASmart.Model
{
public class LocalMaterails
{


+ 3
- 3
BPASmart.Model/配方/LocalRecipes.cs View File

@@ -6,11 +6,11 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace BPASmart.Model.配方
namespace BPASmart.Model
{
public class LocalRecipes
public class LocalRecipes
{
public ObservableCollection<Recipes> locaRecipes { get; set; } = new ObservableCollection<Recipes>();
}
}

+ 2
- 2
BPASmart.Model/配方/Order.cs View File

@@ -6,9 +6,9 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace BPASmart.Model.配方
namespace BPASmart.Model
{
public class Order:ObservableObject
public class Order : ObservableObject
{
/// <summary>
/// 订单ID


+ 2
- 2
BPASmart.Model/配方/Property.cs View File

@@ -5,9 +5,9 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace BPASmart.Model.配方
namespace BPASmart.Model
{
public class Property:ObservableObject
public class Property : ObservableObject
{
public string PropertyId { get { return _propertyId; } set { _propertyId = value; OnPropertyChanged(); } }
private string _propertyId;


+ 8
- 5
BPASmart.Model/配方/RecipeMaterials.cs View File

@@ -2,13 +2,14 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace BPASmart.Model.配方
namespace BPASmart.Model
{
public class RecipeMaterials:ObservableObject
public class RecipeMaterials : ObservableObject
{
/// <summary>
/// 原料ID
@@ -18,7 +19,7 @@ namespace BPASmart.Model.配方
/// <summary>
/// 物料名称
/// </summary>
public string Name { get { return _name; } set { _name = value;OnPropertyChanged(); } }
public string Name { get { return _name; } set { _name = value; OnPropertyChanged(); } }
private string _name;
/// <summary>
/// 物料种类
@@ -28,22 +29,24 @@ namespace BPASmart.Model.配方
/// <summary>
/// 物料重量
/// </summary>
[NotMapped]
public int MaterialWeight { get { return _materialWeight; } set { _materialWeight = value; OnPropertyChanged(); } }
private int _materialWeight;
/// <summary>
/// 原料位置
/// </summary>
public string MaterialPosion { get { return _materialPosion; } set { _materialPosion = value;OnPropertyChanged(); } }
public string MaterialPosion { get { return _materialPosion; } set { _materialPosion = value; OnPropertyChanged(); } }
private string _materialPosion;

/// <summary>
/// 自定义原料属性集合
/// </summary>
[NotMapped]
public ObservableCollection<Property> PropertyCollections = new ObservableCollection<Property>();
}

public enum MaterialType
{
{
无 = 0,
干料 = 1,
湿料 = 2,


+ 4
- 4
BPASmart.Model/配方/Recipes.cs View File

@@ -6,9 +6,9 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace BPASmart.Model.配方
namespace BPASmart.Model
{
public class Recipes:ObservableObject
public class Recipes : ObservableObject
{
/// <summary>
/// 配方ID
@@ -38,8 +38,8 @@ namespace BPASmart.Model.配方
/// </summary>
public ObservableCollection<RecipeMaterials> recipeMaterials { get; set; }

public ObservableCollection<TechnologyProcessModel> TechnologyProcessModels { get; set; } = new ObservableCollection<TechnologyProcessModel>();
public ObservableCollection<TechnologyProcessModel> TechnologyProcessModels { get; set; } = new ObservableCollection<TechnologyProcessModel>();

}



+ 3
- 3
BPASmart.Model/配方/TechnologyProcessModel.cs View File

@@ -5,15 +5,15 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace BPASmart.Model.配方
namespace BPASmart.Model
{
public class TechnologyProcessModel:ObservableObject
public class TechnologyProcessModel : ObservableObject
{

/// <summary>
/// 工艺步骤
/// </summary>
public string Step { get { return _step; } set { _step = value; OnPropertyChanged(); } }
public string Step { get { return _step; } set { _step = value; OnPropertyChanged(); } }
private string _step;

/// <summary>


+ 1
- 1
BPASmart.PageLoad/BPASmart.PageLoad.csproj View File

@@ -8,7 +8,7 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="BPA.Helper" Version="1.0.11" />
<PackageReference Include="BPA.Helper" Version="1.0.15" />
</ItemGroup>

<ItemGroup>


+ 3
- 3
BPASmart.RecipeManagement/Globle/GlobleData.cs View File

@@ -1,4 +1,4 @@
using BPASmart.Model.配方;
using BPASmart.Model;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
@@ -18,7 +18,7 @@ namespace BPASmart.RecipeManagement.Globle
/// <summary>
/// 修改配方传值
/// </summary>
public static Recipes ChangeRecipes = new Recipes();
public static Recipes ChangeRecipes = new Recipes();

/// <summary>
///
@@ -28,6 +28,6 @@ namespace BPASmart.RecipeManagement.Globle
/// <summary>
/// 配方的工艺流程传值
/// </summary>
public static Recipes recipeTechnologyProcess = new Recipes();
public static Recipes recipeTechnologyProcess = new Recipes();
}
}

+ 8
- 8
BPASmart.RecipeManagement/ViewModel/CreateOrderViewModel.cs View File

@@ -1,4 +1,4 @@
using BPASmart.Model.配方;
using BPASmart.Model;
using BPASmartClient.Helper;
using Microsoft.Toolkit.Mvvm.ComponentModel;
using Microsoft.Toolkit.Mvvm.Input;
@@ -9,10 +9,10 @@ using System.Linq;

namespace BPASmart.RecipeManagement.ViewModel
{
public class CreateOrderViewModel: ObservableObject
public class CreateOrderViewModel : ObservableObject
{

public ObservableCollection<Recipes> recipes { get; set; } = new ObservableCollection<Recipes>();
public ObservableCollection<Recipes> recipes { get; set; } = new ObservableCollection<Recipes>();

public ObservableCollection<string> recipesName { get; set; } = new ObservableCollection<string>();

@@ -24,8 +24,8 @@ namespace BPASmart.RecipeManagement.ViewModel

private void Delete(object o)
{
if(o == null) return;
if(o is string id)
if (o == null) return;
if (o is string id)
{
var res = recipes.FirstOrDefault(x => x.ID == id);
recipes.Remove(res);
@@ -44,15 +44,15 @@ namespace BPASmart.RecipeManagement.ViewModel
});
ActionManage.GetInstance.Send("CloseCreateOrderView");
});
DeleteCommand = new RelayCommand<object>(Delete);

AddRecipeCommand = new RelayCommand(() =>
{
recipes.Add(new Recipes() { ID = Guid.NewGuid().ToString() ,RecipeCount =1,});
recipes.Add(new Recipes() { ID = Guid.NewGuid().ToString(), RecipeCount = 1, });
});

foreach( var item in Json<LocalRecipes>.Data.locaRecipes )
foreach (var item in Json<LocalRecipes>.Data.locaRecipes)
{
recipesName.Add(item.Name);
}


+ 2
- 2
BPASmart.RecipeManagement/ViewModel/MainWindowViewModel.cs View File

@@ -1,4 +1,4 @@
using BPASmart.Model.配方;
using BPASmart.Model;
using BPASmartClient.Helper;
using Microsoft.Toolkit.Mvvm.ComponentModel;
using System;
@@ -9,7 +9,7 @@ using System.Threading.Tasks;

namespace BPASmart.RecipeManagement.ViewModel
{
public class MainWindowViewModel: ObservableObject
public class MainWindowViewModel : ObservableObject
{

public MainWindowViewModel()


+ 19
- 19
BPASmart.RecipeManagement/ViewModel/MaterialConfigureViewModel.cs View File

@@ -1,4 +1,4 @@
using BPASmart.Model.配方;
using BPASmart.Model;
using BPASmart.RecipeManagement.Globle;
using BPASmartClient.Helper;
using Microsoft.Toolkit.Mvvm.ComponentModel;
@@ -12,16 +12,16 @@ using System.Threading.Tasks;

namespace BPASmart.RecipeManagement.ViewModel
{
public class MaterialConfigureViewModel:ObservableObject
public class MaterialConfigureViewModel : ObservableObject
{
public ObservableCollection<Property> currentProperty { get; set; } = new ObservableCollection<Property>();

public string MaterialName { get { return _materialName; } set { _materialName = value; OnPropertyChanged(); } }
public string MaterialName { get { return _materialName; } set { _materialName = value; OnPropertyChanged(); } }
private string _materialName;

public ObservableCollection<MaterialType> MaterialTypes { get; set; } = new ObservableCollection<MaterialType>();

public MaterialType MaterialType { get{ return _materialType; } set { _materialType = value; OnPropertyChanged(); } }
public MaterialType MaterialType { get { return _materialType; } set { _materialType = value; OnPropertyChanged(); } }
private MaterialType _materialType = 0;

public string MaterialPosion { get { return _materialPosion; } set { _materialPosion = value; OnPropertyChanged(); } }
@@ -61,46 +61,46 @@ namespace BPASmart.RecipeManagement.ViewModel
MaterialName = GlobleData.ChangeMaterail.Name;
MaterialType = GlobleData.ChangeMaterail.MaterialType;
MaterialPosion = GlobleData.ChangeMaterail.MaterialPosion;
foreach(var item in currentProperty)
foreach (var item in currentProperty)
{
var res = GlobleData.ChangeMaterail.PropertyCollections.FirstOrDefault(p => p.PropertyId == item.PropertyId);
if (res != null)
{
item.PropertyValue = res.PropertyValue;
}
}
}

foreach(MaterialType item in Enum.GetValues(typeof(MaterialType)))
foreach (MaterialType item in Enum.GetValues(typeof(MaterialType)))
{
MaterialTypes.Add(item);
}



SaveCommand = new RelayCommand(() =>
{
if(MaterialName == null)
if (MaterialName == null)
{
ErrorMessage = "原料名称不能为空";
return;
}
if(GlobleData.ChangeMaterail!=null)//编辑原料
{
var res = Json<LocalMaterails>.Data.locaMaterails.FirstOrDefault(p=>p.ID == GlobleData.ChangeMaterail.ID);
if (res != null)
if (GlobleData.ChangeMaterail != null)//编辑原料
{
var res = Json<LocalMaterails>.Data.locaMaterails.FirstOrDefault(p => p.ID == GlobleData.ChangeMaterail.ID);
if (res != null)
{
if (MaterialName != res.Name )//修改了原料名称
if (MaterialName != res.Name)//修改了原料名称
{
if (Json<LocalMaterails>.Data.locaMaterails.FirstOrDefault(p => p.Name == MaterialName) != null)
{
ErrorMessage = "原料名称已存在";
return ;
return;
}
}
if(MaterialPosion != res.MaterialPosion)//修改了原料位置
if (MaterialPosion != res.MaterialPosion)//修改了原料位置
{
if (Json<LocalMaterails>.Data.locaMaterails.FirstOrDefault(p => p.MaterialPosion == MaterialPosion) != null)
{
@@ -116,7 +116,7 @@ namespace BPASmart.RecipeManagement.ViewModel
}
else //添加新原料
{
if(Json<LocalMaterails>.Data.locaMaterails != null)
if (Json<LocalMaterails>.Data.locaMaterails != null)
{
var res = Json<LocalMaterails>.Data.locaMaterails.FirstOrDefault(p => p.Name == MaterialName);
if (res != null)
@@ -124,7 +124,7 @@ namespace BPASmart.RecipeManagement.ViewModel
ErrorMessage = "原料名称已存在";
return;
}
var item = Json<LocalMaterails>.Data.locaMaterails.FirstOrDefault(p=>p.MaterialPosion == MaterialPosion);
var item = Json<LocalMaterails>.Data.locaMaterails.FirstOrDefault(p => p.MaterialPosion == MaterialPosion);
if (item != null)
{
ErrorMessage = "原料位置重复";
@@ -134,7 +134,7 @@ namespace BPASmart.RecipeManagement.ViewModel
else
{
AddMaterials();
}
}
}
Json<LocalMaterails>.Save();
ActionManage.GetInstance.Send("CloseMaterialConfigureView");


+ 7
- 7
BPASmart.RecipeManagement/ViewModel/MaterialManagerViewModel.cs View File

@@ -5,7 +5,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Collections.ObjectModel;
using BPASmart.Model.配方;
using BPASmart.Model;
using Microsoft.Toolkit.Mvvm.Input;
using BPASmart.RecipeManagement.View;
using System.Windows.Controls;
@@ -14,7 +14,7 @@ using BPASmartClient.Helper;

namespace BPASmart.RecipeManagement.ViewModel
{
public class MaterialManagerViewModel:ObservableObject
public class MaterialManagerViewModel : ObservableObject
{
/// <summary>
/// 原料集合
@@ -24,12 +24,12 @@ namespace BPASmart.RecipeManagement.ViewModel
public RelayCommand CreateMaterailCommand { get; set; }
public RelayCommand<object> EditMaterailCommand { get; set; }
public RelayCommand<object> DeleteMaterailCommand { get; set; }

private void EditMaterail(object o)
{
if(o == null) return;
if(o is int item && item >= 0)
if (o == null) return;
if (o is int item && item >= 0)
{
GlobleData.ChangeMaterail = new RecipeMaterials();
GlobleData.ChangeMaterail = MaterialList[item];
@@ -41,7 +41,7 @@ namespace BPASmart.RecipeManagement.ViewModel
private void DeleteMaterail(object o)
{
if (o == null) return;
if (o is int item && item >= 0)
if (o is int item && item >= 0)
{
MaterialList.RemoveAt(item);
Json<LocalMaterails>.Save();
@@ -50,7 +50,7 @@ namespace BPASmart.RecipeManagement.ViewModel

public MaterialManagerViewModel()
{

CreateMaterailCommand = new RelayCommand(() =>
{


+ 2
- 2
BPASmart.RecipeManagement/ViewModel/OrderManagerViewModel.cs View File

@@ -1,4 +1,4 @@
using BPASmart.Model.配方;
using BPASmart.Model;
using BPASmart.RecipeManagement.View;
using Microsoft.Toolkit.Mvvm.ComponentModel;
using Microsoft.Toolkit.Mvvm.Input;
@@ -11,7 +11,7 @@ using System.Threading.Tasks;

namespace BPASmart.RecipeManagement.ViewModel
{
public class OrderManagerViewModel:ObservableObject
public class OrderManagerViewModel : ObservableObject
{
/// <summary>
/// 订单集合


+ 4
- 4
BPASmart.RecipeManagement/ViewModel/PowerManagerViewModel.cs View File

@@ -1,4 +1,4 @@
using BPASmart.Model.配方;
using BPASmart.Model;
using BPASmartClient.Helper;
using Microsoft.Toolkit.Mvvm.ComponentModel;
using Microsoft.Toolkit.Mvvm.Input;
@@ -11,7 +11,7 @@ using System.Threading.Tasks;

namespace BPASmart.RecipeManagement.ViewModel
{
public class PowerManagerViewModel:ObservableObject
public class PowerManagerViewModel : ObservableObject
{
public ObservableCollection<string> UserName { get; set; } = new ObservableCollection<string>();
/// <summary>
@@ -66,7 +66,7 @@ namespace BPASmart.RecipeManagement.ViewModel
UserMaterials.Clear();
foreach (RecipeMaterials item in AllMaterials)
{
UserMaterials.Add(item);
UserMaterials.Add(item);
}

}
@@ -78,7 +78,7 @@ namespace BPASmart.RecipeManagement.ViewModel
UserRecipes.Add(item);
}
}
}

private void AddMaterial(object o)


+ 5
- 5
BPASmart.RecipeManagement/ViewModel/PropertySettingViewModel.cs View File

@@ -1,4 +1,4 @@
using BPASmart.Model.配方;
using BPASmart.Model;
using BPASmartClient.Helper;
using Microsoft.Toolkit.Mvvm.ComponentModel;
using Microsoft.Toolkit.Mvvm.Input;
@@ -11,7 +11,7 @@ using System.Threading.Tasks;

namespace BPASmart.RecipeManagement.ViewModel
{
public class PropertySettingViewModel:ObservableObject
public class PropertySettingViewModel : ObservableObject
{
public ObservableCollection<Property> properties { get; set; } = Json<LocalMaterails>.Data.PorpertyCollections;

@@ -31,7 +31,7 @@ namespace BPASmart.RecipeManagement.ViewModel
private void Delete(object o)
{
if (o == null) return;
if(o is string id)
if (o is string id)
{
var res = properties.FirstOrDefault(p => p.PropertyId == id);
if (res != null)
@@ -45,7 +45,7 @@ namespace BPASmart.RecipeManagement.ViewModel
{
SaveCommand = new RelayCommand(() =>
{
if(PropertyName == null)
if (PropertyName == null)
{
ErrorName = "属性名称不能为空";
return;
@@ -55,7 +55,7 @@ namespace BPASmart.RecipeManagement.ViewModel
ErrorName = "请添加属性说明";
return;
}
if(properties.FirstOrDefault(p=>p.PropertyName == PropertyName) != null)
if (properties.FirstOrDefault(p => p.PropertyName == PropertyName) != null)
{
ErrorName = "属性名重复";
return;


+ 6
- 6
BPASmart.RecipeManagement/ViewModel/RecipeManagerViewModel.cs View File

@@ -1,4 +1,4 @@
using BPASmart.Model.配方;
using BPASmart.Model;
using BPASmart.RecipeManagement.View;
using BPASmartClient.Helper;
using BPASmartClient.RecipeManagement.View;
@@ -13,7 +13,7 @@ using System.Threading.Tasks;

namespace BPASmart.RecipeManagement.ViewModel
{
public class RecipeManagerViewModel:ObservableObject
public class RecipeManagerViewModel : ObservableObject
{
public ObservableCollection<Recipes> RecipeList { get; set; } = Json<LocalRecipes>.Data.locaRecipes;

@@ -26,7 +26,7 @@ namespace BPASmart.RecipeManagement.ViewModel
private void EditRecipe(object o)
{
if (o == null) return;
if (o is int item && item >= 0)
if (o is int item && item >= 0)
{
Globle.GlobleData.ChangeRecipes = new Recipes();
Globle.GlobleData.ChangeRecipes = RecipeList[item];
@@ -48,16 +48,16 @@ namespace BPASmart.RecipeManagement.ViewModel
private void PecipeSetting(object o)
{
if (o == null) return;
if (o is string id )
if (o is string id)
{
var res = Json<LocalRecipes>.Data.locaRecipes.FirstOrDefault(p=>p.ID == id);
var res = Json<LocalRecipes>.Data.locaRecipes.FirstOrDefault(p => p.ID == id);
if (res != null)
{
Globle.GlobleData.recipeTechnologyProcess = null;
Globle.GlobleData.recipeTechnologyProcess = res;
TechnologyProcess technologyProcess = new TechnologyProcess();
technologyProcess.ShowDialog();
}
}
}


+ 16
- 16
BPASmart.RecipeManagement/ViewModel/RecipesConfigureViewModel.cs View File

@@ -1,4 +1,4 @@
using BPASmart.Model.配方;
using BPASmart.Model;
using BPASmartClient.Helper;
using Microsoft.Toolkit.Mvvm.ComponentModel;
using Microsoft.Toolkit.Mvvm.Input;
@@ -11,7 +11,7 @@ using System.Threading.Tasks;

namespace BPASmart.RecipeManagement.ViewModel
{
public class RecipesConfigureViewModel:ObservableObject
public class RecipesConfigureViewModel : ObservableObject
{
public ObservableCollection<RecipeMaterials> recipeMaterials { get; set; } = new ObservableCollection<RecipeMaterials>();

@@ -26,7 +26,7 @@ namespace BPASmart.RecipeManagement.ViewModel
public string RecipeName { get { return _repiceName; } set { _repiceName = value; OnPropertyChanged(); } }
private string _repiceName;



public string ErrorMessage { get { return _errorMessage; } set { _errorMessage = value; OnPropertyChanged(); } }
@@ -37,13 +37,13 @@ namespace BPASmart.RecipeManagement.ViewModel
public RelayCommand SaveCommand { get; set; }

public RelayCommand<object> DeleteCommand { get; set; }
private void Delete(object o)
{
if (o == null) return;
if(o is string id)
if (o is string id)
{
var res = recipeMaterials.FirstOrDefault(p=>p.ID == id);
var res = recipeMaterials.FirstOrDefault(p => p.ID == id);
if (res != null) recipeMaterials.Remove(res);
}
}
@@ -60,17 +60,17 @@ namespace BPASmart.RecipeManagement.ViewModel
});
});


SaveCommand = new RelayCommand(() =>
{
if(RecipeName == null)
if (RecipeName == null)
{
ErrorMessage = "配方名称为空";
return;
}
if (Globle.GlobleData.ChangeRecipes!=null)
if (Globle.GlobleData.ChangeRecipes != null)
{
var res = Json<LocalRecipes>.Data.locaRecipes.FirstOrDefault(p => p.ID == Globle.GlobleData.ChangeRecipes.ID);
res.recipeMaterials = recipeMaterials;
@@ -84,9 +84,9 @@ namespace BPASmart.RecipeManagement.ViewModel
ErrorMessage = "配方名称已存在";
return;
}
Json<LocalRecipes>.Data.locaRecipes.Add(new Recipes
{
ID = Guid.NewGuid().ToString() ,
Json<LocalRecipes>.Data.locaRecipes.Add(new Recipes
{
ID = Guid.NewGuid().ToString(),
Name = RecipeName,
recipeMaterials = recipeMaterials
});
@@ -104,12 +104,12 @@ namespace BPASmart.RecipeManagement.ViewModel
materialsName.Add(materail.Name);
}
}
if(Globle.GlobleData.ChangeRecipes != null)
if (Globle.GlobleData.ChangeRecipes != null)
{
RecipeName = Globle.GlobleData.ChangeRecipes.Name.ToString();

recipeMaterials = Globle.GlobleData.ChangeRecipes.recipeMaterials;
recipeMaterials = Globle.GlobleData.ChangeRecipes.recipeMaterials;
}
}
}


+ 9
- 9
BPASmart.RecipeManagement/ViewModel/TechnologyProcessViewModel.cs View File

@@ -1,4 +1,4 @@
using BPASmart.Model.配方;
using BPASmart.Model;
using BPASmartClient.Helper;
using Microsoft.Toolkit.Mvvm.ComponentModel;
using Microsoft.Toolkit.Mvvm.Input;
@@ -11,18 +11,18 @@ using System.Threading.Tasks;

namespace BPASmart.RecipeManagement.ViewModel
{
public class TechnologyProcessViewModel:ObservableObject
public class TechnologyProcessViewModel : ObservableObject
{
public static int currentItemId;

public int Id { get { return _id; } set { _id = value; OnPropertyChanged(); } }
private int _id = 0;
public ObservableCollection<TechnologyProcessModel> technologyProcessModels { get; set; } = new ObservableCollection<TechnologyProcessModel>();
public ObservableCollection<TechnologyProcessModel> technologyProcessModels { get; set; } = new ObservableCollection<TechnologyProcessModel>();

public string currentRecipeName { get { return _currentRecipeName; } set { _currentRecipeName = value; OnPropertyChanged(); } }
private string _currentRecipeName = string.Empty;

public RelayCommand CloseWindowCommand { get; set; }

@@ -36,11 +36,11 @@ namespace BPASmart.RecipeManagement.ViewModel

public TechnologyProcessViewModel()
{
foreach(var item in Json<LocalMaterails>.Data.locaMaterails)
foreach (var item in Globle.GlobleData.recipeTechnologyProcess.recipeMaterials)
{
meterailItems.Add(item.Name);
}
ActionManage.GetInstance.Register(new Action<object>((obj) =>
{
if (obj != null)
@@ -63,14 +63,14 @@ namespace BPASmart.RecipeManagement.ViewModel
ConfirmCommand = new RelayCommand(() =>
{
var res = Json<LocalRecipes>.Data.locaRecipes.FirstOrDefault(p => p.ID == Globle.GlobleData.recipeTechnologyProcess.ID);
if(res != null)
if (res != null)
{
res.TechnologyProcessModels = technologyProcessModels;
}
Json<LocalRecipes>.Save();

;
;
ActionManage.GetInstance.Send("CloseTechnologyProcessView");
});



+ 2
- 1
BPASmart.Server/BPASmart.Server.csproj View File

@@ -9,7 +9,8 @@

<ItemGroup>
<PackageReference Include="BPA.Communication" Version="1.0.19" />
<PackageReference Include="BPA.Helper" Version="1.0.11" />
<PackageReference Include="BPA.Helper" Version="1.0.15" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="6.0.9" />
</ItemGroup>

<ItemGroup>


+ 21
- 10
BPASmart.Server/CommunicationServer.cs View File

@@ -98,7 +98,18 @@ namespace BPASmart.Server
{
while (msg.Count > 0)
{
DeviceControl();
if (msg.TryDequeue(out string s))
{
var res = JsonConvert.DeserializeObject(s) as IMessage;
if (res != null)
{
if (res is PublishInfo _mPublishInfo)
{
DeviceControl(_mPublishInfo);
}
}

}
}
Thread.Sleep(100);
}), "MQTT 消息监听");
@@ -109,14 +120,14 @@ namespace BPASmart.Server
});
}

private void DeviceControl()
private void DeviceControl(PublishInfo publishInfo)
{
if (msg.TryDequeue(out string s))
{
var res = JsonConvert.DeserializeObject<PublishInfo>(s);
if (res != null)
{
res.PublishModels.ForEach(item =>
//if (msg.TryDequeue(out string s))
//{
// var res = JsonConvert.DeserializeObject<PublishInfo>(s);
// if (res != null)
// {
publishInfo.PublishModels.ForEach(item =>
{
if (CommunicationDevices.ContainsKey(item.DeviceName))
{
@@ -160,8 +171,8 @@ namespace BPASmart.Server

}
});
}
}
//}
//}
}

private void SetValue(Array arrays, string DeviceName, ReadDataModel readDataModel, EDataType eDataType)


+ 72
- 0
BPASmart.Server/SqliteContext.cs View File

@@ -0,0 +1,72 @@
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using BPASmart.Model;
using System.Collections.ObjectModel;

namespace BPASmart.Server
{
public class SqliteContext : DbContext, IRecipeMaterials
{
private volatile static SqliteContext _Instance;
public static SqliteContext GetInstance => _Instance ?? (_Instance = new SqliteContext());
private SqliteContext() { }


string path
{
get
{
Directory.CreateDirectory(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, $"AccessFile\\DB"));
return $"{AppDomain.CurrentDomain.BaseDirectory}AccessFile\\DB\\RecipeInfo.db";
}
}

public DbSet<RecipeMaterials> RecipeMaterialsS { get; set; }

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlite($"FileName={path}");
}

public async Task<bool> AddAsync(RecipeMaterials recipeMaterials)
{
Database.EnsureCreated();
await RecipeMaterialsS.AddAsync(recipeMaterials);
return await SaveChangesAsync() > 1;
}

public async Task<bool> AddRangeAsync(RecipeMaterials[] recipeMaterials)
{
Database.EnsureCreated();
await RecipeMaterialsS.AddRangeAsync(recipeMaterials);
return await SaveChangesAsync() > 1;
}

public async Task<bool> UpdateAsync(RecipeMaterials recipeMaterials)
{
Database.EnsureCreated();
RecipeMaterialsS.Update(recipeMaterials);
return await SaveChangesAsync() > 1;
}

public async Task<bool> DeleteAsync(string ID)
{
Database.EnsureCreated();
RecipeMaterialsS.Remove(RecipeMaterialsS.FirstOrDefault(p => p.ID == ID));
return await SaveChangesAsync() > 1;
}

public async Task<List<RecipeMaterials>> GetData()
{
return await Task.Factory.StartNew(new Func<List<RecipeMaterials>>(() =>
{
Database.EnsureCreated();
return RecipeMaterialsS.ToList();
}));
}
}
}

+ 1
- 1
BPASmart.VariableManager/BPASmart.VariableManager.csproj View File

@@ -30,7 +30,7 @@

<ItemGroup>
<PackageReference Include="BPA.Communication" Version="1.0.19" />
<PackageReference Include="BPA.Helper" Version="1.0.11" />
<PackageReference Include="BPA.Helper" Version="1.0.15" />
</ItemGroup>

<ItemGroup>


+ 32
- 5
BPASmart.VariableManager/ViewModels/VariableConfigViewModel.cs View File

@@ -21,21 +21,18 @@ namespace BPASmart.VariableManager.ViewModels
{
public class VariableConfigViewModel : NoticeBase
{
//PipeClient pipeClient = new PipeClient(PipeTopic.PipeName);
private int varialeInfosIndex = -1;
ICommunicationDevice DeviceType;
public VariableConfigViewModel(string o)
{
//pipeClient.StartPipeStream();
//MessageLog.GetInstance.NotifyShow = new Action<string>((o) => { if (pipeClient.IsConnected) pipeClient.SendCommand(o); });
ServiceCenter.GetInstance.Init();

DataInit(o);
VarNameChanged();

SaveCommand = new RelayCommand(() => { ServiceCenter.GetInstance.VarSave(); });

//DelegationNotifi.GetInstance.VariableSave = new Action(() => { Json<CommunicationPar>.Save(); });
GenerateEntityClassCommand = new RelayCommand(() => { GenerateEntityClass(); });

StartMotionCommand = new RelayCommand(() =>
{
switch (ButtonContext)
@@ -76,6 +73,34 @@ namespace BPASmart.VariableManager.ViewModels
});
}

private void GenerateEntityClass()
{
StringBuilder sb = new StringBuilder();
string deviceName = Json<CommunicationPar>.Data.CommunicationDevices.ElementAt(varialeInfosIndex).DeviceName;
sb.Append("using System;\r\n");
sb.Append("using System.Text;\r\n");
sb.Append("using System.Linq;\r\n");
sb.Append("namespace ProjectName\r\n");
sb.Append("{\r\n");
sb.Append($"public class {deviceName}\r\n");
sb.Append("{\r\n");
Json<CommunicationPar>.Data.CommunicationDevices.ElementAt(varialeInfosIndex).VarTableModels.ToList().ForEach(item =>
{
if (!string.IsNullOrEmpty(item.VarName))
{
sb.Append("/// <summary>\r\n");
sb.Append($"/// {item.VarName}\r\n");
sb.Append("/// <summary>\r\n");
sb.Append($"public {item.DataType.ToEnum<EDataType>().ToSystemData()} {item.VarName}");
sb.Append("{get;set;}\r\n \r\n");
}
});
sb.Append("}\r\n");
sb.Append("}\r\n");
TextHelper.GetInstance.WriteTextInfo(sb.ToString(), $"{deviceName}.cs", "EntityClass");

}

private void DataInit(string o)
{
varialeInfosIndex = Array.FindIndex(Json<CommunicationPar>.Data.CommunicationDevices.ToArray(), p => p.DeviceName == o);
@@ -281,6 +306,8 @@ namespace BPASmart.VariableManager.ViewModels
public RelayCommand StartMotionCommand { get; set; }

public RelayCommand<object> RemoveCommand { get; set; }

public RelayCommand GenerateEntityClassCommand { get; set; }
#endregion

private void SetValue(Array arrays, ReadDataModel readDataModel, EDataType eDataType)


+ 13
- 5
BPASmart.VariableManager/Views/VariableConfig.xaml View File

@@ -155,6 +155,14 @@
</Grid.RowDefinitions>

<StackPanel HorizontalAlignment="Right" Orientation="Horizontal">
<Button
Width="150"
Height="40"
Margin="10,0,10,0"
Command="{Binding GenerateEntityClassCommand}"
Content="生成实体类"
FontSize="20"
Style="{StaticResource ImageButtonStyle}" />
<Button
Width="150"
Height="40"
@@ -248,7 +256,7 @@
<!--#endregion-->

<Grid Grid.Row="2">
<ScrollViewer HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Hidden">
<ScrollViewer HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Hidden">
<ItemsControl ItemsSource="{Binding varialeInfos}">
<ItemsControl.ItemTemplate>
<DataTemplate>
@@ -274,9 +282,9 @@

<Grid Grid.Column="1" KeyDown="TextBox_KeyDown">
<TextBox
IsEnabled="{Binding DataContext.IsEnable, RelativeSource={RelativeSource AncestorType=ItemsControl, Mode=FindAncestor}}"
Width="{Binding DataContext.NameWidth, RelativeSource={RelativeSource AncestorType=ItemsControl, Mode=FindAncestor}}"
Foreground="{Binding IsRedundant, Converter={StaticResource tabConvert}}"
IsEnabled="{Binding DataContext.IsEnable, RelativeSource={RelativeSource AncestorType=ItemsControl, Mode=FindAncestor}}"
Style="{StaticResource InputTextboxStyle}"
TabIndex="{Binding ID}"
Text="{Binding VarName}" />
@@ -288,10 +296,10 @@

<TextBox
Grid.Column="2"
IsEnabled="{Binding DataContext.IsEnable, RelativeSource={RelativeSource AncestorType=ItemsControl, Mode=FindAncestor}}"
KeyDown="TextBox_KeyDown"
Width="{Binding DataContext.AddressWidth, RelativeSource={RelativeSource AncestorType=ItemsControl, Mode=FindAncestor}}"
Foreground="{Binding IsRedundant, Converter={StaticResource tabConvert}}"
IsEnabled="{Binding DataContext.IsEnable, RelativeSource={RelativeSource AncestorType=ItemsControl, Mode=FindAncestor}}"
KeyDown="TextBox_KeyDown"
Style="{StaticResource InputTextboxStyle}"
TabIndex="{Binding ID}"
Text="{Binding Address}" />
@@ -304,9 +312,9 @@
BorderThickness="1"
FontFamily="楷体"
FontSize="20"
IsEnabled="{Binding DataContext.IsEnable,RelativeSource={RelativeSource AncestorType=ItemsControl,Mode=FindAncestor}}"
Foreground="{Binding IsRedundant, Converter={StaticResource tabConvert}}"
IsEditable="False"
IsEnabled="{Binding DataContext.IsEnable, RelativeSource={RelativeSource AncestorType=ItemsControl, Mode=FindAncestor}}"
ItemsSource="{Binding DataContext.dataType, RelativeSource={RelativeSource AncestorType=ItemsControl, Mode=FindAncestor}}"
SelectedValue="{Binding DataType}"
Style="{StaticResource ComboBoxStyle}"


+ 167
- 0
BPASmartClient.SCADAControl/Converters/HoneycombPanel.cs View File

@@ -0,0 +1,167 @@
using System;
using System.Windows;
using System.Windows.Controls;


namespace BPASmartClient.SCADAControl.Converters
{
public class HoneycombPanel : Panel
{
private double _unitLength;

private HoneycombStuffer _stuffer;

private static int GetXCount(int count)
{
if (count == 0) return 0;

count -= 1;

var index = (int)Math.Floor(Math.Pow((12.0 * count + 25) / 36, 0.5) - 5.0 / 6);
var valeIndex = 3 * index * index + 5 * index;
var centerValue = valeIndex + 2;

return count >= centerValue
? 4 * index + 6
: count > valeIndex
? 4 * index + 4
: 4 * index + 2;
}

private static int GetYCount(int count)
{
if (count == 0) return 0;

count -= 1;

var index = (int)Math.Floor(Math.Pow(count / 3.0 + 0.25, 0.5) - 0.5);
var valeIndex = 3 * index * index + 3 * index;

return count > valeIndex
? 2 * index + 2
: 2 * index;
}

/*
* layout order
*
* ● ●
* (7) (8)
*
* ● ● ●
* (6) (1) (9)
*
* ● ● ● ...
* (5) (0) (2)
*
* ● ● ...
* (4) (3)
*
*/
protected override Size MeasureOverride(Size availableSize)
{
var maxSize = new Size();

foreach (UIElement child in InternalChildren)
{
if (child != null)
{
child.Measure(availableSize);
maxSize.Width = Math.Max(maxSize.Width, child.DesiredSize.Width);
maxSize.Height = Math.Max(maxSize.Height, child.DesiredSize.Height);
}
}

_unitLength = Math.Max(maxSize.Width, maxSize.Height) / 2;

var xCount = GetXCount(InternalChildren.Count);
var yCount = GetYCount(InternalChildren.Count);

var availableWidth = xCount * _unitLength;
var availableHeight = yCount * Math.Pow(3, 0.5) * _unitLength + _unitLength * 2;

return new Size(availableWidth, availableHeight);
}

protected override Size ArrangeOverride(Size finalSize)
{
var childLength = _unitLength * 2;
_stuffer = new HoneycombStuffer(new Rect(finalSize.Width / 2 - _unitLength,
finalSize.Height / 2 - _unitLength, childLength, childLength));

foreach (UIElement child in InternalChildren)
{
child.Arrange(_stuffer.Move());
}

return finalSize;
}

private class HoneycombStuffer
{
private int _turns;

private int _maxIndex;

private int _currentIndex = -1;

private readonly double _offsetX;

private readonly double _offsetY;

private Rect _childBounds;

private readonly double[] _offsetXArr;

private readonly double[] _offsetYArr;

public HoneycombStuffer(Rect childBounds)
{
_childBounds = childBounds;
_offsetX = childBounds.Width / 2;
_offsetY = Math.Pow(3, 0.5) * _offsetX;

_offsetXArr = new[]
{
2 * _offsetX,
_offsetX,
-_offsetX,
-2 * _offsetX,
-_offsetX,
_offsetX
};

_offsetYArr = new[]
{
0,
_offsetY,
_offsetY,
0,
-_offsetY,
-_offsetY
};
}

public Rect Move()
{
_currentIndex++;
if (_currentIndex > _maxIndex)
{
_turns++;
_maxIndex = _turns * 6 - 1;
_currentIndex = 0;
_childBounds.Offset(_offsetX, -_offsetY);
return _childBounds;
}

if (_turns > 0)
{
var index = _currentIndex / _turns;
_childBounds.Offset(_offsetXArr[index], _offsetYArr[index]);
}

return _childBounds;
}
}
}
}

+ 37
- 32
BPASmartClient.SCADAControl/CustomerControls/Silos.xaml View File

@@ -7,11 +7,13 @@
mc:Ignorable="d"
d:DesignHeight="270" d:DesignWidth="180" >
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<TextBlock
<Viewbox Width="auto" Height="auto" Grid.Row="1">
<Grid Width="180" Height="270">
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<TextBlock
HorizontalAlignment="Center"
VerticalAlignment="Top"
Margin="0 10 0 35"
@@ -19,61 +21,64 @@
Foreground="#FF1FD622"
Tag="出料控制"
Text="出料中..." Visibility="Collapsed"/>
<Ellipse Grid.Row="0" Tag="出料圆" Margin="0,40,0,0" Visibility="Collapsed" StrokeThickness="60" Width="150" Height="70" RenderTransformOrigin="0.5,0.5" VerticalAlignment="Top">
<Ellipse.RenderTransform>
<TransformGroup>
<ScaleTransform/>
<SkewTransform AngleY="0"/>
<RotateTransform Angle="0"/>
<TranslateTransform/>
</TransformGroup>
</Ellipse.RenderTransform>
<Ellipse.Stroke>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0" Opacity="0.4">
<GradientStop Color="#CCA48E42"/>
<GradientStop Color="#CC2D48DA" Offset="1"/>
<GradientStop Color="#FF3FD256" Offset="0.305"/>
<!--<GradientStop Color="#FFB12C87" Offset="0.67"/>-->
</LinearGradientBrush>
</Ellipse.Stroke>
</Ellipse>
<Ellipse Grid.Row="0" Tag="出料圆" Margin="0,40,0,0" Visibility="Collapsed" StrokeThickness="60" Width="150" Height="70" RenderTransformOrigin="0.5,0.5" VerticalAlignment="Top">
<Ellipse.RenderTransform>
<TransformGroup>
<ScaleTransform/>
<SkewTransform AngleY="0"/>
<RotateTransform Angle="0"/>
<TranslateTransform/>
</TransformGroup>
</Ellipse.RenderTransform>
<Ellipse.Stroke>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0" Opacity="0.4">
<GradientStop Color="#CCA48E42"/>
<GradientStop Color="#CC2D48DA" Offset="1"/>
<GradientStop Color="#FF3FD256" Offset="0.305"/>
<!--<GradientStop Color="#FFB12C87" Offset="0.67"/>-->
</LinearGradientBrush>
</Ellipse.Stroke>
</Ellipse>

<TextBlock

<TextBlock
HorizontalAlignment="Center"
VerticalAlignment="Bottom"
Margin="0 0 0 35"
FontSize="45"
Foreground="#FFCCD61F" Tag="Title"
Text="{Binding Title,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" />
<StackPanel Grid.Row="1" Orientation="Horizontal" HorizontalAlignment="Center">
<TextBlock
<StackPanel Grid.Row="1" Orientation="Horizontal" HorizontalAlignment="Center">
<TextBlock
Margin="0,20,0,0"
HorizontalAlignment="Center"
FontSize="20"
Foreground="#FF00FFF9" Tag="Value"
Text="{Binding Value,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" />
<TextBlock
<TextBlock
Margin="0,20,0,0"
HorizontalAlignment="Center"
FontSize="20"
Foreground="#FF00FFF9"
Text="(g)" />
</StackPanel>
<TextBlock
</StackPanel>
<TextBlock
Grid.Row="1" Tag="Text"
Margin="0,70,0,0"
HorizontalAlignment="Center"
FontSize="25"
Foreground="#FFFFA400"
Text="{Binding Text,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" />
<Image
<Image
Grid.RowSpan="2"
Source="/BPASmartClient.SCADAControl;component/Images/光柱.png"
Stretch="Fill" />
<!--<StackPanel Tag="ControlEvent" HorizontalAlignment="Right" Orientation="Vertical" Grid.Row="1" VerticalAlignment="Bottom" >
<!--<StackPanel Tag="ControlEvent" HorizontalAlignment="Right" Orientation="Vertical" Grid.Row="1" VerticalAlignment="Bottom" >
<Image Margin="20,10,0,0" Tag="出料" Source="/BPASmartClient.SCADAControl;component/Images/借出.png" Cursor="Hand" ToolTip="出料" Width="24" ></Image>
<Image Margin="20,10,0,10" Tag="停止出料" Source="/BPASmartClient.SCADAControl;component/Images/退出.png" Cursor="Hand" Width="24" ToolTip="停止出料"></Image>
</StackPanel>-->
</Grid>
</Viewbox>
</Grid>
</UserControl>

+ 21
- 0
BPASmartClient.SCADAControl/CustomerControls/TheEllipse.xaml View File

@@ -0,0 +1,21 @@
<UserControl x:Class="BPASmartClient.SCADAControl.CustomerControls.TheEllipse"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:BPASmartClient.SCADAControl.CustomerControls"
mc:Ignorable="d"
x:Name="root"
Foreground="#FF00EDFF"
BorderBrush="Transparent"
BorderThickness="4"
d:DesignHeight="800" d:DesignWidth="800">
<Ellipse Tag="Ellipse"
Fill="{Binding ElementName=root,Path=BJColor,Mode=TwoWay}"
Stroke="{Binding ElementName=root,Path=Foreground}"
StrokeThickness="{Binding ElementName=root,Path=BKThickness}"
StrokeDashArray="{Binding ElementName=root,Path=DoubleArray,Mode=TwoWay}"
>
</Ellipse>
</UserControl>

+ 144
- 0
BPASmartClient.SCADAControl/CustomerControls/TheEllipse.xaml.cs View File

@@ -0,0 +1,144 @@
using BPASmartClient.Compiler;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace BPASmartClient.SCADAControl.CustomerControls
{
/// <summary>
/// TheEllipse.xaml 的交互逻辑
/// </summary>
public partial class TheEllipse : UserControl, IExecutable
{
Ellipse LeftTog = null;
public TheEllipse()
{
InitializeComponent();
this.Loaded += TheEllipse_Loaded; ; ;
this.SizeChanged += TheEllipse_SizeChanged; ; ;
}

private void TheEllipse_SizeChanged(object sender, SizeChangedEventArgs e)
{
if (LeftTog == null)
{
foreach (Ellipse tb in FindVisualChildren<Ellipse>(this))
{
if (tb.Tag != null)
{
if (tb.Tag.ToString() == "Ellipse") LeftTog = tb;
}
}
}
}

public static IEnumerable<T> FindVisualChildren<T>(DependencyObject depObj) where T : DependencyObject
{
if (depObj != null)
{
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++)
{
DependencyObject child = VisualTreeHelper.GetChild(depObj, i);
if (child != null && child is T)
{
yield return (T)child;
}

foreach (T childOfChild in FindVisualChildren<T>(child))
{
yield return childOfChild;
}
}
}
}

private void TheEllipse_Loaded(object sender, RoutedEventArgs e)
{
if (this.ActualWidth <= 20)
{
Width = 80;
Height = 80;
}
BKStrokeDashArray.CollectionChanged += BKStrokeDashArray_CollectionChanged;
}

private void BKStrokeDashArray_CollectionChanged(object? sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
Refresh();
}

public Brush BJColor
{
get { return (Brush)GetValue(BJColorProperty); }
set { SetValue(BJColorProperty, value); }
}
public static readonly DependencyProperty BJColorProperty =
DependencyProperty.Register("BJColor", typeof(Brush), typeof(TheEllipse), new PropertyMetadata(new SolidColorBrush(Colors.Transparent)));
public double BKThickness
{
get { return (double)GetValue(BKThicknessProperty); }
set { SetValue(BKThicknessProperty, value); }
}
public static readonly DependencyProperty BKThicknessProperty =
DependencyProperty.Register("BKThickness", typeof(double), typeof(TheEllipse), new PropertyMetadata(1.0));
public ObservableCollection<double> BKStrokeDashArray
{
get { return (ObservableCollection<double>)GetValue(BKStrokeDashArrayProperty); }
set { SetValue(BKStrokeDashArrayProperty, value); }
}
public static readonly DependencyProperty BKStrokeDashArrayProperty =
DependencyProperty.Register("BKStrokeDashArray", typeof(ObservableCollection<double>), typeof(TheEllipse), new PropertyMetadata(new ObservableCollection<double>(),new PropertyChangedCallback(OnPropertyChanged)));
public DoubleCollection DoubleArray
{
get { return (DoubleCollection)GetValue(DoubleArrayProperty); }
set { SetValue(DoubleArrayProperty, value); }
}
public static readonly DependencyProperty DoubleArrayProperty =
DependencyProperty.Register("DoubleArray", typeof(DoubleCollection), typeof(TheEllipse), new PropertyMetadata(new DoubleCollection()));


private static void OnPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
(d as TheEllipse)?.Refresh();
}
private void Refresh()
{
DoubleArray = new DoubleCollection(BKStrokeDashArray);
}
public event EventHandler PropertyChange; //声明一个事件
public string ControlType => "控件";
private bool isExecuteState;
public bool IsExecuteState
{
get { return isExecuteState; }
set
{
isExecuteState = value;
if (IsExecuteState)
{
Register();
}
}
}
// <summary>
/// 运行事件
/// </summary>
public void Register()
{

}
}
}

+ 22
- 0
BPASmartClient.SCADAControl/CustomerControls/TheRectangle.xaml View File

@@ -0,0 +1,22 @@
<UserControl x:Class="BPASmartClient.SCADAControl.CustomerControls.TheRectangle"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:BPASmartClient.SCADAControl.CustomerControls"
mc:Ignorable="d"
x:Name="root"
Foreground="#FF00EDFF"
BorderBrush="Transparent"
BorderThickness="4"
Tag="10"
d:DesignHeight="450" d:DesignWidth="800">
<Rectangle Tag="border"
Fill="{Binding ElementName=root,Path=BJColor,Mode=TwoWay}"
Stroke="{Binding ElementName=root,Path=Foreground}"
StrokeThickness="{Binding ElementName=root,Path=BKThickness}"
StrokeDashArray="{Binding ElementName=root,Path=DoubleArray,Mode=TwoWay}"
>
</Rectangle>
</UserControl>

+ 142
- 0
BPASmartClient.SCADAControl/CustomerControls/TheRectangle.xaml.cs View File

@@ -0,0 +1,142 @@
using BPASmartClient.Compiler;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace BPASmartClient.SCADAControl.CustomerControls
{
/// <summary>
/// TheRectangle.xaml 的交互逻辑
/// </summary>
public partial class TheRectangle : UserControl, IExecutable
{
Border LeftTog = null;

public TheRectangle()
{
InitializeComponent();
this.Loaded += TheRectangle_Loaded; ;
this.SizeChanged += TheRectangle_SizeChanged; ;
}

private void TheRectangle_SizeChanged(object sender, SizeChangedEventArgs e)
{
if (LeftTog == null)
{
foreach (Border tb in FindVisualChildren<Border>(this))
{
if (tb.Tag != null)
{
if (tb.Tag.ToString() == "border") LeftTog = tb;
}
}
}
}
public static IEnumerable<T> FindVisualChildren<T>(DependencyObject depObj) where T : DependencyObject
{
if (depObj != null)
{
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++)
{
DependencyObject child = VisualTreeHelper.GetChild(depObj, i);
if (child != null && child is T)
{
yield return (T)child;
}

foreach (T childOfChild in FindVisualChildren<T>(child))
{
yield return childOfChild;
}
}
}
}

private void TheRectangle_Loaded(object sender, RoutedEventArgs e)
{
if (this.ActualWidth <= 20)
{
Width = 80;
Height = 80;
}
BKStrokeDashArray.CollectionChanged += BKStrokeDashArray_CollectionChanged;
}
private void BKStrokeDashArray_CollectionChanged(object? sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
Refresh();
}
private static void OnPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
(d as TheRectangle)?.Refresh();
}
private void Refresh()
{
DoubleArray = new DoubleCollection(BKStrokeDashArray);
}

public Brush BJColor
{
get { return (Brush)GetValue(BJColorProperty); }
set { SetValue(BJColorProperty, value); }
}
public static readonly DependencyProperty BJColorProperty =
DependencyProperty.Register("BJColor", typeof(Brush), typeof(TheRectangle), new PropertyMetadata(new SolidColorBrush(Colors.Transparent)));
public double BKThickness
{
get { return (double)GetValue(BKThicknessProperty); }
set { SetValue(BKThicknessProperty, value); }
}
public static readonly DependencyProperty BKThicknessProperty =
DependencyProperty.Register("BKThickness", typeof(double), typeof(TheRectangle), new PropertyMetadata(1.0));
public ObservableCollection<double> BKStrokeDashArray
{
get { return (ObservableCollection<double>)GetValue(BKStrokeDashArrayProperty); }
set { SetValue(BKStrokeDashArrayProperty, value); }
}
public static readonly DependencyProperty BKStrokeDashArrayProperty =
DependencyProperty.Register("BKStrokeDashArray", typeof(ObservableCollection<double>), typeof(TheRectangle), new PropertyMetadata(new ObservableCollection<double>(), new PropertyChangedCallback(OnPropertyChanged)));
public DoubleCollection DoubleArray
{
get { return (DoubleCollection)GetValue(DoubleArrayProperty); }
set { SetValue(DoubleArrayProperty, value); }
}
public static readonly DependencyProperty DoubleArrayProperty =
DependencyProperty.Register("DoubleArray", typeof(DoubleCollection), typeof(TheRectangle), new PropertyMetadata(new DoubleCollection()));

public event EventHandler PropertyChange; //声明一个事件
public string ControlType => "控件";
private bool isExecuteState;
public bool IsExecuteState
{
get { return isExecuteState; }
set
{
isExecuteState = value;
if (IsExecuteState)
{
Register();
}
}
}
// <summary>
/// 运行事件
/// </summary>
public void Register()
{

}
}
}

+ 87
- 0
BPASmartClient.SCADAControl/CustomerControls/TheWuLiaoControl.xaml View File

@@ -0,0 +1,87 @@
<UserControl x:Class="BPASmartClient.SCADAControl.CustomerControls.TheWuLiaoControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:kj="clr-namespace:BPASmartClient.SCADAControl.Converters"
xmlns:local="clr-namespace:BPASmartClient.SCADAControl.CustomerControls"
mc:Ignorable="d"
x:Name="main"
Width="200" Height="200">
<UserControl.Resources>
<Style x:Key="ListBoxItemCustom" TargetType="ListBoxItem">
<Setter Property="SnapsToDevicePixels" Value="True" />
<Setter Property="FocusVisualStyle" Value="{x:Null}" />
<Setter Property="Padding" Value="0" />
<Setter Property="HorizontalContentAlignment" Value="{Binding HorizontalContentAlignment, RelativeSource={RelativeSource AncestorType=ItemsControl}}" />
<Setter Property="VerticalContentAlignment" Value="Top" />
<Setter Property="Background" Value="Transparent" />
<Setter Property="BorderBrush" Value="Transparent" />
<Setter Property="BorderThickness" Value="0" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem">
<ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="ListBoxBaseStyle" TargetType="ListBox">
<Setter Property="FocusVisualStyle" Value="{x:Null}" />
<Setter Property="BorderThickness" Value="1" />
<Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Disabled" />
<Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto" />
<Setter Property="ScrollViewer.CanContentScroll" Value="true" />
<Setter Property="ScrollViewer.PanningMode" Value="Both" />
<Setter Property="Stylus.IsFlicksEnabled" Value="False" />
<Setter Property="VerticalContentAlignment" Value="Center" />
<Setter Property="Padding" Value="2,2,2,0" />
</Style>
<Style x:Key="ListBoxCustom" BasedOn="{StaticResource ListBoxBaseStyle}" TargetType="ListBox">
<Setter Property="ItemContainerStyle" Value="{StaticResource ListBoxItemCustom}" />
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
</Style>
</UserControl.Resources>
<Grid>
<Ellipse Fill="Transparent" Stroke="{Binding Foreground, ElementName=main}" StrokeThickness="{Binding BorderThickness, ElementName=main}" Width="{Binding Width, ElementName=main}" Height="{Binding Width, ElementName=main}"/>
<Viewbox Width="auto" Height="auto" >
<Grid>
<ListBox Background="Transparent" Margin="30" ItemsSource="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=UserControl},Path=vs}" Style="{DynamicResource ListBoxCustom}" BorderThickness="0" >
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<kj:HoneycombPanel />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate>
<Grid Width="150" Height="150" Margin="10">
<Ellipse Width="140" Height="140" Fill="Transparent" Stroke="{Binding Foreground, ElementName=main}" StrokeThickness="{Binding BorderThickness, ElementName=main}"/>
<TextBlock Text="一号料仓" Margin="0,-10,0,0" Foreground="{Binding Foreground, ElementName=main}" HorizontalAlignment="Center"></TextBlock>
<Viewbox Width="auto" Height="auto">
<ListBox Background="Transparent" ItemsSource="{Binding dataModel}" Style="{DynamicResource ListBoxCustom}" BorderThickness="0" >
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<kj:HoneycombPanel />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate>
<Grid>
<Ellipse Width="100" Height="100" Fill="Transparent" Stroke="{Binding Foreground, ElementName=main}" StrokeThickness="{Binding BorderThickness, ElementName=main}" Margin="10"/>
<TextBlock HorizontalAlignment="Center" Foreground="{Binding Foreground, ElementName=main}" VerticalAlignment="Center" FontSize="24" Text="味精"></TextBlock>
</Grid>
</DataTemplate>

</ListBox.ItemTemplate>
</ListBox>
</Viewbox>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>

</Viewbox>
</Grid>
</UserControl>

+ 119
- 0
BPASmartClient.SCADAControl/CustomerControls/TheWuLiaoControl.xaml.cs View File

@@ -0,0 +1,119 @@
using BPASmartClient.Compiler;
using BPASmartClient.DATABUS;
using BPASmartClient.MessageCommunication;
using BPASmartClient.MessageCommunication.MsgControl;
using BPASmartClient.MessageName;
using BPASmartClient.MessageName.EnumHelp;
using BPASmartClient.MessageName.发送消息Model;
using BPASmartClient.MessageName.接收消息Model;
using BPASmartClient.MessageName.接收消息Model.物料仓;
using Newtonsoft.Json;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Drawing.Design;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Threading;


namespace BPASmartClient.SCADAControl.CustomerControls
{
/// <summary>
/// TheWuLiaoControl.xaml 的交互逻辑
/// </summary>
public partial class TheWuLiaoControl : UserControl, IExecutable, IDisposable
{
public TheWuLiaoControl()
{
InitializeComponent();
vs.Add(new shujuModel
{
name = "",
dataModel = new ObservableCollection<string> { "", "" }
});
vs.Add(new shujuModel
{
name = "",
dataModel = new ObservableCollection<string> { "", "", "", "" }
});
Width = 200;
Height = 200;
}

public string ControlType => "物料仓";
private bool isExecuteState;
public bool IsExecuteState
{
get { return isExecuteState; }
set
{
isExecuteState = value;
if (IsExecuteState)
{
IsEnabled = true;
Register();
}
}
}
public event EventHandler PropertyChange; //声明一个事件
/// <summary>
/// 数据模板
/// </summary>
private ObservableCollection<shujuModel> vs
{
get { return (ObservableCollection<shujuModel>)GetValue(vsProperty); }
set { SetValue(vsProperty, value); }
}
private static readonly DependencyProperty vsProperty =
DependencyProperty.Register("vs", typeof(ObservableCollection<shujuModel>), typeof(TheWuLiaoControl), new PropertyMetadata(new ObservableCollection<shujuModel>()));
/// <summary>
/// 数据模板
/// </summary>
private Dictionary<string, object> DataModel
{
get { return (Dictionary<string, object>)GetValue(DataModelProperty); }
set { SetValue(DataModelProperty, value); }
}
private static readonly DependencyProperty DataModelProperty =
DependencyProperty.Register("DataModel", typeof(Dictionary<string, object>), typeof(TheWuLiaoControl), new PropertyMetadata(new Dictionary<string, object>()));
public void Register()
{
Class_DataBus.GetInstance().BindingAction += BindingActionHeader;
}

public void BindingActionHeader(object sender, EventArgs e)
{
this.Dispatcher.Invoke((Action)(() =>
{
DataModel = Class_DataBus.GetInstance().Dic_RedisDataBinding;
PropertyChange?.Invoke(this, EventArgs.Empty);
}));
}
public void Dispose()
{

}

}

public class shujuModel
{
public string name { get; set; }
public ObservableCollection<string> dataModel { get; set; }
}
}

+ 2
- 0
BPASmartClient.SCADAControl/Themes/Generic.xaml View File

@@ -2293,4 +2293,6 @@
<GradientStop Offset="1" Color="#E3E3E3" />
</LinearGradientBrush>
<!--#endregion-->

</ResourceDictionary>

+ 1
- 1
BeDesignerSCADA/Common/PropertyHelper.cs View File

@@ -20,7 +20,7 @@ namespace BeDesignerSCADA.Common
"IsChecked", "Value", "CurValue",
"StatusValue", "NumberValue", "Text",
"Direction","RefreshData",
"ChangedText","Content","SendText"
"ChangedText","Content","SendText","LeftTogIsChecked","RightTogIsChecked"
};
public static List<ControlName> GetCustomerControlProperty(List<FrameworkElement> selectItems)
{


+ 43
- 35
BeDesignerSCADA/Controls/MainCanvasPanel.xaml View File

@@ -148,7 +148,7 @@
<icon:Material Kind="FileCode"/>
</ToggleButton>

<Slider DockPanel.Dock="Right" Width="100" Maximum="16" Minimum="1" Margin="4 0 0 0"
<Slider DockPanel.Dock="Right" x:Name="slikl" Width="100" Maximum="16" Minimum="1" Margin="4 0 0 0" ValueChanged="Slider_ValueChanged"
HorizontalContentAlignment="Center" Value="{Binding ElementName=cav,Path=GridPxiel}" ></Slider>
<TextBlock DockPanel.Dock="Right" Text="对齐:" VerticalAlignment="Center" Margin="16 0 0 0"/>

@@ -164,37 +164,40 @@
<ColumnDefinition/>
<ColumnDefinition Width="auto"/>
</Grid.ColumnDefinitions>
<Compiler:CanvasPanel x:Name="cav" Visibility="{Binding CanvasPanelVisibility}" SelectedItem="{Binding CanSelectedItem,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" AllowDrop="True" RenderTransformOrigin="0.5,0.5" ClipToBounds="True" UseLayoutRounding="True" Focusable="True" SnapsToDevicePixels="True">
<Compiler:CanvasPanel.Background>
<VisualBrush TileMode="Tile" Viewport="0,0,20,20" ViewportUnits="Absolute">
<VisualBrush.Visual>
<Rectangle Width="20" Height="20" StrokeDashArray="4,2" StrokeThickness="0.5" Stroke="#CBCBCB">
<Rectangle.Style>
<Style TargetType="{x:Type Rectangle}">
<Style.Triggers>
<DataTrigger Binding="{Binding UseAutoAlignment, RelativeSource={RelativeSource AncestorType={x:Type Compiler:CanvasPanel}, Mode=FindAncestor}}" Value="True">
<Setter Property="Visibility" Value="Visible"/>
</DataTrigger>
<DataTrigger Binding="{Binding UseAutoAlignment, RelativeSource={RelativeSource AncestorType={x:Type Compiler:CanvasPanel}, Mode=FindAncestor}}" Value="False">
<Setter Property="Visibility" Value="Collapsed"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Rectangle.Style>
</Rectangle>
</VisualBrush.Visual>
</VisualBrush>
</Compiler:CanvasPanel.Background>

<Compiler:CanvasPanel.RenderTransform>
<TransformGroup>
<TranslateTransform x:Name="CanvasTranslate"/>
</TransformGroup>
</Compiler:CanvasPanel.RenderTransform>
</Compiler:CanvasPanel>

<ScrollViewer VerticalScrollBarVisibility="Visible" HorizontalScrollBarVisibility="Visible">
<Viewbox Width="auto" Height="auto" Grid.Row="1">
<Compiler:CanvasPanel x:Name="cav" Width="1920" Height="1080" Visibility="{Binding CanvasPanelVisibility}" SelectedItem="{Binding CanSelectedItem,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" AllowDrop="True" RenderTransformOrigin="0.5,0.5" ClipToBounds="True" UseLayoutRounding="True" Focusable="True" SnapsToDevicePixels="True">
<Compiler:CanvasPanel.Background>
<VisualBrush TileMode="Tile" Viewport="0,0,20,20" ViewportUnits="Absolute">
<VisualBrush.Visual>
<Rectangle Width="20" Height="20" StrokeDashArray="4,2" StrokeThickness="0.5" Stroke="#CBCBCB">
<Rectangle.Style>
<Style TargetType="{x:Type Rectangle}">
<Style.Triggers>
<DataTrigger Binding="{Binding UseAutoAlignment, RelativeSource={RelativeSource AncestorType={x:Type Compiler:CanvasPanel}, Mode=FindAncestor}}" Value="True">
<Setter Property="Visibility" Value="Visible"/>
</DataTrigger>
<DataTrigger Binding="{Binding UseAutoAlignment, RelativeSource={RelativeSource AncestorType={x:Type Compiler:CanvasPanel}, Mode=FindAncestor}}" Value="False">
<Setter Property="Visibility" Value="Collapsed"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Rectangle.Style>
</Rectangle>
</VisualBrush.Visual>
</VisualBrush>
</Compiler:CanvasPanel.Background>

<Compiler:CanvasPanel.RenderTransform>
<TransformGroup>
<TranslateTransform x:Name="CanvasTranslate"/>
</TransformGroup>
</Compiler:CanvasPanel.RenderTransform>
</Compiler:CanvasPanel>
</Viewbox>
</ScrollViewer>
<ctl:RunCanvas x:Name="runCanvas" Visibility="{Binding RunCanvasVisibility}" />

<avae:TextEditor x:Name="codeEditor" ShowLineNumbers="True" Padding="4" WordWrap="True" IsReadOnly="True" SyntaxHighlighting="XML" BorderThickness="1 0 0 0" BorderBrush="{StaticResource ControlBorderBrush}" Grid.Column="1" Width="480" Visibility="{Binding ElementName=showCode, Path=IsChecked, Converter={x:Static s:BoolToVisibilityConverter.Instance}}"/>
</Grid>
</Border>
@@ -225,9 +228,10 @@
<mypro:PropertyDefinition DisplayName="物料描述" Category="基本属性" DisplayOrder="2" Name="WLText" Description="物料描述"/>
<mypro:PropertyDefinition DisplayName="物料标题" Category="基本属性" DisplayOrder="2" Name="WLTitle" Description="物料标题"/>
<mypro:PropertyDefinition DisplayName="标题" Category="基本属性" DisplayOrder="2" Name="Title" Description="标题"/>
<mypro:PropertyDefinition DisplayName="运行状态" Category="基本属性" DisplayOrder="2" Name="Direction" Description="Direction"/>
<mypro:PropertyDefinition DisplayName="运行状态" Category="基本属性" DisplayOrder="2" Name="Direction" Description="Direction"/>
<mypro:PropertyDefinition DisplayName="Tag" Category="基本属性" DisplayOrder="2" Name="Tag" Description="Tag"/>


<mypro:PropertyDefinition DisplayName="最大值" Category="基本属性" DisplayOrder="3" Name="MaxValue" Description="MaxValue"/>
<mypro:PropertyDefinition DisplayName="最小值" Category="基本属性" DisplayOrder="3" Name="MinValue" Description="MinValue"/>
<mypro:PropertyDefinition DisplayName="最大值" Category="基本属性" DisplayOrder="3" Name="Maximum" Description="Maximum"/>
@@ -265,10 +269,9 @@
<mypro:PropertyDefinition DisplayName="启动测试" Category="基本属性" DisplayOrder="9" Name="TestData"/>
<mypro:PropertyDefinition DisplayName="气缸左执行" Category="基本属性" DisplayOrder="10" Name="LeftTogIsChecked"/>
<mypro:PropertyDefinition DisplayName="气缸右执行" Category="基本属性" DisplayOrder="10" Name="RightTogIsChecked"/>
<mypro:PropertyDefinition DisplayName="背景透明" Category="基本属性" DisplayOrder="10" Name="IsCheckedColor"/>

<mypro:PropertyDefinition DisplayName="数据来源类型" Category="数据绑定模块" DisplayOrder="0" Name="DataSouceType"/>

<mypro:PropertyDefinition DisplayName="数据来源类型" Category="数据绑定模块" DisplayOrder="0" Name="DataSouceType"/>
<mypro:PropertyDefinition DisplayName="设备名称" Category="数据绑定模块" DisplayOrder="0" Name="DeviceName"/>
<mypro:PropertyDefinition DisplayName="接口类型" Category="数据绑定模块" DisplayOrder="1" Name="InterfaceMode"/>
@@ -292,6 +295,11 @@

<mypro:PropertyDefinition DisplayName="前景色" Category="颜色设置" Name="Foreground"/>
<mypro:PropertyDefinition DisplayName="背景色" Category="颜色设置" Name="Background"/>
<mypro:PropertyDefinition DisplayName="填充颜色" Category="颜色设置" Name="BJColor"/>
<mypro:PropertyDefinition DisplayName="边框宽度" Category="基本属性" Name="BKThickness"/>
<mypro:PropertyDefinition DisplayName="虚线绘制" Category="基本属性" Name="BKStrokeDashArray"/>

<mypro:PropertyDefinition DisplayName="边框色" Category="颜色设置" Name="BorderBrush"/>
<mypro:PropertyDefinition DisplayName="填充" Category="基本属性" DisplayOrder="5" Name="WaveFill"/>
<mypro:PropertyDefinition DisplayName="边框粗细" Category="基本属性" DisplayOrder="5" Name="WaveThickness"/>
@@ -312,7 +320,7 @@
</mypro:PropertyGrid.PropertyDefinitions>

<mypro:PropertyGrid.EditorDefinitions>
<mypro:EditorTemplateDefinition TargetProperties="Foreground,Background,BorderBrush,WaveFill,WaveStroke,Fill,Stroke">
<mypro:EditorTemplateDefinition TargetProperties="Foreground,Background,BorderBrush,WaveFill,WaveStroke,Fill,Stroke,BJColor">
<mypro:EditorTemplateDefinition.EditingTemplate>
<DataTemplate>
<mypro:ColorPicker SelectedColor="{Binding Value,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged, Converter={x:Static s:ColorToStringConverter.Instance}}" />


+ 5
- 1
BeDesignerSCADA/Controls/MainCanvasPanel.xaml.cs View File

@@ -487,6 +487,7 @@ namespace BeDesignerSCADA.Controls
}
}


#endregion

#region 不需要的
@@ -588,7 +589,10 @@ namespace BeDesignerSCADA.Controls
//}
#endregion


private void Slider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
}
}




+ 15
- 0
BeDesignerSCADA/Themes/Styles.xaml View File

@@ -361,6 +361,21 @@
<Setter TargetName="txt" Property="Text" Value="气缸控件" />
</DataTrigger>

<DataTrigger Binding="{Binding Name}" Value="TheRectangle">
<Setter TargetName="icon" Property="Kind" Value="AlphaGCircleOutline" />
<Setter TargetName="txt" Property="Text" Value="矩形" />
</DataTrigger>

<DataTrigger Binding="{Binding Name}" Value="TheEllipse">
<Setter TargetName="icon" Property="Kind" Value="AlphaGCircleOutline" />
<Setter TargetName="txt" Property="Text" Value="圆形" />
</DataTrigger>

<DataTrigger Binding="{Binding Name}" Value="TheWuLiaoControl">
<Setter TargetName="icon" Property="Kind" Value="AlphaGCircleOutline" />
<Setter TargetName="txt" Property="Text" Value="物料集合控件" />
</DataTrigger>

</DataTemplate.Triggers>
</DataTemplate>



+ 1
- 1
ComputerTestDemo/ComputerTestDemo.csproj View File

@@ -10,7 +10,7 @@

<ItemGroup>
<PackageReference Include="BPA.Communication" Version="1.0.19" />
<PackageReference Include="BPA.Helper" Version="1.0.11" />
<PackageReference Include="BPA.Helper" Version="1.0.15" />
</ItemGroup>

<ItemGroup>


Loading…
Cancel
Save