【云岚到家】-day02-1-区域服务后续开发及完善


1 区域服务后续开发

1.1 添加区域服务

1.1.1 接口定义

1.1.1.1 接口设计

下边设计添加区域服务接口,重点设计:传入参数类型、参数内容、响应结果内容。

根据界面原型梳理操作流程:

首先进入某个区域的服务列表:

在这里插入图片描述

点击添加服务,如下图:
在这里插入图片描述

选择要添加到区域中的服务,点击“添加”按钮。

最终向serve表添加数据。

serve表存储了区域中开通的服务,根据字段信息思考数据来源:

字段名含义数据来源
id服务id主键,自动生成
serve_item_id服务项id接口传入
region_id区域id接口传入
city_code城市编码根据区域id查询region表得到
sale_status售卖状态默认为草稿状态,数据库设置了默认值
price价格默认为服务项的价格,用户可修改
is_hot是否为热门默认为非热门,数据库设置了默认值
hot_time_stamp更新为热门的时间戳默认空
create_time创建时间数据库设置了默认值
update_time更新时间数据库设置了默认值
create_by创建人由framework的MyBatisAutoFillInterceptor自动处理
update_by更新人由framework的MyBatisAutoFillInterceptor自动处理

根据上边的分析,通过接口传入服务项id、区域id、价格,支持多个服务传入,实现批量添加。

传入参数内容为数组,所以使用json格式。

传入参数内容包括:服务项id、区域id、价格。

响应结果内容可为空,前端根据状态码判断是否添加成功。

接口设计信息:

接口路径:POST/foundations/operation/serve/batch

请求数据类型 application/json

在这里插入图片描述

在这里插入图片描述

1.1.1.2 接口定义-json

controller

@PutMapping("/batch")
@ApiOperation("批量添加区域服务")
public void batch(@RequestBody List<ServeUpsertReqDTO> serveUpsertReqDTOList) {
    return;
}

批量添加的请求参数用List来接收,@RequestBody主要用来接收前端传递给后端的json字符串中的数据的(请求体中的数据的);而最常用的使用请求体传参的无疑是POST请求了,所以使用@RequestBody接收数据时,一般都用POST方式进行提交。而GET请求一般是key-value格式,则不用添加@RequestBody

查看接口文档:

重启服务,查看swagger文档如下:

在这里插入图片描述

1.1.2 接口开发

1.1.2.1 mapper

添加接口只向serve表添加数据所以使用mybatisplus提供的单表CRUD方法即可无需自定义mapper接口。

1.1.2.2 service

定义service接口:

void batchAdd(List<ServeUpsertReqDTO> serveUpsertReqDTOList);

定义service实现方法:

@Resource
private ServeItemMapper serveItemMapper;
@Resource
private RegionMapper regionMapper;

/**
 * 批量添加区域服务
 * @param serveUpsertReqDTOList
 */
@Override
@Transactional
public void batchAdd(List<ServeUpsertReqDTO> serveUpsertReqDTOList) {
    for (ServeUpsertReqDTO serveUpsertReqDTO : serveUpsertReqDTOList) {
        //1.校验服务项是否为启用状态,不是启用状态不能新增
        ServeItem serveItem = serveItemMapper.selectById(serveUpsertReqDTO.getServeItemId());
        //如果服务项信息不存在或未启用
        if(ObjectUtil.isNull(serveItem) || serveItem.getActiveStatus()!= FoundationStatusEnum.ENABLE.getStatus()){
            throw new ForbiddenOperationException("该服务未启用无法添加到区域下使用");
        }

        //2.校验是否重复新增
        Integer count = lambdaQuery()
                .eq(Serve::getRegionId, serveUpsertReqDTO.getRegionId())
                .eq(Serve::getServeItemId, serveUpsertReqDTO.getServeItemId())
                .count();
        if(count>0){
            throw new ForbiddenOperationException(serveItem.getName()+"服务已存在");
        }

        //3.新增服务
        Serve serve = BeanUtil.toBean(serveUpsertReqDTO, Serve.class);
        Region region = regionMapper.selectById(serveUpsertReqDTO.getRegionId());
        serve.setCityCode(region.getCityCode());
        baseMapper.insert(serve);
    }

}

说明:

对于增、删、改类的接口通常会先进行入参校验,校验失败抛出异常,由异常处理器统一对异常进行处理。

我们抛出的异常是自定义异常类型,自定义的异常类型都继承了CommonException类型,在异常处理器中对此类型的异常进行处理。

异常处理器的源码在jzo2o-framework中,如下图:

在这里插入图片描述

通过@RestControllerAdvice注解加@ExceptionHandler注解实现,具体的原理是当controller抛出异常由DispatcherServlet统一拦截处理,再根据异常类型找到@ExceptionHandler标识方法去执行该方法进行异常处理。

1.1.2.3 controller

在controller方法中调用service接口添加区域服务。

@PostMapping("/batch")
@ApiOperation("批量添加区域服务")
public void batch(@RequestBody List<ServeUpsertReqDTO> serveUpsertReqDTOList) {
    serveService.batchAdd(serveUpsertReqDTOList);
}

1.1.3 测试

我们通过前后端联调测试添加区域服务接口。

启动foundations服务和gateway服务。

通过cmd进入project-xzb-pc-admin-vue3-java目录启动前端项目

运行命令,启动前端工程

npm run dev 

因为代码是我们写的,我们在前后端联调时除了测试成功结果还要测试失败结果。

下边我们先测试成功结果。

进入运营管理端,点击“区域管理”菜单,点击“设置服务”

在这里插入图片描述

区域服务列表如下图:

在这里插入图片描述

点击添加服务

在这里插入图片描述

点击添加服务,如下图:

在这里插入图片描述

添加成功查询区域服务列表是否存在已添加的服务。

如果列表没有显示已添加的服务则需要进行排查,可以进入数据库直接查询serve表查看是否添加成功,如果后台的错误日志需要根据错误日志进行排查。

下边测试失败结果。

在这里插入图片描述

1.2 修改价格

1.2.1 接口定义

1.2.1.1 接口设计

根据界面原型设计传入参数类型、参数内容、响应结果内容。

进入修改界面
在这里插入图片描述

输入价格进行修改

在这里插入图片描述

传入参数内容:价格、区域服务ID(serve表主键)

根据id更新serve表的价格字段。

传入参数类型:form表单格式

响应结果内容可为空,前端根据状态码判断是否添加成功。

接口设计信息如下:

接口路径:PUT/foundations/operation/serve/{id}

请求数据类型 application/x-www-form-urlencoded
在这里插入图片描述
在这里插入图片描述

1.2.1.2 接口定义-form表单

编写controller方法,HTTP方法使用PUT方式,代码如下:

PUT/foundations/operation/serve/{id}从url中接,用@PathVariable,id是从url中获取,而price是前端传过来了的,所以用 @RequestParam来接收。

@PutMapping("/{id}")
@ApiOperation("区域服务价格修改")
@ApiImplicitParams({
        @ApiImplicitParam(name = "id", value = "服务id", required = true, dataTypeClass = Long.class),
        @ApiImplicitParam(name = "price", value = "价格", required = true, dataTypeClass = BigDecimal.class)
})
public void update( @PathVariable("id") Long id,
                    @RequestParam("price") BigDecimal price) {

}

1.2.2 接口开发

1.2.2.1 mapper

修改接口只向serve表更新数据所以使用mybatisplus提供的单表CRUD方法即可无需自定义mapper接口。

1.2.2.2 service

定义service接口:

Serve update(Long id, BigDecimal price);

返回修改后的Serve类型有助于我们后期做缓存,就不用再查了。

定义service实现方法:

@Override
@Transactional
public Serve update(Long id, BigDecimal price) {
    //1.更新服务价格
    boolean update = lambdaUpdate()
            .eq(Serve::getId, id)
            .set(Serve::getPrice, price)
            .update();
    if(!update){
        throw new CommonException("修改服务价格失败");
    }
    return baseMapper.selectById(id);
}
1.2.2.3 controller

在controller方法中调用service接口价格修改。

@PutMapping("/{id}")
@ApiOperation("区域服务价格修改")
@ApiImplicitParams({
    @ApiImplicitParam(name = "id", value = "服务id", required = true, dataTypeClass = Long.class),
    @ApiImplicitParam(name = "price", value = "价格", required = true, dataTypeClass = BigDecimal.class)
})
public void update(@PathVariable("id") Long id,
          @RequestParam("price") BigDecimal price) {
  serveService.update(id, price);
}

1.2.3 测试

在这里插入图片描述

查看控制台

在这里插入图片描述

测试成功

1.3 服务上架

1.3.1 接口定义

1.3.1.1 接口设计

根据业务流程、界面原型进行设计。

在区域服务列表中点击“上架”,此服务在该区域将生效,用户即可对该服务进行下单。

在这里插入图片描述

业务流程如下:

在这里插入图片描述

在serve表有一个售卖状态sale_status,服务上架后将状态更改为“上架”,代码为2。

下边分析接口的传入参数类型、参数内容、响应结果内容。

传入参数内容:服务Id(serve表的主键),

传入参数类型:form表单格式

响应结果内容: 内容可为空,前端根据状态码判断是否添加成功。

注意:区分 服务id和服务项id,服务id即serve表的主键,服务项id即serve_item表的主键。

接口信息如下:

接口路径:PUT/foundations/operation/serve/onSale/{id}

请求数据类型 application/x-www-form-urlencoded

在这里插入图片描述

在这里插入图片描述

1.3.1.2 接口定义-form表单格式

编写controller方法,HTTP方法使用PUT方式,代码如下:

@PutMapping("/onSale/{id}")
@ApiOperation("区域服务上架")
@ApiImplicitParam(name = "id", value = "服务id", required = true, dataTypeClass = Long.class)
public void onSale(@PathVariable("id") Long id) {
    return;
}

1.3.2 接口开发

1.3.2.1 mapper

服务上架最终修改serve表的状态,所以使用mybatisplus提供的单表CRUD方法即可无需自定义mapper接口。

1.3.2.2 service

定义service接口:

Serve onSale(Long id);

实现:

@Override
@Transactional
public Serve onSale(Long id) {
    //1.校验服务是否存在
    Serve serve = baseMapper.selectById(id);
    if(ObjectUtil.isNull(serve)){
        throw new ForbiddenOperationException("区域服务不存在");
    }
    //2.校验服务状态是否为草稿或下架状态
    if(serve.getSaleStatus()!= FoundationStatusEnum.INIT.getStatus() || serve.getSaleStatus()!= FoundationStatusEnum.DISABLE.getStatus()){
        throw new ForbiddenOperationException("服务状态不为草稿或下架状态,无法上架");
    }
    //3.校验服务项是否为启用状态
    ServeItem serveItem = serveItemMapper.selectById(serve.getServeItemId());
    if(serveItem.getActiveStatus()!= FoundationStatusEnum.ENABLE.getStatus()){
        throw new ForbiddenOperationException("本服务所属的服务项未启用,无法上架");
    }
    //4.更新服务状态为上架
    boolean update = lambdaUpdate()
            .eq(Serve::getId, id)
            .set(Serve::getSaleStatus, FoundationStatusEnum.ENABLE.getStatus())
            .update();
    if(!update){
        throw new CommonException("服务上架失败");
    }
    return baseMapper.selectById(id);
}
1.3.2.3 controller
@PutMapping("/onSale/{id}")
@ApiOperation("区域服务上架")
@ApiImplicitParam(name = "id", value = "服务id", required = true, dataTypeClass = Long.class)
public void onSale(@PathVariable("id") Long id) {
    serveService.onSale(id);
}

1.3.3 测试

在这里插入图片描述

上架成功

1.4 删除区域服务开发

1.4.1 接口定义

1.4.1.1 接口设计

根据业务流程、界面原型进行设计。

在区域服务列表中点击“删除”,此服务在该区域将删除。

业务流程如下:
在这里插入图片描述

在serve表中删除该服务。

下边分析接口的传入参数类型、参数内容、响应结果内容。

传入参数内容:服务Id(serve表的主键),

传入参数类型:form表单格式

响应结果内容: 内容可为空,前端根据状态码判断是否添加成功。

注意:区分 服务id和服务项id,服务id即serve表的主键,服务项id即serve_item表的主键。

接口信息如下:

接口路径:DELETE/foundations/operation/serve/{id}

请求数据类型 application/x-www-form-urlencoded

在这里插入图片描述

1.4.1.2 接口定义-form表单
@DeleteMapping("/{id}")
@ApiOperation("区域服务删除")
@ApiImplicitParam(name = "id", value = "服务id", required = true, dataTypeClass = Long.class)
public void delete(@PathVariable("id") Long id) {
    return;
}

1.4.2 接口开发

1.4.2.1 mapper

服务上架最终修改serve表的状态,所以使用mybatisplus提供的单表CRUD方法即可无需自定义mapper接口。

1.4.2.2 service

定义service接口:

void delete(Long id);

实现:

@Override
@Transactional
public void delete(Long id) {
    //1.校验服务是否存在
    Serve serve = baseMapper.selectById(id);
    if(ObjectUtil.isNull(serve)){
        throw new ForbiddenOperationException("区域服务不存在");
    }
    //2.校验服务状态是否为草稿状态
    if(serve.getSaleStatus()!= FoundationStatusEnum.INIT.getStatus()){
        throw new ForbiddenOperationException("服务状态不为草稿状态,无法删除");
    }
    //3.删除服务
    baseMapper.deleteById(id);
}
1.4.2.3 controller
@DeleteMapping("/{id}")
@ApiOperation("区域服务删除")
@ApiImplicitParam(name = "id", value = "服务id", required = true, dataTypeClass = Long.class)
public void delete(@PathVariable("id") Long id) {
    serveService.delete(id);
}

1.4.3 测试

在这里插入图片描述

1.5 区域服务下架开发

业务流程:

接口文档:

在这里插入图片描述

1.5.1 mapper

服务上架最终修改serve表的状态,所以使用mybatisplus提供的单表CRUD方法即可无需自定义mapper接口。

1.5.2 service

接口:

void offSale(Long id);

实现:

@Override
@Transactional
public void offSale(Long id) {
    //1.校验服务是否存在
    Serve serve = baseMapper.selectById(id);
    if(ObjectUtil.isNull(serve)){
        throw new ForbiddenOperationException("区域服务不存在");
    }
    //2.校验服务状态是否为上架状态
    if(serve.getSaleStatus()!= FoundationStatusEnum.ENABLE.getStatus()){
        throw new ForbiddenOperationException("服务状态不为上架状态,无法下架");
    }
    //3.更新服务状态为下架
    boolean update = lambdaUpdate()
            .eq(Serve::getId, id)
            .set(Serve::getSaleStatus, FoundationStatusEnum.DISABLE.getStatus())
            .update();
    if(!update){
        throw new CommonException("服务下架失败");
    }
}

1.5.3 controller

@PutMapping("/offSale/{id}")
@ApiOperation("区域服务下架")
@ApiImplicitParam(name = "id", value = "服务id", required = true, dataTypeClass = Long.class)
public void offSale(@PathVariable("id") Long id) {
    serveService.offSale(id);
}

1.5.4 测试

在这里插入图片描述

1.6 设置热门开发

要求:实现更新serve表的是否热门字段。

接口文档:

在这里插入图片描述

1.6.1 mapper

服务上架最终修改serve表的状态,所以使用mybatisplus提供的单表CRUD方法即可无需自定义mapper接口。

1.6.2 service

接口:

Serve onHot(Long id);

实现:

@Override
@Transactional
public Serve onHot(Long id) {
    //1.校验服务是否存在
    Serve serve = baseMapper.selectById(id);
    if(ObjectUtil.isNull(serve)){
        throw new ForbiddenOperationException("区域服务不存在");
    }
    //2.校验服务状态是否为上架状态
    if(serve.getSaleStatus()!= FoundationStatusEnum.ENABLE.getStatus()){
        throw new ForbiddenOperationException("服务状态不为上架状态,无法设置热门");
    }
    //3.更新服务状态为热门
    boolean update = lambdaUpdate()
            .eq(Serve::getId, id)
            .set(Serve::getIsHot, FoundationStatusEnum.ONHOT.getStatus())
            .update();
    if(!update){
        throw new CommonException("服务设置热门失败");
    }
    return baseMapper.selectById(id);
}

1.6.3 controller

@PutMapping("/onHot/{id}")
@ApiOperation("区域服务设置热门")
@ApiImplicitParam(name = "id", value = "服务id", required = true, dataTypeClass = Long.class)
public void onHot(@PathVariable("id") Long id) {
    serveService.onHot(id);
}

1.6.4 测试

在这里插入图片描述

在这里插入图片描述

1.7 取消热门开发

要求:实现更新serve表的是否热门字段。

接口文档:

在这里插入图片描述

1.7.1 mapper

服务上架最终修改serve表的状态,所以使用mybatisplus提供的单表CRUD方法即可无需自定义mapper接口。

1.7.2 service

接口:

Serve offHot(Long id);

实现:

@Override
@Transactional
public Serve offHot(Long id) {
    //1.校验服务是否存在
    Serve serve = baseMapper.selectById(id);
    if(ObjectUtil.isNull(serve)){
        throw new ForbiddenOperationException("区域服务不存在");
    }
    //2.校验服务状态是否为上架状态
    if(serve.getSaleStatus()!= FoundationStatusEnum.ENABLE.getStatus()){
        throw new ForbiddenOperationException("服务状态不为上架状态,无法取消热门");
    }
    //3.更新服务状态为非热门
    boolean update = lambdaUpdate()
            .eq(Serve::getId, id)
            .set(Serve::getIsHot, FoundationStatusEnum.OFFHOT.getStatus())
            .update();
    if(!update){
        throw new CommonException("服务取消热门失败");
    }
    return baseMapper.selectById(id);
}

1.7.3 controller

@PutMapping("/offHot/{id}")
@ApiOperation("区域服务取消热门")
@ApiImplicitParam(name = "id", value = "服务id", required = true, dataTypeClass = Long.class)
public void offHot(@PathVariable("id") Long id) {
    serveService.offHot(id);
}

1.7.4 测试

同1.6.4

1.8 启用区域功能完善

业务流程:

在这里插入图片描述

增加校验:区域下存在上架的服务方可启用。

1.8.1 创建按区域id和状态查询的mapper

在com.jzo2o.foundations.mapper.ServeMapper中创建

List<ServeResDTO> queryServeListByRegionIdAndStatus(@Param("regionId") Long regionId, @Param("status") Integer status);

xml

<select id="queryServeListByRegionIdAndStatus"
        resultType="com.jzo2o.foundations.model.dto.response.ServeResDTO">
    SELECT
    st.id serve_type_id,
        si.NAME serve_item_name,
        s.update_time update_time,
        s.sale_status sale_status,
        si.id serve_item_id,
        si.reference_price reference_price,
        s.create_time create_time,
        s.region_id region_id,
        s.price price,
        s.id id,
        s.is_hot is_hot,
        st.NAME serve_type_name
    FROM
        serve s
            INNER JOIN serve_item si ON s.serve_item_id = si.id
            INNER JOIN serve_type st ON si.serve_type_id = st.id
    WHERE
        region_id = #{regionId} AND sale_status = #{status}
</select>

1.8.2 增加校验逻辑

在com.jzo2o.foundations.service.impl.RegionServiceImpl#active方法中

//如果需要启用区域,需要校验该区域下是否有上架的服务
List<ServeResDTO> serveResDTOS = serveMapper.queryServeListByRegionIdAndStatus(region.getId(), FoundationStatusEnum.ENABLE.getStatus());
if (serveResDTOS.size() == 0) {
    throw new ForbiddenOperationException("区域内无可用的上架服务,无法启用");
}

1.9 禁用区域功能完善

业务流程:
在这里插入图片描述

增加校验:区域下不存在上架的服务方可禁用。

1.9.1 增加校验逻辑

在com.jzo2o.foundations.service.impl.RegionServiceImpl#deactivate方法中

List<ServeResDTO> serveResDTOS = serveMapper.queryServeListByRegionIdAndStatus(region.getId(), FoundationStatusEnum.ENABLE.getStatus());
if (serveResDTOS.size() > 0) {
    throw new ForbiddenOperationException("区域内有上架服务,无法禁用");
}

1.10 禁用服务项功能完善

业务流程

在这里插入图片描述

1.10.1 创建按服务项id和状态查询的mapper

在com.jzo2o.foundations.mapper.ServeMapper中创建

List<ServeResDTO> queryServeListByServeItemIdAndStatus(@Param("serveItemId") Long serveItemId, @Param("status") Integer status);

xml

<select id="queryServeListByServeItemIdAndStatus"
        resultType="com.jzo2o.foundations.model.dto.response.ServeResDTO">
    SELECT
        st.id serve_type_id,
        si.NAME serve_item_name,
        s.update_time update_time,
        s.sale_status sale_status,
        si.id serve_item_id,
        si.reference_price reference_price,
        s.create_time create_time,
        s.region_id region_id,
        s.price price,
        s.id id,
        s.is_hot is_hot,
        st.NAME serve_type_name
    FROM
        serve s
            INNER JOIN serve_item si ON s.serve_item_id = si.id
            INNER JOIN serve_type st ON si.serve_type_id = st.id
    WHERE
        serve_item_id = #{serveItemId} AND sale_status = #{status}
</select>

1.10.2 增加校验逻辑

在com.jzo2o.foundations.service.impl.ServeItemServiceImpl#deactivate中

//有区域在使用该服务将无法禁用(存在关联的区域服务且状态为上架表示有区域在使用该服务项)
List<ServeResDTO> serveResDTOS = serveMapper.queryServeListByServeItemIdAndStatus(id, FoundationStatusEnum.ENABLE.getStatus());
if (serveResDTOS.size() > 0) {
    throw new ForbiddenOperationException("存在关联的区域服务且状态为上架表示有区域在使用该服务项");
}
  • 24
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

AAA码农宝哥.

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值