极简实用的Asp.NetCore框架再新增商城模块

简介: 新增加一个商城模块,主要包含商品管理(支持多个sku),商品分类,小程序用户,用户收获地址、订单各种状态的列表。

概述

关于这个框架的背景,在前面我已经交代过了。不清楚的可以查看这个链接

1、极简实用的Asp.NetCore模块化框架决定免费开源了

2、极简实用的Asp.NetCore模块化框架新增CMS模块

算下来确实好长时间没更新博客了,在这段时间内一直在出差,闲暇时间一直在想dotnetcore框架本身就是模块化的,为什么还要在这个上层应用上面继续进行模块化封装,意义何在?是为了更好地划分业务还是轮子重复利用?

细细想来,这个框架不应该再继续模块化下去,主要有以下几点理由支持:

1、本身于我现有地业务而言,没必要模块化,我只是做个大而全地系统(权限管理,内容管理,商城,微信管理等)。

2、如果要做模块化,本身就要牺牲掉一些性能,这是我反反复复斟酌以后不能接受的,主要是牺牲性能有点多!

3、dotnetcore本身就更友好模块化,没必要在这个上层应用上面再包裹一层,没有任何意义,我下载了dotnetcore源码后,觉得它的设计理念特别棒,于是“dotnetcore”本身就是最好的模块化(组件化)框架,可以把很多时间和精力投身于源码上面研究,没有必要在纠结于模块化这个概念,在上层应用折腾来折腾去,对于技术的成长微乎其微。

4、以前划分为模块化,是想朝微服务的方向发展,到时尽量改动小一点。现在想想我就一个后台管理,没必要想那么多。

基于以上几点,我于是把框架进行了更改,对于原来的模块化框架也进行了分支保留(一定意义上来说也不全是模块化)。

新增业务功能

新增加一个商城模块,主要包含商品管理(支持多个sku),商品分类,小程序用户,用户收获地址、订单各种状态的列表。
1046844-20211028174838124-233934674.png
1046844-20211028175053624-1269823241.png
1046844-20211028175424696-733318187.png

关于添加和修改商品的部分后端代码:

        {
            try
            {
                Db.BeginTran();
                // 保存商品
                var goods = _mapper.Map<Goods>(input);
                var goodsId = await Db.Insertable<Goods>(goods).ExecuteReturnIdentityAsync();
                // 保存规格
                await DealwithGoodsSpec(goodsId, input);
                Db.CommitTran();
            }
            catch (Exception e)
            {
                Db.RollbackTran();
                return new ApiResult(e.Message);
            }
            return new ApiResult();
        }
        /// <summary>
        /// 公共的商品规格信息处理
        /// </summary>
        /// <param name="goodsId"></param>
        /// <param name="input"></param>
        /// <returns></returns>
        private async Task DealwithGoodsSpec(int goodsId, GoodsInput input)
        {
            // 保存规格
            if (input.SpecType == SpecTypeEnum.Single.GetValue<int>())
            {
                var specSingle = JsonConvert.DeserializeObject<GoodsSpecInput>(input.SpecSingle);
                input.GoodsSpecInput = specSingle;
                var goodsSpec = input.BuildGoodsSpec(goodsId);
                if (null == goodsSpec)
                {
                    throw new FriendlyException("商品规格实体数据不能为空!");
                }
                await Db.Insertable(goodsSpec).ExecuteReturnIdentityAsync();
            }
            else
            {
                var goodsSpecs = input.BuildGoodsSpecs(goodsId);
                if (null == goodsSpecs || goodsSpecs.Count == 0)
                {
                    throw new FriendlyException("商品规格实体数据集合不能为空!");
                }
                await Db.Insertable(goodsSpecs).ExecuteReturnIdentityAsync();
                var goodsSpecRels = input.BuildGoodsSpecRels(goodsId);
                if (goodsSpecRels.Count == 0 || goodsSpecRels == null)
                {
                    throw new FriendlyException("商品规格实体关系集合数据不能为空!");
                }
                //根据规格值反推规格组id
                var specValues = await Db.Queryable<SpecValue>().Where(d => d.Status).ToListAsync();
                foreach (var item in goodsSpecRels)
                {
                    var specId = specValues.Where(d => d.Status && d.Id == item.SpecValueId).Select(d => d.SpecId);
                    item.SpecId = specId.FirstOrDefault();
                }
                await Db.Insertable(goodsSpecRels).ExecuteReturnIdentityAsync();
            }
        }
        public async Task<ApiResult> ModifyAsync(GoodsModifyInput input)
        {
            var goods = await GetModelAsync(d => d.Id == input.Id);
            if (goods == null) throw new FriendlyException($"此商品{input.Id}没有查找对应的商品信息");
            try
            {
                Db.BeginTran();
                // 更新商品
                var model = _mapper.Map<Goods>(input);
                var goodsId = await Db.Updateable(model).IgnoreColumns(d => new { d.CreateTime }).ExecuteCommandAsync();
                // 更新规格 
                await Db.Deleteable<GoodsSpec>().Where(d => d.GoodsId == input.Id).ExecuteCommandAsync();
                await Db.Deleteable<GoodsSpecRel>().Where(d => d.GoodsId == input.Id).ExecuteCommandAsync();
                // 保存规格
                await DealwithGoodsSpec(input.Id, input);
                Db.CommitTran();
            }
            catch (Exception e)
            {
                Db.RollbackTran();
                return new ApiResult(e.Message);
            }
            return new ApiResult();
        }

前端添加商品部分代码:

        tinymce.init({
            selector: '#content',
            auto_focus: true,
            height: 500,
            content_style: "img {max-width:100%;}",
            image_advtab: true,//开启图片上传的高级选项功能
            images_upload_url: '/api/goods/UploadImg',//图片上传
            plugins: 'print preview code searchreplace autolink directionality visualblocks visualchars fullscreen image link media codesample table charmap hr pagebreak nonbreaking anchor toc insertdatetime advlist lists textcolor wordcount imagetools contextmenu colorpicker textpattern help ',
            toolbar: 'formatselect styleselect | bold italic forecolor backcolor | link  | alignleft aligncenter alignright alignjustify  | numlist bullist outdent indent  | removeformat'
        });
        layui.use(['form', 'common'], function () {
            var form = layui.form,
                $ = layui.$,
                apiUtil = layui.common;
            // 当前弹出层,防止ID被覆盖
            var parentIndex = parent.layer.getFrameIndex(window.name);

            apiUtil.BindParentCategory();
            form.render();

            // 注册商品多规格组件
            var specMany = new GoodsSpec({
                container: '.goods-spec-many'
            });

            //处理单/多规格的显示问题
            form.on('radio(specType)', function (data) {
                //但规格
                if (data.value == 10) {
                    $("#sigleSpec").show() && $(".goods-spec-many").hide();
                }
                //多规格
                if (data.value == 20) {
                    $("#sigleSpec").hide() && $(".goods-spec-many").show();
                }
                //console.log(data.elem); //得到radio原始DOM对象
            });
          
            //监听提交
            form.on('submit(saveBtn)', function (data) {
                data.field.content = tinyMCE.editors[0].getContent();
                var specType = $('input[name=specType]:checked').val();
                if (specType == 20) {
                    var specMany2 = JSON.stringify(specMany.getData());
                    console.log("specMany:" + specMany2);
                    var isEmpty = specMany.isEmptySkuList();
                    if (isEmpty == true) {
                        layer.msg('商品规格不能为空');
                        return false;
                    }
                    data.field.specMany = specMany2;
                } else {
                    var specSingle =  {
                        goods_no: data.field.goodsNo,
                        line_price: data.field.linePrice,
                        goods_price: data.field.goodsPrice,
                        goods_weight: data.field.goodsWeight,
                        stock_num: data.field.stockNum,
                    };
                    data.field.specSingle=JSON.stringify(specSingle);
                }                
                data.field.specType = specType;
                data.field.goodsStatus = $('input[name=goodsStatus]:checked').val();
                data.field.deductStockType = $('input[name=deductStockType]:checked').val();
                data.field.imgUrl = $(".div_img input").map(function () { return $(this).attr("value"); }).get().join(',');
                if (data.field.imgUrl == "" || data.field.imgUrl == null) {
                   apiUtil.error("商品图片至少需要上传一张!");
                    return false;
                }
                apiUtil.ajax('goods/add', data.field, "application/json", "post", function (res) {
                    apiUtil.success(res.msg);
                    parent.layer.close(parentIndex);
                });
                return false;
            });           
        });

    </script>
}

这里只贴部分代码吧,更多的细节可以直接去看源码。另外关于商城的设计其实写个系列也不过分,下次抽时间具体写篇文章介绍下商品的多规格怎么设计好一点。

源码地址:https://gitee.com/shenniu_code_group/shen-nius.-modularity

相关文章
|
1月前
|
开发框架 JavaScript 前端开发
一个适用于 ASP.NET Core 的轻量级插件框架
一个适用于 ASP.NET Core 的轻量级插件框架
|
3月前
|
存储 开发框架 算法
ASP.NET Core 标识(Identity)框架系列(四):闲聊 JWT 的缺点,和一些解决思路
ASP.NET Core 标识(Identity)框架系列(四):闲聊 JWT 的缺点,和一些解决思路
|
3月前
|
开发框架 JSON .NET
ASP.NET Core 标识(Identity)框架系列(三):在 ASP.NET Core Web API 项目中使用标识(Identity)框架进行身份验证
ASP.NET Core 标识(Identity)框架系列(三):在 ASP.NET Core Web API 项目中使用标识(Identity)框架进行身份验证
|
3月前
|
存储 开发框架 JSON
ASP.NET Core 标识(Identity)框架系列(二):使用标识(Identity)框架生成 JWT Token
ASP.NET Core 标识(Identity)框架系列(二):使用标识(Identity)框架生成 JWT Token
|
3月前
|
开发框架 .NET 数据库连接
ASP.NET Core 标识(Identity)框架系列(一):如何使用 ASP.NET Core 标识(Identity)框架创建用户和角色?
ASP.NET Core 标识(Identity)框架系列(一):如何使用 ASP.NET Core 标识(Identity)框架创建用户和角色?
|
缓存 NoSQL 程序员
极简实用的Asp.NetCore模块化框架新增CMS模块
Asp.NetCore模块化框架新增CMS模块
172 0
极简实用的Asp.NetCore模块化框架新增CMS模块
|
开发框架 JSON 前端开发
极简实用的Asp.NetCore模块化框架决定免费开源了
在开发这个框架之前,前前后后看过好几款模块化的框架,最后在一段时间内对ABP VNext痛下狠心,研究一段时间后,不得不说 ABP VNext的代码层面很规范,也都是一些最佳实践,开发出一个模块效率也很高。但不得不说,于我而言太重了。还看过一些其他模块化的框架,就不说了,学习成本于我而言太高了,主要是自己懒。
228 0
极简实用的Asp.NetCore模块化框架决定免费开源了
|
开发框架 前端开发 .NET
|
开发框架 .NET 数据安全/隐私保护
基于ASP.Net Core开发的一套通用后台框架
基于ASP.Net Core开发的一套通用后台框架写在前面这是本人在学习的过程中搭建学习的框架,如果对你有所帮助那再好不过。如果您有发现错误,请告知我,我会第一时间修改。知其然,知其所以然,并非重复的造轮子。
18485 0
|
Web App开发 前端开发 .NET
从头编写 asp.net core 2.0 web api 基础框架 (1)
原文:从头编写 asp.net core 2.0 web api 基础框架 (1) 工具: 1.Visual Studio 2017 V15.3.5+ 2.Postman (Chrome的App) 3.
1419 0