【C#】最全业务单据号生成(支持定义规则、流水号、传参数)

系列文章

【C#】最全业务单据号生成(支持定义规则、流水号、传参数)
本文链接:https://blog.csdn.net/youcheng_ge/article/details/129129787

【C#】日期范围生成器(开始日期、结束日期)
本文链接:https://blog.csdn.net/youcheng_ge/article/details/129040663

【C#】组件化开发,调用dll组件方法
本文链接:https://blog.csdn.net/youcheng_ge/article/details/129492112

【C#】数据实体类使用
本文链接:https://blog.csdn.net/youcheng_ge/article/details/128816638

【C#】单据审批流方案
本文链接:https://blog.csdn.net/youcheng_ge/article/details/128972545

【C#】条码管理操作手册
本文链接:https://blog.csdn.net/youcheng_ge/article/details/126589496

【C#】IIS平台下,WebAPI发布及异常处理
本文链接:https://blog.csdn.net/youcheng_ge/article/details/126539836

【C#】代码模板生成工具
本文链接:https://blog.csdn.net/youcheng_ge/article/details/126890673

【C#】MySQL数据库导入工具(批量Excel插入)
本文链接:https://blog.csdn.net/youcheng_ge/article/details/126427323

【C#】简单二维码制作和打印工具
本文链接:https://blog.csdn.net/youcheng_ge/article/details/126884228

【C#】最全单据打印(打印模板、条形码&二维码、字体样式、项目源码)
本文链接:https://blog.csdn.net/youcheng_ge/article/details/129415723

【C#】Windows服务(Service)安装及启停方案
本文链接:https://blog.csdn.net/youcheng_ge/article/details/124053794

【C#】穿透Session隔离,服务调用外部程序(无窗体界面解决)
本文链接:https://blog.csdn.net/youcheng_ge/article/details/124053033

【C#】任务计划实现,使用Quartz类
本文链接:https://blog.csdn.net/youcheng_ge/article/details/123667723

【C#】源码解析正则表达式
本文链接:https://blog.csdn.net/youcheng_ge/article/details/118337074

【C#】软件版本和文件MD5记录(XML操作)
本文链接:https://blog.csdn.net/youcheng_ge/article/details/112513871

【C#】测试网络是否连通
本文链接:https://blog.csdn.net/youcheng_ge/article/details/110137288

【C#】根据名称获取编码(Dictionary获取key方法)
本文链接:https://blog.csdn.net/youcheng_ge/article/details/129816701

【C#】数据建模,你是使用DataTable还是List?
本文链接:https://blog.csdn.net/youcheng_ge/article/details/129792726

【C#】GridControl控件和数据集双向绑定
本文链接:https://blog.csdn.net/youcheng_ge/article/details/129423755

【C#】GridControl动态更换DataSource,数据查询异常处理
本文链接:https://blog.csdn.net/youcheng_ge/article/details/130305424

【C#】GridControl日期字段显示时分秒
本文链接:https://blog.csdn.net/youcheng_ge/article/details/130718303

【C#】GridControl增加选择列(不用二次点击)
本文链接:https://blog.csdn.net/youcheng_ge/article/details/130763713

【C#】数据库检查工具(可跨库访问)
本文链接:https://blog.csdn.net/youcheng_ge/article/details/97172329

【C#】代码解析–打印数据集
本文链接:https://blog.csdn.net/youcheng_ge/article/details/131431829

【C#】代码解析–截取整个方法函数
本文链接:https://blog.csdn.net/youcheng_ge/article/details/109817809

【C#】反射机制,动态加载类文件
本文链接:https://blog.csdn.net/youcheng_ge/article/details/131435110



更新日志

版本更新日期更新说明
V1.02023-02-20首次发布自动编号生成器
V1.12023-03-15代码未变更,仅仅调整文章章节,使之结构更清晰
V2.02023-03-21原编号规则–流水号位数,采用分号分割。因新业务需求,我需要在编码中传入【参数】,我没有特殊字符识别这类,改造流水号位数为阿拉伯数字。见3.4 创建自动编号客户端(V2.0)
V3.02023-11-15规则中,传入参数个数可以根据参数表自动定义,使用public static String Format(String format, params object[] args)
V4.02023-12-25代码简化,增加注释,【流水号】不是必传参数`

前言

我能抽象出整个世界,但是我不能抽象你。 想让你成为私有常量,这样外部函数就无法访问你。 又想让你成为全局常量,这样在我的整个生命周期都可以调用你。 可惜世上没有这样的常量,我也无法定义你,因为你在我心中是那么的具体。

哈喽大家好,本专栏为【项目实战】,有别于【底层库】专栏,我们可以发现增加 了『问题描述』、『项目展示』章节,十分贴合项目开发流程,让读者更加清楚本文能够解决的问题、以及产品能够达到的效果。本专栏收纳项目开发过程中的解决方案,是我项目开发相对成熟、可靠方法的总结,在不涉及职务作品保密协议 的前提下,我将问题的解决方案重新梳理,撰写本文分享给大家,大家遇到类似问题,可按本文方案处理。

本专栏会持续更新,不断完善,专栏文章关联性较弱(文章之间依赖性较弱,没有阅读顺序)。大家有任何问题,可以私信我。如果您对本专栏感兴趣,欢迎关注吧,我将带你用最简洁的代码,实现复杂的功能。

·提示:本专栏为项目实战篇,未接触项目开发的同学可能理解困难,不推荐阅读。
3A0N000001


一、问题描述

1.1 原业务需求

我在生产型公司担任 软件工程师。问题起因,各部门日常运营会产生各种各样的单据,而这些单据标识需要用到 编号。比如:销售订单–销售订单号、采购订单–采购订单号、材料入库单–入库单号、原材料出库单–出库单号、财务凭证单–凭证单号、成品发货单–物流单号等。

大部分人员会使用随机数Guid、自增列,作为标识。但是,业务部门未必认可这样的编号。有意义的业务单据号设计,业务员看到就能够对业务进行分类,知道这个单据应该走哪类处理流程。

显然,单纯的随机数、自增id,无法实现这样的效果。
在这里插入图片描述
在这里插入图片描述

提示:这是业务部门给出的部分编号规则,,只是物料部分。

1.2 新业务需求

公司实验室需要对物料进行质检,“样品编号”,需要能够明显关联“原物料”(不查系统,人工看编号)。我们的“样品编号”,要包含“物料编号”,这样就解决这个问题。
故而,我们的业务单据号生成器 还需要支持 传参数,直接把原物料的编号传入,编号规则中。
在这里插入图片描述

二、解决方案

2.1 可行性分析

如上图所示,业务部门给出的“编号规则”,基本是 固定字符+流水号 的形式。这是最简单的版本,如果再复杂一点,可以细分为 固定字符+日期缩写+流水号。再进行复杂一点,又可以分为 固定字符+类型(获取系统参数)+日期缩写+员工代号+流水号等等。

那么我们的处理必然要区分“编号组成”,分开处理,采用字符串拼接的方式。固定字符,保留;流水号是数值类型(1,2,3,4,5…),需要先取得上一次的数值,执行+1操作;类型,获取系统参数,解决思路从用户登录信息、功能模块操作记录、点击事件中抓取数据。

所以,我们要解决的核心问题:要先获取上一次单据号,看流水号排到多少了,然后才能进行+1操作。我们就要查询数据库业务表,获得最大的流水号是多少。

2.2 采用方案

在代码里写大量取数,拼接字符串,这工作量太大了,而且很容易出错。就算他们不出错,如果对于业务部门,哪天业务调整了,编号要变化,又要改程序太麻烦了。

所以我为了解决这个问题,我想开发一个专门的服务,统一生成这么个编号。

我将这服务通用化,对平台、开发语言的依赖要尽可能低,就是说,无论你用 电脑、平板、手机、浏览器还是以后的什么设备,都可以获取我的“自动编号”。

解决方案:①创建API应用接口 ②编写自动编号生成器 ③部署服务 ④客户端调用,获取自动编号。

2.3 方案增补(V2.0)

解决编号【传参】问题,使用string.Format()

public const string 钨条样编号规则 = “WT-{0}-[2位流水号]”;
string.Format(编号规则.钨条样编号规则,item.钨条编号)

2.4 方案增补(V3.0)

解决编号【传参】参数个数不确定问题,为了通用化,规则表不再使用 字符串拼接

开发时遇到string.Format 需要传递任意个参数的情况(一般是配置中不确定参数个数)
string.Format有以下重载,最适合的是public static String Format(String format, params object[] args);

2.5 方案增补(V4.0)

简化代码,【流水号】不作为必须参数。

三、软件开发(项目源码)

3.1 引入底层库

Visual Studio创建WebAPI项目,使用本文内容,还需要两个底层库支持,在 底层库 专栏你可以找到它。

1、C#底层库–MySQL数据库访问操作辅助类(推荐阅读)
2、C#底层库–StringExtension字符串扩展类
3、C#底层库–SQLSuger数据库访问操作类(推荐阅读),如果想支持多数据库产品,使用Sqlsuger
提示:C#底层库专栏,包含开发中最基础的库,

3.2 创建数据模型

创建类AutoCodeRuleModel.cs,作为 传入的参数实体,复制以下代码:

using System;

namespace DLMESWebAPI
{
    public class AutoCodeRuleModel
    {
        public string 编号规则 { get; set; } //自动编号规则
        public string{ get; set; } //数据库表
        public string 字段 { get; set; } //表字段
    }
}

3.3 创建自动编号客户端(V1.0)

创建类 AutoCodeClient.cs,用于自动编号生成,是核心方法,复制以下代码:

using BaseClass_NameSpace;
using System;
using System.Data;

namespace DLMESWebAPI.BLL
{
    public class AutoCodeClient
    {
        /// <summary>
        /// 获取自动编号
        /// </summary>
        /// <param name="a_strAutoRule">编号规则</param>
        /// <param name="a_strCodeTable">表名</param>
        /// <param name="a_strCodeField">字段名</param>
        /// <returns></returns>
        public static string GetAutoCode(string a_strAutoRule, string a_strCodeTable, string a_strCodeField)
        {
            int a_CodeLength = 4;
            string[] array = a_strAutoRule.Split(new char[]
            {
                ',',
                ';'
            });
            if (array.Length > 1) //编号规则是否定义了流水号位数。
            {
                int.TryParse(array[1], out a_CodeLength);
                return AutoCodeClient.GetAutoCode(array[0], a_CodeLength, a_strCodeTable, a_strCodeField);
            }
            return AutoCodeClient.GetAutoCode(a_strAutoRule, a_CodeLength, a_strCodeTable, a_strCodeField);
        }

        public static string GetAutoCode(string a_strAutoRule, int a_CodeLength, string a_strCodeTable, string a_strCodeField)
        {
            string text = "";
            string text2 = "";
            checked
            {
                for (int i = 0; i < a_CodeLength; i++)
                {
                    text += "_";
                    text2 += "0";
                }
                string text3 = AutoCodeClient.ParseCodeRule(a_strAutoRule, a_CodeLength);
                string s = AutoCodeClient.ParseQueryRule(a_strAutoRule, a_CodeLength);
                int num = text3.IndexOf(text);

                MySQLHelper fetchData = new MySQLHelper();
                string text4 = "select {0} from {1} where {2} like {3} order by 1 desc LIMIT 0,1";

                text4 = string.Format(text4, new object[]
                {
                    string.Format("SUBSTRING({0}, {1}, {2})", a_strCodeField, num + 1, a_CodeLength),
                    a_strCodeTable,
                    a_strCodeField,
                    s.QuotedStr()
                });
                DataTable l_dt = fetchData.Query(text4).Tables[0];

                if (l_dt!=null)
                {
                    string newValue;
                    if (l_dt.Rows.Count<=0)
                    {
                        newValue = 1.ToString(text2);
                    }
                    else
                    {
                        text3.Substring(0, num);
                        if (text3.Length > num + 4)
                        {
                            text3.Substring(num + 4);
                        }
                        string s2 = l_dt.Rows[0][0].ToString();
                        int num2 = 0;
                        int.TryParse(s2, out num2);
                        num2++;
                        newValue = num2.ToString(text2);
                    }
                    text3 = text3.Replace(text, newValue);
                }

                return text3;
            }
        }

        public static string GetAutoCodeAlpha(string a_strAutoRule, string a_strCodeTable, string a_strCodeField)
        {
            int num = 1;
            string text = "";
            string str = "";
            checked
            {
                for (int i = 0; i < num; i++)
                {
                    text += "_";
                    str += "0";
                }
                string text2 = AutoCodeClient.ParseCodeRule(a_strAutoRule, num);
                string s = AutoCodeClient.ParseQueryRule(a_strAutoRule, num);
                int num2 = text2.IndexOf(text);

                //BaseMySQL fetchData = new BaseMySQL();
                MySQLHelper fetchData = new MySQLHelper();
                string text3 = "select top 1 {0} from {1} where {2} like {3} order by 1 desc";
                text3 = string.Format(text3, new object[]
                {
                    string.Format("SUBSTRING({0}, {1}, {2})", a_strCodeField, num2 + 1, num),
                    a_strCodeTable,
                    a_strCodeField,
                    s.QuotedStr()
                });
                DataTable l_dt = fetchData.Query(text3).Tables[0];

                if (l_dt!=null)
                {
                    string newValue;
                    if (l_dt.Rows.Count<=0)
                    {
                        newValue = "A";
                    }
                    else
                    {
                        text2.Substring(0, num2);
                        if (text2.Length > num2 + 4)
                        {
                            text2.Substring(num2 + 4);
                        }
                        string text4 = l_dt.Rows[0][0].ToString();
                        int num3 = 65;
                        if (text4.Length > 0)
                        {
                            num3 = (int)text4[0];
                        }
                        num3++;
                        if (num3 > 90)
                        {
                            return AutoCodeClient.GetAutoCodeAlpha2(a_strAutoRule, a_strCodeTable, a_strCodeField);
                        }
                        newValue = Convert.ToString((char)num3);
                    }
                    text2 = text2.Replace(text, newValue);
                }

                return text2;
            }
        }

        private static string GetAutoCodeAlpha2(string a_strAutoRule, string a_strCodeTable, string a_strCodeField)
        {
            int num = 2;
            string text = "";
            string str = "";
            checked
            {
                for (int i = 0; i < num; i++)
                {
                    text += "_";
                    str += "0";
                }
                string text2 = AutoCodeClient.ParseCodeRule(a_strAutoRule, num);
                string s = AutoCodeClient.ParseQueryRule(a_strAutoRule, num);
                int num2 = text2.IndexOf(text);

                //BaseMySQL fetchData = new BaseMySQL();
                MySQLHelper fetchData = new MySQLHelper();
                string text3 = "select top 1 {0} from {1} where {2} like {3} order by 1 desc";
                text3 = string.Format(text3, new object[]
                {
                    string.Format("SUBSTRING({0}, {1}, {2})", a_strCodeField, num2 + 1, num),
                    a_strCodeTable,
                    a_strCodeField,
                    s.QuotedStr()
                });
                DataTable l_dt = fetchData.Query(text3).Tables[0];
                if (l_dt!=null)
                {
                    string newValue;
                    if (l_dt.Rows.Count<=0)
                    {
                        newValue = "AA";
                    }
                    else
                    {
                        string input = l_dt.Rows[0][0].ToString();
                        newValue = AutoCodeClient.IncAlphaCode(input);
                    }
                    text2 = text2.Replace(text, newValue);
                }
                return text2;
            }
        }

        private static string IncAlphaCode(string input)
        {
            char c = input[0];
            char c2 = input[1];
            int num = (int)c;
            int num2 = (int)c2;
            checked
            {
                if (num2 < 90)
                {
                    return Convert.ToString((char)num) + Convert.ToString((char)(num2 + 1));
                }
                return Convert.ToString((char)(num + 1)) + "A";
            }
        }

        private static string ParseCodeRule(string a_strAutoRule, int a_CodeLength)
        {
            DateTime date = DateTime.Now.Date;
            if (a_strAutoRule.Contains("[紧缩天数]"))
            {
                a_strAutoRule = a_strAutoRule.Replace("[紧缩天数]", date.Day.ToString());
            }
            if (a_strAutoRule.Contains("[两位天数]"))
            {
                a_strAutoRule = a_strAutoRule.Replace("[两位天数]", date.Day.ToString("00"));
            }
            if (a_strAutoRule.Contains("[紧缩月份]"))
            {
                a_strAutoRule = a_strAutoRule.Replace("[两位月份]", date.Month.ToString());
            }
            if (a_strAutoRule.Contains("[两位月份]"))
            {
                a_strAutoRule = a_strAutoRule.Replace("[两位月份]", date.Month.ToString("00"));
            }
            checked
            {
                if (a_strAutoRule.Contains("[一位年份]"))
                {
                    a_strAutoRule = a_strAutoRule.Replace("[一位年份]", date.Year.ToString().Substring(date.Year.ToString().Length - 1, 1));
                }
                if (a_strAutoRule.Contains("[两位年份]"))
                {
                    a_strAutoRule = a_strAutoRule.Replace("[两位年份]", date.Year.ToString().Substring(date.Year.ToString().Length - 2, 2));
                }
                if (a_strAutoRule.Contains("[四位年份]"))
                {
                    a_strAutoRule = a_strAutoRule.Replace("[四位年份]", date.Year.ToString("0000"));
                }
               
                string text2 = "";
                for (int i = 0; i < a_CodeLength; i++)
                {
                    text2 += "_";
                }
                a_strAutoRule = a_strAutoRule.Replace("[流水编号]", text2);
                a_strAutoRule = a_strAutoRule.Replace("[按月编号]", text2);
                a_strAutoRule = a_strAutoRule.Replace("[按年编号]", text2);
                return a_strAutoRule;
            }
        }

        private static string ParseQueryRule(string a_strAutoRule, int a_CodeLength)
        {
            DateTime date = DateTime.Now.Date;
            if (a_strAutoRule.Contains("[紧缩天数]"))
            {
                a_strAutoRule = a_strAutoRule.Replace("[紧缩天数]", date.Day.ToString());
            }
            if (a_strAutoRule.Contains("[两位天数]"))
            {
                if (a_strAutoRule.Contains("[按月编号]") || a_strAutoRule.Contains("[按年编号]"))
                {
                    a_strAutoRule = a_strAutoRule.Replace("[两位天数]", "__");
                }
                else
                {
                    a_strAutoRule = a_strAutoRule.Replace("[两位天数]", date.Day.ToString("00"));
                }
            }
            if (a_strAutoRule.Contains("[紧缩月份]"))
            {
                a_strAutoRule = a_strAutoRule.Replace("[两位月份]", date.Month.ToString());
            }
            if (a_strAutoRule.Contains("[两位月份]"))
            {
                if (a_strAutoRule.Contains("[按年编号]"))
                {
                    a_strAutoRule = a_strAutoRule.Replace("[两位月份]", "__");
                }
                else
                {
                    a_strAutoRule = a_strAutoRule.Replace("[两位月份]", date.Month.ToString("00"));
                }
            }
            checked
            {
                if (a_strAutoRule.Contains("[一位年份]"))
                {
                    a_strAutoRule = a_strAutoRule.Replace("[一位年份]", date.Year.ToString().Substring(date.Year.ToString().Length - 1, 1));
                }
                if (a_strAutoRule.Contains("[两位年份]"))
                {
                    a_strAutoRule = a_strAutoRule.Replace("[两位年份]", date.Year.ToString().Substring(date.Year.ToString().Length - 2, 2));
                }
                if (a_strAutoRule.Contains("[四位年份]"))
                {
                    a_strAutoRule = a_strAutoRule.Replace("[四位年份]", date.Year.ToString("0000"));
                }
               
                string text2 = "";
                for (int i = 0; i < a_CodeLength; i++)
                {
                    text2 += "_";
                }
                a_strAutoRule = a_strAutoRule.Replace("[流水编号]", text2);
                a_strAutoRule = a_strAutoRule.Replace("[按月编号]", text2);
                a_strAutoRule = a_strAutoRule.Replace("[按年编号]", text2);
                return a_strAutoRule;
            }
        }
    }
}


3.4 创建自动编号客户端(V2.0)

AutoCodeClient.cs,代码进行了修改,引入了正则表达式,增加【参数】支持。

以下是修改后的代码:

using BaseClass_NameSpace;
using System;
using System.Data;
using System.Text.RegularExpressions;

namespace WBF.Utils
{
    /// <summary>
    /// 自动编号客户端
    /// 创建人:gyc
    /// 创建时间:2022-11-16
    /// 备注:流水号经过压力测试,位数可以任意
    /// </summary>
    public class AutoCodeClient
    {
        //实在不适合字符串分割,所以我引入了强大的正则
        public const string 流水号正则 = @"(\[[0-9]+位流水号])";
        public const string 流水号位数正则 = "[0-9]+";

        /// <summary>
        /// 获取自动编号
        /// </summary>
        /// <param name="a_strAutoRule">编号规则</param>
        /// <param name="a_strCodeTable">表名</param>
        /// <param name="a_strCodeField">数据库表字段,存储编号的字段</param>
        /// <returns></returns>
        public static string AutoCode(string a_strAutoRule, string a_strCodeTable, string a_strCodeField)
        {
            string l_strSNText = RegexForString(流水号正则, a_strAutoRule);//流水号文本
            int l_intSNLength = 4;//流水号长度
            string l_strSN = RegexForString(流水号位数正则, l_strSNText);
            int.TryParse(l_strSN, out l_intSNLength);

            //string[] array = a_strAutoRule.Split(new char[]
            //{
            //    ';'
            //});
            //if (array.Length > 1) //编号规则是否定义了流水号位数。
            //{
            //    int.TryParse(array[1], out l_intSNLength);
            //    return AutoCodeClient.GetAutoCode(array[0], l_intSNLength, a_strCodeTable, a_strCodeField);
            //}

            return AutoCodeClient.GetAutoCode(a_strAutoRule, l_strSNText, l_intSNLength, a_strCodeTable, a_strCodeField);
        }

        /// <summary>
        /// 获取自动编号
        /// </summary>
        /// <param name="a_strAutoRule">编号规则</param>
        /// <param name="a_strSNText">d位流水号</param>
        /// <param name="a_intSNLength">d</param>
        /// <param name="a_strCodeTable">数据库表</param>
        /// <param name="a_strCodeField">数据库表字段,存储编号的字段</param>
        /// <returns></returns>
        public static string GetAutoCode(string a_strAutoRule,string a_strSNText, int a_intSNLength, string a_strCodeTable, string a_strCodeField)
        {
            string text = "";
            string text2 = "";
            checked
            {
                for (int i = 0; i < a_intSNLength; i++)
                {
                    text += "_";
                    text2 += "0";
                }
                string text3 = AutoCodeClient.ParseCodeRule(a_strAutoRule, a_strSNText, a_intSNLength);
                string s = AutoCodeClient.ParseQueryRule(a_strAutoRule, a_strSNText, a_intSNLength);
                int num = text3.IndexOf(text);

                //使用 BaseMySQL取数,需要指定 数据库名
                //MySQLHelper fetchData = new MySQLHelper();
                BaseMySQL fetchData = new BaseMySQL();
                string text4 = "select {0} from {1} where {2} like {3} order by 1 desc LIMIT 0,1";

                text4 = string.Format(text4, new object[]
                {
                    string.Format("SUBSTRING({0}, {1}, {2})", a_strCodeField, num + 1, a_intSNLength),
                    a_strCodeTable,
                    a_strCodeField,
                    s.QuotedStr()
                });
                //DataTable l_dt = fetchData.Query(text4).Tables[0];
                DataTable l_dt = fetchData.Query(text4);
                if (l_dt!=null)
                {
                    string newValue;
                    if (l_dt.Rows.Count<=0)
                    {
                        newValue = 1.ToString(text2);
                    }
                    else
                    {
                        text3.Substring(0, num);
                        if (text3.Length > num + 4)
                        {
                            text3.Substring(num + 4);
                        }
                        string s2 = l_dt.Rows[0][0].ToString();
                        int num2 = 0;
                        int.TryParse(s2, out num2);
                        num2++;
                        newValue = num2.ToString(text2);
                    }
                    text3 = text3.Replace(text, newValue);
                }

                return text3;
            }
        }


        private static string ParseCodeRule(string a_strAutoRule, string a_strSNText, int a_CodeLength)
        {
            DateTime date = DateTime.Now.Date;
            if (a_strAutoRule.Contains("[紧缩天数]"))
            {
                a_strAutoRule = a_strAutoRule.Replace("[紧缩天数]", date.Day.ToString());
            }
            if (a_strAutoRule.Contains("[两位天数]"))
            {
                a_strAutoRule = a_strAutoRule.Replace("[两位天数]", date.Day.ToString("00"));
            }
            if (a_strAutoRule.Contains("[紧缩月份]"))
            {
                a_strAutoRule = a_strAutoRule.Replace("[两位月份]", date.Month.ToString());
            }
            if (a_strAutoRule.Contains("[两位月份]"))
            {
                a_strAutoRule = a_strAutoRule.Replace("[两位月份]", date.Month.ToString("00"));
            }
            checked
            {
                if (a_strAutoRule.Contains("[一位年份]"))
                {
                    a_strAutoRule = a_strAutoRule.Replace("[一位年份]", date.Year.ToString().Substring(date.Year.ToString().Length - 1, 1));
                }
                if (a_strAutoRule.Contains("[两位年份]"))
                {
                    a_strAutoRule = a_strAutoRule.Replace("[两位年份]", date.Year.ToString().Substring(date.Year.ToString().Length - 2, 2));
                }
                if (a_strAutoRule.Contains("[四位年份]"))
                {
                    a_strAutoRule = a_strAutoRule.Replace("[四位年份]", date.Year.ToString("0000"));
                }
               
                string text2 = "";
                for (int i = 0; i < a_CodeLength; i++)
                {
                    text2 += "_";
                }
                a_strAutoRule = a_strAutoRule.Replace(a_strSNText, text2);
                a_strAutoRule = a_strAutoRule.Replace("[按月编号]", text2);
                a_strAutoRule = a_strAutoRule.Replace("[按年编号]", text2);
                return a_strAutoRule;
            }
        }

        private static string ParseQueryRule(string a_strAutoRule, string a_strSNText, int a_CodeLength)
        {
            DateTime date = DateTime.Now.Date;
            if (a_strAutoRule.Contains("[紧缩天数]"))
            {
                a_strAutoRule = a_strAutoRule.Replace("[紧缩天数]", date.Day.ToString());
            }
            if (a_strAutoRule.Contains("[两位天数]"))
            {
                if (a_strAutoRule.Contains("[按月编号]") || a_strAutoRule.Contains("[按年编号]"))
                {
                    a_strAutoRule = a_strAutoRule.Replace("[两位天数]", "__");
                }
                else
                {
                    a_strAutoRule = a_strAutoRule.Replace("[两位天数]", date.Day.ToString("00"));
                }
            }
            if (a_strAutoRule.Contains("[紧缩月份]"))
            {
                a_strAutoRule = a_strAutoRule.Replace("[两位月份]", date.Month.ToString());
            }
            if (a_strAutoRule.Contains("[两位月份]"))
            {
                if (a_strAutoRule.Contains("[按年编号]"))
                {
                    a_strAutoRule = a_strAutoRule.Replace("[两位月份]", "__");
                }
                else
                {
                    a_strAutoRule = a_strAutoRule.Replace("[两位月份]", date.Month.ToString("00"));
                }
            }
            checked
            {
                if (a_strAutoRule.Contains("[一位年份]"))
                {
                    a_strAutoRule = a_strAutoRule.Replace("[一位年份]", date.Year.ToString().Substring(date.Year.ToString().Length - 1, 1));
                }
                if (a_strAutoRule.Contains("[两位年份]"))
                {
                    a_strAutoRule = a_strAutoRule.Replace("[两位年份]", date.Year.ToString().Substring(date.Year.ToString().Length - 2, 2));
                }
                if (a_strAutoRule.Contains("[四位年份]"))
                {
                    a_strAutoRule = a_strAutoRule.Replace("[四位年份]", date.Year.ToString("0000"));
                }
               
                string text2 = "";
                for (int i = 0; i < a_CodeLength; i++)
                {
                    text2 += "_";
                }
                a_strAutoRule = a_strAutoRule.Replace(a_strSNText, text2);
                a_strAutoRule = a_strAutoRule.Replace("[按月编号]", text2);
                a_strAutoRule = a_strAutoRule.Replace("[按年编号]", text2);
                return a_strAutoRule;
            }
        }



        /// <summary>
        /// 匹配返回string
        /// </summary>
        /// <param name="a_strPattern">正则表达式</param>
        /// <param name="a_txtContext">匹配文本</param>
        /// <returns></returns>
        private static string RegexForString(string a_strPattern, string a_txtContext)
        {
            Regex l_reg = new Regex(@a_strPattern, RegexOptions.IgnoreCase);
            MatchCollection matches_Type = l_reg.Matches(a_txtContext);
            foreach (Match item in matches_Type)
            {
                return item.Value;
            }
            return "";
        }




    }
}

3.5 创建自动编号客户端(V4.0)

推荐使用该版本,代码简化了,更容易理解。

//函数内容: 自动编号处理
//函数版本: 0.0.0.1
//修改时间: 2023.03.26
//============================================================================================
//注意事项
//  1.  a_strAutoRule保存规则
//  2.  a_strCodeTable编码表
//  3. a_strCodeField编码字段
//============================================================================================
public string AutoCode(string a_strAutoRule, string a_strCodeTable, string a_strCodeField)
{
    DateTime date = DateTime.Now.Date;

    //年份
    if (a_strAutoRule.Contains("[四位年份]"))
    {
        a_strAutoRule = a_strAutoRule.Replace("[四位年份]", date.Year.ToString("0000"));
    }

    if (a_strAutoRule.Contains("[两位年份]"))
    {
        a_strAutoRule = a_strAutoRule.Replace("[两位年份]", date.Year.ToString().Substring(date.Year.ToString().Length - 2, 2));
    }

    if (a_strAutoRule.Contains("[一位年份]"))
    {
        a_strAutoRule = a_strAutoRule.Replace("[一位年份]", date.Year.ToString().Substring(date.Year.ToString().Length - 1, 1));
    }

    //月份
    if (a_strAutoRule.Contains("[紧缩月份]")) //0-9月一位,10-12月两位
    {
        a_strAutoRule = a_strAutoRule.Replace("[两位月份]", date.Month.ToString());
    }

    if (a_strAutoRule.Contains("[两位月份]"))
    {
        a_strAutoRule = a_strAutoRule.Replace("[两位月份]", date.Month.ToString("00"));
    }

    //天数
    if (a_strAutoRule.Contains("[紧缩天数]"))
    {
        a_strAutoRule = a_strAutoRule.Replace("[紧缩天数]", date.Day.ToString());
    }
    if (a_strAutoRule.Contains("[两位天数]"))
    {
        a_strAutoRule = a_strAutoRule.Replace("[两位天数]", date.Day.ToString("00"));
    }

    //流水号(没有流水号,不执行)
    string 流水号正则 = @"(\[[0-9]+位流水号])";
    if (!string.IsNullOrEmpty(RegexForString(流水号正则, a_strAutoRule)))
    {
        a_strAutoRule = BuildSerialNum(a_strAutoRule, a_strCodeTable, a_strCodeField);
    }

    return a_strAutoRule;
}


//函数内容: 构造流水号
//函数版本: 0.0.0.1
//修改时间: 2023.03.26
//============================================================================================
//注意事项
//  1.  
//  2.  
//============================================================================================
private string BuildSerialNum(string a_strAutoRule, string a_strCodeTable, string a_strCodeField)
{
    string text1 = "";//通配符
    string text2 = "";//补位格式
    string 流水号正则 = @"(\[[0-9]+位流水号])";
    string 流水号位数正则 = "[0-9]+";
    string str_SNText = RegexForString(流水号正则, a_strAutoRule);//流水号文本

    int int_SNLength = 0; //流水号长度
    if (!int.TryParse(RegexForString(流水号位数正则, str_SNText), out int_SNLength)) //格式不符合,不处理
    {
        return string.Empty;
    }

    for (int i = 0; i < int_SNLength; i++)
    {
        text1 += "_";
        text2 += "0";
    }

    a_strAutoRule = a_strAutoRule.Replace(str_SNText, text1);//转码
    int int_StartIndex = a_strAutoRule.IndexOf(text1);//起始位置

    //使用 BaseMySQL取数
    string str_Sql = "SELECT {0} FROM {1} WHERE {2} LIKE {3} ORDER BY 1 DESC LIMIT 0,1;";
    str_Sql = string.Format(str_Sql, new object[]
    {
            string.Format("SUBSTRING({0}, {1}, {2})", a_strCodeField, int_StartIndex + 1, int_SNLength),
            a_strCodeTable,
            a_strCodeField,
            "'"+a_strAutoRule+"'"
    });
    DataTable dt_Result = AdoGetDataTable(str_Sql);
    if (dt_Result != null)
    {
        string newValue;
        if (dt_Result.Rows.Count <= 0)
        {
            newValue = 1.ToString(text2);
        }
        else
        {
            string s2 = dt_Result.Rows[0][0].ToString();
            int num2 = 0;
            int.TryParse(s2, out num2);
            num2++;
            newValue = num2.ToString(text2);
        }
        a_strAutoRule = a_strAutoRule.Replace(text1, newValue);

        return a_strAutoRule;
    }
    return string.Empty;
}


//函数内容: 正则表达式判断
//函数版本: 0.0.0.1
//修改时间: 2023.03.26
//============================================================================================
//注意事项
//  1.  
//  2.  
//============================================================================================
private string RegexForString(string a_strPattern, string a_txtContext)
{
    Regex l_reg = new Regex(@a_strPattern, RegexOptions.IgnoreCase);
    MatchCollection matches_Type = l_reg.Matches(a_txtContext);
    foreach (Match item in matches_Type)
    {
        return item.Value;
    }
    return "";
}

3.6 创建数据库操作类

创建数据库操作类 MySQLHelper.cs,代码收纳在《C#底层库》专栏。使用MySQL数据,用MySQLHelper.cs;SQL server,用SQLHelper.cs;使用Sqlsuger,用 SqlsugerHelper.cs。

3.7 创建字符串操作类

C#底层库–StringExtension字符串扩展类
本文链接:https://blog.csdn.net/youcheng_ge/article/details/129520428

3.8 编写API控制器

Controllers文件夹下,创建类QRController.cs,当然如果你也可以不采用这种方式,直接C/S架构,客户端直接调用【核心类】获取自动编号,本章节可以跳过。
注意:非必要内容,不采用WebAPI调用方式,可以不看本章节。

位置:ApiController.cs

 /// <summary>
 /// 自动编号
 /// </summary>
 /// <param name="parm">参数</param>
 /// <returns></returns>
 [HttpPost]
 public IActionResult AutoCode([FromBody] AutoCodeDto parm)
 {
     try
     {
         return toResponse(GetAutoCode(parm));
     }
     catch (Exception ex)
     {
         return toResponse(StatusCodeType.Error, ex.Message);
     }
 }

位置:BaseController.cs,WebAPI统一返回数据格式。

 /// <summary>
 /// 获得自动编号
 /// </summary>
 /// <param name="rule">规则</param>
 /// <param name="parm"></param>
 /// <returns></returns>
 public static string GetAutoCode(AutoCodeDto param)
 {
     //TODO:待确认出入库编码格式,业务部门他想自己定,不用开发编号
     BaseService<裸砂原料信息表> sqlSugar = new BaseService<裸砂原料信息表>();
     string strAutoCode = sqlSugar.AutoCode(string.Format(param.rule, param.paramValue),
              param.tableName, param.fieldName);
     return strAutoCode;
 }

数据实体 AutoCodeDto,前端传来的参数。

 public class AutoCodeDto
 {
     /// <summary>
     /// 描述 :  编号规则
     /// 空值 : False
     /// 默认 : 
     /// </summary>
     [Display(Name = "编号规则")]
     public string rule  { get; set; }

     /// <summary>
     /// 描述 :  参数值
     /// 空值 : False
     /// 默认 : 
     /// </summary>
     [Display(Name = "参数值")]
     public List<string> paramValue { get; set; }

     /// <summary>
     /// 描述 :  表名
     /// 空值 : False
     /// 默认 : 
     /// </summary>
     [Display(Name = "表名")]
     public string tableName { get; set; }

     /// <summary>
     /// 描述 :  字段名
     /// 空值 : False
     /// 默认 : 
     /// </summary>
     [Display(Name = "字段名")]
     public string fieldName { get; set; }

四、运行效果

4.1 调用方式

【业务编号】获取方式,已部署API服务,支持多端(pad、PC)获取业务编号。

URL: http://172.16.**.*:8888/API/QR/GetAutoCode
http请求方式:POST
数据类型:json
调用样例:
{
“编号规则”: “[一位年份]A0N[流水编号];6”,
“表”: “t_codenumbertest”,
“字段”: “编号”
}

4.2 参数说明

“编号规则”:自动编号的规则定义,系统参数带中括号
“表”:业务编号存储的数据库表
“字段”:业务编号存储的表字段。如“钨条标签打印纪录表”字段“钨条编号”是单据号,那么 表=“钨条标签打印纪录表”、字段=“钨条编号”
其它问题:
①编号规则,系统预留:
[四位年份]
[两位年份]
[一位年份]
[紧缩月份] --10以内,不补位
[两位月份]
[紧缩天数] --10以内,不补位
[两位天数]
[[0-9]+位流水号]–正则,位数阿拉伯数字
②规则中,“固定值”如何设置?
不加中括号 []为固定值,编码保留。
③规则中,流水号位数如何设置?
1(阿拉伯数字)位流水号,例如:1位流水号,3位流水号.

4.3 项目展示

4.3.1 Postman测试效果

① “编号规则”: “[一位年份]A0N[流水编号];6”,
在这里插入图片描述
② “编号规则”: “SO[四位年份][两位月份][流水编号];4”,
在这里插入图片描述
③ “编号规则”: “[两位年份][两位月份][流水编号]PZ;10”,
在这里插入图片描述
你想怎么定义规则,编号就怎么生成。

4.3.2 vue测试效果

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

五、资源链接

5.1 数据库脚本

业务编号查询的SQL语句参考

SELECT SUBSTRING(出入库单据编号, 10, 3) FROM 裸砂原料出入库表 WHERE 出入库单据编号 LIKE 'YLY202312___' ORDER BY 1 DESC LIMIT 0,1;

注意:_为通配符,占用1位

  • 7
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

花北城

你的鼓励是我最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值