Spring Cloud Alibaba 商城项目(2)

1.后端分类列表树展示

  1. 在分类实体类CategoryEntity添加childrenList
    @TableField(exist = false)
    private List<CategoryEntity> childrenList;
  1. 业务代码
//对查询结果封装
 @Override
    public List<CategoryEntity> queryListByTree() {
        //查出全部信息
        List<CategoryEntity> categoryEntities = this.baseMapper.selectList(null);
        //排序
        List<CategoryEntity> collect = categoryEntities.stream().filter(data -> data.getParentCid() == 0).map(
                data -> {
                    data.setChildrenList(convertList(data, categoryEntities));
                    return data;
                }
        ).sorted((data1, data2) -> {
            return data1.getSort() - data2.getSort();
        }).collect(Collectors.toList());
        return collect;
    }

    // 递归组合子元素
    public List<CategoryEntity> convertList(CategoryEntity currentList, List<CategoryEntity> allList) {
        List<CategoryEntity> collect = allList.stream().filter(data -> {
            return data.getParentCid() == currentList.getCatId();
        }).map(data -> {
            data.setChildrenList(convertList(data, allList));
            return data;
        }).sorted((data1, data2) -> {
            return data1.getSort() - data2.getSort();
        }).collect(Collectors.toList());
        return collect;
    }

2.前端分类列表树展示

  1. 启动人人fast项目 创建一级分类
    在这里插入图片描述
  2. 创建二级分类
    在这里插入图片描述
  3. 创建商品管理分类管理目录结构
    在这里插入图片描述
  4. 修改人人代码前端请求路径改成http://localhost:88/renren-fast,默认都请求到网关,并将人人后台配置到注册中心

为了节约时间我就剔除掉了配置中心的配置 不从配置中心读取renren fast的依赖了

  1. 修改网关配置
spring:
  application:
    name: shop-gateway
  cloud:
    nacos:
      config:
        server-addr: 127.0.0.1:8848
        file-extension: yml
        namespace: f176f0a9-ee0b-4de6-bf0c-545be48a780d
        group: dev
    gateway:
      routes:
        - id: renre_id
          #均匀的负载到shop-renren的服务器上面
          uri: lb://shop-renren
          #包含配置请求规则
          predicates:
            - Path=/renren-fast/**
  1. 网关配置允许跨域
package com.fyx.shop.shopgateway.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.reactive.CorsWebFilter;
import org.springframework.web.cors.reactive.UrlBasedCorsConfigurationSource;

@Configuration
public class MyCorsConfiguration {

    @Bean
    public CorsWebFilter corsWebFilter(){
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();

        CorsConfiguration corsConfiguration = new CorsConfiguration();
        //1.配置跨域
        //允许哪种请求头跨域
        corsConfiguration.addAllowedHeader("*");
        //允许哪种方法类型跨域 get post delete put
        corsConfiguration.addAllowedMethod("*");
        // 允许哪些请求源跨域
        corsConfiguration.addAllowedOrigin("*");
        // 是否携带cookie跨域
        corsConfiguration.setAllowCredentials(true);

        //允许跨域的路径
        source.registerCorsConfiguration("/**",corsConfiguration);
        return new CorsWebFilter(source);
    }
}

  1. 注释掉人人开源代码跨域请求代码 io.renren.config.CorsConfig.CorsConfig
  2. 配置goods服务的路由规则

注:如果id_goods的顺序没 id_renren 顺序高,那么id_goods的拦截会优先进入id_renren服务中,就会被id_renren得到拦截器抢先一步拦截从而走不到id_goods 的代码中

spring:
  application:
    name: shop-gateway
  cloud:
    nacos:
      config:
        server-addr: 127.0.0.1:8848
        file-extension: yml
        namespace: f176f0a9-ee0b-4de6-bf0c-545be48a780d
        group: dev
    gateway:
      routes:
        - id: id_goods
          uri: lb://shop-goods
          predicates:
            - Path=/renren-fast/goods/**
          filters:
            #意思是将http://localhost:88/renren-fast/goods/test/list 转为 http://shop-goods/test/list
            - RewritePath=/renren-fast/goods/(?<segment>.*),/$\{segment}

        - id: id_renren
          uri: lb://shop-renren
          predicates:
            - Path=/renren-fast/**
  1. 前端分类代码
<template>
  <el-tree :data="menus"
           :props="defaultProps"></el-tree>

</template>

<script>
export default {
  components: {},
  props: {},
  data () {
    return {
      menus: [],
      defaultProps: {
        children: 'childrenList',
        label: 'name'
      }
    }
  },
  watch: {},
  computed: {},
  methods: {
    getTreeList () {
      this.$http({
        url: this.$http.adornUrl('/goods/shopgoods/category/list/tree'),
        method: 'get'
      }).then(({ data }) => {
        console.log(data)
        this.menus = data.page
      })
    }
  },
  created () { this.getTreeList() },
  mounted () { }
}
</script>
<style lang="scss" scoped>
.wrapper {
}
</style>
  1. 访问成功

在这里插入图片描述

3.前端分类列表树展示

完成复选框,增加添加删除按钮,有子节点的不显示删除,第三季的不显示添加按钮

<template>
  <el-tree :data="menus"
           :props="defaultProps"
           :expand-on-click-node="false"
           show-checkbox
           node-key="catId">

    <span class="custom-tree-node"
          slot-scope="{ node, data }">
      <span>{{ node.label }}</span>
      <span>
        <el-button v-if="node.level <=2"
                   type="text"
                   size="mini"
                   @click="() => append(data)">
          添加
        </el-button>
        <el-button v-if="node.childNodes.length==0"
                   type="text"
                   size="mini"
                   @click="() => remove(node, data)">
          删除
        </el-button>
      </span>
    </span>
  </el-tree>

</template>

<script>
export default {
  components: {},
  props: {},
  data () {
    return {
      menus: [],
      defaultProps: {
        children: 'childrenList',
        label: 'name'
      }
    }
  },
  watch: {},
  computed: {},
  methods: {
    append (data) {
      console.log(data)
    },

    remove (node, data) {
      console.log(data)
    },
    getTreeList () {
      this.$http({
        url: this.$http.adornUrl('/goods/shopgoods/category/list/tree'),
        method: 'get'
      }).then(({ data }) => {
        console.log(data)
        this.menus = data.page
      })
    }
  },
  created () { this.getTreeList() },
  mounted () { }
}
</script>
<style lang="scss" scoped>
.wrapper {
}
</style>

4.后端分类列表树删除

  1. 配置Mybatis-plus 整合项目的逻辑删除代码(逻辑删除是为了解决物理删除有的数据有关联而返回的Null数据)
mybatis-plus:
  global-config:
    db-config:
      #1 代表删除 0 代表未删除
      logic-delete-value: 1
      logic-not-delete-value: 0
  1. 给需要逻辑删除的实体类字段加入
    //如果数据库字段的删除标识不对应则可以通过  @TableLogic(value = "0",delval = "1") 指定逻辑删除对应的值
    @TableLogic
    private Integer showStatus;
  1. 调用Mybatis-plus 封装的删除代码
    @Override
    public void removeListByIds(List<Long> asList) {
        return baseMapper.deleteBatchIds(asList);
    }

5.前端分类列表树删除

<template>
  <el-tree :data="menus"
           :props="defaultProps"
           :expand-on-click-node="false"
           show-checkbox
           node-key="catId"
           :default-expanded-keys="expandedkey">

    <span class="custom-tree-node"
          slot-scope="{ node, data }">
      <span>{{ node.label }}</span>
      <span>
        <el-button v-if="node.level <=2"
                   type="text"
                   size="mini"
                   @click="() => append(data)">
          添加
        </el-button>
        <el-button v-if="node.childNodes.length==0"
                   type="text"
                   size="mini"
                   @click="() => remove(node, data)">
          删除
        </el-button>
      </span>
    </span>
  </el-tree>

</template>

<script>
export default {
  components: {},
  props: {},
  data () {
    return {
      expandedkey: [],
      menus: [],
      defaultProps: {
        children: 'childrenList',
        label: 'name'
      }
    }
  },
  watch: {},
  computed: {},
  methods: {
    open () {

    },
    append (data) {
      console.log(data)
    },
    // 删除节点
    remove (node, data) {
      this.$confirm(`是否要删除${data.name}, 是否继续 ? `, '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(() => {
        var ids = [data.catId]
        this.$http({
          url: this.$http.adornUrl('/goods/shopgoods/category/delete'),
          method: 'post',
          data: this.$http.adornData(ids, false)
        }).then(({ data }) => {
          this.$message({
            type: 'success',
            message: '删除成功'
          })
          this.getTreeList()
          // 设置默认展开的节点
          this.expandedkey = [node.parent.data.catId]
        })
      }).catch(() => {
        this.$message({
          type: 'info',
          message: '已取消删除'
        })
      })
    },
    getTreeList () {
      this.$http({
        url: this.$http.adornUrl('/goods/shopgoods/category/list/tree'),
        method: 'get'
      }).then(({ data }) => {
        console.log(data)
        this.menus = data.page
      })
    }
  },
  created () { this.getTreeList() },
  mounted () { }
}
</script>
<style lang="scss" scoped>
.wrapper {
}
</style>

6.前端分类列表树添加

<template>
  <div>
    <el-tree :data="menus"
             :props="defaultProps"
             :expand-on-click-node="false"
             show-checkbox
             node-key="catId"
             :default-expanded-keys="expandedkey">

      <span class="custom-tree-node"
            slot-scope="{ node, data }">
        <span>{{ node.label }}</span>
        <span>
          <el-button v-if="node.level <=2"
                     type="text"
                     size="mini"
                     @click="() => append(data)">
            添加
          </el-button>
          <el-button v-if="node.childNodes.length==0"
                     type="text"
                     size="mini"
                     @click="() => remove(node, data)">
            删除
          </el-button>
        </span>
      </span>
    </el-tree>

    <el-dialog title="提示"
               :visible.sync="flag"
               width="30%">
      <el-form :model="category">
        <el-form-item label="分类名称">
          <el-input v-model="category.name"></el-input>
        </el-form-item>
      </el-form>
      <span slot="footer"
            class="dialog-footer">
        <el-button @click="flag=false">取 消</el-button>
        <el-button type="primary"
                   @click="addcategory">确 定</el-button>
      </span>
    </el-dialog>
  </div>

</template>

<script>
export default {
  components: {},
  props: {},
  data () {
    return {
      category: {
        name: '',
        parentCid: 0,
        catLevel: 0,
        showStatus: 1,
        sort: 0

      },
      flag: false,
      expandedkey: [],
      menus: [],
      defaultProps: {
        children: 'childrenList',
        label: 'name'
      }
    }
  },
  watch: {},
  computed: {},
  methods: {
    append (data) {
      console.log(data)
      this.flag = true
      this.category.parentCid = data.catId
      this.category.catLevel = data.catLevel * 1 + 1
    },
    addcategory () {
      this.$http({
        url: this.$http.adornUrl('/goods/shopgoods/category/save'),
        method: 'post',
        data: this.$http.adornData(this.category, false)
      }).then(({ data }) => {
        this.$message({
          type: 'success',
          message: '保存成功'
        })
        this.flag = false
        this.getTreeList()
        // 设置默认展开的节点
        this.expandedkey = [this.category.parentCid]
      })
    },
    // 删除节点
    remove (node, data) {
      this.$confirm(`是否要删除${data.name}, 是否继续 ? `, '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(() => {
        var ids = [data.catId]
        this.$http({
          url: this.$http.adornUrl('/goods/shopgoods/category/delete'),
          method: 'post',
          data: this.$http.adornData(ids, false)
        }).then(({ data }) => {
          this.$message({
            type: 'success',
            message: '删除成功'
          })
          this.getTreeList()
          // 设置默认展开的节点
          this.expandedkey = [node.parent.data.catId]
        })
      })
    },
    getTreeList () {
      this.$http({
        url: this.$http.adornUrl('/goods/shopgoods/category/list/tree'),
        method: 'get'
      }).then(({ data }) => {
        console.log(data)
        this.menus = data.page
      })
    }
  },
  created () { this.getTreeList() },
  mounted () { }
}
</script>
<style lang="scss" scoped>
.wrapper {
}
</style>
posted @   xiye1  阅读(61)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 周边上新:园子的第一款马克杯温暖上架
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?
· 使用C#创建一个MCP客户端
点击右上角即可分享
微信分享提示