diff --git a/README.md b/README.md index 99afaa57..e0da82c4 100644 --- a/README.md +++ b/README.md @@ -1,14 +1,14 @@ # README -#### ![image-20210705143529597](doc/img/readme/image-20210705143529597.png) +![image-20210705143529597](doc/img/readme/image-20210705143529597.png) -### 前言 +## 前言 本商城是基于Spring Cloud、Nacos、Seata、Mysql、Redis、RocketMQ、canal、ElasticSearch、minio的微服务B2B2C电商商城系统,采用主流的互联网技术架构、全新的UI设计、支持集群部署、服务注册和发现以及拥有完整的订单流程等,代码完全开源,没有任何二次封装,是一个非常适合二次开发的电商平台系统。 本商城致力于为中大型企业打造一个功能完整、易于维护的微服务B2B2C电商商城系统,采用主流微服务技术实现。后台管理系统包含平台管理,店铺管理、商品管理、订单管理、规格管理、权限管理、资源管理等模块。 -### 文档 +## 文档 这代码有没有文档呀? 当然有啦,你已经下载了,在doc这个文件夹上,实在不知道,我就给链接出来咯: @@ -21,7 +21,7 @@ gitee:https://gitee.com/gz-yami/mall4cloud/tree/master/doc 具体目录结构和代码规范,可以查看 https://gitee.com/gz-yami/mall4cloud/tree/master/doc/%E4%BB%A3%E7%A0%81%E7%9B%AE%E5%BD%95%E7%BB%93%E6%9E%84 -### 授权 +## 授权 除开源版本外,本商城还提供商业版本的商城,欲知详情,请访问官网。 @@ -29,7 +29,7 @@ gitee:https://gitee.com/gz-yami/mall4cloud/tree/master/doc 商城使用 AGPLv3 开源,请遵守 AGPLv3 的相关条款,或者联系作者获取商业授权(https://www.mall4j.com) -### 项目链接 +## 项目链接 JAVA后台:https://gitee.com/gz-yami/mall4cloud @@ -39,7 +39,7 @@ JAVA后台:https://gitee.com/gz-yami/mall4cloud uni-app:https://gitee.com/gz-yami/mall4cloud-uniapp -### 演示地址 +## 演示地址 商业版演示地址: @@ -49,9 +49,68 @@ H5端:https://h5.mall4j.com/cloud 小程序:微信搜索 “mall4j微服务版” - - -### 技术选型 +## 目录结构规范 + +我们也有自己的目录结构 + +![img](https://gitee.com/gz-yami/mall4cloud/raw/master/doc/img/%E7%9B%AE%E5%BD%95%E7%BB%93%E6%9E%84%E5%92%8C%E8%A7%84%E8%8C%83/%E5%BA%94%E7%94%A8%E5%88%86%E5%B1%82.png) + +- VO(View Object):显示层对象,通常是 Web 向模板渲染引擎层传输的对象。 +- DTO(Data Transfer Object):数据传输对象,前端像后台进行传输的对象,类似于param。 +- BO(Business Object):业务对象,内部业务对象,只在内部传递,不对外进行传递。 +- Model:模型层,此对象与数据库表结构一一对应,通过 Mapper 层向上传输数据源对象。 +- Controller:主要是对外部访问控制进行转发,各类基本参数校验,或者不复用的业务简单处理等。为了简单起见,一些与事务无关的代码也在这里编写。 +- FeignClient:由于微服务之间存在互相调用,这里是内部请求的接口。 +- Controller:主要是对内部访问控制进行转发,各类基本参数校验,或者不复用的业务简单处理等。为了简单起见,一些与事务无关的代码也在这里编写。 +- Service 层:相对具体的业务逻辑服务层。 +- Manager 层:通用业务处理层,它有如下特征: + - 1) 对第三方平台封装的层,预处理返回结果及转化异常信息,适配上层接口。 + - 2) 对 Service 层通用能力的下沉,如缓存方案、中间件通用处理。 + - 3) 与 DAO 层交互,对多个 DAO 的组合复用。 +- Mapper持久层:数据访问层,与底层 MySQL进行数据交互。 +- Task层:由于每个服务之间会存在定时任务,比如定时确认收货,定时将活动失效等情况,这里面的Task实际上连接的是`xxl-job`(具体可以查看 https://github.com/xuxueli/xxl-job )进行任务调度。 +- Listener:监听 `RocketMQ` 进行处理,有时候会监听`easyexcel`相关数据。 + +关于`FeignClient`,由于微服务之间存在互相调用,`Feign` 是http协议,理论上是为了解耦,而实际上提供方接口进行修改,调用方却没有进行修改的时候,会造成异常,所以我们抽取出来。还有就是对内暴露的接口,是很多地方都公用的,所以我们还将接口抽取了出了一个模块,方便引用。可以看到`mall4cloud-api`这个模块下是所有对内`feign`接口的信息。 + +## 目录结构 + +``` +mall4cloud +├─mall4cloud-api -- 内网接口 +│ ├─mall4cloud-api-auth -- 授权对内接口 +│ ├─mall4cloud-api-biz -- biz对内接口 +│ ├─mall4cloud-api-leaf -- 美团分布式id生成接口 +│ ├─mall4cloud-api-multishop -- 店铺对内接口 +│ ├─mall4cloud-api-order -- 订单对内接口 +│ ├─mall4cloud-api-platform -- 平台对内接口 +│ ├─mall4cloud-api-product -- 商品对内接口 +│ ├─mall4cloud-api-rbac -- 用户角色权限对内接口 +│ ├─mall4cloud-api-search -- 搜索对内接口 +│ └─mall4cloud-api-user -- 用户对内接口 +├─mall4cloud-auth -- 授权校验模块 +├─mall4cloud-biz -- mall4cloud 业务代码。如图片上传/短信等 +├─mall4cloud-common -- 一些公共的方法 +│ ├─mall4cloud-common-cache -- 缓存相关公共代码 +│ ├─mall4cloud-common-core -- 公共模块核心(公共中的公共代码) +│ ├─mall4cloud-common-database -- 数据库连接相关公共代码 +│ ├─mall4cloud-common-order -- 订单相关公共代码 +│ ├─mall4cloud-common-product -- 商品相关公共代码 +│ ├─mall4cloud-common-rocketmq -- rocketmq相关公共代码 +│ └─mall4cloud-common-security -- 安全相关公共代码 +├─mall4cloud-gateway -- 网关 +├─mall4cloud-leaf -- 基于美团leaf的生成id服务 +├─mall4cloud-multishop -- 商家端 +├─mall4cloud-order -- 订单服务 +├─mall4cloud-payment -- 支付服务 +├─mall4cloud-platform -- 平台端 +├─mall4cloud-product -- 商品服务 +├─mall4cloud-rbac -- 用户角色权限模块 +├─mall4cloud-search -- 搜索模块 +└─mall4cloud-user -- 用户服务 +``` + +## 技术选型 | 技术 | 版本 | 说明 | | :-----------: | :-----: | :-----------: | @@ -73,11 +132,11 @@ H5端:https://h5.mall4j.com/cloud | Element UI | 2.13 | UI框架 | | vue、uni-app | vue2.6 | JS框架 | -### 系统架构图 +## 系统架构图 ![架构图](doc/img/readme/架构图.png) -### 商城部署后 API 地址 +## 商城部署后 API 地址 | 服务 | 地址 | | ---------------------------------------------------- | --------------------- | @@ -95,13 +154,13 @@ H5端:https://h5.mall4j.com/cloud -### 部署教程 +## 部署教程 部署教程请参考该文件夹下的`/基本开发文档/mall4cloud开发环境搭建.md`以及`/开发环境搭建`目录下的中间件安装。 -### 代码运行相关截图 +## 代码运行相关截图 -#### 1.后台截图 +### 1.后台截图 - 平台端 @@ -113,15 +172,14 @@ H5端:https://h5.mall4j.com/cloud ![image-20210705151847270](doc/img/readme/image-20210705151847270.png) -#### 2.小程序截图 +### 2.小程序截图 ![小程序-1625472143277](doc/img/readme/小程序.png) -#### 3.uni-app截图 +### 3.uni-app截图 ![uniapp-1625469707350](doc/img/readme/uniapp.png) -### ## 提交反馈 - Mall4j官网 https://www.mall4j.com diff --git a/mall4cloud-product/src/main/java/com/mall4j/cloud/product/mapper/CategoryMapper.java b/mall4cloud-product/src/main/java/com/mall4j/cloud/product/mapper/CategoryMapper.java index 3b12de8c..cfe5f18b 100644 --- a/mall4cloud-product/src/main/java/com/mall4j/cloud/product/mapper/CategoryMapper.java +++ b/mall4cloud-product/src/main/java/com/mall4j/cloud/product/mapper/CategoryMapper.java @@ -89,13 +89,12 @@ public interface CategoryMapper { int updateBatchOfStatus(@Param("categoryIds") List categoryIds, @Param("status") Integer status); /** - * 根据分类名获取分类的数量 + * 查询分类名是否存在 * - * @param categoryId - * @param name + * @param category * @return */ - int getCountByName(@Param("categoryId") Long categoryId, @Param("name") String name); + int existCategoryName(@Param("category") Category category); /** * 根据分类id列表,获取分类列表 diff --git a/mall4cloud-product/src/main/java/com/mall4j/cloud/product/service/impl/CategoryServiceImpl.java b/mall4cloud-product/src/main/java/com/mall4j/cloud/product/service/impl/CategoryServiceImpl.java index 00625026..53e39d51 100644 --- a/mall4cloud-product/src/main/java/com/mall4j/cloud/product/service/impl/CategoryServiceImpl.java +++ b/mall4cloud-product/src/main/java/com/mall4j/cloud/product/service/impl/CategoryServiceImpl.java @@ -54,7 +54,7 @@ public CategoryVO getById(Long categoryId) { @Override public void save(Category category) { - checkName(null, category.getName()); + existCategoryName(category); category.setShopId(AuthUserContext.get().getTenantId()); String path = ""; if (!Objects.equals(CategoryLevel.First.value(), category.getLevel())) { @@ -76,7 +76,7 @@ public void update(Category category) { if (Objects.equals(dbCategory.getCategoryId(), category.getParentId())) { throw new Mall4cloudException("分类不能成为本身的上级分类"); } - checkName(category.getCategoryId(), category.getName()); + existCategoryName(category); int updateCount = categoryMapper.update(category); } @@ -251,11 +251,11 @@ private void setChildCategory(List categories, List chil /** * 校验分类名是否已存在 * - * @param categoryId - * @param name + * @param category */ - private void checkName(Long categoryId, String name) { - int countByName = categoryMapper.getCountByName(categoryId, name); + private void existCategoryName(Category category) { + category.setShopId(AuthUserContext.get().getTenantId()); + int countByName = categoryMapper.existCategoryName(category); if (countByName > 0) { throw new Mall4cloudException("分类名已存在,请重新输入"); } diff --git a/mall4cloud-product/src/main/resources/mapper/CategoryMapper.xml b/mall4cloud-product/src/main/resources/mapper/CategoryMapper.xml index c4ae48ef..49e92ddb 100644 --- a/mall4cloud-product/src/main/resources/mapper/CategoryMapper.xml +++ b/mall4cloud-product/src/main/resources/mapper/CategoryMapper.xml @@ -92,10 +92,13 @@ - + SELECT COUNT(*) FROM category WHERE `name` = #{category.name} AND parent_id = #{category.parentId} + + AND category_id != #{category.categoryId} + + + AND shop_id = #{category.shopId}