首页 星云 工具 资源 星选 资讯 热门工具
:

PDF转图片 完全免费 小红书视频下载 无水印 抖音视频下载 无水印 数字星空

Known框架实战演练——进销存业务单据

编程知识
2024年07月24日 15:01

本文介绍如何实现进销存管理系统的业务单据模块,业务单据模块包括采购进货单、采购退货单、销售出货单、销售退货单4个菜单页面。由于进销单据字段大同小异,因此设计共用一个页面组件类。

1. 配置模块

运行项目,在【系统管理-模块管理】中配置如下模块菜单,配置教程参考之前的教程。

一级模块 二级模块 代码 图标 Url 描述
进货管理 Import import
采购进货单 ImportList unordered-list /bms/ImportList 查询和维护采购进货单信息。
采购退货单 ImportReturn unordered-list /bms/ImportReturn 查询和维护采购退货单信息。
销货管理 Export export
销售出货单 ExportList unordered-list /bms/ExportList 查询和维护销售出货单信息。
销售退货单 ExportReturn unordered-list /bms/ExportReturn 查询和维护销售退货单信息。

2. 实体类

JxcLite项目Entities文件夹下面添加JxBillHead.csJxBillList.cs两个实体类文件,实体类代码可以直接复制模块管理中由模型设置生成的代码。文章中只简单描述一下实体类的定义,具体代码参见开源,代码定义如下:

namespace JxcLite.Entities;

/// <summary>
/// 业务单据表头信息类。
/// </summary>
public class JxBillHead : EntityBase { }

/// <summary>
/// 业务单据表体信息类。
/// </summary>
public class JxBillList : EntityBase { }

3. 建表脚本

打开JxcLite.Web项目Resources文件夹下的Tables.sql资源文件,复制粘贴由【模块管理-模型设置】中生成的建表脚本。文章中只简单描述一下建表脚本,具体脚本参见开源,内容如下:

CREATE TABLE [JxBillHead] (
    [Id]         varchar(50)      NOT NULL PRIMARY KEY,
    ...
    [Files]      nvarchar(500)    NULL
);

CREATE TABLE [JxBillList] (
    [Id]         varchar(50)      NOT NULL PRIMARY KEY,
    ...
    [Note]       ntext            NULL
);

4. 服务接口

JxcLite项目Services文件夹下面添加业务单据模块服务接口,文件名定义为IBillService.cs,该接口定义前后端交互的Api访问方法,包括分页查询、批量删除实体、保存实体。具体方法定义如下:

namespace JxcLite.Services;

public interface IBillService : IService
{
    //分页查询业务单据信息
    Task<PagingResult<JxBillHead>> QueryBillsAsync(PagingCriteria criteria);
    //根据单据类型获取默认单据信息
    Task<JxBillHead> GetDefaultBillAsync(string type);
    //根据表头ID获取单据表体信息列表
    Task<List<JxBillList>> GetBillListsAsync(string headId);
    //批量删除业务单据信息
    Task<Result> DeleteBillsAsync(List<JxBillHead> models);
    //保存业务单据信息
    Task<Result> SaveBillAsync(UploadInfo<JxBillHead> info);
}

5. 服务实现

JxcLite.Web项目Services文件夹下面添加业务单据模块服务接口的实现类,文件名定义为BillService.cs,文章中只简单描述一下实现类的定义和继承,具体实现参见开源,定义如下:

namespace JxcLite.Web.Services;

class BillService(Context context) : ServiceBase(context), IBaseDataService
{
    public Task<PagingResult<JxBillHead>> QueryBillsAsync(PagingCriteria criteria) { }
    public Task<JxBillHead> GetDefaultBillAsync(string type) { }
    public Task<List<JxBillList>> GetBillListsAsync(string headId) { }
    public Task<Result> DeleteBillsAsync(List<JxBillHead> models) { }
    public Task<Result> SaveBillAsync(UploadInfo<JxBillHead> info) { }
}

双击打开JxcLite.Web项目中的AppWeb.cs文件,在AddJxcLiteCore方法中注册服务类,前端组件可以通过依赖注入工厂创建服务的实例。代码如下:

public static class AppWeb
{
    public static void AddJxcLiteCore(this IServiceCollection services)
    {
        services.AddScoped<IBillService, BillService>();
    }
}

6. 数据依赖

JxcLite.Web项目Repositories文件夹下面添加业务单据模块数据依赖类,文件名定义为BillRepository.cs,文章中只简单描述一下依赖类的定义,具体实现参见开源,定义如下:

namespace JxcLite.Web.Repositories;

class BillRepository
{
    internal static Task<PagingResult<JxBillHead>> QueryBillsAsync(Database db, PagingCriteria criteria) { }

    internal static Task<List<JxBillList>> GetBillListsAsync(Database db, string headId) { }
    //根据前缀获取最大业务单号
    internal static Task<string> GetMaxBillNoAsync(Database db, string prefix) { }
}

7. 列表页面

JxcLite.Client项目Pages\BillData文件夹下面添加BillList.cs单据列表组件,该组件是进销单及退货单的列表组件共用类,具体实现参见开源,部分代码如下:

namespace JxcLite.Client.Pages.BillData;

public class BillList : BaseTablePage<JxBillHead>
{
    private IBillService Service;
    //取得业务单据类型(进货、进退货、销货、销退货),由具体单据页面重写该类型
    protected virtual string Type { get; }
    
    protected override async Task OnPageInitAsync()
    {
        await base.OnPageInitAsync();
        Service = await CreateServiceAsync<IBillService>();//创建服务
        Table.FormType = typeof(BillForm);//自定义表单类型
        Table.OnQuery = QueryBillsAsync;  //查询方法
        //下面是设置列表栏位显示的模板
        Table.Column(c => c.Status).Template((b, r) => b.Tag(r.Status));
        Table.Column(c => c.BillDate).Type(FieldType.Date);
    }
    //新增
    public async void New()
    {
        var row = await Service.GetDefaultBillAsync(Type);
        Table.NewForm(Service.SaveBillAsync, row);
    }
    //编辑
    public async void Edit(JxBillHead row)
    {
        row.Lists = await Service.GetBillListsAsync(row.Id);
        Table.EditForm(Service.SaveBillAsync, row);
    }
    //批量删除和删除
    public void DeleteM() => Table.DeleteM(Service.DeleteBillsAsync);
    public void Delete(JxBillHead row) => Table.Delete(Service.DeleteBillsAsync, row);
    //复制和退货
    public void Copy() => Table.SelectRow(async row => {});
    public void Return() => Table.SelectRow(async row => {});
    //打印
    public void Print() => Table.SelectRow(async row =>
    {
        row.Lists = await Service.GetBillListsAsync(row.Id);
        //BillPrint为业务单据打印组件
        await JS.PrintAsync<BillPrint>(f => f.Set(c => c.Model, row));
    });
    //导出
    public async void Export() => await ExportDataAsync();
    
    private Task<PagingResult<JxBillHead>> QueryBillsAsync(PagingCriteria criteria)
    {
        //设置单据类型查询条件
        criteria.SetQuery(nameof(JxBillHead.Type), QueryType.Equal, Type);
        return Service.QueryBillsAsync(criteria);
    }
}

8. 供应商和客户选择框

JxcLite.Client项目Shared文件夹下面添加PartnerPicker.cs,该组件继承BasePicker,用于弹窗选择客户和供应商信息,具体实现参见开源,部分代码如下:

namespace JxcLite.Client.Shared;

public class PartnerPicker : BasePicker<JxPartner>
{
    private IBaseDataService Service;
    private TableModel<JxPartner> Table;
    //取得弹框选择的数据列表
    public override List<JxPartner> SelectedItems => Table.SelectedRows?.ToList();
    //取得或设置商业伙伴类型(客户、供应商)
    [Parameter] public string Type { get; set; }
    
    protected override async Task OnInitAsync() {}
    protected override void BuildContent(RenderTreeBuilder builder) => builder.Table(Table);
}

9. 商品信息选择框

JxcLite.Client项目Shared文件夹下面添加GoodsPicker.cs,该组件继承BasePicker,用于弹窗选择商品信息,具体实现参见开源,部分代码如下:

namespace JxcLite.Client.Shared;

public class GoodsPicker : BasePicker<JxGoods>
{
    private IBaseDataService Service;
    private TableModel<JxGoods> Table;
    //取得弹框选择的数据列表
    public override List<JxGoods> SelectedItems => Table.SelectedRows?.ToList();
    
    protected override async Task OnInitAsync() {}
    protected override void BuildContent(RenderTreeBuilder builder) => builder.Table(Table);
}

10. 表单组件

首先在JxcLite.Client项目Shared文件夹下面添加TypeForms.csTypeTables.cs文件,添加业务单据表头类型表单组件和业务单据表体类型表格组件,代码如下:

namespace JxcLite.Client.Shared;

public class BillHeadTypeForm : AntForm<JxBillHead> { }

public class BillListTypeTable : AntTable<JxBillList> { }

再在JxcLite.Client项目Pages\BillData文件夹下面添加BillForm.razorBillForm.razor.cs文件,由于单据表单组件有点复杂,代码较长,所以采用razor语法来实现,该组件是进销单及退货单的列表组件共用类,具体实现参见开源,部分代码如下:

@inherits BaseForm<JxBillHead>

<BillHeadTypeForm Form="Model">
    <AntRow>
        <DataItem Span="6" Label="业务单号" Required>
            <AntInput Disabled @bind-Value="@context.BillNo" />
        </DataItem>
        <DataItem Span="6" Label="单证状态">
            <KTag Text="@context.Status" />
        </DataItem>
        <DataItem Span="6" Label="单证日期" Required>
            <AntDatePicker @bind-Value="@context.BillDate" />
        </DataItem>
        <DataItem Span="6" Label="商业伙伴" Required>
            <PartnerPicker Value="@context.Partner" AllowClear
                           Type="@GetPartnerPickerType(context)" />
        </DataItem>
    </AntRow>
</BillHeadTypeForm>
<KToolbar>
    <KTitle Text="商品明细" />
    <div>
        @if (!Model.IsView)
        {
            <Button Type="@ButtonType.Primary" Icon="plus" OnClick="OnAdd">添加</Button>
        }
    </div>
</KToolbar>
<BillListTypeTable DataSource="Model.Data.Lists" HidePagination ScrollX="1300px" ScrollY="200px">
    <IntegerColumn Title="序号" Field="@context.SeqNo" Width="60" Fixed="left" />
    <StringColumn Title="商品编码" Width="120" Fixed="left">
        <AntInput @bind-Value="@context.Code" Style="width:100px" />
    </StringColumn>
    <StringColumn Title="金额" Width="100">
        <AntDecimal @bind-Value="@context.Amount" OnChange="e=>OnGoodsChange(3, context)" />
    </StringColumn>
    @if (!Model.IsView)
    {
        <ActionColumn Title="操作" Align="ColumnAlign.Center" Width="100" Fixed="right">
            <Tag Color="red-inverse" OnClick="e=>OnDelete(context)">删除</Tag>
        </ActionColumn>
    }
    <SummaryRow>
        <SummaryCell Fixed="left">合计</SummaryCell>
        <SummaryCell>@Model.Data.Lists.Sum(l => l.Amount)</SummaryCell>
        <SummaryCell />
        @if (!Model.IsView)
        {
            <SummaryCell />
        }
    </SummaryRow>
</BillListTypeTable>
namespace JxcLite.Client.Pages.BillData;

partial class BillForm
{
    private KUpload upload;
    private static string GetPartnerPickerType(JxBillHead model) {}
    private async void OnFilesChanged(List<FileDataInfo> files) {}
    private void OnAdd() {}
    private void OnDelete(JxBillList row) => Model.Data.Lists.Remove(row);
    private void OnGoodsChange(int field, JxBillList row) {}
}

11. 打印组件

JxcLite.Client项目Pages\BillData文件夹下面添加BillPrint.cs,该组件是打印业务单据内容组件,具体实现参见开源,部分代码如下:

namespace JxcLite.Client.Pages.BillData;

class BillPrint : ComponentBase
{
    //业务单据实体对象
    [Parameter] public JxBillHead Model { get; set; }

    protected override void BuildRenderTree(RenderTreeBuilder builder)
    {
        BuildStyle(builder);//构建样式表,打印时调用浏览器的预览,选打印机打印
        BuildForm(builder); //构建打印表单
    }

    private static void BuildStyle(RenderTreeBuilder builder)
    {
        builder.Markup(@"<style>
.bill-print {position:relative;}
</style>");
    }

    private void BuildForm(RenderTreeBuilder builder) {}
}
From:https://www.cnblogs.com/known/p/18321104
本文地址: http://www.shuzixingkong.net/article/376
0评论
提交 加载更多评论
其他文章 Linux 文本文件编辑相关命令简介【Linux 常用命令系列二】
本文介绍了如何通过 vim 命令,对文本文件进行打开、编辑、保存等相关操作,并通过简单的示例演示了常用用法。
Linux 文本文件编辑相关命令简介【Linux 常用命令系列二】 Linux 文本文件编辑相关命令简介【Linux 常用命令系列二】 Linux 文本文件编辑相关命令简介【Linux 常用命令系列二】
2024-07-24:用go语言,给定一个整数数组 nums,其中至少包含两个元素。 可以根据以下规则执行操作:选择最前面两个元素删除、选择最后两个元素删除,或选择第一个和最后一个元素删除。 每次操作
2024-07-24:用go语言,给定一个整数数组 nums,其中至少包含两个元素。 可以根据以下规则执行操作:选择最前面两个元素删除、选择最后两个元素删除,或选择第一个和最后一个元素删除。 每次操作的得分是被删除元素的和。 在每次操作后,所有操作得分需保持相同。 问题要求确定在这些前提下,最多可以
2024-07-24:用go语言,给定一个整数数组 nums,其中至少包含两个元素。 可以根据以下规则执行操作:选择最前面两个元素删除、选择最后两个元素删除,或选择第一个和最后一个元素删除。 每次操作
关于学习.NET的历程回顾与今后的探索实践方向
关于学习.NET的历程回顾 自从2023年9月11日注册公众号以来,这次还是第一次介绍自己。我今年24岁,双非本,211硕,非计算机相关专业。大学期间接触过计算机相关的课程可能就《大学生计算机基础》、《C语言程序设计》,并且也没掌握多好。 22年4月研究生复试结束,联系好导师后,由于导师研究方向的缘
关于学习.NET的历程回顾与今后的探索实践方向 关于学习.NET的历程回顾与今后的探索实践方向 关于学习.NET的历程回顾与今后的探索实践方向
Python用shp文件裁剪多个遥感影像的方法
本文介绍基于Python中ArcPy模块,基于矢量数据范围,对大量栅格遥感影像加以批量裁剪掩膜的方法~
Python用shp文件裁剪多个遥感影像的方法
Android Spingboot 实现SSE通信案例
SSE SSE(Server-Sent Events)是一种用于实现服务器主动向客户端推送数据的技术,它基于 HTTP 协议,利用了其长连接特性,在客户端与服务器之间建立一条持久化连接,并通过这条连接实现服务器向客户端的实时数据推送。 Server-Sent Events (SSE) 和 Socke
Android Spingboot 实现SSE通信案例 Android Spingboot 实现SSE通信案例 Android Spingboot 实现SSE通信案例
DASCTF 2023 & 0X401七月暑期挑战赛【PWN】(FileEditor篇)
DASCTF 2023 &amp; 0X401七月暑期挑战赛【PWN】(FileEditor篇) 题目保护情况(保护全家桶) 64位ida逆向 模拟了一个类似vim的功能,有打开文件,打印内容,插入行,删除行,复制行,和编辑行,还有查找字符和替换字符的功能,然后就是保存退出 一个一个来分析吧 1.o
DASCTF 2023 & 0X401七月暑期挑战赛【PWN】(FileEditor篇) DASCTF 2023 & 0X401七月暑期挑战赛【PWN】(FileEditor篇) DASCTF 2023 & 0X401七月暑期挑战赛【PWN】(FileEditor篇)
RestSharp编写api接口测试,并实现异步调用(不卡顿)
首先,确保你已经安装了RestSharp NuGet包。如果没有安装,可以通过以下命令安装: bash Install-Package RestSharp 然后,在你的C#代码中,你可以按照以下步骤操作: 引用RestSharp命名空间。 创建一个RestClient实例。 创建一个RestRequ
博弈论
一、要素 局中人:在一场竞赛或博弈中,每一个有决策权的参与者成为一个局中人。只有两个局中人的博弈现象称为“两人博弈”,而多于两个局中人的博弈称为“多人博弈”。 策略:一局博弈中,每个局中人都有选择实际可行的完整的行动方案,即方案不是某阶段的行动方案,而是指导整个行动的一个方案,一个局中人的一个可行的
博弈论 博弈论 博弈论