后端开发9.商品类型模块

概述

简介

商品类型我设计的复杂了点,设计了多级类型

效果图

c92c5d6c0a8040f0b964ab2cee275cf9.png

 

a46a334d5a61496a911e4a0cebd10c4e.png 

 

ec50bf59eb70474a856a78d41fd4d6fa.png

73f35a316cb041928e6f0d23fe1fc5d4.png 

 

 

 

 

数据库设计

创建表

DROP TABLE IF EXISTS `goods_type`;

CREATE TABLE `goods_type` (

  `goodsTypeId` int(11) NOT NULL AUTO_INCREMENT,

  `goodsTypeName` varchar(255) DEFAULT NULL,

  `goodsTypeLevel` int(11) DEFAULT NULL,

  `goodsTypeParentId` int(11) DEFAULT NULL,

  PRIMARY KEY (`goodsTypeId`)

) ENGINE=InnoDB AUTO_INCREMENT=71 DEFAULT CHARSET=utf8mb4;

 

添加数据

INSERT INTO `goods_type` VALUES ('3', '电脑、手机、数码', '1', null);

INSERT INTO `goods_type` VALUES ('15', '网络设备', '2', '3');

INSERT INTO `goods_type` VALUES ('16', '路由器', '3', '15');

INSERT INTO `goods_type` VALUES ('17', '网卡', '3', '15');

INSERT INTO `goods_type` VALUES ('18', '电脑整机', '2', '3');

INSERT INTO `goods_type` VALUES ('19', '笔记本', '3', '18');

INSERT INTO `goods_type` VALUES ('20', '超极本', '3', '18');

INSERT INTO `goods_type` VALUES ('21', '游戏本', '3', '18');

INSERT INTO `goods_type` VALUES ('22', '平板电脑', '3', '18');

INSERT INTO `goods_type` VALUES ('23', '手机通讯', '2', '3');

INSERT INTO `goods_type` VALUES ('24', '手机', '3', '23');

INSERT INTO `goods_type` VALUES ('25', '对讲机', '3', '23');

INSERT INTO `goods_type` VALUES ('26', '手机配件', '2', '3');

INSERT INTO `goods_type` VALUES ('27', '蓝牙耳机', '3', '26');

INSERT INTO `goods_type` VALUES ('28', '手机耳机', '3', '26');

INSERT INTO `goods_type` VALUES ('29', '数据线、充电器', '3', '26');

INSERT INTO `goods_type` VALUES ('30', '手机膜', '3', '26');

INSERT INTO `goods_type` VALUES ('31', '充电宝', '3', '26');

INSERT INTO `goods_type` VALUES ('32', '摄影摄像', '2', '3');

INSERT INTO `goods_type` VALUES ('33', '数码相机', '3', '32');

INSERT INTO `goods_type` VALUES ('34', '运动相机', '3', '32');

INSERT INTO `goods_type` VALUES ('35', '大家电、小家电', '1', null);

INSERT INTO `goods_type` VALUES ('36', '大家电', '2', '35');

INSERT INTO `goods_type` VALUES ('37', '平板电视', '3', '36');

INSERT INTO `goods_type` VALUES ('38', '空调', '3', '36');

INSERT INTO `goods_type` VALUES ('39', '冰箱', '3', '36');

INSERT INTO `goods_type` VALUES ('40', '洗衣机', '3', '36');

INSERT INTO `goods_type` VALUES ('41', '生活电器', '2', '35');

INSERT INTO `goods_type` VALUES ('42', '净化器', '3', '41');

INSERT INTO `goods_type` VALUES ('43', '取暖电器', '3', '41');

INSERT INTO `goods_type` VALUES ('44', '吸尘器', '3', '41');

INSERT INTO `goods_type` VALUES ('45', '厨房电器', '2', '35');

INSERT INTO `goods_type` VALUES ('46', '五金家装', '2', '35');

INSERT INTO `goods_type` VALUES ('47', '电动工具', '3', '46');

INSERT INTO `goods_type` VALUES ('48', '手动工具', '3', '46');

INSERT INTO `goods_type` VALUES ('49', '浴霸、排气扇', '3', '46');

INSERT INTO `goods_type` VALUES ('50', '电饭煲', '3', '45');

INSERT INTO `goods_type` VALUES ('51', '特产、食品、保健', '1', null);

INSERT INTO `goods_type` VALUES ('52', '地方特产', '2', '51');

INSERT INTO `goods_type` VALUES ('53', '河南', '3', '52');

INSERT INTO `goods_type` VALUES ('54', '休闲食品', '2', '51');

INSERT INTO `goods_type` VALUES ('55', '坚果炒货', '3', '54');

INSERT INTO `goods_type` VALUES ('56', '肉干肉脯', '3', '54');

INSERT INTO `goods_type` VALUES ('57', '蜜饯果干', '3', '54');

INSERT INTO `goods_type` VALUES ('58', '蛋糕饼干', '3', '54');

INSERT INTO `goods_type` VALUES ('59', '饮料冲调', '2', '51');

INSERT INTO `goods_type` VALUES ('60', '饮料', '3', '59');

INSERT INTO `goods_type` VALUES ('61', '牛奶', '3', '59');

INSERT INTO `goods_type` VALUES ('62', '咖啡奶茶', '3', '59');

INSERT INTO `goods_type` VALUES ('63', '茗茶', '2', '51');

INSERT INTO `goods_type` VALUES ('64', '铁观音', '3', '63');

INSERT INTO `goods_type` VALUES ('65', '粮油调味', '2', '51');

INSERT INTO `goods_type` VALUES ('66', '食用油', '3', '65');

INSERT INTO `goods_type` VALUES ('67', '调味品', '3', '65');

INSERT INTO `goods_type` VALUES ('68', '中外名酒', '2', '51');

INSERT INTO `goods_type` VALUES ('69', '白酒', '3', '68');

INSERT INTO `goods_type` VALUES ('70', '葡萄酒', '3', '68');

 

实体类设计

@Data
public class GoodsType implements Serializable {
    @TableId
    private Integer goodsTypeId;//id
    private String goodsTypeName;//类型名
    private Integer goodsTypeLevel; // 级别,目前只支持1,2,3三级
    private Integer goodsTypeParentId; // 父级的id
    @TableField(exist = false)
    private List<GoodsType> children;//子类型
}

 

服务层逻辑

GoodsTypeService

package jkw.service;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import jkw.pojo.GoodsType;

import java.util.List;

public interface GoodsTypeService {
    void add(GoodsType goodsType);
    void update(GoodsType goodsType);
    void delete(Integer id);
    GoodsType findById(Integer id);
    //分页查询一级类型并把2,3级类型封装到里面
    Page<GoodsType> searchLevelOne(int page, int size);
    //查询所有一级类型
    List<GoodsType> findAllOne();
    //查询所有二级类型
    List<GoodsType> findAllTwo();
    //查询所有三级类型
    List<GoodsType> findAllThree();
}

 

 

GoodsTypeServiceImpl

package jkw.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import jkw.exception.MyException;
import jkw.mapper.GoodsTypeMapper;
import jkw.pojo.GoodsType;
import jkw.service.GoodsTypeService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

@Service
@Transactional
public class GoodsTypeServiceImpl implements GoodsTypeService {
    @Autowired
    private GoodsTypeMapper goodsTypeMapper;

    @Override
    public void add(GoodsType goodsType) {
        //查询父类型,没有则为1级,有则为父级+1
        GoodsType goodsTypeParent = goodsTypeMapper.selectById(goodsType.getGoodsTypeParentId());
        if (goodsTypeParent == null) {
            goodsType.setGoodsTypeLevel(1);
        } else {
            goodsType.setGoodsTypeLevel(goodsTypeParent.getGoodsTypeLevel() + 1);
        }
        goodsTypeMapper.insert(goodsType);
    }

    @Override
    public void update(GoodsType goodsType) {
        goodsTypeMapper.updateById(goodsType);
    }

    @Override
    public void delete(Integer id) {
        //查询子类型,有子类则不可删除
        QueryWrapper<GoodsType> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("goodsTypeParentId", id);
        List<GoodsType> goodsTypeChildren = goodsTypeMapper.selectList(queryWrapper);
        if (goodsTypeChildren != null && goodsTypeChildren.size() > 0) {
            throw new MyException(601, "有子类型不可删除!!");
        } else {
            goodsTypeMapper.deleteById(id);
        }
    }

    @Override
    public GoodsType findById(Integer id) {
        return goodsTypeMapper.selectById(id);
    }

    @Override
    public Page<GoodsType> searchLevelOne(int page, int size) {
        QueryWrapper<GoodsType> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("goodsTypeLevel", "1");
        Page<GoodsType> goodsTypePage = goodsTypeMapper.selectPage(new Page<>(page, size), queryWrapper);
        List<GoodsType> goodsTypeOnes = goodsTypePage.getRecords();
        for (GoodsType goodsTypeOne : goodsTypeOnes) {
            //根据父id查找子类
            QueryWrapper<GoodsType> queryWrapper1 = new QueryWrapper<>();
            queryWrapper1.eq("goodsTypeParentId", goodsTypeOne.getGoodsTypeId());
            List<GoodsType> goodsTypeTwos = goodsTypeMapper.selectList(queryWrapper1);
            for (GoodsType goodsTypeTwo : goodsTypeTwos) {
                QueryWrapper<GoodsType> queryWrapper2 = new QueryWrapper<>();
                queryWrapper2.eq("goodsTypeParentId", goodsTypeTwo.getGoodsTypeId());
                List<GoodsType> goodsTypeThrees = goodsTypeMapper.selectList(queryWrapper2);
                goodsTypeTwo.setChildren(goodsTypeThrees);
            }
            goodsTypeOne.setChildren(goodsTypeTwos);
        }
        goodsTypePage.setRecords(goodsTypeOnes);
        return goodsTypePage;
    }

    @Override
    public List<GoodsType> findAllOne() {
        QueryWrapper<GoodsType> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("goodsTypeLevel", "1");
        return goodsTypeMapper.selectList(queryWrapper);
    }

    @Override
    public List<GoodsType> findAllTwo() {
        QueryWrapper<GoodsType> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("goodsTypeLevel", "2");
        return goodsTypeMapper.selectList(queryWrapper);
    }

    @Override
    public List<GoodsType> findAllThree() {
        QueryWrapper<GoodsType> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("goodsTypeLevel", "3");
        return goodsTypeMapper.selectList(queryWrapper);
    }
}

 

控制层

package jkw.controller;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import jkw.pojo.GoodsType;
import jkw.service.GoodsTypeService;
import jkw.vo.BaseResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
@RequestMapping("/goods/goodsType")
@CrossOrigin
public class GoodsTypeCon {
    @Autowired
    private GoodsTypeService goodsTypeService;

    /**
     * 新增
     *
     * @param goodsType
     * @return
     */
    @PostMapping("/add")
    public BaseResult add(GoodsType goodsType) {
        goodsTypeService.add(goodsType);
        return BaseResult.ok();
    }

    /**
     * 修改
     *
     * @param goodsType
     * @return
     */
    @PostMapping("/update")
    public BaseResult update(GoodsType goodsType) {
        goodsTypeService.update(goodsType);
        return BaseResult.ok();
    }

    /**
     * 删除
     *
     * @param goodsTypeId
     * @return
     */
    @DeleteMapping("/delete")
    public BaseResult delete(Integer goodsTypeId) {
        goodsTypeService.delete(goodsTypeId);
        return BaseResult.ok();
    }

    /**
     * 根据id查询
     *
     * @param goodsTypeId
     * @return
     */
    @GetMapping("/findById")
    public BaseResult findById(Integer goodsTypeId) {
        GoodsType goodsType = goodsTypeService.findById(goodsTypeId);
        return BaseResult.ok(goodsType);
    }

    /**
     * 分页查询一级的类型
     *
     * @param page
     * @param size
     * @return
     */
    @GetMapping("/search")
    public BaseResult search(int page, int size) {
        Page<GoodsType> TypePage = goodsTypeService.searchLevelOne(page, size);
        return BaseResult.ok(TypePage);
    }

    /**
     * 查询所有一级分类
     * @return
     */
    @GetMapping("/findAllOne")
    public BaseResult findAllOne() {
        List<GoodsType> goodsTypeList = goodsTypeService.findAllOne();
        return BaseResult.ok(goodsTypeList);
    }

    /**
     * 查询所有二级分类
     * @return
     */
    @GetMapping("/findAllTwo")
    public BaseResult findAllTwo() {
        List<GoodsType> goodsTypeList = goodsTypeService.findAllTwo();
        return BaseResult.ok(goodsTypeList);
    }

    /**
     * 查询所有三级分类
     * @return
     */
    @GetMapping("/findAllThree")
    public BaseResult findAllThree() {
        List<GoodsType> goodsTypeList = goodsTypeService.findAllThree();
        return BaseResult.ok(goodsTypeList);
    }
}

 

 

 

后台ui设计

<template>
  <div class="data-container">
    <!--添加 start-->
    <div class="data-header">
      <el-button round @click="addHander" size="large" type="primary">
        <el-icon>
          <DocumentAdd/>
        </el-icon>
        <span>新增</span>
      </el-button>
    </div>
    <!--添加 end-->
    <!--表格数据展示 start-->
    <div class="data-table">
      <el-table row-key="goodsTypeId" :data="dataList.list" style="width: 700px;">
        <el-table-column label="类型名" prop="goodsTypeName" width="200px"></el-table-column>
        <el-table-column label="级别" prop="goodsTypeLevel" width="100px">
          <template #default="scope">
            <el-tag  type="success">
             {{scope.row.goodsTypeLevel}}
            </el-tag>
          </template>
        </el-table-column>
        <el-table-column label="操作" align="center" >
          <template #default="scope">
            <el-button v-if="scope.row.goodsTypeLevel==3" size="small" type="info">不可再增</el-button>
            <el-button v-if="scope.row.goodsTypeLevel!=3" size="small" type="primary" @click="handleAddChild(scope.$index, scope.row)">新增子类</el-button>
            <el-button size="small" type="success" @click="handleEdit(scope.$index, scope.row)">编辑</el-button>
            <el-button size="small" type="danger" @click="handleDelete(scope.$index, scope.row)">删除</el-button>
          </template>
        </el-table-column>
      </el-table>
      <!--分页 start-->
      <div class="page">
        <el-pagination background
                       layout="prev,pager,next,jumper"
                       :default-page-size="defaultPageSize"
                       :total="totalData"
                       @current-change="currentChangeHaddler"></el-pagination>
      </div>
      <!--分页 end-->
    </div>
    <!--表格数据展示 end-->
    <!--添加对话框 start-->
    <el-dialog draggable destroy-on-close v-model="dialogAddVisible" title="添加" width="35%" center>
      <el-form inline :model="addFormInfo" label-width="150px">
        <el-form-item label="类型名">
          <el-input v-model="addFormInfo.goodsTypeName"></el-input>
        </el-form-item>
      </el-form>
      <template #footer>
            <span class="dialog-footer">
                <el-button @click="dialogAddVisible = false">取消</el-button>
                <el-button type="primary" @click="sureHandler">确定</el-button>
            </span>
      </template>
    </el-dialog>
    <!--添加对话框 end-->
    <!--添加子级别对话框 start-->
    <el-dialog draggable destroy-on-close v-model="dialogAddChildVisible" title="添加子级" width="35%" center>
      <el-form inline :model="addChildFormInfo" label-width="150px">
        <el-form-item label="类型名">
          <el-input v-model="addChildFormInfo.goodsTypeName"></el-input>
        </el-form-item>
      </el-form>
      <template #footer>
            <span class="dialog-footer">
                <el-button @click="dialogAddChildVisible = false">取消</el-button>
                <el-button type="primary" @click="sureAddChildHandler">确定</el-button>
            </span>
      </template>
    </el-dialog>
    <!--添加子级别对话框 end-->
    <!--编辑对话框 start-->
    <!--destroy-on-close:每次关闭对话框时直接销毁对话框,没有缓存-->
    <el-dialog
        draggable
        destroy-on-close
        v-model="dialogEditorVisible"
        title="编辑"
        width="35%"
        center>
      <el-form inline :model="editorFormInfo" label-width="150px">
        <el-form-item label="类型名">
          <el-input v-model="editorFormInfo.goodsTypeName"></el-input>
        </el-form-item>
      </el-form>
      <template #footer>
            <span class="dialog-footer">
                <el-button @click="dialogEditorVisible = false">取消</el-button>
                <el-button type="primary" @click="sureEditorHandler">确定</el-button>
            </span>
      </template>
    </el-dialog>
    <!--编辑对话框 end-->
  </div>
</template>

<script setup>
import axios from "@/utils/request.js"
import {onMounted, reactive, ref} from "vue";
import {ElMessage} from "element-plus";
//初始化权限查询数据
const dataList = reactive({
  list: []
})
//初始化总条数
const totalData = ref(0)
//当前页
const currentPage = ref(1)
//初始化分页显示条数
const defaultPageSize = ref(10)
//添加添加对话框控制器
const dialogAddVisible = ref(false)
//初始化添加对话框状态
const addFormInfo = reactive({
  goodsTypeName: "",
})
//添加添加子级对话框控制器
const dialogAddChildVisible=ref(false)
//初始化添加子级对话框控制器
const addChildFormInfo = reactive({
  goodsTypeName: "",
  goodsTypeParentId: "",
})
//编辑对话框控制器
const dialogEditorVisible = ref(false)
//初始化编辑对话框状态
const editorFormInfo = reactive({
  goodsTypeId: '',
  goodsTypeName: "",
  goodsTypeLevel: "",
  goodsTypeParentId: "",
})
/**
 * 网路请求:分页查询
 *  */
const http = (page, size) => {
  axios.get('goods/goodsType/search', {
    params: {
      page: page,
      size: size
    }
  }).then(res => {
    if (res.data.code == 200) {
      dataList.list = res.data.data.records
      totalData.value = res.data.data.total
    } else {
      ElMessage.error(res.data.message)
    }

  })
}
onMounted(() => {
  http(currentPage.value, defaultPageSize.value)
})
/**
 * 分页
 */
const currentChangeHaddler = (nowPage) => {
  http(nowPage, defaultPageSize.value)
  currentPage.value = nowPage
}
/**
 * 添加对话框弹出事件
 */
const addHander = () => {
  dialogAddVisible.value = true
}
/**
 * 添加对话框 确定事件
 */
const sureHandler = () => {
  axios.post('goods/goodsType/add', {
    goodsTypeName: addFormInfo.goodsTypeName,
  }).then(res => {
    if (res.data.code == 200) {
      dialogAddVisible.value = false
      http(currentPage.value, defaultPageSize.value)
    } else {
      ElMessage.error(res.data.message)
    }
  })
}
/**
 * 新增子类弹出事件
 */
const handleAddChild=(index, row)=>{
  addChildFormInfo.goodsTypeParentId=row.goodsTypeId
  dialogAddChildVisible.value=true
}
/**
 * 新增子类 确定事件
 */
const sureAddChildHandler=()=>{
  axios.post('goods/goodsType/add', {
    goodsTypeName: addChildFormInfo.goodsTypeName,
    goodsTypeParentId:addChildFormInfo.goodsTypeParentId
  }).then(res => {
    if (res.data.code == 200) {
      dialogAddChildVisible.value = false
      http(currentPage.value, defaultPageSize.value)
    } else {
      ElMessage.error(res.data.message)
    }
  })
}
/**
 * 编辑对话框 弹出事件
 *  */
const handleEdit = (index, row) => {

  dialogEditorVisible.value = true
  axios.get('goods/goodsType/findById', {
    params: {
      goodsTypeId: row.goodsTypeId
    }
  }).then(res => {
    if (res.data.code == 200) {
      editorFormInfo.goodsTypeId = res.data.data.goodsTypeId;
      editorFormInfo.goodsTypeName = res.data.data.goodsTypeName;
      editorFormInfo.goodsTypeLevel = res.data.data.goodsTypeLevel;
      editorFormInfo.goodsTypeParentId = res.data.data.goodsTypeParentId;
    } else {
      ElMessage.error(res.data.data.message)
    }
  })

}
/**
 * 编辑对话框 确定事件
 */
const sureEditorHandler = () => {
  axios.post('goods/goodsType/update', {
    goodsTypeId: editorFormInfo.goodsTypeId,
    goodsTypeName: editorFormInfo.goodsTypeName,
    goodsTypeLevel: editorFormInfo.goodsTypeLevel,
    goodsTypeParentId: editorFormInfo.goodsTypeParentId,
  }).then(res => {
    if (res.data.code == 200) {
      dialogEditorVisible.value = false
      http(currentPage.value, defaultPageSize.value)
    } else {
      //添加失败:给出提示信息(element-plus/反馈组件/message信息提示)
      ElMessage.error(res.data.message)
    }
  })
}
/**删除 */
const handleDelete = (index, row) => {
  ElMessageBox.confirm(
      '确定删除么',
      '删除',
      {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning',
      }
  ).then(() => {
    //确认删除
    axios.delete("goods/goodsType/delete", {
      params: {
        goodsTypeId: row.goodsTypeId
      }
    }).then(res => {
      if (res.data.code == 200) {
        ElMessage({
          type: 'success',
          message: "删除成功!!!",
        })
        //刷新
        http(currentPage.value, defaultPageSize.value)
      } else {
        ElMessage({
          type: 'error',
          message: res.data.message,
        })
      }
    })
  }).catch(error => {
    ElMessage({
      type: 'info',
      message: "取消删除",
    })
  })


}
</script>
<style scoped>
.data-container {
  background: linear-gradient(left, rgb(89, 234, 233) 27%, rgb(131, 231, 218) 44%, rgb(69, 150, 216) 88%);
  background: -o-linear-gradient(left, rgb(89, 234, 233) 27%, rgb(131, 231, 218) 44%, rgb(69, 150, 216) 88%);
  background: -ms-linear-gradient(left, rgb(89, 234, 233) 27%, rgb(131, 231, 218) 44%, rgb(69, 150, 216) 88%);
  background: -moz-linear-gradient(left, rgb(89, 234, 233) 27%, rgb(131, 231, 218) 44%, rgb(69, 150, 216) 88%);
  background: -webkit-linear-gradient(left, rgb(89, 234, 233) 27%, rgb(131, 231, 218) 44%, rgb(69, 150, 216) 88%);
  height: 800px;
}

.data-header {
  padding: 20px;
}

.data-table {
  padding: 20px;
}

.page {
  position: fixed;
  right: 10px;
  bottom: 10px;
}
</style>

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

月木@

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

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

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

打赏作者

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

抵扣说明:

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

余额充值