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