You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1469 lines
57 KiB
C#

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

using HighWayIot.Log4net;
using HighWayIot.Plc;
using HighWayIot.Plc.PlcHelper;
using HighWayIot.Repository.domain;
using HighWayIot.Repository.service;
using HighWayIot.Winform.Business;
using HighWayIot.Winform.MainForm;
using HighWayIot.Winform.UserControlPages.RecipeConfigPages;
using HighWayIot.Winform.UserControlPages.SysConfigPages;
using HslCommunication;
using HslCommunication.Profinet.Siemens.S7PlusHelper;
using Models;
using NPOI.SS.Formula.Functions;
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Xml.Schema;
using static Org.BouncyCastle.Math.EC.ECCurve;
namespace HighWayIot.Winform.UserControlPages
{
public partial class RecipeConfigPage : UserControl
{
/// <summary>
/// 配方服务类实例
/// </summary>
private ZxRecipeService zxRecipeService = ZxRecipeService.Instance;
/// <summary>
/// 称重服务类实例
/// </summary>
private ZxWeightService zxWeightService = ZxWeightService.Instance;
/// <summary>
/// 配方服务类实例
/// </summary>
private ZxMaterialService zxMaterialService = ZxMaterialService.Instance;
/// <summary>
/// 配方字段服务类实例
/// </summary>
private ZxRecipeParaService zxRecipeParaService = ZxRecipeParaService.Instance;
/// <summary>
/// 工位配方字段服务类实例
/// </summary>
private ZxRecipePositionParaService zxRecipePositionParaService = ZxRecipePositionParaService.Instance;
/// <summary>
/// 配方同步服务类实例
/// </summary>
private ZxMesPlanTransferService zxMesPlanTransferService = ZxMesPlanTransferService.Instance;
/// <summary>
/// 开炼机胶料配置
/// </summary>
private ZxOpenMixMaterialService zxOpenMixMaterialService = ZxOpenMixMaterialService.Instance;
/// <summary>
/// 开炼机胶料配置列表
/// </summary>
private List<ZxOpenMixMaterialEntity> openMixConfig;
/// <summary>
/// 配方字段实例
/// </summary>
private ZxRecipeParaEntity zxRecipeParaEntity = new ZxRecipeParaEntity();
/// <summary>
/// 工位配方字段实例
/// </summary>
private List<ZxRecipePositionParaEntity> zxRecipePositionParaEntity = new List<ZxRecipePositionParaEntity>();
/// <summary>
/// 称重DataGridView数据源
/// </summary>
private List<WeightDataSourceEntity> weightDataSourceEntities;
/// <summary>
/// 配方列表
/// </summary>
private List<ZxRecipeEntity> RecipeLists;
/// <summary>
/// 称量列表
/// </summary>
private List<ZxWeightEntity> WeightLists;
/// <summary>
/// 现所选配方号
/// </summary>
private string NowRecipeCode;
/// <summary>
/// 配方字段剪切板
/// </summary>
private ZxRecipeParaEntity ParaCopyBoard = new ZxRecipeParaEntity();
/// <summary>
/// 工位全部配方字段剪切板
/// </summary>
private List<ZxRecipePositionParaEntity> PositionParaCopyBoard = new List<ZxRecipePositionParaEntity>();
/// <summary>
/// 工位单个配方字段剪切板
/// </summary>
private ZxRecipePositionParaEntity SingalPositionParaCopyBoard;
/// <summary>
/// PLC实例
/// </summary>
private RecipeParaHelper recipeParaHelper = new RecipeParaHelper();
public RecipeConfigPage()
{
InitializeComponent();
Init();
}
private void Init()
{
RecipeDataGridView.AutoGenerateColumns = false;
WeightDataGridView.AutoGenerateColumns = false;
RecipeLists = zxRecipeService.GetRecipeInfos();
RecipeDataGridView.DataSource = null;
RecipeDataGridView.DataSource = RecipeLists.OrderBy(x => x.RecipeName).ToList();
NowRecipeCode = RecipeDataGridView.Rows[0].Cells["RecipeCode"].Value.ToString();
InitPositionEntities();
//try
//{
// OperateResult res = PlcConnect.ReadByte2("D200", 1);
// if (res.IsSuccess)
// {
// //读取SPEC编号
// PlcSpecNoLabel.Text = PlcConnect.ReadUInt322("D206").Content.ToString();
// //读取SPEC名称
// PlcSpecNameLabel.Text = PlcConnect.ReadString2("D290", 10).Content.ToString();
// }
// else
// {
// MessageBox.Show(res.Message);
// }
//}
//catch
//{
// PlcSpecNoLabel.Text = "PLC连接失败";
// PlcSpecNameLabel.Text = "PLC连接失败";
//}
openMixConfig = zxOpenMixMaterialService.GetInfos();
Station1MaterialName.Text = openMixConfig.Single(x => x.StationNo == 1).MaterialName;
Station2MaterialName.Text = openMixConfig.Single(x => x.StationNo == 2).MaterialName;
Station3MaterialName.Text = openMixConfig.Single(x => x.StationNo == 3).MaterialName;
Station4MaterialName.Text = openMixConfig.Single(x => x.StationNo == 4).MaterialName;
Station5MaterialName.Text = openMixConfig.Single(x => x.StationNo == 5).MaterialName;
}
#region 配方信息
/// <summary>
/// 所选配方内容更改事件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void RecipeDataGridView_SelectionChanged(object sender, EventArgs e)
{
int a = RecipeDataGridView.CurrentRow.Index;
NowRecipeCode = RecipeDataGridView.Rows[a].Cells["RecipeCode"].Value.ToString();
SpecNoLabel.Text = RecipeDataGridView.Rows[a].Cells["RecipeSpecCode"].Value.ToString();
SpecNameLabel.Text = RecipeDataGridView.Rows[a].Cells["RecipeSpecName"].Value.ToString();
WeightLists = zxWeightService.GetWeightInfos(NowRecipeCode);
//WeightToDataSource();
WeightDataGridView.DataSource = null;
WeightDataGridView.DataSource = WeightLists;
ParaRefresh();
}
/// <summary>
/// 添加配方信息
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void AddRecipeButton_Click(object sender, EventArgs e)
{
AddRecipeForm form = new AddRecipeForm();
if (form.ShowDialog() == DialogResult.OK)
{
if (form.CloseValue == null)
{
return;
}
//PLC字段更新
ZxRecipeParaEntity paraEntity = new ZxRecipeParaEntity()
{
SpecCode = form.CloseValue.RecipeSpecCode,
SpecName = form.CloseValue.RecipeSpecName,
RecipeCode = form.CloseValue.RecipeCode,
LightWidth = (int)form.CloseValue.FixedWidth,
RimInch = (int)form.CloseValue.SizeKind,
};
zxRecipeParaService.InsertRecipeParaInfo(paraEntity);
RecipeLists = zxRecipeService.GetRecipeInfos();
RecipeDataGridView.DataSource = null;
RecipeDataGridView.DataSource = RecipeLists.OrderBy(x => x.RecipeName).ToList();
}
}
/// <summary>
/// 删除配方信息
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void DeleteRecipeButton_Click(object sender, EventArgs e)
{
int a = RecipeDataGridView.CurrentRow.Index;
//string s = RecipeDataGridView.Rows[a].Cells["RecipeCode"].Value.ToString();
int id;
try
{
id = int.Parse(RecipeDataGridView.Rows[a].Cells["RId"].Value.ToString());
}
catch (Exception ex)
{
MessageBox.Show("ID转换发生错误" + ex.Message);
return;
}
if (MessageBox.Show($"确定要删除编号为 [{NowRecipeCode}] 的配方信息?", "确认", MessageBoxButtons.OKCancel) == DialogResult.Cancel)
{
return;
}
//删除成型信息
if (zxWeightService.GetWeightInfos(NowRecipeCode).Count > 0)
{
if (MessageBox.Show("是否要删除其关联的所有成型信息?", "确认", MessageBoxButtons.OKCancel) == DialogResult.OK)
{
if (zxWeightService.DeleteWeightInfoByRecipeCode(NowRecipeCode))
{
MessageBox.Show("成型信息删除成功");
SqlLogHelper.AddLog($"成型信息删除成功 [{NowRecipeCode}]");
}
else
{
MessageBox.Show("称量信息删除失败!请检查数据库连接情况");
}
}
}
//删除配方字段信息
if (!zxRecipeParaService.DeleteRecipeParaInfoByRecipeCode(NowRecipeCode))
{
MessageBox.Show("配方信息删除失败");
}
if (!zxRecipePositionParaService.DeleteRecipePositionParaInfoByRecipeCode(NowRecipeCode))
{
MessageBox.Show("配方工位信息删除失败");
}
//删除硫化配方防止报错
List<ZxSchedulingEntity> schedulingEntity = ZxSchedulingService.Instance.GetSchedulingInfo();
var updateInfos = schedulingEntity.Where(x => x.RecipeCode1 == NowRecipeCode || x.RecipeCode2 == NowRecipeCode).ToList();
foreach (var entity in updateInfos)
{
if (entity.RecipeCode1 == NowRecipeCode)
{
entity.RecipeCode1 = string.Empty;
entity.RecipeName1 = string.Empty;
}
if (entity.RecipeCode2 == NowRecipeCode)
{
entity.RecipeCode2 = string.Empty;
entity.RecipeName2 = string.Empty;
}
}
ZxSchedulingService.Instance.UpdateSchedulingInfo(updateInfos);
if (zxRecipeService.DeleteRecipeInfoById(id))
{
MessageBox.Show("配方信息删除成功!");
SqlLogHelper.AddLog($"成型信息删除成功 [{NowRecipeCode}]");
}
else
{
MessageBox.Show("配方信息删除失败!请检查数据库连接情况");
}
RecipeLists = zxRecipeService.GetRecipeInfos();
RecipeDataGridView.DataSource = null;
RecipeDataGridView.DataSource = RecipeLists.OrderBy(x => x.RecipeName).ToList();
}
/// <summary>
/// 修改配方信息
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void UpdateRecipeButton_Click(object sender, EventArgs e)
{
DataGridViewRow nowRow = RecipeDataGridView.CurrentRow;
if (MessageBox.Show($"确认要更改编号为 [{nowRow.Cells["RecipeCode"].Value.ToString()}] 配方的数据吗", "确认", MessageBoxButtons.OKCancel) == DialogResult.Cancel)
{
return;
}
ZxRecipeEntity entity = new ZxRecipeEntity();
try
{
entity.Id = int.Parse(nowRow.Cells["RId"].Value.ToString().Trim());
entity.RecipeCode = nowRow.Cells["RecipeCode"].Value.ToString().Trim();
entity.RecipeName = nowRow.Cells["RecipeName"].Value.ToString().Trim();
entity.RecipeSpecCode = nowRow.Cells["RecipeSpecCode"].Value.ToString().Trim();
entity.RecipeSpecName = nowRow.Cells["RecipeSpecName"].Value.ToString().Trim();
entity.SizeKind = int.Parse(Convert.ToString(nowRow.Cells["SizeKind"].Value) ?? "0");
entity.FixedWidth = int.Parse(Convert.ToString(nowRow.Cells["FixedWidth"].Value) ?? "0");
entity.WeightError = float.Parse(Convert.ToString(nowRow.Cells["WeightError"].Value) ?? "0");
//entity.BatchCode = nowRow.Cells["BatchCode"].Value.ToString().Trim();
entity.IsUse = bool.Parse(Convert.ToString(nowRow.Cells["IsUse"].Value) ?? "0");
entity.IsDeleted = false;
}
catch (Exception ex)
{
MessageBox.Show("数据格式错误!" + ex.Message);
return;
}
if (zxRecipeService.UpdateRecipeInfo(entity))
{
//PLC字段更新
ZxRecipeParaEntity paraentity = zxRecipeParaService.GetRecipeParaInfoByRecipeCode(entity.RecipeCode).FirstOrDefault();
if(paraentity != null)
{
paraentity.RimInch = entity.SizeKind;
paraentity.LightWidth = (int)entity.FixedWidth;
paraentity.SpecCode = entity.RecipeSpecName;
paraentity.SpecName = entity.RecipeSpecName;
zxRecipeParaService.UpdateRecipeParaInfo(paraentity);
}
MessageBox.Show("配方更新成功!");
SqlLogHelper.AddLog($"配方更新成功 [{NowRecipeCode}]");
}
else
{
MessageBox.Show("配方更新失败!");
}
RecipeLists = zxRecipeService.GetRecipeInfos();
RecipeDataGridView.DataSource = null;
RecipeDataGridView.DataSource = RecipeLists.OrderBy(x => x.RecipeName).ToList();
}
/// <summary>
/// 刷新配方信息
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void RefreshRecipeButton_Click(object sender, EventArgs e)
{
RecipeLists = zxRecipeService.GetRecipeInfos();
RecipeDataGridView.DataSource = null;
RecipeDataGridView.DataSource = RecipeLists.OrderBy(x => x.RecipeName).ToList();
}
#endregion
#region 称量信息
/// <summary>
/// 添加称量信息
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void AddWeightButton_Click(object sender, EventArgs e)
{
if (RecipeDataGridView.CurrentRow == null)
{
MessageBox.Show("请先选择一条配方!");
return;
}
AddWeightForm form = new AddWeightForm(NowRecipeCode);
if (form.ShowDialog() == DialogResult.OK)
{
if (form.OutValue == null)
{
return;
}
//连同更新PLC字段信息
var config = openMixConfig.Where(x => x.MaterialName == form.OutValue.MaterialName).FirstOrDefault();
if (config != null)
{
//更新公众参数
ZxRecipeParaEntity recipePara = zxRecipeParaService.GetRecipeParaInfoByRecipeCode(form.OutValue.RecipeCode).FirstOrDefault();
//自动工位选择
var prop = recipePara.GetType().GetProperty($"S{config.StationNo + 1}");
if (prop != null)
{
prop.SetValue(recipePara, true);
}
//自动包边选择
if (!(form.OutValue.SetLayer2 == 0
|| form.OutValue.SetLayer2 == null
|| form.OutValue.SetWidth2 == null
|| form.OutValue.SetWidth2 == 0))
{
var propp = recipePara.GetType().GetProperty($"B{config.StationNo - 1}");
if (propp != null)
{
propp.SetValue(recipePara, true);
}
}
if (!(form.OutValue.SetLayer3 == 0
|| form.OutValue.SetLayer3 == null
|| form.OutValue.SetWidth3 == null
|| form.OutValue.SetWidth3 == 0))
{
var propp = recipePara.GetType().GetProperty($"B{config.StationNo + 4}");
if (propp != null)
{
propp.SetValue(recipePara, true);
}
}
//设置胎体重量
if (form.OutValue.MaterialType == "胎面胶")
{
recipePara.TireWeight = Convert.ToSingle(form.OutValue.SetWeight);
switch (config.StationNo)
{
case 3:
recipePara.S7 = true;
break;
case 4:
recipePara.S8 = true;
break;
case 5:
recipePara.S9 = true;
break;
default:
break;
}
}
zxRecipeParaService.UpdateRecipeParaInfo(recipePara);
//更新工位字段
var positionInfo = zxRecipePositionParaService.GetRecipePositionParaInfos(x => x.Position == config.StationNo && x.RecipeCode == NowRecipeCode);
if (positionInfo.Count == 0) //如果不存在就新增
{
ZxRecipePositionParaEntity zxRecipePositionParaEntity = new ZxRecipePositionParaEntity()
{
RecipeCode = NowRecipeCode,
Position = config.StationNo,
E1 = 15,
E2 = 52,
E5 = form.OutValue.SetLayer * 10,
E9 = form.OutValue.SetWidth,
E6 = form.OutValue.SetLayer2 * 10,
E7 = form.OutValue.SetWidth2,
E3 = form.OutValue.SetLayer3 * 10,
E4 = form.OutValue.SetWidth3,
E10 = 800,
E8 = 300
};
zxRecipePositionParaService.InsertRecipePositionParaInfo(zxRecipePositionParaEntity);
}
else //存在就更新
{
var entity = positionInfo.FirstOrDefault();
entity.E5 = form.OutValue.SetLayer * 10;
entity.E9 = (int)form.OutValue.SetWidth;
entity.E6 = form.OutValue.SetLayer2 * 10;
entity.E7 = (int)form.OutValue.SetWidth2;
entity.E3 = form.OutValue.SetLayer3 * 10;
entity.E4 = (int)form.OutValue.SetWidth3;
zxRecipePositionParaService.UpdateRecipePositionParaInfo(entity);
}
}
}
ParaRefresh();
WeightLists = zxWeightService.GetWeightInfos(NowRecipeCode);
//WeightToDataSource();
WeightDataGridView.DataSource = null;
WeightDataGridView.DataSource = WeightLists;
}
/// <summary>
/// 删除称量信息
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void DeleteWeightButton_Click(object sender, EventArgs e)
{
int a = WeightDataGridView.CurrentRow.Index;
string s2 = WeightDataGridView.Rows[a].Cells["MaterialCode"].Value.ToString();
int id;
try
{
id = int.Parse(WeightDataGridView.Rows[a].Cells["Id"].Value.ToString());
}
catch (Exception ex)
{
MessageBox.Show("ID转换发生错误" + ex.Message);
return;
}
if (MessageBox.Show($"确定要删除配方编号为 [{NowRecipeCode}] 物料编码为 [{s2}] 的成型信息?", "确认", MessageBoxButtons.OKCancel) == DialogResult.Cancel)
{
return;
}
if (zxWeightService.DeleteWeightInfoById(id))
{
MessageBox.Show("成型信息删除成功!");
SqlLogHelper.AddLog($"成型信息删除成功 配方编号为[{NowRecipeCode}] 物料编码为[{s2}]");
}
else
{
MessageBox.Show("配方信息删除失败!请检查数据库连接情况");
}
WeightLists = zxWeightService.GetWeightInfos(NowRecipeCode);
//WeightToDataSource();
WeightDataGridView.DataSource = null;
WeightDataGridView.DataSource = WeightLists;
}
/// <summary>
/// 修改称量信息
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void UpdateWeightButton_Click(object sender, EventArgs e)
{
DataGridViewRow nowRow = WeightDataGridView.CurrentRow;
if (MessageBox.Show($"确认要更改配方编号为 [{NowRecipeCode}] 物料编号为 [{nowRow.Cells["MaterialCode"].Value.ToString()}] 的数据吗"
, "确认"
, MessageBoxButtons.OKCancel)
== DialogResult.Cancel)
{
return;
}
ZxWeightEntity entity = new ZxWeightEntity();
try
{
entity.Id = int.Parse(nowRow.Cells["Id"].Value.ToString().Trim());
entity.RecipeCode = NowRecipeCode;
entity.MaterialCode = nowRow.Cells["MaterialCode"].Value.ToString().Trim();
entity.MaterialName = nowRow.Cells["MaterialName"].Value.ToString().Trim();
entity.MaterialType = nowRow.Cells["MaterialType"].Value.ToString().Trim();
entity.SetThickness = decimal.Parse(Convert.ToString(nowRow.Cells["SetThickness"].Value ?? "0"));
entity.SetWidth = int.Parse(Convert.ToString(nowRow.Cells["SetWidth1"].Value ?? "0"));
entity.SetWidth2 = int.Parse(Convert.ToString(nowRow.Cells["SetWidth2"].Value ?? "0"));
entity.SetWidth3 = int.Parse(Convert.ToString(nowRow.Cells["SetWidth3"].Value ?? "0"));
entity.SetLayer = int.Parse(Convert.ToString(nowRow.Cells["SetLayer1"].Value ?? "0"));
entity.SetLayer2 = int.Parse(Convert.ToString(nowRow.Cells["SetLayer2"].Value ?? "0"));
entity.SetLayer3 = int.Parse(Convert.ToString(nowRow.Cells["SetLayer3"].Value ?? "0"));
entity.SetWeight = int.Parse(Convert.ToString(nowRow.Cells["SetWeight"].Value ?? "0"));
entity.SetError = decimal.Parse(Convert.ToString(nowRow.Cells["SetError"].Value ?? "0"));
//entity.IsUse = bool.Parse(Convert.ToString(nowRow.Cells["WeightIsUse"].Value));
entity.IsDeleted = false;
}
catch (Exception ex)
{
MessageBox.Show("数据格式错误!" + ex.Message);
return;
}
if (zxWeightService.UpdateWeightInfo(entity))
{
var config = openMixConfig.Where(x => x.MaterialName == entity.MaterialName).FirstOrDefault();
ZxRecipeParaEntity recipePara = zxRecipeParaService.GetRecipeParaInfoByRecipeCode(entity.RecipeCode).FirstOrDefault();
//自动包边选择
if (!(entity.SetLayer2 == 0
|| entity.SetLayer2 == null
|| entity.SetWidth2 == null
|| entity.SetWidth2 == 0))
{
var propp = recipePara.GetType().GetProperty($"B{config.StationNo - 1}");
if (propp != null)
{
propp.SetValue(recipePara, true);
}
}
else
{
var propp = recipePara.GetType().GetProperty($"B{config.StationNo - 1}");
if (propp != null)
{
propp.SetValue(recipePara, false);
}
}
if (!(entity.SetLayer3 == 0
|| entity.SetLayer3 == null
|| entity.SetWidth3 == null
|| entity.SetWidth3 == 0))
{
var propp = recipePara.GetType().GetProperty($"B{config.StationNo + 4}");
if (propp != null)
{
propp.SetValue(recipePara, true);
}
}
else
{
var propp = recipePara.GetType().GetProperty($"B{config.StationNo + 4}");
if (propp != null)
{
propp.SetValue(recipePara, false);
}
}
//是否更新重量
if (entity.MaterialType == "胎面胶")
{
recipePara.TireWeight = Convert.ToSingle(entity.SetWeight);
}
zxRecipeParaService.UpdateRecipeParaInfo(recipePara);
//连同更新配方字段信息
if (config != null)
{
var positionInfo = zxRecipePositionParaService.GetRecipePositionParaInfos(x => x.Position == config.StationNo && x.RecipeCode == NowRecipeCode);
if (positionInfo.Count == 0)
{
ZxRecipePositionParaEntity zxRecipePositionParaEntity = new ZxRecipePositionParaEntity() //没有就添加
{
RecipeCode = NowRecipeCode,
Position = config.StationNo,
E5 = entity.SetLayer * 10,
E9 = (int)entity.SetWidth,
E6 = entity.SetLayer2 * 10,
E7 = (int)entity.SetWidth2,
E3 = entity.SetLayer3 * 10,
E4 = (int)entity.SetWidth3,
};
zxRecipePositionParaService.InsertRecipePositionParaInfo(zxRecipePositionParaEntity);
}
else //有就修改
{
var positionEntity = positionInfo.FirstOrDefault();
positionEntity.E5 = entity.SetLayer * 10;
positionEntity.E9 = (int)entity.SetWidth;
positionEntity.E6 = entity.SetLayer2 * 10;
positionEntity.E7 = (int)entity.SetWidth2;
positionEntity.E3 = entity.SetLayer3 * 10;
positionEntity.E4 = (int)entity.SetWidth3;
zxRecipePositionParaService.UpdateRecipePositionParaInfo(positionEntity);
}
}
MessageBox.Show("成型信息更新成功!");
SqlLogHelper.AddLog($"成型信息更新成功 配方编号为[{NowRecipeCode}] 物料编码为[{entity.MaterialCode}]");
}
else
{
MessageBox.Show("成型信息更新失败!");
}
ParaRefresh();
WeightLists = zxWeightService.GetWeightInfos(NowRecipeCode);
//WeightToDataSource();
WeightDataGridView.DataSource = null;
WeightDataGridView.DataSource = WeightLists;
}
/// <summary>
/// 刷新称量信息
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void RefreshWeightButton_Click(object sender, EventArgs e)
{
WeightLists = zxWeightService.GetWeightInfos(NowRecipeCode);
//WeightToDataSource();
WeightDataGridView.DataSource = null;
WeightDataGridView.DataSource = WeightLists;
}
/// <summary>
/// 称重数据关联物料数据
/// </summary>
private void WeightToDataSource()
{
weightDataSourceEntities = new List<WeightDataSourceEntity>();
foreach (var item in WeightLists)
{
var entitys = zxMaterialService.GetEntityByMaterialCode(item.MaterialCode);
if (entitys == null && entitys.Count == 0)
{
return;
}
if (entitys.Count > 1)
{
MessageBox.Show("请检查是否有多条物料编号相同的可用物料");
return;
}
ZxMaterialEntity material = new ZxMaterialEntity();
if (entitys.Count > 0)
{
material = entitys[0];
}
weightDataSourceEntities.Add(new WeightDataSourceEntity()
{
Id = item.Id,
RecipeCode = item.RecipeCode,
MaterialCode = item.MaterialCode,
MaterialName = material.MaterialName,
MaterialType = material.MaterialType,
MaterialChildType = material.ChildType,
SetThickness = item.SetThickness,
SetWidth = item.SetWidth,
SetLayer = item.SetLayer,
SetWeight = item.SetWeight,
SetError = item.SetError,
IsUse = item.IsUse,
});
}
}
#endregion
#region 参数设置
/// <summary>
/// 参数刷新
/// </summary>
private void ParaRefresh()
{
//初始化工位参数类
InitPositionEntities();
//设置参数
var paraData = zxRecipeParaService.GetRecipeParaInfoByRecipeCode(NowRecipeCode);
int flag = GetSelectIndex();
var positionParaData = zxRecipePositionParaService.GetRecipePositionParaInfos(x => x.RecipeCode == NowRecipeCode);
//没有就全0
if (paraData.Count == 0)
{
SetPublicParaValue(new ZxRecipeParaEntity());
zxRecipeParaEntity = new ZxRecipeParaEntity();
}
//有就显示
else if (paraData.Count == 1)
{
SetPublicParaValue(paraData[0]);
zxRecipeParaEntity = paraData[0];
}
//有多条设为第一条
else
{
MessageBox.Show("存在多条未删除的相同公共配方字段信息!将设置为第一条。点击清除脏数据");
SetPublicParaValue(paraData[0]);
zxRecipeParaEntity = paraData[0];
}
//没有就全0
if (positionParaData.Count == 0)
{
SetPrivateParaValue(new ZxRecipePositionParaEntity());
}
else
{
foreach (var item in positionParaData)
{
ChangePositionEntities(item);
}
SetPrivateParaValue(zxRecipePositionParaEntity.Where(x => x.Position == flag).FirstOrDefault());
}
}
/// <summary>
/// 参数保存
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void SaveParaButton_Click(object sender, EventArgs e)
{
if (MessageBox.Show($"确定要保存配方编号为 [{NowRecipeCode}] 的配方的参数?", "确认", MessageBoxButtons.OKCancel) == DialogResult.Cancel)
{
return;
}
var index = GetSelectIndex();
//从前端更新值
GetPublicParaValue();
GetPrivateParaValue(index);
//查重
var paraEntity = zxRecipeParaService.GetRecipeParaInfoByRecipeCode(NowRecipeCode);
var positionParaEntity = zxRecipePositionParaService.GetRecipePositionParaInfoByRecipeCode(NowRecipeCode);
zxRecipeParaEntity.RecipeCode = NowRecipeCode;
//保存公共参数
var flag1 = true;
if (paraEntity.Count == 0) //没有就插入
{
flag1 = zxRecipeParaService.InsertRecipeParaInfo(zxRecipeParaEntity);
}
else if (paraEntity.Count == 1) //有就更新
{
zxRecipeParaEntity.Id = paraEntity[0].Id;
flag1 = zxRecipeParaService.UpdateRecipeParaInfo(zxRecipeParaEntity);
}
else //多条更新第一条
{
zxRecipeParaEntity.Id = paraEntity[0].Id;
flag1 = zxRecipeParaService.UpdateRecipeParaInfo(zxRecipeParaEntity);
MessageBox.Show("存在多条未删除的相同公共配方字段信息!将设置为第一条。点击清除脏数据");
}
//保存贴合参数
var flag2 = true;
foreach (var item in zxRecipePositionParaEntity)
{
item.RecipeCode = NowRecipeCode;
var count = positionParaEntity.Count(x => x.Position == item.Position);
//如果没有
if (count == 0)
{
flag2 = zxRecipePositionParaService.InsertRecipePositionParaInfo(item);
}
else //有 多条存第一条
{
item.Id = positionParaEntity.FirstOrDefault(x => x.Position == item.Position).Id;
flag2 = zxRecipePositionParaService.UpdateRecipePositionParaInfo(item);
if (count != 1) //多条提示
{
MessageBox.Show("存在多条未删除的相同公共配方字段信息!将设置为第一条。点击清除脏数据");
}
}
if (!flag2) break;
}
if (flag1 && flag2)
{
BaseForm.LogRefreshAction.Invoke("更新成功");
SqlLogHelper.AddLog($"配方参数保存成功 配方编号为[{NowRecipeCode}]");
}
else
{
BaseForm.LogRefreshAction.Invoke("更新失败");
}
//保存贴合参数
}
/// <summary>
/// 全部的工位参数刷新
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void PositionSelectRefreshButton_Click(object sender, EventArgs e)
{
if (MessageBox.Show("确定要按照配方信息称量信息更新所有PLC配方参数可能会导致数据丢失不可恢复", "确认", MessageBoxButtons.OKCancel) != DialogResult.OK)
{
return;
}
try
{
//获取所有称重信息
List<ZxWeightEntity> allWeightData = zxWeightService.GetWeightInfos();
List<ZxRecipeEntity> allRecipeData = zxRecipeService.GetRecipeInfos();
List<ZxRecipeParaEntity> allParaData = zxRecipeParaService.GetRecipeParaInfos();
List<ZxRecipePositionParaEntity> allPositionData = zxRecipePositionParaService.GetRecipePositionParaInfos();
//先把公共选择参数全部归零
foreach(ZxRecipeParaEntity para in allParaData)
{
for (int i = 0; i < 10; i++)
{
var propS = para.GetType().GetProperty($"S{i}");
if (propS != null)
{
propS.SetValue(para, false);
}
var propB = para.GetType().GetProperty($"B{i}");
if (propB != null)
{
propB.SetValue(para, false);
}
}
var pE = allRecipeData.Where(x => x.RecipeCode == para.RecipeCode).FirstOrDefault();
if (pE != null)
{
para.RimInch = pE.SizeKind;
para.LightWidth = (int?)pE.FixedWidth;
}
}
foreach (ZxWeightEntity entity in allWeightData)
{
//工位参数
int positionNo;
var openMixinfo = openMixConfig.Where(x => x.MaterialName == entity.MaterialName).FirstOrDefault();
if(openMixinfo == null)
{
continue;
}
else
{
positionNo = openMixinfo.StationNo;
}
allPositionData.Where(x => x.RecipeCode == entity.RecipeCode && x.Position == positionNo)
.ToList().ForEach(p =>
{
p.E5 = entity.SetLayer * 10;
p.E9 = (int?)entity.SetWidth;
p.E6 = entity.SetLayer2 * 10;
p.E7 = (int?)entity.SetWidth2;
p.E3 = entity.SetLayer3 * 10;
p.E4 = (int?)entity.SetWidth3;
});
//公共参数
allParaData.Where(x => x.RecipeCode == entity.RecipeCode)
.ToList().ForEach(p =>
{
//自动工位选择
var prop = p.GetType().GetProperty($"S{positionNo + 1}");
if (prop != null)
{
prop.SetValue(p, true);
}
//自动包边选择
if (!(entity.SetLayer2 == 0
|| entity.SetLayer2 == null
|| entity.SetWidth2 == null
|| entity.SetWidth2 == 0))
{
var propp = p.GetType().GetProperty($"B{positionNo - 1}");
if (propp != null)
{
propp.SetValue(p, true);
}
}
if (!(entity.SetLayer3 == 0
|| entity.SetLayer3 == null
|| entity.SetWidth3 == null
|| entity.SetWidth3 == 0))
{
var propp = p.GetType().GetProperty($"B{positionNo + 4}");
if (propp != null)
{
propp.SetValue(p, true);
}
}
//设置胎体重量
if (entity.MaterialType == "胎面胶")
{
p.TireWeight = Convert.ToSingle(entity.SetWeight);
switch (positionNo)
{
case 3:
p.S7 = true;
break;
case 4:
p.S8 = true;
break;
case 5:
p.S9 = true;
break;
default:
break;
}
}
});
}
if (!zxRecipeParaService.UpdateRangeRecipeParaInfo(allParaData))
{
MessageBox.Show("修改失败");
return;
}
if (!zxRecipePositionParaService.UpdateRecipePositionParaInfo(allPositionData))
{
MessageBox.Show("修改失败");
return;
}
MessageBox.Show("修改成功");
}
catch (Exception ex)
{
MessageBox.Show("修改失败 ERROR:" + ex.Message);
}
}
/// <summary>
/// 初始化工位参数
/// </summary>
private void InitPositionEntities()
{
zxRecipePositionParaEntity.Clear();
zxRecipePositionParaEntity.Add(new ZxRecipePositionParaEntity()
{
Position = 1
});
zxRecipePositionParaEntity.Add(new ZxRecipePositionParaEntity()
{
Position = 2
});
zxRecipePositionParaEntity.Add(new ZxRecipePositionParaEntity()
{
Position = 3
});
zxRecipePositionParaEntity.Add(new ZxRecipePositionParaEntity()
{
Position = 4
});
zxRecipePositionParaEntity.Add(new ZxRecipePositionParaEntity()
{
Position = 5
});
}
/// <summary>
/// 替换工位信息中的元素
/// </summary>
/// <param name="entity"></param>
private void ChangePositionEntities(ZxRecipePositionParaEntity entity)
{
int index = zxRecipePositionParaEntity.FindIndex(x => x.Position == entity.Position);
if (index == -1)
{
BaseForm.LogRefreshAction.Invoke($"[{entity.RecipeCode}]工位信息数据未找到");
return;
}
zxRecipePositionParaEntity[index] = entity;
}
/// <summary>
/// 设置显示的贴合参数字段值
/// </summary>
/// <param name="entity"></param>
private void SetPrivateParaValue(ZxRecipePositionParaEntity entity)
{
E1TextBox.Text = GeneralUtils.IntEmptyOrToString(entity.E1);
E2TextBox.Text = GeneralUtils.IntEmptyOrToString(entity.E2);
E3TextBox.Text = GeneralUtils.IntEmptyOrToString(entity.E3);
E4TextBox.Text = GeneralUtils.IntEmptyOrToString(entity.E4);
E5TextBox.Text = GeneralUtils.IntEmptyOrToString(entity.E5);
E6TextBox.Text = GeneralUtils.IntEmptyOrToString(entity.E6);
E7TextBox.Text = GeneralUtils.IntEmptyOrToString(entity.E7);
E8TextBox.Text = GeneralUtils.IntEmptyOrToString(entity.E8);
E9TextBox.Text = GeneralUtils.IntEmptyOrToString(entity.E9);
E10TextBox.Text = GeneralUtils.IntEmptyOrToString(entity.E10);
}
/// <summary>
/// 设置公共参数
/// </summary>
/// <param name="paraEntity"></param>
private void SetPublicParaValue(ZxRecipeParaEntity paraEntity)
{
S2Check.Checked = paraEntity.S2 ?? false;
S3Check.Checked = paraEntity.S3 ?? false;
S4Check.Checked = paraEntity.S4 ?? false;
S5Check.Checked = paraEntity.S5 ?? false;
S6Check.Checked = paraEntity.S6 ?? false;
S7Check.Checked = paraEntity.S7 ?? false;
S8Check.Checked = paraEntity.S8 ?? false;
S9Check.Checked = paraEntity.S9 ?? false;
B0Check.Checked = paraEntity.B0 ?? false;
B1Check.Checked = paraEntity.B1 ?? false;
B2Check.Checked = paraEntity.B2 ?? false;
B3Check.Checked = paraEntity.B3 ?? false;
B4Check.Checked = paraEntity.B4 ?? false;
B5Check.Checked = paraEntity.B5 ?? false;
B6Check.Checked = paraEntity.B6 ?? false;
B7Check.Checked = paraEntity.B7 ?? false;
B8Check.Checked = paraEntity.B8 ?? false;
B9Check.Checked = paraEntity.B9 ?? false;
RimInchTextBox.Text = GeneralUtils.IntEmptyOrToString(paraEntity.RimInch);
LightWidthTextBox.Text = GeneralUtils.IntEmptyOrToString(paraEntity.LightWidth);
SlowDistanceTextBox.Text = GeneralUtils.IntEmptyOrToString(paraEntity.SlowDistance);
StopDistanceTextBox.Text = GeneralUtils.IntEmptyOrToString(paraEntity.StopDistance);
TireWeightTextBox.Text = paraEntity.TireWeight == null ? "0" : paraEntity.TireWeight.ToString();
//SpecNoLabel.Text = GeneralUtils.IntEmptyOrToString(paraEntity.SpecCode);
//SpecNameLabel.Text = paraEntity.SpecName;
}
/// <summary>
/// 贴合参数获取值 存到实体
/// </summary>
/// <returns></returns>
private void GetPrivateParaValue(int flag)
{
var e = zxRecipePositionParaEntity.FirstOrDefault(x => x.Position == flag);
e.E1 = GeneralUtils.StringNullOrToInt(E1TextBox.Text);
e.E2 = GeneralUtils.StringNullOrToInt(E2TextBox.Text);
e.E3 = GeneralUtils.StringNullOrToInt(E3TextBox.Text);
e.E4 = GeneralUtils.StringNullOrToInt(E4TextBox.Text);
e.E5 = GeneralUtils.StringNullOrToInt(E5TextBox.Text);
e.E6 = GeneralUtils.StringNullOrToInt(E6TextBox.Text);
e.E7 = GeneralUtils.StringNullOrToInt(E7TextBox.Text);
e.E8 = GeneralUtils.StringNullOrToInt(E8TextBox.Text);
e.E9 = GeneralUtils.StringNullOrToInt(E9TextBox.Text);
e.E10 = GeneralUtils.StringNullOrToInt(E10TextBox.Text);
e.Position = GetSelectIndex();
e.RecipeCode = NowRecipeCode;
ChangePositionEntities(e);
}
/// <summary>
/// 公共参数获取值 存到实体
/// </summary>
/// <returns></returns>
private void GetPublicParaValue()
{
zxRecipeParaEntity.S2 = S2Check.Checked;
zxRecipeParaEntity.S3 = S3Check.Checked;
zxRecipeParaEntity.S4 = S4Check.Checked;
zxRecipeParaEntity.S5 = S5Check.Checked;
zxRecipeParaEntity.S6 = S6Check.Checked;
zxRecipeParaEntity.S7 = S7Check.Checked;
zxRecipeParaEntity.S8 = S8Check.Checked;
zxRecipeParaEntity.S9 = S9Check.Checked;
zxRecipeParaEntity.B0 = B0Check.Checked;
zxRecipeParaEntity.B1 = B1Check.Checked;
zxRecipeParaEntity.B2 = B2Check.Checked;
zxRecipeParaEntity.B3 = B3Check.Checked;
zxRecipeParaEntity.B4 = B4Check.Checked;
zxRecipeParaEntity.B5 = B5Check.Checked;
zxRecipeParaEntity.B6 = B6Check.Checked;
zxRecipeParaEntity.B7 = B7Check.Checked;
zxRecipeParaEntity.B8 = B8Check.Checked;
zxRecipeParaEntity.B9 = B9Check.Checked;
zxRecipeParaEntity.RimInch = GeneralUtils.StringNullOrToInt(RimInchTextBox.Text);
zxRecipeParaEntity.LightWidth = GeneralUtils.StringNullOrToInt(LightWidthTextBox.Text);
zxRecipeParaEntity.SlowDistance = GeneralUtils.StringNullOrToInt(SlowDistanceTextBox.Text);
zxRecipeParaEntity.StopDistance = GeneralUtils.StringNullOrToInt(StopDistanceTextBox.Text);
try
{
zxRecipeParaEntity.TireWeight = float.Parse(TireWeightTextBox.Text == string.Empty ? "0" : TireWeightTextBox.Text);
}
catch
{
MessageBox.Show("胎体重量请输入整数或小数");
}
zxRecipeParaEntity.SpecCode = SpecNoLabel.Text;
zxRecipeParaEntity.SpecName = SpecNameLabel.Text;
}
/// <summary>
/// 工位改变 保存现在的,显示换的
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void PositionRadioBoxChange(object sender, EventArgs e)
{
RadioButton s = sender as RadioButton;
if (s.Checked)
{
int flag = GetSelectIndex();
SetPrivateParaValue(zxRecipePositionParaEntity.Where(x => x.Position == flag).FirstOrDefault());
}
}
/// <summary>
/// 获取选择的工位包边
/// </summary>
/// <returns>选的不对劲就返回0</returns>
private int GetSelectIndex()
{
if (Position1RadioButton.Checked)
{
return 1;
}
if (Position2RadioButton.Checked)
{
return 2;
}
if (Position3RadioButton.Checked)
{
return 3;
}
if (Position4RadioButton.Checked)
{
return 4;
}
if (Position5RadioButton.Checked)
{
return 5;
}
return 0;
}
/// <summary>
/// 暂存工位参数
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void PositionRadioButton_MouseDown(object sender, MouseEventArgs e)
{
int index = GetSelectIndex();
GetPrivateParaValue(index);
BaseForm.LogRefreshAction.Invoke($"[{index.ToString()}] 工位参数已暂存");
}
/// <summary>
/// 公共参数复制
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void CopyParaButton_Click(object sender, EventArgs e)
{
ParaCopyBoard = zxRecipeParaEntity;
NowCopyLabel.Text = NowRecipeCode;
}
/// <summary>
/// 公共参数粘贴
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void PasteParaButton_Click(object sender, EventArgs e)
{
if (ParaCopyBoard == null)
{
MessageBox.Show("剪切板为空!");
return;
}
SetPublicParaValue(ParaCopyBoard);
}
/// <summary>
/// 贴合参数复制
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void CopyPositionButton_Click(object sender, EventArgs e)
{
var index = GetSelectIndex();
GetPrivateParaValue(index);
SingalPositionParaCopyBoard = zxRecipePositionParaEntity.FirstOrDefault(x => x.Position == index);
PositionCopyBoardLabel.Text = index.ToString() + "|" + NowRecipeCode;
}
/// <summary>
/// 贴合参数粘贴
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void PastePositionButton_Click(object sender, EventArgs e)
{
if (SingalPositionParaCopyBoard == null)
{
MessageBox.Show("剪切板为空!");
return;
}
SetPrivateParaValue(SingalPositionParaCopyBoard);
}
/// <summary>
/// 整体复制
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void CopyAllButton_Click(object sender, EventArgs e)
{
int index = GetSelectIndex();
GetPrivateParaValue(index);
ParaCopyBoard = new ZxRecipeParaEntity()
{
S2 = zxRecipeParaEntity.S2 ?? false,
S3 = zxRecipeParaEntity.S3 ?? false,
S4 = zxRecipeParaEntity.S4 ?? false,
S5 = zxRecipeParaEntity.S5 ?? false,
S6 = zxRecipeParaEntity.S6 ?? false,
S7 = zxRecipeParaEntity.S7 ?? false,
S8 = zxRecipeParaEntity.S8 ?? false,
S9 = zxRecipeParaEntity.S9 ?? false,
RimInch = zxRecipeParaEntity.RimInch,
LightWidth = zxRecipeParaEntity.LightWidth,
SlowDistance = zxRecipeParaEntity.SlowDistance,
StopDistance = zxRecipeParaEntity.StopDistance,
TireWeight = zxRecipeParaEntity.TireWeight,
};
PositionParaCopyBoard.Clear();
foreach (var entity in zxRecipePositionParaEntity)
{
var clone = new ZxRecipePositionParaEntity()
{
E1 = entity.E1,
E2 = entity.E2,
E3 = entity.E3,
E4 = entity.E4,
E5 = entity.E5,
E6 = entity.E6,
E7 = entity.E7,
E8 = entity.E8,
E9 = entity.E9,
E10 = entity.E10,
E11 = entity.E11,
E12 = entity.E12,
E13 = entity.E13,
E14 = entity.E14,
E15 = entity.E15,
Position = entity.Position,
};
PositionParaCopyBoard.Add(clone);
}
//PositionParaCopyBoard = zxRecipePositionParaEntity;
NowCopyLabel.Text = NowRecipeCode + " 全复制";
PositionCopyBoardLabel.Text = "全复制";
}
/// <summary>
/// 整体粘贴
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void PasteAllButton_Click(object sender, EventArgs e)
{
if (zxRecipeParaEntity != null && (zxRecipePositionParaEntity != null || zxRecipePositionParaEntity.Count != 8))
{
zxRecipePositionParaEntity = PositionParaCopyBoard;
zxRecipeParaEntity = ParaCopyBoard;
}
else
{
MessageBox.Show("粘贴失败,请重新复制数据");
}
SetPublicParaValue(zxRecipeParaEntity);
SetPrivateParaValue(zxRecipePositionParaEntity.First(x => x.Position == GetSelectIndex()));
}
/// <summary>
/// 清除脏数据
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void ClearDirtyData_Click(object sender, EventArgs e)
{
if (MessageBox.Show($"确定要清除脏数据?", "确认", MessageBoxButtons.OKCancel) == DialogResult.Cancel)
{
return;
}
if (zxRecipeParaService.DeleteDirtyData() &&
zxRecipePositionParaService.DeleteDirtyData())
{
MessageBox.Show("清除成功");
}
else
{
MessageBox.Show("清除失败");
}
}
/// <summary>
/// 上载到plc
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void UploadToPlc_Click(object sender, EventArgs e)
{
if (MessageBox.Show($"是否要将此配方下传到PLC", "确认", MessageBoxButtons.OKCancel) == DialogResult.Cancel)
{
return;
}
if (!PlcConnect.ReadByte2("D200", 1).IsSuccess)
{
MessageBox.Show("PLC未连接");
return;
}
GetPublicParaValue();
GetPrivateParaValue(GetSelectIndex());
if (recipeParaHelper.UploadToPLC(zxRecipeParaEntity, zxRecipePositionParaEntity))
{
MessageBox.Show("下发到PLC成功");
SqlLogHelper.AddLog($"配方参数下发到PLC 配方编号为[{NowRecipeCode}]");
}
else
{
MessageBox.Show("下发到PLC失败");
}
PlcSpecNameLabel.Text = zxRecipeParaEntity.SpecName.Trim();
PlcSpecNoLabel.Text = zxRecipeParaEntity.SpecCode.Trim();
}
/// <summary>
/// 从plc读取
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void DownloadFromPlc_Click(object sender, EventArgs e)
{
if (MessageBox.Show($"是否要从PLC读取配方", "确认", MessageBoxButtons.OKCancel) == DialogResult.Cancel)
{
return;
}
if (!PlcConnect.ReadByte2("D200", 1).IsSuccess)
{
MessageBox.Show("PLC未连接");
return;
}
zxRecipePositionParaEntity = recipeParaHelper.DownLoadFormPlc(ref zxRecipeParaEntity);
SetPublicParaValue(zxRecipeParaEntity);
SetPrivateParaValue(zxRecipePositionParaEntity.First(x => x.Position == GetSelectIndex()));
SqlLogHelper.AddLog($"配方参数从PLC下载到本地 配方编号为[{NowRecipeCode}]");
PlcSpecNameLabel.Text = zxRecipeParaEntity.SpecName.Trim();
PlcSpecNoLabel.Text = zxRecipeParaEntity.SpecCode.Trim();
}
#endregion
}
}