using BO; using BO.BO.Bill; using BO.Utils; using BO.Utils.BillRpc; using BWP.WinFormControl; using BWP.WinFormControl.WeightDataFormat; using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.IO.Ports; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; using System.Windows.Forms; namespace WeighAndGrading { public partial class GradeFrom : Form, IAfterLogin { #region IAfterLogin public string RoleName { get { return "定级员"; } } public Form Generate() { return this; } #endregion private delegate void InvokeHandler(); List list; List details; SerialPort weightPort; int maxIndex = 0; ConcurrentQueue noLivestockList = new ConcurrentQueue(); ConcurrentQueue noWeightList = new ConcurrentQueue(); Thread syncWork; #region weightNeed private IDataFormat _dataFormat; private Thread _inQueryThread; private bool _mainProcessIsRun; readonly StringBuilder _dataStrBuilder = new StringBuilder(); #endregion public GradeFrom() { InitializeComponent(); butcherTimeInput.Date = DateTime.Today; dataGridView.AutoGenerateColumns = false; dataGridView.DataSource = null; historyGrid.AutoGenerateColumns = false; AddLivestockBtn(); BuildDiscontPanel(); weightPort = new SerialPort(); this.FormClosing += delegate { if (_inQueryThread != null && _inQueryThread.IsAlive) DisableWeight(); if (syncWork != null && syncWork.IsAlive) syncWork.Abort(); }; } GradeAndWeight_Detail modifyDetail; void AddLivestockBtn() { var livestocks = BaseInfoRpcUtil.GetLivestockList(); foreach (var item in livestocks) { var btn = new Button() { Name = "_" + item.Item1, Text = item.Item2, Tag = item, Size = new Size(70, 60), TextAlign = ContentAlignment.MiddleCenter, Margin = new Padding { All = 10 }, Font = new Font("宋体", 15) }; btn.Click += (sender, e) => { if (details == null) { MessageBox.Show("请先同步数据"); return; } var livestockTag = btn.Tag as CTuple; if (modifyDetail == null) AddDetail(livestockTag); else { modifyDetail.Livestock_ID = livestockTag.Item1; modifyDetail.Livestock_Name = livestockTag.Item2; modifyDetail.Technics = livestockTag.Item3; modifyDetail.Technics_Name = livestockTag.Item3 == 0 ? "烫褪" : "毛剥"; GradeAndWeightRpc.UpdateLivestock(modifyDetail.ID, modifyDetail.Livestock_ID, modifyDetail.Livestock_Name, modifyDetail.Technics, modifyDetail.Technics_Name); historyGrid.Refresh(); modifyDetail = null; modifyPanel.Hide(); } //var name = livestock.Technics == 0 ? "带皮白条" : "去皮白条"; //Print(name, entity.Index); }; if (item.Item3 == 0) ttPanel.Controls.Add(btn); else mbPanel.Controls.Add(btn); } } private void closeBtn_Click(object sender, EventArgs e) { this.Close(); } private void syncBtn_Click(object sender, EventArgs e) { list = GradeAndWeightRpc.GetGradeAndWeightList(butcherTimeInput.Date.Value); BindDataGrid(); tangRow = FindRowSetSelected(tangEntity); maoRow = FindRowSetSelected(maoEntity); dataGridView.Refresh(); details = GradeAndWeightRpc.GetDetails(butcherTimeInput.Date.Value, 50); FillQueue(); BindDetailGrid(); if (details.Any()) maxIndex = details.First().Index; if (syncWork == null || !syncWork.IsAlive) { syncWork = new Thread(Sync); syncWork.Start(); syncBtn.BackColor = Color.FromArgb(15, 215, 107); syncBtn.ForeColor = Color.White; } else { syncWork.Abort(); syncBtn.BackColor = Color.FromKnownColor(KnownColor.Control); syncBtn.ForeColor = Color.FromKnownColor(KnownColor.ControlText); } } void Sync() { while (true) { Thread.Sleep(5000); this.Invoke(new InvokeHandler(delegate() { list = GradeAndWeightRpc.GetGradeAndWeightList(butcherTimeInput.Date.Value); BindDataGrid(); tangRow = FindRowSetSelected(tangEntity); maoRow = FindRowSetSelected(maoEntity); dataGridView.Refresh(); })); } } void FillQueue() { noWeightList = new ConcurrentQueue(); noLivestockList = new ConcurrentQueue(); var stack = new Stack(); foreach (var item in details) { if (item.Livestock_ID == 0 || item.Weight == null) stack.Push(item); else break; } while (stack.Count > 0) { var bottom = stack.Pop(); if (bottom.Weight == null) noWeightList.Enqueue(bottom); else noLivestockList.Enqueue(bottom); } } void BindDataGrid() { dataGridView.DataSource = list.OrderBy(x => x.Order).OrderBy(x => x.Finish).ToList(); foreach (DataGridViewRow row in dataGridView.Rows) { if ((bool)row.Cells["D_Finish"].Value) row.DefaultCellStyle.BackColor = Color.YellowGreen; } InitScrollBar1(); dataGridView.ClearSelection(); try { if (leftRoll != -1) dataGridView.FirstDisplayedScrollingRowIndex = leftRoll; } catch { leftRoll = -1; } } void BindDetailGrid() { historyGrid.DataSource = null; if (details.Any()) historyGrid.DataSource = details; InitScrollBar2(); if (lastSelectID.HasValue) { foreach (DataGridViewRow row in historyGrid.Rows) { if ((long)row.Cells["H_ID"].Value == lastSelectID) { historyGrid.CurrentCell = row.Cells[row.Cells.Count - 1]; break; } } } try { if (rightRoll != -1) historyGrid.FirstDisplayedScrollingRowIndex = rightRoll; } catch { rightRoll = -1; } historyGrid.Refresh(); } private void printBtn_Click(object sender, EventArgs e) { var entity = new PrintEntity(); entity.AccountingUnit_Name = "青花瓷软件(北京)有限公司"; entity.Goods_Name = "B2/B3 ERP"; entity.Date = DateTime.Today; entity.Checker = "管理员"; entity.StoreCondition = "0-4℃ 5日"; entity.Place = "北京市海淀区"; entity.TelNumber = "010-62701591"; entity.Address = "北京市北京市海淀区知春路49号"; entity.BarCode = string.Format("BWP{0}{1:00000}", DateTime.Today.ToString("yyyyMMdd"), new Random().Next(1, 1000)); entity._2DQRCode = string.Format("http://www.bwpsoft.com?code={0}", entity.BarCode); PrintAPI.Print(entity); } private void configBtn_Click(object sender, EventArgs e) { new GradeSettingFrom().ShowDialog(); } GradeAndWeight tangEntity; GradeAndWeight maoEntity; #region weightNeed void OpenSerialPort() { if (enableWeight.Checked) return; if (GradeContext.Config.RateSet == null) throw new Exception("请先配置称相关信息"); weightPort.PortName = GradeContext.Config.ComSet; weightPort.BaudRate = GradeContext.Config.RateSet.Value; weightPort.DataBits = GradeContext.Config.BitSet.Value; weightPort.ReadBufferSize = 4096 * 100; if (!string.IsNullOrEmpty(GradeContext.Config.Format)) format = "{0:{format}}".Replace("{format}", GradeContext.Config.Format); switch (GradeContext.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 (GradeContext.Config.WeightType == 0) { if (string.IsNullOrEmpty(str)) str = "0"; this.Invoke(new InvokeHandler(delegate() { lblChengZhong.Text = string.Format(format, decimal.Parse(str)); if (str != "0") { AddWeightDetail(decimal.Parse(lblChengZhong.Text)); } })); } else { decimal num = 0; if (decimal.TryParse(str, out num)) { this.Invoke(new InvokeHandler(delegate() { lblChengZhong.Text = string.Format(format, num); })); WeighAvgControl.Add(num, isStatic); } if (WeighAvgControl.TryGetValue(out num)) { this.Invoke(new InvokeHandler(delegate() { //lblChengZhong.Text = string.Format(format, num); if (str != "0") { AddWeightDetail(decimal.Parse(string.Format(format, num))); } })); } } } _dataStrBuilder.Clear(); } else if (_dataStrBuilder.Length != 0) { _dataStrBuilder.Append(c); } } } } 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 >= GradeContext.Config.MinWeight && value <= GradeContext.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(); } public void enableWeight_Click(object sender, EventArgs e) { if (details == null) { MessageBox.Show("请先同步数据"); return; } if (!enableWeight.Checked) { OpenSerialPort(); _mainProcessIsRun = true; ReadData(); } else DisableWeight(); enableWeight.CheckState = enableWeight.Checked ? CheckState.Unchecked : CheckState.Checked; } #endregion static object _obj = new object(); void AddDetail(CTuple livestock) { lock (_obj) { var currentRow = livestock.Item3 == 0 ? tangEntity : maoEntity; var tech = livestock.Item3 == 0 ? "烫褪" : "毛剥"; GradeAndWeight_Detail first; if (noLivestockList.TryPeek(out first) && first.Livestock_ID == 0) { noLivestockList.TryDequeue(out first); if (currentRow != null) first.OrderDetail_ID = currentRow.OrderDetail_ID; first.Date = butcherTimeInput.Date.Value; first.Livestock_ID = livestock.Item1; first.Livestock_Name = livestock.Item2; first.Technics = livestock.Item3; first.Technics_Name = tech; GradeAndWeightRpc.UpdateOrInsertDetail(first, true); historyGrid.Refresh(); } else//add { maxIndex++; var entity = new GradeAndWeight_Detail(); entity.Index = maxIndex; if (currentRow != null) entity.OrderDetail_ID = currentRow.OrderDetail_ID; entity.Date = butcherTimeInput.Date.Value; entity.Livestock_ID = livestock.Item1; entity.Livestock_Name = livestock.Item2; entity.Technics = livestock.Item3; entity.Technics_Name = tech; entity.Time = DateTime.Now; entity.Date = butcherTimeInput.Date.Value; if (details.Count == 50) details.RemoveAt(49); details.Insert(0, entity); GradeAndWeightRpc.UpdateOrInsertDetail(entity, true); noWeightList.Enqueue(entity); BindDetailGrid(); } if (currentRow != null) { currentRow.Already = currentRow.Already + 1; orderLabel.Text = currentRow.Order.ToString(); alreadyLabel.Text = currentRow.Already.ToString(); dataGridView.Refresh(); } else { orderLabel.Text = string.Empty; alreadyLabel.Text = string.Empty; } } } void AddWeightDetail(decimal weight) { lock (_obj) { weight -= (GradeContext.Config.Discont ?? 0); GradeAndWeight_Detail first; if (noWeightList.TryPeek(out first)) { noWeightList.TryDequeue(out first); if (first.Weight < 0) first.Weight = (first.Weight ?? 0) + weight; else first.Weight = weight; GradeAndWeightRpc.UpdateOrInsertDetail(first); historyGrid.Refresh(); } else//add { maxIndex++; var entity = new GradeAndWeight_Detail(); entity.Index = maxIndex; entity.Weight = (entity.Weight ?? 0) + weight; entity.Time = DateTime.Now; entity.Date = butcherTimeInput.Date.Value; if (details.Count == 50) details.RemoveAt(49); details.Insert(0, entity); GradeAndWeightRpc.UpdateOrInsertDetail(entity); noLivestockList.Enqueue(entity); BindDetailGrid(); } } } private void cancelBtn_Click(object sender, EventArgs e) { modifyDetail = null; modifyPanel.Hide(); } GradeAndWeight_Detail lastCheckItem; long? lastSelectID = null; private void historyGrid_CellClick(object sender, DataGridViewCellEventArgs e) { if (e.RowIndex < 0) return; var currentRow = historyGrid.CurrentRow.DataBoundItem as GradeAndWeight_Detail; lastSelectID = currentRow.ID; if (e.ColumnIndex == 2) { if (lastCheckItem != null && lastCheckItem.ID != currentRow.ID) lastCheckItem.ReadWeight = false; lastCheckItem = currentRow; lastCheckItem.ReadWeight = !lastCheckItem.ReadWeight; modifyDetail = null; if (modifyPanel.Visible) modifyPanel.Hide(); historyGrid.Refresh(); if (lastCheckItem.ReadWeight) { noWeightList = new ConcurrentQueue(); var stack = new Stack(); foreach (var item in details) { stack.Push(item); if (item.ID == lastCheckItem.ID) break; } while (stack.Count > 0) noWeightList.Enqueue(stack.Pop()); } else { FillQueue(); lastCheckItem = null; } return; } modifyDetail = currentRow; stateLabel.Text = string.Format("您正在修改序号为 {0} 的信息", modifyDetail.Index); modifyPanel.Show(); } DataGridViewRow tangRow; DataGridViewRow maoRow; private void dataGridView_CellClick(object sender, DataGridViewCellEventArgs e) { if (e.RowIndex == -1) return; var entity = dataGridView.CurrentRow.DataBoundItem as GradeAndWeight; if (entity.Technics_Name == "烫褪") { if (tangRow != null) { if (tangEntity.Finish) tangRow.DefaultCellStyle.BackColor = Color.YellowGreen; else tangRow.DefaultCellStyle.BackColor = dataGridView.RowsDefaultCellStyle.BackColor; } tangRow = dataGridView.CurrentRow; tangRow.DefaultCellStyle.BackColor = tangRow.DefaultCellStyle.SelectionBackColor = entity.Finish ? Color.YellowGreen : dataGridView.RowsDefaultCellStyle.SelectionBackColor; tangEntity = entity; } else { if (maoRow != null) { if (maoEntity.Finish) maoRow.DefaultCellStyle.BackColor = Color.YellowGreen; else maoRow.DefaultCellStyle.BackColor = dataGridView.RowsDefaultCellStyle.BackColor; } maoRow = dataGridView.CurrentRow; maoRow.DefaultCellStyle.BackColor = maoRow.DefaultCellStyle.SelectionBackColor = entity.Finish ? Color.YellowGreen : Color.Yellow; maoEntity = entity; } if (e.ColumnIndex == dataGridView.ColumnCount - 1 && !entity.Finish) { entity.Finish = true; GradeAndWeightRpc.SetGradeFinish(entity.OrderDetail_ID, entity.Technics); BindDataGrid(); if (entity.Technics == 0) { maoRow = FindRowSetSelected(maoEntity); tangEntity = null; tangRow = null; } else { tangRow = FindRowSetSelected(tangEntity); maoEntity = null; maoRow = null; } } dataGridView.Refresh(); } DataGridViewRow FindRowSetSelected(GradeAndWeight tag) { if (tag == null) return null; foreach (DataGridViewRow row in dataGridView.Rows) { if ((long)row.Cells["D_OrderDetail_ID"].Value == tag.OrderDetail_ID && (string)row.Cells["D_Technics_Name"].Value == tag.Technics_Name) { if (tag.Finish) row.DefaultCellStyle.BackColor = Color.YellowGreen; else row.DefaultCellStyle.BackColor = tag.Technics == 1 ? Color.Yellow : dataGridView.RowsDefaultCellStyle.SelectionBackColor; if (tag.Technics == 0) tangEntity = row.DataBoundItem as GradeAndWeight; else maoEntity = row.DataBoundItem as GradeAndWeight; return row; } } return null; } private void discontBtn_Click(object sender, EventArgs e) { if (new BodyDiscontSetting().ShowDialog() == DialogResult.OK) BuildDiscontPanel(); } void BuildDiscontPanel() { var disconts = GradeAndWeightRpc.GetBodyDiscontItem().Where(x => x.Discont > 0).OrderBy(x => x.ID); discontPanel.Controls.Clear(); foreach (var item in disconts) { var btn = new Button() { Name = "_D" + item.ID, Text = item.Name, Tag = item.Discont, Size = new Size(70, 60), TextAlign = ContentAlignment.MiddleCenter, Margin = new Padding { Left = 0, Right = 0, Top = 10, Bottom = 10 }, Font = new Font("宋体", 15) }; btn.Click += (sender, e) => { if (modifyDetail == null) throw new Exception("请先选择要扣重的记录"); modifyDetail.Weight = (modifyDetail.Weight ?? 0) - Convert.ToDecimal(btn.Tag); GradeAndWeightRpc.UpdateWeight(modifyDetail.ID, modifyDetail.Weight); historyGrid.Refresh(); modifyDetail = null; modifyPanel.Hide(); }; discontPanel.Controls.Add(btn); } } int leftRoll = -1; private void InitScrollBar1() { vScrollBar1.Maximum = (dataGridView.RowCount - dataGridView.DisplayedRowCount(false) + 30) * dataGridView.RowTemplate.Height; vScrollBar1.Minimum = 0; vScrollBar1.SmallChange = dataGridView.RowTemplate.Height; vScrollBar1.LargeChange = dataGridView.RowTemplate.Height * 30; this.vScrollBar1.Scroll += (sender, e) => { leftRoll = e.NewValue / dataGridView.RowTemplate.Height; dataGridView.FirstDisplayedScrollingRowIndex = leftRoll; }; } int rightRoll = -1; private void InitScrollBar2() { vScrollBar2.Maximum = (historyGrid.RowCount - historyGrid.DisplayedRowCount(false) + 30) * historyGrid.RowTemplate.Height; vScrollBar2.Minimum = 0; vScrollBar2.SmallChange = historyGrid.RowTemplate.Height; vScrollBar2.LargeChange = historyGrid.RowTemplate.Height * 30; this.vScrollBar2.Scroll += (sender, e) => { rightRoll = e.NewValue / historyGrid.RowTemplate.Height; historyGrid.FirstDisplayedScrollingRowIndex = rightRoll; }; } } }