猿实战13——实现你没听说过的前台类目

猿实战是一个原创系列文章,通过实战的方式,采用前后端分离的技术结合SpringMVC Spring Mybatis,手把手教你撸一个完整的电商系统,跟着教程走下来,变身猿人找到工作不是问题。想要一起实战吗?关注公号,获取基础代码,动手实战吧。

上几个章节,猿人君教会了你实现了属性/属性值和后台类目的绑定关系,今天,猿人君就带你来实现前台类目。

为什么会有前台类目

为了方便运营,在电商系统中,类目分为前台类目和后台类目。如果你经常网购,你会发现一个比较有意思的事情。鼠标移动到一级类目,会展示二级类目,点击一级二级类目,会跳转到对应的频道页面(不过做得大了都是分站,我们先考虑业务),点击三级类目会出发搜索的功能。

这些在之前的设计文章猿设计5——真电商之颠覆你的类目认知中已经讲述过了,这里就不再赘述了。

 

功能概览

前台类目,从某种程度上说,肩负了部分站点的导航以及内容组织的职责,要完成这一职责,我们可以先来看看需要实现的功能。

在前台类目模块中,系统体现了前台类目的层级关系,每一级类目都有对应的列表、新增/编辑功能。在一级类目中可以维护广告牌、在三级类目中,重点维护前后台类目的关系(以上本章节暂不讨论)。

数据库设计

根据之前的前台类目设计文章,我们很清楚的获知了前台类目的一些特征,我们根据之前的设计,将这些设计落地为数据库的物理设计,大家可以看一下(本章节仅讲述前台类目的实现)。

就类目而言,类目就像是一棵树,每一级类目都有可能有下一级类目,像这种特性,在数据库的设计上,是一种典型的自关联结构。但是类目用于检索时,往往伴随着层级关系的查找,比如提取某一级类目的信息。所以,我们在设计时,给予了一个level字段,用于方便提取固定层级的信息。

由于每一级维护的信息可能不同,所以在数据库设计上,我们做了一个整合,每一条行记录的信息是一二三级所有信息的集合,事实上,不同的层级只涉及部分字段内容,这种设计,也是一种常见的设计。

前台类目整体前端

类目的层级维护,从功能上讲,依然是一种整体和部分的关系,出于业务的考虑,在规模不是特别庞大的情况下,三级已经足够支撑你的运营。我们可以参考下之前的实现思路——将一级类目、二级类目、三级类目分别定义成小的组件。最后,由一个view来组织和整合它们就好了。

<template>
  <div id="fnCategoryDiv">
    <div v-if="oneCategoryShow">
      <frontDeskCategoryOneSearch ref="frontDeskCategoryOneSearch" @lookSubordinate="lookOneSubordinate" />
    </div>
    <div v-if="twoCategoryShow">
      <frontDeskCategoryTwoSearch ref="frontDeskCategoryTwoSearch" :pid="parentId" :pname="parentName" @lookSubordinate="lookTwoSubordinate" @returnBack="returnTwoBack" />
    </div>
    <div v-if="threeCategoryShow">
      <frontDeskCategoryThreeSearch ref="frontDeskCategoryThreeSearch" :pid="parentId" :pname="parentName" @returnBack="returnThreeBack" />
    </div>
  </div>
</template>
 
<script>
import frontDeskCategoryOneSearch from '@/components/productManage/frontDeskCategoryOneSearch'
import frontDeskCategoryTwoSearch from '@/components/productManage/frontDeskCategoryTwoSearch'
import frontDeskCategoryThreeSearch from '@/components/productManage/frontDeskCategoryThreeSearch'
export default {
  components: {
    frontDeskCategoryOneSearch,
    frontDeskCategoryTwoSearch,
    frontDeskCategoryThreeSearch
  },
  data() {
    return {
      // 一级类目
      oneCategoryShow: false,
      // 二级类目
      twoCategoryShow: false,
      // 三级类目
      threeCategoryShow: false,
      parentId: 0,
      parentName: '',
      catOneId: 0
    }
  },
  created() {
    // 显示一级类目
    this.oneCategoryShow = true
  },
  methods: {
    // 二级回退
    returnTwoBack() {
      // 一级二级三级类目显示设置
      this.oneCategoryShow = true
      this.twoCategoryShow = false
      this.threeCategoryShow = false
    },
    // 三级回退
    returnThreeBack(pid, pname) {
      // 一级二级三级类目显示设置
      this.oneCategoryShow = false
      this.twoCategoryShow = true
      this.threeCategoryShow = false
      this.parentId = this.catOneId
      this.parentName = pname
      console.log(this.parentId)
    },
    // 一级查看下级类目
    lookOneSubordinate(row) {
      // 一级二级三级类目显示设置
      this.oneCategoryShow = false
      this.twoCategoryShow = true
      this.threeCategoryShow = false
      this.parentId = row.fnCategoryId
      this.parentName = row.fnCategoryName
      this.catOneId = row.fnCategoryId
    },
    // 二级查看下级类目
    lookTwoSubordinate(row) {
      // 一级二级三级类目显示设置
      this.oneCategoryShow = false
      this.twoCategoryShow = false
      this.threeCategoryShow = true
      this.parentId = row.fnCategoryId
      this.parentName = row.fnCategoryName
    }
  }
}
</script>
 
<style scoped>
 
</style>

值得注意的是,在查看下级和返回上级种,涉及组件之间的参数传递。您需要将,本级类目的ID作为父ID传入下级,而在下级返回上级的操作种,您需要将上上级的id作为父ID传入上一级列表页面(二级除外)。

关于父子组件之间的通信问题,在之前的文章中已经讲述过很多了,这里就不再赘述了。

前台类目后端实现

其实就前台类目的普通功能而言,目前来说相对简单,最主要的是建立父子关联这样一个自关联的概念。

由于之前已经给出了我们自己定义的代码生成器,属性组的实现也相对简单,考虑到篇幅问题,这一部分我们给出Controller层面的功能实现,service、和dao,还是希望你自行实现,在初学时期,多谢代码,对你熟悉掌握代码编写的技巧,是一个必不可少的环节。

/**
 * Copyright(c) 2004-2020 pangzi
 * com.pz.basic.mall.controller.product.fncategory.MallFnCategoryController.java
 */
package com.pz.basic.mall.controller.product.fncategory;
 
import com.pz.basic.mall.domain.base.Result;
import com.pz.basic.mall.domain.product.category.query.QueryMallCategory;
import com.pz.basic.mall.domain.product.category.vo.MallCategoryVo;
import com.pz.basic.mall.domain.product.fncategory.MallFnBgCategoryRel;
import com.pz.basic.mall.domain.product.fncategory.MallFnCategory;
import com.pz.basic.mall.domain.product.fncategory.query.QueryMallFnBgCategoryRel;
import com.pz.basic.mall.domain.product.fncategory.query.QueryMallFnCategory;
import com.pz.basic.mall.service.product.category.MallCategoryService;
import com.pz.basic.mall.service.product.fncategory.MallFnBgCategoryRelService;
import com.pz.basic.mall.service.product.fncategory.MallFnCategoryService;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
 
import java.util.List;
 
 
/**
 *
 * @author pangzi
 * @date 2020-06-22 20:47:27
 *
 *
 */
@RestController
@RequestMapping("/fncategory")
public class MallFnCategoryController {
 
 
    private MallFnCategoryService mallFnCategoryService;
 
 
    public void setMallFnCategoryService(MallFnCategoryService mallFnCategoryService) {
        this.mallFnCategoryService = mallFnCategoryService;
    }
 
    /**
     * 新增类目
     * @param mallFnCategory
     * @return
     */
    @RequestMapping("/addMallFnCategory")
    public Result<MallFnCategory>  addMallFnCategory(@RequestBody MallFnCategory mallFnCategory){
        try{
            return mallFnCategoryService.addMallFnCategory(mallFnCategory);
        }catch(Exception e){
            e.printStackTrace();
            return new Result(false);
        }
    }
 
    /**
     * 根据ID查找类目
     * @param id
     * @return
     */
    @RequestMapping("/findMallFnCategoryById")
    public  Result<MallFnCategory> findMallFnCategoryById(Long id){
        return mallFnCategoryService.getMallFnCategoryById(id.intValue());
    }
 
    /**
     * 修改类目
     * @param mallFnCategory
     * @return
     */
    @RequestMapping("/updateMallFnCategory")
    public Result updateMallFnCategory(@RequestBody MallFnCategory mallFnCategory){
        try{
            return  mallFnCategoryService.updateMallFnCategoryById(mallFnCategory);
        }catch(Exception e){
            e.printStackTrace();
            return new Result(false);
        }
    }
 
 
    /**
     * 分页返回类目列表
     * @param queryMallFnCategory
     * @return
     */
    @RequestMapping("/findByPage")
    public  Result<List<MallFnCategory>> findByPage(@RequestBody QueryMallFnCategory queryMallFnCategory){
        return mallFnCategoryService.getMallFnCategorysByPage(queryMallFnCategory);
    }
}

后台类目前端实现

聊完了后端数据接口的事情,我们一起来看看前端实现的问题,考虑到大部分朋友前端并不是很熟悉,我们再讲讲后台类目前端API组件的封装。

我们先封装访问后端的数据接口:

// 前台类目
 
export function fetchFnCategoryList(query) {
  return request({
    url: '/fncategory/findByPage',
    method: 'post',
    data: query
  })
}
 
export function createMallFnCategory(data) {
  return request({
    url: '/fncategory/addMallFnCategory',
    method: 'post',
    data
  })
}
 
export function updateMallFnCategory(data) {
  return request({
    url: '/fncategory/updateMallFnCategory',
    method: 'post',
    data
  })
}

考虑到之前有朋友说页面编写起来实在困难,在这里, 为了让你更好的掌握前台类目的内容,这次将一二三级的前台页面都给到你。不过猿人君还是希望你尽量自己编码。不然,你真的很难掌握开发技巧。

一级前台类目

<template>
  <div id="frontDeskCategoryOneSearchDiv">
    <div>
      <el-form ref="listQuery" :model="listQuery" :inline="true">
        <el-form-item label="类目名称:" prop="fnCategoryNameLike">
          <el-input v-model="listQuery.fnCategoryNameLike" placeholder="请输入类目名称" clearable />
        </el-form-item>
        <el-form-item>
          <el-button type="primary" icon="el-icon-search" @click="fetchData()">查询</el-button>
          <el-button type="primary" icon="el-icon-edit" style="float:right;margin-bottom:20px;" @click="addDate()">新增一级</el-button>
        </el-form-item>
      </el-form>
    </div>
    
    <div>
      <el-table
        ref="table"
        v-loading="listLoading"
        :data="list"
        style="width: 100%"
        border
      >
        <el-table-column label="类目ID">
          <template slot-scope="scope">{
   { scope.row.fnCatego
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值