轉帖|使用教程|編輯:龔雪|2024-02-23 11:05:44.337|閱讀 105 次
概述:本文主要介紹如何在WinForms應用界面中實現(xiàn)通用的業(yè)務編碼規(guī)則生成,希望幫助到大家~
# 界面/圖表報表/文檔/IDE等千款熱門軟控件火熱銷售中 >>
相關鏈接:
在我們很多應用系統(tǒng)中,往往都需要根據(jù)實際情況生成一些編碼規(guī)則,如訂單號、入庫單號、出庫單號、退貨單號等。有時候根據(jù)規(guī)則自行增加一個函數(shù)來生成處理,不過仔細觀察后,發(fā)現(xiàn)它們的編碼規(guī)則有很大的共通性,因此可以考慮使用一些通用的業(yè)務編碼規(guī)則生成,從而在系統(tǒng)中統(tǒng)一維護即可,本文將介紹如何在WinForm界面中實現(xiàn)通用的業(yè)務編碼規(guī)則生成。
PS:給大家推薦一個C#開發(fā)可以用到的界面組件——DevExpress WinForms,它能完美構建流暢、美觀且易于使用的應用程序,無論是Office風格的界面,還是分析處理大批量的業(yè)務數(shù)據(jù),它都能輕松勝任!
DevExpress技術交流群9:909157416 歡迎一起進群討論
剛才我們提到一些編碼規(guī)則,如訂單號、入庫單號、出庫單號、退貨單號等等,它們都是有大同小異的規(guī)則,有前綴、有日期的編碼、有一些流水號,還有一些特殊的規(guī)則處理,往往就是這些,需要協(xié)調(diào)好流水號的增加處理即可。
例如,原來在我的CRM業(yè)務模塊中,增加了一個函數(shù),用來生成訂單號的,如下所示。
/// <summary> /// 生成單據(jù)號碼,編碼為XS-{userId}-{yyyyMMdd}-流水號 /// </summary> /// <returns></returns> public async Task<string> GetOrderNo() { string prefix = string.Format("XS-{0}-{1}", CurrentApiUser.Id, DateTime.Now.ToString("yyyyMMdd")); //獲取當天的記錄數(shù)量+1 DateTime currentDate = DateTime.Now.ToString("yyyy-MM-dd").ToDateTime(); //當前日期 //計算條件數(shù)量+1 int count = this.EntityDb.Count(s => s.OrderDate >= currentDate && s.OrderDate <= currentDate.AddDays(1)) + 1; //循環(huán)檢索,直到不重復的編號 string number = string.Format("{0}-{1}", prefix, count); while (true) { var result = await CheckNumberExist(number); if (result) { //存在增加1再判斷 number = string.Format("{0}-{1}", prefix, count++); } else { break; } } return number; }
這里為了增加對流水號的循環(huán)判斷,直到?jīng)]有重復的即可輸出來作為訂單號。
大多數(shù)的編碼規(guī)則大同小異,因此我們可以考慮使用共同的規(guī)則進行處理,類似通用字典的模塊處理。訂單編碼,可以在新建訂單的時候生成,也可以提供用戶手動生成【生成編號】的操作,如下界面所示。
我們歸納了一些編碼規(guī)則,基本上也就是前綴,日期分隔,分隔符,后綴,流水號這些元素的組合,如果需要更加復雜的也可以自行調(diào)整接口,這里設計一個通用的編碼規(guī)則,對這些元素進行組合配置,數(shù)據(jù)庫設計如下所示。
根據(jù)這些內(nèi)容,使用手工編碼或者代碼生成工具生成相關的基礎代碼 (可以基于EnterpriseLibrary的框架代碼或者基于SqlSugar開發(fā)框架的代碼),最終我們都用于WinForm的界面調(diào)用。
這里以基于SqlSugar開發(fā)框架的代碼生成為例。
生成后,會生成一個相關的業(yè)務類,實現(xiàn)相關的CRUD接口,如下代碼定義所示,如果你有自己的基礎框架實現(xiàn),那么也可以忽略具體的代碼生成,關注業(yè)務編碼的生成的的規(guī)則即可。
/// <summary> /// 業(yè)務表編碼規(guī)則 應用層服務接口實現(xiàn) /// </summary> public class TableNumberService : MyCrudService<TableNumberInfo, string, TableNumberPagedDto>, ITableNumberService
為了控制編碼的規(guī)則生成,我們增加一個同步鎖來實現(xiàn)沖突處理。
/// <summary> /// 同步鎖 /// </summary> private static SemaphoreSlim syncRoot = new SemaphoreSlim(1);
最終我們的實現(xiàn)代碼如下所示。
/// <summary> /// 根據(jù)定義表名、單據(jù)頭、分割符1、分割符2,生成業(yè)務編碼。如果生成錯誤,返回空字符串 /// </summary> /// <param name="tableNameOrCode">表名或代碼</param> /// <returns></returns> public async Task<string> GenerateNumber(string tableNameOrCode) { string businessNumber = ""; await syncRoot.WaitAsync(); //等待鎖 try { var info = await base.GetFirstAsync(s => s.TableName == tableNameOrCode || s.Code == tableNameOrCode); if (info != null) { string currentDate = ""; string lastDate = ""; int currentNumber = 1; //流水號起始值 int serialLength = 3; //流水號長度 if(!info.LastGenerateTime.HasValue) { info.LastGenerateTime = DateTime.Now; } if (info.RuleFormat == "年月日") { currentDate = DateTime.Now.ToString("yyyyMMdd"); lastDate = info.LastGenerateTime.Value.ToString("yyyyMMdd"); } else if (info.RuleFormat == "年月") { currentDate = DateTime.Now.ToString("yyyyMM"); lastDate = info.LastGenerateTime.Value.ToString("yyyyMM"); } //如果當前日期和最后日期不一致,流水號重置為0 if(!currentDate.Equals(lastDate)) { info.CurrentValue = 0; } //如果流水號非起始值,那么累計計算 if(info.CurrentValue.HasValue && info.CurrentValue >= 0) { currentNumber = (int)info.CurrentValue + 1;//流水號當前值 } //流水號長度 if(info.ValueLength.HasValue && info.ValueLength > 3) { serialLength = (int)info.ValueLength;//流水號長度 } var SplitString1 = string.IsNullOrEmpty(info.SplitString1) ? "-" : info.SplitString1; var SplitString2 = string.IsNullOrEmpty(info.SplitString2) ? "-" : info.SplitString2; //生成業(yè)務編碼 businessNumber = $"{info.Prex}{SplitString1}{currentDate}{SplitString2}{currentNumber.ToString().PadLeft(serialLength, '0')}{info.Suffix}"; //更新記錄 info.CurrentValue = currentNumber; info.SplitString1 = SplitString1; info.SplitString2 = SplitString2; info.CurrentNumberString = businessNumber; info.LastGenerateTime = DateTime.Now;//更新最后生成編碼日期 await base.UpdateAsync(info); } } catch (Exception ex) { var errorText = $"生成單號時出現(xiàn)錯誤:{ex.Message}"; LogTextHelper.Error(errorText, ex); } finally { syncRoot.Release();//釋放鎖 } return businessNumber; }
上面主要注意的就是流水號的生成,這個稍微特殊處理一下,如果定義的規(guī)則是年月日,那么和最后的生成日期和當前日期不一致的話(轉換為年月日對比),就認為流水號重新重置為1,否則是同一天的,流水號遞增即可。如果是年月的,也是判斷最后日期和當前日期的年月是否一致,不一致則重置為1,否則遞增。注意流水號的編碼長度,一般為4位,如果不滿足的可以增加到6位等。
最終我們實際的業(yè)務編碼的管理界面和查看的對應編碼的界面如下所示,供參考設計界面處理。
編輯單個業(yè)務編碼規(guī)則的界面如下所示。
為了方便,我們這里提供一個【測試生成】的按鈕,用于測試具體的編碼生成,我們具體的業(yè)務調(diào)用,就是類似這個調(diào)用即可。
var handNo = await BLLFactory<ITableNumberService>.Instance.GenerateNumber(tableNameOrCode);
同樣,我們也可以把這個界面搬到WPF框架界面上去,可以重用具體的業(yè)務編碼規(guī)則處理,如上類似的界面處理。
單個通用的業(yè)務編碼規(guī)則的編輯界面如下所示。
因此,不管對于Winform還是WPF的界面,他們的展示方式都是類似的,我們可以重用業(yè)務層對通用編碼規(guī)則的定義。
本文轉載自:
本站文章除注明轉載外,均為本站原創(chuàng)或翻譯。歡迎任何形式的轉載,但請務必注明出處、不得修改原文相關鏈接,如果存在內(nèi)容上的異議請郵件反饋至chenjj@fc6vip.cn
文章轉載自: