.NET Winform超级代码生成器V6.1 - 快速生成Winform三层架构代码


.NET Winform超级代码生成器V6.1 - 快速生成Winform三层架构代码

.NET Winform超级代码生成器V6.1

 

C/S框架代码生成器(Code Generator)是一款完全自主知识产权研发的源代码生成平台,作为C/S框架旗舰版产品系列配套工具。代码生成器可以自动生成Winform界面,支持数据操作基本功能,如:增加、删除、修改、查询、审核、打印等功能,包括生成 ORM、BLL、DAL、Form三层架构源码。

最新版本:CSFramework Code Generator V6.1

代码生成器主界面:

.NET Winform超级代码生成器V6.1 - 快速生成Winform三层架构代码

 

核心功能介绍

1、生成业务模块

生成Visual Studio Project项目,编译生成DLL类库。

代码生成器生成的源码文件:

贴图图片-代码生成器-工程项目

将源码添加到VS解决方案:

贴图图片-代码生成器-工程项目1

双击打开 frmModuleMain.cs文件,模块主窗体:

贴图图片-代码生成器-生成模块主窗体

 

2、生成基础资料窗体(单表)

 

生成的C#源码:

贴图图片-代码生成器-生成单表基础资料窗体2

将源码复制到vs解决方案:

贴图图片-代码生成器-生成单表基础资料窗体3

双击打开窗体设计器:

数据查询界面:

.NET Winform超级代码生成器V6.1 - 快速生成Winform三层架构代码

数据编辑页面:

.NET Winform超级代码生成器V6.1 - 快速生成Winform三层架构代码

 

3、生成业务单据窗体(主从表)

生成的C#源码:

贴图图片-代码生成器-生成业务单据窗体

将源码复制到vs解决方案:

贴图图片-代码生成器-生成业务单据窗体1

双击打开窗体设计器:

数据查询界面:

.NET Winform超级代码生成器V6.1 - 快速生成Winform三层架构代码

 

数据编辑页面:

 

.NET Winform超级代码生成器V6.1 - 快速生成Winform三层架构代码

 

4、生成表格编辑窗体

贴图图片-代码生成器-生成表格编辑窗体

将源码复制到vs解决方案:

贴图图片-代码生成器-生成表格编辑窗体2

双击打开窗体设计器:

数据查询及编辑界面:

.NET Winform超级代码生成器V6.1 - 快速生成Winform三层架构代码

 

5、生成数据查询窗体

贴图图片-代码生成器-生成数据查询窗体

将源码复制到vs解决方案:

贴图图片-代码生成器-生成数据查询窗体2

 

双击打开窗体设计器:

数据查询界面:

.NET Winform超级代码生成器V6.1 - 快速生成Winform三层架构代码

 

6、生成FastReport报表(Master 单表报表)

贴图图片-代码生成器-生成单表报表

打开报表模板文件:rpt_Demo_Customer.frx

.NET Winform超级代码生成器V6.1 - 快速生成Winform三层架构代码

 

预览报表:

.NET Winform超级代码生成器V6.1 - 快速生成Winform三层架构代码

 

7、生成FastReport报表(Master/Detail 单从表报表)

 

贴图图片-代码生成器-生成主从表报表

打开报表模板文件:rpt_Demo_IN.frx

.NET Winform超级代码生成器V6.1 - 快速生成Winform三层架构代码

 

预览报表

.NET Winform超级代码生成器V6.1 - 快速生成Winform三层架构代码

 

生成的C#代码参考

 

1、窗体代码

C# 全选
using System;
using System.ComponentModel;
using System.Collections.Generic;
using System.Data;
using System.Text;
using System.Linq;
using CSFrameworkV6.Business;
using CSFrameworkV6.Common;
using CSFrameworkV6.Core;
using CSFrameworkV6.Core.Extensions;
using CSFrameworkV6.Library;
using CSFrameworkV6.Library.CommonClass;
using CSFrameworkV6.Library.Extensions;
using CSFrameworkV6.Models;
using CSFrameworkV6.Models.ReqModels;
using CSFrameworkV6.Models.ResModels;
using DevExpress.XtraEditors;
using System.Windows.Forms;

/*===================================================================
 *   程序说明: _Demo_Customer - 基础资料窗体
 *   创建日期: 2024-09-24
 *   最后修改: 2024-09-24
 *   作者资料: CSFramework
 *   版权所有 Copyright 2006~2024, C/S框架网 (www.csframework.com)
 *   ----------------------------------------------------------------
 *   修改记录:
 *      2024-09-24: 自动生成代码
 *      2024-09-24: 您的修改记录
 *===================================================================*/

namespace CSFrameworkV6.HumanResource
{
    ///<summary>
    /// _Demo_Customer的资料管理窗体,由代码生成器(Code Generator)自动生成
    /// </summary>
    public partial class frm__Demo_Customer : frmBaseDataDictionary
    {
        private bll__Demo_Customer _BLL;

        public frm__Demo_Customer()
        {
            InitializeComponent();
        }

        private void frm__Demo_Customer_Load(object sender, EventArgs e)
        {
            this.InitializeForm();//自定义初始化操作
        }

        protected override void InitializeForm()
        {
            _SummaryView = new DevGridView(gvSummary);//实例化主表表格数据视图,框架支持多种视图,比如表格GridControl,树视图TreeList.
            //_ActiveEditor = txtisid;//进入修改状态,显示第一个焦点的输入框,可以不设置
            //_KeyEditor = txtisid;//主键字段输入框,可以不设置
            _DetailGroupControl = pcDetailEditor;//【资料编辑】页面的输入框的容器组件
            _BLL = new bll__Demo_Customer(); //实例化基类的业务逻辑层

            base.InitializeForm();
            this.BoundLookupData(this);

            #region 以下代码全自动生成,请调整排版和顺序


            #endregion
        }

        /// <summary>
        /// 初始化界面按钮
        /// </summary>
        public override void InitButtons()
        {
            base.InitButtons();
            _buttons.RemoveButton(ButtonNameList.btnRefreshDataDict);
        }
        #region 自动生成的事件或方法的主体部份


        #endregion

        public override void BoundLookupData(object sender = null)
        {
            //
            //DataBinderTools绑定下拉组件数据源
            //
            //DataBinderTools.BoundUser(txtCreatedBy.Properties);
            //
        }


        protected override void ShowSummary()
        {
            //有查询条件:打开窗体时不显示数据

            //打开窗体默认加载100条数据(DAL层控制记录数)
            //gcSummary.DataSource = _BLL.GetSummaryData();
        }

        /// <summary>
        /// 绑定修改页面所有文本框的数据源
        /// </summary>
        /// <param name="summary">数据源</param>
        protected override void DoBindingSummaryEditor(object summary)
        {
            this.DoBindingEditorPanel(pcDetailEditor, summary);

            //在此绑定其它特殊组件的数据源。参考frmCustomer的DoBindingSummaryEditor方法
        }

        /// <summary>
        /// 新增记录, btnAdd按钮事件
        /// </summary>
        public override void DoAdd(IButtonInfo sender)
        {
            try
            {
                frmWaitingEx.ShowMe(this);
                _BLL.CreateDataBinder(null);//实例化业务逻辑层_DataBinder成员变量
                this._UpdateType = UpdateType.Add;//设置为新增模式
                this.DoBindingSummaryEditor(_BLL.DataBinder); //绑定数据编辑页所有文本框的数据源
                this.SetEditMode();//设置为编辑模式(Add或Modify模式),控制按钮显示/禁用状态
                this.ButtonStateChanged(_UpdateType);//通知按钮状态事件
                this.ShowDetailPage(true);
            }
            finally
            {
                frmWaitingEx.HideMe(this);
            }
        }

        /// <summary>
        /// 删除记录, btnDelete按钮事件
        /// </summary>
        public override void DoDelete(IButtonInfo sender)
        {
            AssertFocusedRow();
            if (!Msg.AskQuestion("确定要删除吗?")) return;

            try
            {
                frmWaitingEx.ShowMe(this);

                var row = _SummaryView.GetFocusedRow() as _Demo_Customer;//获取表格中当前记录
                var result = _BLL.Delete(row.isid);//调用BLL层删除接口,删除逻辑校验可放到DAL层
                AssertEqual(result, true, "删除记录时发生错误!");

                this.DeleteSummaryRow(_SummaryView.FocusedRowHandle);//删除表格中当前记录
                this.NotifyDataDictChanged<_Demo_Customer>(this);//通知数据缓存器
                if (_SummaryView.FocusedRowHandle < 0) //删除表格中最后一条记录,要显示数据查询页.
                {
                    ShowSummaryPage(true);
                }
                else
                {
                    _BLL.CreateDataBinder(_SummaryView.GetObject<_Demo_Customer>());
                    DoBindingSummaryEditor(_BLL.DataBinder);
                }
            }
            finally
            {
                frmWaitingEx.HideMe(this);
            }
        }

        /// <summary>
        /// 修改资料,btnEdit按钮事件
        /// </summary>
        public override void DoEdit(IButtonInfo sender)
        {
            //
            //逻辑判断:是否可修改当前资料
            //
            //调用基类方法,修改事件代码逻辑可复用
            base.DoEdit(sender);
        }

        /// <summary>
        /// 查看资料,btnViewContent按钮事件。显示当前记录的详细资料
        /// </summary>
        public override void DoViewContent(IButtonInfo sender)
        {
            AssertFocusedRow();//检查是否选择一条记录.
            try
            {
                frmWaitingEx.ShowMe(this);
                _BLL.CreateDataBinder(_SummaryView.GetObject<_Demo_Customer>());
                this.DoBindingSummaryEditor(_BLL.DataBinder);
                this.ButtonStateChanged(_UpdateType);
                this.ShowDetailPage(false);
            }
            finally
            {
                frmWaitingEx.HideMe(this);
            }
        }

        /// <summary>
        /// 保存资料,btnSave按钮事件
        /// </summary>
        public override void DoSave(IButtonInfo sender)
        {
            try
            {
                frmWaitingEx.ShowMe(this);
                this.UpdateLastControl(); //更新最后一个输入控件的数据源
                if (!ValidatingData()) return; //检查资料完整性

                bool result = _BLL.Update(_UpdateType);//调用业务逻辑层接口保存数据
                if (result)
                {
                    var dt = _BLL.GetDataByKey(_BLL.DataBinder.isid);//获取最新数据
                    this.UpdateSummaryRow(dt); //刷新表格当前记录
                    this.DoSave_ResetState();//保存成功后要设置各种状态,调用基类通用逻辑
                }
                else
                {
                    Msg.Warning("保存失败!");
                }
            }
            finally
            {
                frmWaitingEx.HideMe(this);
            }
        }

        /// <summary>
        /// 按钮状态改变时触发的事件
        /// </summary>
        /// <param name="currentState">当前操作状态</param>
        protected override void ButtonStateChanged(UpdateType currentState)
        {
            base.ButtonStateChanged(currentState);
            txtCreationDate.Properties.ReadOnly = true;//禁止修改
            txtCreatedBy.Properties.ReadOnly = true;//禁止修改
            txtLastUpdateDate.Properties.ReadOnly = true;//禁止修改
            txtLastUpdatedBy.Properties.ReadOnly = true;//禁止修改
        }

        private void btnEmpty_Click(object sender, EventArgs e)
        {
            base.ClearContainerEditorText(pnlSearch);
        }

        private void btnQuery_Click(object sender, EventArgs e)
        {
            //搜索数据     
            try
            {
                frmWaitingEx.ShowMe(this);

                var input = new req__Demo_Customer
                {
                    CustomerCode = txt_CustomerCode.EditValue.ToStringEx(),
                    NativeName = txt_NativeName.EditValue.ToStringEx(),
                };

                var data = _BLL.Query(input);
                this.DoBindingSummaryGrid(data); //绑定主表表格数据源
                this.ShowSummaryPage(true);
                //if (gvSummary.RowCount == 0) Msg.Warning("没有找到数据!");
            }
            finally
            {
                frmWaitingEx.HideMe(this);
            }

        }

        public override void DoShowLog(IButtonInfo button)
        {
            //显示审计日志
            this.MainForm.OpenModuleForm(Globals.LogViewerForm, "", nameof(_Demo_Customer));
        }
    }
}

 

2、BLL代码

C# 全选
using System;
using System.Collections.Generic;
using CSFrameworkV6.Models;
using CSFrameworkV6.Models.UpdateModel;
using CSFrameworkV6.Models.ReqModels;
using CSFrameworkV6.Common;
using CSFrameworkV6.Core;
using CSFrameworkV6.Interfaces;
using CSFrameworkV6.Business;
using CSFrameworkV6.DataAccess;
using CSFrameworkV6.WebApiClient;

/*===================================================================
 *   程序说明: _Demo_Customer 基础资料BLL层(直连DAL层)
 *   作者资料: CSFramework
 *   创建日期: 2024-09-24 08:58:07
 *   最后修改: 2024-09-24 08:58:07
 *   
 *   注:本文件由CSFramework.CodeGenerator代码生成器自动生成。
 *      请将源码文件复制到 YourProject 对应的项目。
 *   
 *   版权所有 Copyright 2006~2024, C/S框架网 (www.csframework.com)
 *===================================================================*/

namespace CSFrameworkV6.Business
{
    /// <summary>
    /// BLL业务逻辑层:bll__Demo_Customer
    /// </summary>
    public class bll__Demo_Customer : bllBaseDataDict<_Demo_Customer>
    {
        private dal__Demo_Customer _DAL; //数据层实例

        public bll__Demo_Customer()
        {
            _SummaryTableName = nameof(_Demo_Customer);//表名
            _KeyFieldName = nameof(_Demo_Customer.isid);//主键字段
            _DAL = new dal__Demo_Customer(CSFrameworkV6.Core.Loginer.CurrentUser);//实例化DAL
            _DataDictBridge = _DAL;//重要:必须实例化当前数据字典的标准策略接口
        }

        /// <summary>
        /// 新增模式,需要实例化_DataBinder成员变量
        /// </summary>
        public override void CreateDataBinder(_Demo_Customer sourceRow)
        {
            base.CreateDataBinder(sourceRow);
            
            if (sourceRow == null)//新增记录,设置默认值
            {
                 _DataBinder.isid = IdHelper.GetId();//主键
                 //
                 //下面代码给其他字段赋值
                 //
            }
        }
        public List<_Demo_Customer> Query(req__Demo_Customer input)
        {
            return _DAL.Query(input);
        }
    }
}

 

3、DAL代码

C# 全选
using System;
using System.Text;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Linq;
using CSFramework.EF;
using CSFrameworkV6.Core;
using CSFrameworkV6.Common;
using CSFrameworkV6.Core.Extensions;
using CSFrameworkV6.DataAccess;
using CSFrameworkV6.Interfaces;
using CSFrameworkV6.Models;
using CSFrameworkV6.Models.ReqModels;
using CSFrameworkV6.Models.UpdateModel;

/*===================================================================
 *   程序说明: _Demo_Customer 基础资料数据访问层
 *   作者资料: CSFramework
 *   创建日期: 2024-09-24 08:58:07
 *   最后修改: 2024-09-24 08:58:07
 *   
 *   注:本文件由CSFramework.CodeGenerator代码生成器自动生成。
 *      请将源码文件复制到 YourProject 对应的项目。
 *   
 *   版权所有 Copyright 2006~2024, C/S框架网 (www.csframework.com)
 *===================================================================*/

namespace CSFrameworkV6.DataAccess
{
    /// <summary>
    /// DAL数据层:dal__Demo_Customer
    /// </summary>
    [DefaultORM_UpdateMode(typeof(_Demo_Customer), true)]
    public class dal__Demo_Customer : dalBaseDataDict<_Demo_Customer>
    {
         /// <summary>
         /// 构造器
         /// </summary>
         /// <param name="loginer">当前登录用户</param>
        public dal__Demo_Customer(Core.Loginer loginer): base(loginer)
        {
        }

        /// <summary>
        /// 获取表格默认显示的数据
        /// </summary>
        /// <returns></returns>
        public override List<_Demo_Customer> GetSummaryData()
        {
           var q = _Database.GetQueryable<_Demo_Customer>();
           return q.Take(100).ToList();//默认显示100条记录
        }

        /// <summary>
        /// 获取该主数据作为Lookup数据源的数据,如:返回Code,Name字段
        /// </summary>
        /// <returns></returns>
        public override List<_Demo_Customer> GetLookupData()
        {
           //返回所有字段
           return _Database.GetQueryable<_Demo_Customer>().ToList();

           //
           ////若该表的字段多、数据量大建议改为以下方式:
           //var q = _Database.GetQueryable<_Demo_Customer>();
           //var list = q.Select(s => new 
           //{
           //    s.Code,
           //    s.Name,
           //}.Distinct().ToList();
           //
           ////返回结果
           //return ObjectHelper.ConvertList<_Demo_Customer>(list);
           //

        }

        public override bool CheckNoExists(string keyValue)
        {
            return false;

            //参考代码
            //var q = _Database.GetQueryable<_Demo_Customer>();
            //return q.Any(a => a.字段名称 == keyValue);
        }

        /// <summary>
        /// 根据主键获取一条主数据
        /// </summary>
        /// <param name="keyValue">主键</param>
        /// <returns></returns>
        public override _Demo_Customer GetDataByKey(string keyValue)
        {
            var q = _Database.GetQueryable<_Demo_Customer>();
            return q.Where(w => w.isid == keyValue).FirstOrDefault();
        }

        /// <summary>
        /// 删除
        /// </summary>
        /// <param name="keyValue">主键</param>
        /// <returns></returns>
        public override bool Delete(string keyValue)
        {
            return this.Delete(this.GetDataByKey(keyValue));
        }

        /// <summary>
        /// 查询
        /// </summary>
        /// <param name="input">查询条件</param>
        /// <returns></returns>
        public List<_Demo_Customer> Query(req__Demo_Customer input)
        {
            var q = _Database.GetQueryable<_Demo_Customer>();

            if (!input.CustomerCode.IsEmpty())
                q = q.Where(w => w.CustomerCode.CompareTo(input.CustomerCode) ==  0); 

            if (!input.NativeName.IsEmpty())
                q = q.Where(w => w.NativeName.CompareTo(input.NativeName) ==  0); 

            //返回查询结果
            return q.ToList();
        }

        /// <summary>
        /// 保存数据,用于提交自动生成流水号码的数据, SaveResult.DocNo返回最新号码。
        /// </summary>
        /// <param name="data">当前提交的数据</param>
        /// <returns></returns>
        public override SaveResult UpdateEx(MasterDataUpdate<_Demo_Customer> data)
        {
            return base.UpdateEx(data);
        }

        /// <summary>
        /// 通用保存数据的方法
        /// </summary>
        /// <param name="data">当前提交的数据</param>
        /// <returns></returns>
        public override bool Update(MasterDataUpdate<_Demo_Customer> data)
        {
            return base.Update(data);
        }

        /// <summary>
        /// 设置流水序号
        /// </summary>
        /// <param name="data">当前提交的数据</param>
        /// <returns></returns>
        protected override string SetDataSN(MasterDataUpdate<_Demo_Customer> data)
        {
            //注意:当前功能要设置流水序号? 参考:dalReports.SetDataSN方法
            return string.Empty;
        }

     }//public class
}//namespace

 

4、模型Model

C# 全选
using System;
using System.Collections.Generic;
using System.Text;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;


/*===================================================================
 *   程序说明: _Demo_Customer 实体类(ORM模型)
 *   作者资料: CSFramework
 *   创建日期: 2024-09-24 08:58:07
 *   最后修改: 2024-09-24 08:58:07
 *   
 *   注:本文件由CSFramework.CodeGenerator代码生成器自动生成。
 *      请将源码文件复制到 YourProject 对应的项目。
 *   
 *   版权所有 Copyright 2006~2024, C/S框架网 (www.csframework.com)
 *===================================================================*/

namespace CSFrameworkV6.Models
{
    ///<summary>
    /// 数据表:_Demo_Customer的实体模型(ORM Model)。
    /// </summary>
    [Table("_Demo_Customer")]
    public class _Demo_Customer
    {

        #region 所有字段属性

        /// <summary>
        /// 自增
        /// </summary>
        [Key, Column(Order = 1)]
        public String isid { get; set; }

        /// <summary>
        /// 客户
        /// </summary>
        public String CustomerCode { get; set; }

        /// <summary>
        /// 中文名称
        /// </summary>
        public String NativeName { get; set; }

        /// <summary>
        /// 英文名
        /// </summary>
        public String EnglishName { get; set; }

        /// <summary>
        /// 地址1
        /// </summary>
        public String Address1 { get; set; }

        /// <summary>
        /// 地址2
        /// </summary>
        public String Address2 { get; set; }

        /// <summary>
        /// 地址666999
        /// </summary>
        public String Address3 { get; set; }

        /// <summary>
        /// 国家1
        /// </summary>
        public String Country { get; set; }

        /// <summary>
        /// 区域
        /// </summary>
        public String Region { get; set; }

        /// <summary>
        /// 城市
        /// </summary>
        public String City { get; set; }

        /// <summary>
        /// 国家编号
        /// </summary>
        public String CountryCode { get; set; }

        /// <summary>
        /// 城市编码
        /// </summary>
        public String CityCode { get; set; }

        /// <summary>
        /// 电话
        /// </summary>
        public String Tel { get; set; }

        /// <summary>
        /// 传真
        /// </summary>
        public String Fax { get; set; }

        /// <summary>
        /// 区号
        /// </summary>
        public String PostalCode { get; set; }

        /// <summary>
        /// 邮编
        /// </summary>
        public String ZipCode { get; set; }

        /// <summary>
        /// 网址
        /// </summary>
        public String WebAddress { get; set; }

        /// <summary>
        /// 邮件地址
        /// </summary>
        public String Email { get; set; }

        /// <summary>
        /// 银行
        /// </summary>
        public String Bank { get; set; }

        /// <summary>
        /// 银行帐号
        /// </summary>
        public String BankAccount { get; set; }

        /// <summary>
        /// 银行地址
        /// </summary>
        public String BankAddress { get; set; }

        /// <summary>
        /// 联系人
        /// </summary>
        public String ContactPerson { get; set; }

        /// <summary>
        /// 备注
        /// </summary>
        public String Remark { get; set; }

        /// <summary>
        /// 使用
        /// </summary>
        public String InUse { get; set; }

        /// <summary>
        /// 付款期限
        /// </summary>
        public Int32? PaymentTerm { get; set; }

        /// <summary>
        /// 创建日期
        /// </summary>
        public DateTime? CreationDate { get; set; }

        /// <summary>
        /// 创建人
        /// </summary>
        public String CreatedBy { get; set; }

        /// <summary>
        /// 最后更新日期
        /// </summary>
        public DateTime? LastUpdateDate { get; set; }

        /// <summary>
        /// 最后修改人
        /// </summary>
        public String LastUpdatedBy { get; set; }

        #endregion
    }
}

 

本文完整源码

 

.NET Winform超级代码生成器V6.1 - 快速生成Winform三层架构代码

 

CSFramework.CodeGenerator V6.1 代码生成器下载

https://www.cscode.net/archive/codegeneratorv6/396854069219333.html

 

版权声明:本文为开发框架文库发布内容,转载请附上原文出处连接
C/S框架网
评论列表

发表评论

评论内容
昵称:
关联文章

.NET Winform超级代码生成器V6.1 - 快速生成Winform架构代码
C# Winform 架构代码生成器 V5.1版正式发布
Winform+DevExpress架构软件快速开发平台-旗舰版V5.1
原创Winform快速开发框架平台Oracle版本(架构+C#.NET+Oracle数据库)
C/S快速开发框架旗舰版V5.1 - 代码生成器快速生成业务模块Project项目
Winform界面自适应快速开发框架(C#+Dev+架构+多数据库支持)
进销存快速开发框架(Winform架构+DevExpress+SQL2008R2)
Winform架构教程,CS结构图及源码实例讲解
基于Winform架构+WCF+ORM模型的快速开发框架
生成的项目模块(Project)添加到VS解决方案 - C/S框架架构代码生成器操作指南
CSFramework C#代码生成器生成窗体界面UI,BLL,DAL,Model,WCF接口源代码
C/S架构快速开发平台代码生成器CodeGeneratorV5.1
生成的窗体Form源码集成到VS解决方案 - C/S框架架构代码生成器操作指南
C/S架构快速开发平台代码生成器CodeGeneratorV5.1简介
Winform快速开发框架平台代码生成器核心优势
推荐基于C/S架构的软件开发工具(Winform+C#语言+ADO.NET+代码生成器)
CSFramework.CodeGeneratorV6 代码生成器
代码生成器 CodeGenerator - 生成ORM
代码生成器 CodeGenerator V6.1 - 两种策略生成报表(TableObject/TextObject)
代码生成器 CodeGenerator V6.1 - 两种策略生成单表、主从表报表