using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.IO; using System.IO.Ports; using System.Linq; using System.Reflection; using System.Text; using System.Threading; using System.Threading.Tasks; using System.Windows.Forms; using BO; using BO.Utils; using BWP.WinFormControl.WeightDataFormat; using Forks.JsonRpc.Client; using MaterialRequisition.Model; using Newtonsoft.Json; namespace MaterialRequisition { public partial class MaterialRequisitionForm : Form, IAfterLogin { public List RoleName { get { return new List() { "车间业务.领料退料" }; } } public Form Generate() { return this; } private List mSetList; private readonly string mDropDownSetsFileName = "MaterialRequisition_DropDownSets.xml"; private readonly string BaseRpcUrl = "/MainSystem/B3ClientService/Rpcs/BillRpc/MaterialRequisitionRecordRpc/"; private DropDownSets mDropDownSets; #region weightNeed SerialPort weightPort; private IDataFormat _dataFormat; private Thread _inQueryThread; private bool _mainProcessIsRun; readonly StringBuilder _dataStrBuilder = new StringBuilder(); #endregion private Thread tdSyncSubmited; private readonly Thread _tcCheckNetStatus; public MaterialRequisitionForm() { InitializeComponent(); dataGridViewUnSubmit.AutoGenerateColumns = false; dataGridViewSubmited.AutoGenerateColumns = false; weightPort = new SerialPort(); this.FormClosing += delegate { if (_inQueryThread != null && _inQueryThread.IsAlive) { DisableWeight(); } if (tdSyncSubmited != null && tdSyncSubmited.IsAlive) tdSyncSubmited.Abort(); if (_tcCheckNetStatus != null && _tcCheckNetStatus.IsAlive) { _tcCheckNetStatus.Abort(); } }; InitCombox(); InitControl(); BindUnSubmitGrid(); tdSyncSubmited = new Thread(SyncSubmited); tdSyncSubmited.Start(); _tcCheckNetStatus = new Thread(CheckNetStatus); _tcCheckNetStatus.Start(); } private bool laseConnection = false; private void CheckNetStatus() { while (true) { try { var newConnection = LoginRpcUtil.TestConnection(500); if (newConnection && laseConnection) { Thread.Sleep(1000); continue; } var png = "stop.png"; if (newConnection) png = "working.png"; var imgPath = Path.Combine(Application.StartupPath, "BWP.WinFormControl.dll"); var s = Assembly.LoadFile(imgPath).GetManifestResourceStream("BWP.WinFormControl.Images." + png); if (this.InvokeRequired) { this.BeginInvoke(new Action(() => { picNetStatus.Image = Image.FromStream(s); picNetStatus.Refresh(); })); } else { picNetStatus.Image = Image.FromStream(s); picNetStatus.Refresh(); } laseConnection = newConnection; } catch (Exception e) { //LogUtil.Error(e.ToString()); } Thread.Sleep(1000); } } private void InitCombox() { if (LoginRpcUtil.TestConnection(500)) { mDropDownSets = GetmDropDownSets(); XmlUtil.SerializerObjToFile(mDropDownSets, mDropDownSetsFileName); } else { mDropDownSets = XmlUtil.DeserializeFromFile(mDropDownSetsFileName); } var shop = mDropDownSets.Details.FirstOrDefault(x => x.Name == DropDownSets.车间); if (shop != null) { cbxWorkShop.DataSource = shop.Details; cbxWorkShop.DisplayMember = "Name"; cbxWorkShop.ValueMember = "ID"; } var unit = mDropDownSets.Details.FirstOrDefault(x => x.Name == DropDownSets.单元); if (unit != null) { cbxWorkUnit.DataSource = unit.Details; cbxWorkUnit.DisplayMember = "Name"; cbxWorkUnit.ValueMember = "ID"; } var store = mDropDownSets.Details.FirstOrDefault(x => x.Name == DropDownSets.仓库); if (store != null) { cbxStore.DataSource = store.Details; cbxStore.DisplayMember = "Name"; cbxStore.ValueMember = "ID"; } var batch = mDropDownSets.Details.FirstOrDefault(x => x.Name == DropDownSets.批次); if (batch != null) { cbxBatch.DataSource = batch.Details; cbxBatch.DisplayMember = "Name"; cbxBatch.ValueMember = "ID"; } } private DropDownSets GetmDropDownSets() { var sets = new DropDownSets(); var wrokUnitSet = GetWrokUnitSet(); var wrokShopSet = GetWrokShopSet(); var storeSet = GetStoreSet(); var batchSet = GetBatchSet(); sets.Details.Add(wrokUnitSet); sets.Details.Add(wrokShopSet); sets.Details.Add(storeSet); sets.Details.Add(batchSet); return sets; } private DropDownSet GetWrokShopSet() { var json = RpcFacade.Call("/MainSystem/B3ClientService/Rpcs/BaseInfoRpc/GetWorkShopList"); var set = new DropDownSet(); set.Name = DropDownSets.车间; foreach (var detail in JsonConvert.DeserializeObject>(json)) { set.Details.Add(detail); } return set; } private DropDownSet GetStoreSet() { var json = RpcFacade.Call("/MainSystem/B3ClientService/Rpcs/BaseInfoRpc/GetStoreList"); var set = new DropDownSet(); set.Name = DropDownSets.仓库; foreach (var detail in JsonConvert.DeserializeObject>(json)) { set.Details.Add(detail); } return set; } private DropDownSet GetBatchSet() { var json = RpcFacade.Call("/MainSystem/B3ClientService/Rpcs/BaseInfoRpc/GetProductBatchList"); var set = new DropDownSet(); set.Name = DropDownSets.批次; foreach (var detail in JsonConvert.DeserializeObject>(json)) { set.Details.Add(detail); } return set; } private DropDownSet GetWrokUnitSet() { var json = RpcFacade.Call("/MainSystem/B3ClientService/Rpcs/BaseInfoRpc/GetWorkUnitList"); var set = new DropDownSet(); set.Name = DropDownSets.单元; foreach (var detail in JsonConvert.DeserializeObject>(json)) { set.Details.Add(detail); } return set; } BindingList unSubmitList = new BindingList(); BindingList submitedList = new BindingList(); void BindUnSubmitGrid() { var json = RpcFacade.Call(BaseRpcUrl + "GetUnSubmitList"); var list = JsonConvert.DeserializeObject>(json); foreach (MaterialRequisitionRecord record in list) { unSubmitList.Add(record); } dataGridViewUnSubmit.DataSource = unSubmitList; dataGridViewUnSubmit.Refresh(); } void SyncSubmited() { while (true) { var json = RpcFacade.Call(BaseRpcUrl + "GetSubmitedList"); var list = JsonConvert.DeserializeObject>(json); if (this.IsHandleCreated) { this.Invoke(new Action(() => { if (list.Count > 0) { submitedList.Clear(); foreach (MaterialRequisitionRecord record in list) { submitedList.Add(record); } } BindSubmitedGrid(); })); } Thread.Sleep(2000); } } void BindSubmitedGrid() { if (dataGridViewSubmited.DataSource == null) { dataGridViewSubmited.DataSource = submitedList; } else { dataGridViewSubmited.Refresh(); } } private void btnGoodsSet_Click(object sender, EventArgs e) { var f = new GoodsSetForm(); if (f.ShowDialog() == DialogResult.OK) { InitControl(); } } private void InitControl() { mSetList = XmlUtil.DeserializeFromFile>(GoodsSetForm.MaterialRequisitionGoodsSetFileName).Where(x => x.IsSelected).ToList(); if (mSetList.Count < 1) { return; } flpClass.Controls.Clear(); foreach (IGrouping grouping in mSetList.GroupBy(x => x.Name)) { var btnClass = CreateClassButton(grouping.Key); flpClass.Controls.Add(btnClass); } } private Button CreateClassButton(string text) { var btn = new Button(); btn.Text = text; btn.Click += Btn_Click; btn.Font = new System.Drawing.Font("宋体", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134))); btn.BackColor = SystemColors.Control; btn.Width = 100; btn.Height = 60; return btn; } private void Btn_Click(object sender, EventArgs e) { var text = (sender as Button).Text; foreach (Button cbutton in flpClass.Controls) { if (cbutton.Text == text) { cbutton.BackColor = Color.Aqua; } else { cbutton.BackColor = SystemColors.Control; } } flpGoods.Controls.Clear(); foreach (MaterialRequisitionGoodsSet set in mSetList.Where(x => x.Name == text)) { var btnGoods = CreateGoodsButton(set); flpGoods.Controls.Add(btnGoods); } } private Button CreateGoodsButton(MaterialRequisitionGoodsSet set) { var btn = new Button(); btn.Text = set.Goods_Name; btn.Tag = set; btn.Font = new System.Drawing.Font("宋体", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134))); btn.Click += BtnGoods_Click; btn.BackColor = SystemColors.Control; btn.Width = 140; btn.Height = 80; return btn; } private void BtnGoods_Click(object sender, EventArgs e) { if (cbxStore.SelectedValue == null) throw new Exception("请选择领用仓库"); if (cbxWorkUnit.SelectedValue == null) throw new Exception("请选择工作单元"); if (cbxBatch.SelectedValue == null) throw new Exception("请选择生产批次"); var btn = sender as Button; var tag = btn.Tag as MaterialRequisitionGoodsSet; var record = new MaterialRequisitionRecord(); record.Goods_ID = tag.Goods_ID; InsertToServer(record); } bool end = false; private void MaterialRequisitionForm_KeyPress(object sender, KeyPressEventArgs e) { if (cbxStore.SelectedValue == null) throw new Exception("请选择领用仓库"); if (cbxWorkUnit.SelectedValue == null) throw new Exception("请选择工作单元"); if (cbxBatch.SelectedValue == null) throw new Exception("请选择生产批次"); if (end) { textBox1.Text = string.Empty; end = false; } if (!textBox1.Focused) { textBox1.Focus(); textBox1.Text = e.KeyChar.ToString(); textBox1.Select(textBox1.TextLength, 0); } if (e.KeyChar == (char)Keys.Enter) { e.Handled = true; var code = UrlUtil.ParseCode(textBox1.Text); textBox1.Text = code; textBox1.Select(textBox1.TextLength, 0); end = true; if (string.IsNullOrEmpty(code)) return; var json = RpcFacade.Call(BaseRpcUrl + "GetCodeStoreInfo", code); if (string.IsNullOrEmpty(json)) throw new Exception("扫码无效或已被领用"); var re = JsonConvert.DeserializeObject(json); if (re.Store_ID != Convert.ToInt64(cbxStore.SelectedValue)) throw new Exception("所选仓库与存货所在库不一致"); textBox2.Text = re.Goods_Name; textBox3.Text = (re.Weight ?? 0).ToString("#0.######"); var record = new MaterialRequisitionRecord(); record.BarCode = code; record.Goods_ID = re.Goods_ID; record.BeforeWeight = re.BeforeWeight; InsertToServer(record); } } void InsertToServer(MaterialRequisitionRecord record) { record.ID = 0; record.Creator = ButcherAppContext.Context.UserConfig.UserName; if (cbxWorkShop.SelectedValue != null) record.WorkShop_ID = Convert.ToInt64(cbxWorkShop.SelectedValue); record.WorkUnit_ID = Convert.ToInt64(cbxWorkUnit.SelectedValue); record.Store_ID = Convert.ToInt64(cbxStore.SelectedValue); record.ProductBatch_ID = Convert.ToInt64(cbxBatch.SelectedValue); record.ProductBatch = cbxBatch.SelectedText; var json = RpcFacade.Call(BaseRpcUrl + "Insert", JsonConvert.SerializeObject(record)); unSubmitList.Insert(0, JsonConvert.DeserializeObject(json)); dataGridViewUnSubmit.Refresh(); } #region weightNeed void OpenSerialPort() { if (!_enableWeight) return; if (MaterialRequisitionContext.Config.RateSet == null) throw new Exception("请先配置称相关信息"); weightPort.PortName = MaterialRequisitionContext.Config.ComSet; weightPort.BaudRate = MaterialRequisitionContext.Config.RateSet.Value; weightPort.DataBits = MaterialRequisitionContext.Config.BitSet.Value; weightPort.ReadBufferSize = 4096 * 100; if (!string.IsNullOrEmpty(MaterialRequisitionContext.Config.Format)) format = "{0:{format}}".Replace("{format}", MaterialRequisitionContext.Config.Format); switch (MaterialRequisitionContext.Config.WeightSet) { case "IND560": _dataFormat = new IND560DataFormat(); break; case "Xk3124": _dataFormat = new Xk3124DataFormat(); break; case "Xk3190A9": _dataFormat = new Xk3190A9DataFormat(); break; default: _dataFormat = new Xk3190D10DataFormat(); break; } if (!weightPort.IsOpen) { try { weightPort.Open(); } catch (InvalidOperationException) { MessageBox.Show(@"指定的端口已打开"); } catch (UnauthorizedAccessException) { MessageBox.Show(@"对端口的访问被拒绝"); } } } void ReadData() { _inQueryThread = new Thread(InQuery); _inQueryThread.Start(); } string format = "{0:0.00}"; private void InQuery() { while (_mainProcessIsRun) { int availableCount = weightPort.BytesToRead; if (availableCount == 0) { Thread.Sleep(1); } char[] buffer = new char[availableCount]; if (!weightPort.IsOpen) { continue; } weightPort.Read(buffer, 0, availableCount); foreach (var c in buffer) { if (c == _dataFormat.Beginchar) { _dataStrBuilder.Clear(); _dataStrBuilder.Append(c); } else if (c == _dataFormat.Endchar && _dataStrBuilder.Length == _dataFormat.DataLength - 1) { _dataStrBuilder.Append(c); bool isStatic; string str; if (_dataFormat.ParseAscii(_dataStrBuilder.ToString(), out str, out isStatic)) { if (MaterialRequisitionContext.Config.WeightType == 0) { if (string.IsNullOrEmpty(str)) str = "0"; this.Invoke(new Action(delegate() { lblChengZhong.Text = string.Format(format, decimal.Parse(str)); if (str != "0") { //AddWeightDetail(decimal.Parse(lblChengZhong.Text)); doInsertUnSubmit(decimal.Parse(lblChengZhong.Text)); } })); } else { decimal num = 0; if (decimal.TryParse(str, out num)) { this.Invoke(new Action(delegate() { lblChengZhong.Text = string.Format(format, num); })); // LocalGradeAndWeightBL.SaveWeightData(num); WeighAvgControl.Add(num, isStatic); } if (WeighAvgControl.TryGetValue(out num)) { this.Invoke(new Action(delegate() { //lblChengZhong.Text = string.Format(format, num); if (str != "0") { doInsertUnSubmit(decimal.Parse(string.Format(format, num))); //AddWeightDetail(decimal.Parse(string.Format(format, num))); } })); } } } _dataStrBuilder.Clear(); } else if (_dataStrBuilder.Length != 0) { _dataStrBuilder.Append(c); } } } } static object _obj = new object(); private void doInsertUnSubmit(decimal weight) { lock (_obj) { //称重 //找到称重为空条码不为空的 var fd = unSubmitList.LastOrDefault(x => x.Weight == null); if (fd == null) { //todo 记录一个异常 // record.ID = unSumbitList.Max(x => x.ID) + 1; // unSumbitList.Add(record); } else { RpcFacade.Call(BaseRpcUrl + "FillWeight", fd.ID, weight); fd.Weight = weight; dataGridViewUnSubmit.Refresh(); } } } private class WeighAvgControl { public static bool TryGetValue(out decimal result) { List> list; if (mWeighList.TryDequeue(out list)) { var r = list.Where(x => x.Item2).Select(x => x.Item1).GroupBy(x => x); var firstOrDefault = r.OrderByDescending(x => x.Count()).FirstOrDefault(); if (firstOrDefault != null) { result = firstOrDefault.Key; return true; } result = 0; return false; } result = 0; return false; } static ConcurrentQueue>> mWeighList = new ConcurrentQueue>>(); static List> _list = new List>(); public static void Add(decimal value, bool isStatic) { if (value >= MaterialRequisitionContext.Config.MinWeight && value <= MaterialRequisitionContext.Config.MaxWeight) { _list.Add(new Tuple(value, isStatic)); } else { if (_list.Count > 0) { mWeighList.Enqueue(_list); _list = new List>(); } } } } void DisableWeight() { _mainProcessIsRun = false; lblChengZhong.Text = string.Format(format, 0); format = "{0:0.00}"; Thread.Sleep(10); if (_inQueryThread.IsAlive) { _inQueryThread.Abort(); } if (weightPort.IsOpen) weightPort.Close(); } #endregion private bool _enableWeight = false; private void btnEnableWeight_Click(object sender, EventArgs e) { _enableWeight = !_enableWeight; if (_enableWeight) { btnEnableWeight.Text = "停止称重"; btnEnableWeight.BackColor = Color.ForestGreen; OpenSerialPort(); _mainProcessIsRun = true; ReadData(); } else { btnEnableWeight.Text = "开始称重"; btnEnableWeight.BackColor = SystemColors.Control; btnEnableWeight.UseVisualStyleBackColor = true; DisableWeight(); } } private void btnWeightSet_Click(object sender, EventArgs e) { new WeightSettingFrom().ShowDialog(); } private void btnCommit_Click(object sender, EventArgs e) { var ids = unSubmitList.Where(x => x.Weight.HasValue).Select(x => x.ID).ToList(); if (ids.Count == 0) return; RpcFacade.Call(BaseRpcUrl + "Submit", ids); foreach (var id in ids) { var first = unSubmitList.First(x => x.ID == id); unSubmitList.Remove(first); } dataGridViewUnSubmit.Refresh(); } private void btnDelete_Click(object sender, EventArgs e) { if (dataGridViewUnSubmit.CurrentRow == null) return; var id = (long)dataGridViewUnSubmit.CurrentRow.Cells["U_ID"].Value; RpcFacade.Call(BaseRpcUrl + "Delete", id); var first = unSubmitList.First(x => x.ID == id); unSubmitList.Remove(first); dataGridViewUnSubmit.Refresh(); } } }