SpringBoot3 + Vue3 + Uniapp + uView + Elenment 实现动态二级分类以及二级分类的管理

SpringBoot3 + Vue3 + Uniapp + uView + Elenment 实现动态二级分类以及二级分类的管理

  • 1. 效果展示
    • 1.1 前端显示效果
    • 1.2 后台管理一级分类
    • 1.3 后台管理二级分类
  • 2. 后端代码
    • 2.1 GoodsCategoryController.java
    • 2.2.1 GoodsCategoryMapper.java
    • 2.2.2 GoodsCategorySonMapper.java
    • 2.3.1 GoodsCategory.java
    • 2.3.2 GoodsCategorySon.java
    • 2.4 PageParm.java
    • 2.5.1 GoodsCategoryService .java
    • 2.5.2 GoodsCategorySonService.java
    • 2.6.1 GoodsCategoryServiceImpl .java
    • 2.6.2 GoodsCategoryServiceSonImpl.java
  • 3. uniapp 代码
    • 3.1 GoodsCategory.vue
    • 3.2 getSelectList.js
    • 3.3 http.js
  • 4. 后台管理页面代码
    • 4.1 GoodsType.vue
    • 4.2 GoodsType.ts
    • 4.3 goods\index.ts
    • 4.4 PaginationQueryModel.ts

1. 效果展示

1.1 前端显示效果


在这里插入图片描述

1.2 后台管理一级分类


在这里插入图片描述

1.3 后台管理二级分类


点击一级分类可以进入二级分类管理

在这里插入图片描述

2. 后端代码

2.1 GoodsCategoryController.java


package com.zhx.app.controller;import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.zhx.app.model.goods.GoodsCategory;
import com.zhx.app.model.PagePram;
import com.zhx.app.model.goods.GoodsCategorySon;
import com.zhx.app.service.GoodsCategoryService;
import com.zhx.app.service.GoodsCategorySonService;
import com.zhx.app.utils.ResultUtils;
import com.zhx.app.utils.ResultVo;
import io.micrometer.common.util.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;import java.util.List;/*** @ClassName : GoodsCategoryController* @Description : 商品分类* @Author : zhx* @Date: 2024-03-31 10:50*/
@RestController
@RequestMapping("/api/goodsCategory")
public class GoodsCategoryController {@Autowiredprivate GoodsCategoryService goodsCategoryService;@Autowiredprivate GoodsCategorySonService goodsCategorySonService;/*** 获取商品分类列表** @param pagePram* @return*/@GetMapping("/getList")public ResultVo getList(PagePram pagePram) {// 构造分页查询条件QueryWrapper<GoodsCategory> query = new QueryWrapper<>();query.lambda().like(StringUtils.isNotBlank(pagePram.getSearchName()), GoodsCategory::getCategoryName, pagePram.getSearchName()).orderByDesc(GoodsCategory::getOrderNum);// 构建分页对象IPage<GoodsCategory> page = new Page<>(pagePram.getCurrentPage(), pagePram.getPageSize());// 查询IPage<GoodsCategory> list = goodsCategoryService.page(page, query);return ResultUtils.success("查询成功!", list);}/*** 查询二级分类数据* @param categoryFatherId* @param pagePram* @return*/@GetMapping("/getInfo/{categoryFatherId}")public ResultVo getListInfo(@PathVariable String categoryFatherId, PagePram pagePram) {// 构造分页查询条件QueryWrapper<GoodsCategorySon> query = new QueryWrapper<>();query.lambda().like(StringUtils.isNotBlank(categoryFatherId), GoodsCategorySon::getCategoryFatherId,categoryFatherId).orderByDesc(GoodsCategorySon::getOrderNum);// 构建分页对象IPage<GoodsCategorySon> page = new Page<>(pagePram.getCurrentPage(), pagePram.getPageSize());// 查询IPage<GoodsCategorySon> list = goodsCategorySonService.page(page, query);return ResultUtils.success("查询成功!", list);}/*** 新增商品分类** @param goodsCategory* @return*/@PostMappingpublic ResultVo add(@RequestBody GoodsCategory goodsCategory) {if (goodsCategoryService.save(goodsCategory)) {return ResultUtils.success("添加成功!");} else {return ResultUtils.error("添加失败!");}}/*** 新增商品分类** @param goodsCategorySon* @return*/@PostMapping("/son")public ResultVo addSon(@RequestBody GoodsCategorySon goodsCategorySon) {if (goodsCategorySonService.save(goodsCategorySon)) {return ResultUtils.success("添加成功!");} else {return ResultUtils.error("添加失败!");}}/*** 删除商品分类** @param goodsCategoryId* @return*/@DeleteMapping("/{categoryId}")public ResultVo delete(@PathVariable("categoryId") Long goodsCategoryId) {if (goodsCategoryService.removeById(goodsCategoryId)) {return ResultUtils.success("删除成功!");} else {return ResultUtils.error("删除失败!");}}/*** 删除商品分类** @param goodsCategoryId* @return*/@DeleteMapping("/son/{categoryId}")public ResultVo deleteSon(@PathVariable("categoryId") Long goodsCategoryId) {System.out.println(goodsCategoryId);if (goodsCategorySonService.removeById(goodsCategoryId)) {return ResultUtils.success("删除成功!");} else {return ResultUtils.error("删除失败!");}}/*** 修改商品分类** @param goodsCategorySon* @return*/@PutMapping("/son")public ResultVo edit(@RequestBody GoodsCategorySon goodsCategorySon) {if (goodsCategorySonService.updateById(goodsCategorySon)) {return ResultUtils.success("修改成功!");} else {return ResultUtils.error("修改失败!");}}/*** 修改子商品分类** @param goodsCategory* @return*/@PutMappingpublic ResultVo edit(@RequestBody GoodsCategory goodsCategory) {if (goodsCategoryService.updateById(goodsCategory)) {return ResultUtils.success("修改成功!");} else {return ResultUtils.error("修改失败!");}}/*** 获取查询列用于前端 u-picker 组件渲染值* @return*/@GetMapping("/getSelectList")public ResultVo getSelectList() {List<Object> categoryList = goodsCategorySonService.getSelectLists();return ResultUtils.success("查询成功!", categoryList);}/*** 通过二级分类id查询整个分类详情* @param id* @return*/@GetMapping("/{categoryId}")public ResultVo getCategoryListById(@PathVariable("categoryId") String id) {List<String> categoryList = goodsCategorySonService.getCategoryListById(id);return ResultUtils.success("查询成功!", categoryList);}
}

2.2.1 GoodsCategoryMapper.java


package com.zhx.app.mapper;import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.zhx.app.model.goods.GoodsCategory;/*** @ClassName : GoodsCategoryMapper* @Description :* @Author : zhx* @Date: 2024-03-31 10:47*/
public interface GoodsCategoryMapper extends BaseMapper<GoodsCategory> {
}

2.2.2 GoodsCategorySonMapper.java


package com.zhx.app.mapper;import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.zhx.app.model.goods.GoodsCategory;
import com.zhx.app.model.goods.GoodsCategorySon;/*** @ClassName : GoodsCategorySonMapper* @Description :* @Author : zhx* @Date: 2024-03-31 10:47*/
public interface GoodsCategorySonMapper extends BaseMapper<GoodsCategorySon> {
}

2.3.1 GoodsCategory.java

package com.zhx.app.model.goods;import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;/*** @ClassName : GoodsCategory* @Description : 商品一级分类* @Author : zhx* @Date: 2024-03-31 10:44*/
@Data
@TableName("goods_category")
public class GoodsCategory {@TableId(type = IdType.AUTO)private Long categoryId;private String categoryName;private Integer orderNum;
}

2.3.2 GoodsCategorySon.java


package com.zhx.app.model.goods;import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;/*** @ClassName : GoodsCategorySon* @Description : 商品二级分类* @Author : zhx* @Date: 2024-03-31 10:44*/
@Data
@TableName("goods_category_son")
public class GoodsCategorySon {@TableId(type = IdType.AUTO)private Long categoryId;private String categoryName;private Integer orderNum;private Long categoryFatherId;
}

2.4 PageParm.java


package com.zhx.app.model;import lombok.Data;/*** @ClassName : PageParm* @Description : 分页* @Author : zhx* @Date: 2024-03-30 11:00*/
@Data
public class PagePram {private Long currentPage;private Long pageSize;private String searchName;
}

2.5.1 GoodsCategoryService .java


package com.zhx.app.service;import com.baomidou.mybatisplus.extension.service.IService;
import com.zhx.app.model.goods.GoodsCategory;/*** @ClassName : GoodsCategoryService* @Description :* @Author : zhx* @Date: 2024-03-31 10:48*/public interface GoodsCategoryService extends IService<GoodsCategory> {
}

2.5.2 GoodsCategorySonService.java


package com.zhx.app.service;import com.baomidou.mybatisplus.extension.service.IService;
import com.zhx.app.model.goods.GoodsCategorySon;
import lombok.Data;import java.util.ArrayList;
import java.util.List;/*** @ClassName : GoodsCategoryService* @Description :* @Author : zhx* @Date: 2024-03-31 10:48*/public interface GoodsCategorySonService extends IService<GoodsCategorySon> {List<Object> getSelectLists();List<String> getCategoryListById(String id);
}

2.6.1 GoodsCategoryServiceImpl .java


package com.zhx.app.service.impl;import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zhx.app.mapper.GoodsCategoryMapper;
import com.zhx.app.model.goods.GoodsCategory;
import com.zhx.app.model.goods.GoodsCategorySon;
import com.zhx.app.service.GoodsCategoryService;
import org.springframework.stereotype.Service;/*** @ClassName : GoodsCategoryServiceImpl* @Description :* @Author : zhx* @Date: 2024-03-31 10:49*/
@Service
public class GoodsCategoryServiceImpl extends ServiceImpl<GoodsCategoryMapper, GoodsCategory> implements GoodsCategoryService{
}

2.6.2 GoodsCategoryServiceSonImpl.java


package com.zhx.app.service.impl;import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zhx.app.mapper.GoodsCategoryMapper;
import com.zhx.app.mapper.GoodsCategorySonMapper;
import com.zhx.app.model.goods.GoodsCategory;
import com.zhx.app.model.goods.GoodsCategorySon;
import com.zhx.app.service.GoodsCategorySonService;
import io.micrometer.common.util.StringUtils;
import lombok.Data;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Optional;/*** @ClassName : GoodsCategoryServiceSonImpl* @Description :* @Author : zhx* @Date: 2024-03-31 10:49*/
@Service
public class GoodsCategoryServiceSonImpl extends ServiceImpl<GoodsCategorySonMapper, GoodsCategorySon> implements GoodsCategorySonService{@Autowiredprivate GoodsCategoryMapper goodsCategoryMapper;@Autowiredprivate GoodsCategorySonMapper goodsCategorySonMapper;/*** 格式化返回一级分类和二级分类列表* @return*/@Overridepublic List<Object> getSelectLists() {@Dataclass SelectType {private Long id;private String name;}@Dataclass SelectTypeSon {private Long id;private String name;private Long categoryFatherId;}// 查询分类列表// 构造查询QueryWrapper<GoodsCategory> query = new QueryWrapper<>();// 查询条件query.lambda().orderByDesc(GoodsCategory::getCategoryId);// 获取查询结果List<GoodsCategory> list = goodsCategoryMapper.selectList(query);// 构造查询QueryWrapper<GoodsCategorySon> querySon = new QueryWrapper<>();// 查询条件querySon.lambda().orderByDesc(GoodsCategorySon::getOrderNum);// 获取查询结果List<GoodsCategorySon> listSon = goodsCategorySonMapper.selectList(querySon);// 存储需要的类型ArrayList<SelectType> selectList = new ArrayList<>();ArrayList<SelectTypeSon> selectListSon = new ArrayList<>();List<Object> category = new ArrayList<>();// 构造需要的类型Optional.ofNullable(list).orElse(new ArrayList<>()).stream().forEach(x -> {SelectType type = new SelectType();type.setId(x.getCategoryId());type.setName(x.getCategoryName());selectList.add(type);});Optional.ofNullable(listSon).orElse(new ArrayList<>()).stream().forEach(x -> {SelectTypeSon type = new SelectTypeSon();type.setId(x.getCategoryId());type.setName(x.getCategoryName());type.setCategoryFatherId(x.getCategoryFatherId());selectListSon.add(type);});category.add(selectList);category.add(selectListSon);return category;}/*** 根据二级分类的id查询一级分类和二级分类名称* @param id* @return*/@Overridepublic List<String> getCategoryListById(String id) {// 创建容器存放 一级分类和二级分类名称List<String> nameList = new ArrayList<>();// 查询分类列表// 构造查询QueryWrapper<GoodsCategorySon> query = new QueryWrapper<>();query.lambda().like(StringUtils.isNotBlank(id),GoodsCategorySon::getCategoryId, id);GoodsCategorySon son = goodsCategorySonMapper.selectOne(query);// 二级分类添加到容器nameList.add(son.getCategoryName());// 通过二级分类的 父id字段 获取一级分类名Long categoryFatherId = son.getCategoryFatherId();QueryWrapper<GoodsCategory> queryFather = new QueryWrapper<>();queryFather.lambda().like(StringUtils.isNotBlank(String.valueOf(categoryFatherId)),GoodsCategory::getCategoryId, categoryFatherId);GoodsCategory father = goodsCategoryMapper.selectOne(queryFather);nameList.add(father.getCategoryName());Collections.reverse(nameList);return nameList;}
}

3. uniapp 代码

3.1 GoodsCategory.vue


			<!-- 商品分类 --><view class="foot line-border" @tap="showShopType=true;"><view>商品分类</view><view class="foot-right"><u-tag v-if="productData.type==''" @click="showShopType=true":text="productData.type==''?'请选择商品分类':items" :type="productData.newColor" shape="circle"size="mini" style="margin-left: 10rpx;"></u-tag><template v-for="(items, index) in productData.type" :key="index"><u-tag @click="showShopType=true" :text="items" :type="productData.type!=''?'success':''"shape="circle" size="mini" style="margin-left: 10rpx;"></u-tag></template><u-icon name="arrow-right"></u-icon></view></view><!-- 商品分类弹出层 --><view><u-picker :show="showShopType" ref="uPicker" :columns="typeList.columns" @confirm="confirm"@change="changeHandler" confirmColor="green" immediateChange @cancel="showShopType=false"keyName="name" :defaultIndex="[Math.trunc(typeList.columns[0].length / 2),1]"></u-picker></view><script setup>import {reactive,ref} from 'vue';import UpLoadFile from "@/utils/uploadFlie/UpLoadFile.vue"import MapOpen from "@/utils/mapOpen/MapOpen.vue"import {getSelectList} from '../../api/shopcategory';const urlLists = ref([]);const urlList = (data) => {urlLists.value = data;}const showShopType = ref(false);const realyType = ref("");// 发布商品const publishProducts = () => {// 构造商品数据let data = {profile: productData.value.profile,url: '',address: "商品位置",money: productData.value.money,type: realyType.value,oldMoney: productData.value.oldMoney,new: productData.value.new,trading: productData.value.trading,contact: productData.value.contact,contactType: productData.value.contactType}urlLists.value.forEach(x => data.url += x + ",")data.url = data.url.slice(0, -1)console.log(data);// 调用接口写入商品数据}// 商品数据const productData = ref({tips: "清晰的描述品牌型号和宝贝细节,才能更快的卖出~",profile: "", // 商品介绍address: "", // 商品位置money: "", // 商品价格oldMoney: "", // 商品原价type: "",new: "请选择新旧程度", // 新旧程度newColor: "", //新旧颜色trading: "请选择交易方式", // 交易方式contact: "", // 联系方式contactType: "" // 联系方式})// 商品分类const typeList = reactive({columns: [['服饰', '数码']],columnData: []})// 获取数据import {onShow} from '@dcloudio/uni-app'onShow(() => {getList();})const getList = () => {let res = getSelectList();res.then((result) => {// 设置以及分类默认选中let num = Math.trunc(result.data[0].length/2);// 设置一级分类typeList.columns = [result.data[0]];// 构造二级分类// 使用一个 Map 对象来按照 categoryFatherId 分组const groupedData = new Map();result.data[1].forEach(item => {const {categoryFatherId} = item;if (!groupedData.has(categoryFatherId)) {// 如果 Map 中不存在该 categoryFatherId 对应的键,则创建一个新数组groupedData.set(categoryFatherId, [item]);} else {// 如果 Map 中已存在该 categoryFatherId 对应的键,则将对象添加到对应的数组中groupedData.get(categoryFatherId).push(item);}});// 将 Map 中的值(数组)转换为最终的结果数组const resultArray = Array.from(groupedData.values());typeList.columnData = resultArray;// 定义比较函数,按照子数组中第一个对象的 categoryFatherId 进行排序const compareByCategoryFatherId = (a, b) => {const categoryA = a[0].categoryFatherId;const categoryB = b[0].categoryFatherId;if (categoryA < categoryB) {return 1;}if (categoryA > categoryB) {return -1;}return 0;};// 对二级分类进行排序 使得和一级分类的数据一一对应(一个一级分类对应一个二级分类数组)typeList.columnData.sort(compareByCategoryFatherId);// 添加一个二级分类列到一级分类使得一开始就显示一级分类和二级分类 否则刚进去不会显示二级分类typeList.columns.push(typeList.columnData[num])});}const changeHandler = (e) => {const {columnIndex,value,values, // values为当前变化列的数组内容index,picker = this.$refs.uPicker} = e;//当第一列值发生变化时,变化第二列(后一列)对应的选项if (columnIndex === 0) {// picker为选择器this实例,变化第二列对应的选项picker.setColumnValues(1, typeList.columnData[index])}}// 回调参数为包含columnIndex、value、valuesconst confirm = (e) => {let type = [];e.value.forEach(x => type.push(x.name));productData.value.type = type;showShopType.value = falserealyType.value = e.value[1].id;}
</script>

3.2 getSelectList.js


import http from "../../utils/httpRequest/http";// 查询所有分类
export const getSelectList = () =>{return http.get(`/api/goodsCategory/getSelectList`);
} 

3.3 http.js


const baseUrl = 'http://localhost:9999';
const http = (options = {}) => {return new Promise((resolve, reject) => {uni.request({url: baseUrl + options.url || '',method: options.type || 'GET',data: options.data || {},header: options.header || {}}).then((response) => {// console.log(response);if (response.data && response.data.code == 200) {resolve(response.data);} else {uni.showToast({icon: 'none',title: response.data.msg,duration: 2000});}}).catch(error => {reject(error);})});
}
/*** get 请求封装*/
const get = (url, data, options = {}) => {options.type = 'get';options.data = data;options.url = url;return http(options);
}/*** post 请求封装*/
const post = (url, data, options = {}) => {options.type = 'post';options.data = data;options.url = url;return http(options);
}/*** put 请求封装*/
const put = (url, data, options = {}) => {options.type = 'put';options.data = data;options.url = url;return http(options);
}/*** upLoad 上传* */
const upLoad = (parm) => {return new Promise((resolve, reject) => {uni.uploadFile({url: baseUrl + parm.url,filePath: parm.filePath,name: 'file',formData: {openid: uni.getStorageSync("openid")},header: {// Authorization: uni.getStorageSync("token")},success: (res) => {resolve(res.data);},fail: (error) => {reject(error);}})})
}export default {get,post,put,upLoad,baseUrl
}

4. 后台管理页面代码

4.1 GoodsType.vue


<!--* @Date: 2024-04-11 18:15:17* @LastEditors: zhong* @LastEditTime: 2024-04-11 17:25:33* @FilePath: \app-admin\src\views\goods\GoodsType.vue
-->
<template><el-main><!-- 搜索栏 --><el-form :model="searchParm" :inline="true" size="default"><el-form-item><el-input v-model="searchParm.searchName" placeholder="请输入分类名称"></el-input></el-form-item><el-form-item><el-button icon="search" @click="searchBtn()">搜索</el-button><el-button icon="closeBold" type="danger" @click="resetBtn()">重置</el-button><el-button icon="plus" type="primary" @click="addBtn()">新增</el-button><el-button v-if="isShowBack" icon="RefreshRight" type="success" @click="back()"style="justify-content: flex-end;">返回</el-button></el-form-item></el-form><!-- 表格 --><el-table :height="tableHeight" :data="tableList" border stripe><el-table-column label="序号" align="center"><template #default="scope"><div @click="lookInfo(scope.row.categoryId)"> <el-tag>{{ scope.$index + 1 }}</el-tag></div></template></el-table-column><el-table-column label="分类" align="center"><template #default="scope"><div @click="lookInfo(scope.row.categoryId)"> <el-tag>{{ scope.row.categoryName }}</el-tag></div></template></el-table-column><!-- 操作 --><el-table-column prop="status" label="操作" align="center" width="220"><template #default="scope"><el-button type="primary" icon="edit" size="default" @click="editBtn(scope.row)">编辑</el-button><el-button type="danger" icon="delete" size="default" @click="deleteBtn(scope.row)">删除</el-button></template></el-table-column></el-table><div class="tips">Tips: 当前为一级分类,点击查看二级分类。</div><!-- 分页 --><div class="page-helper"><el-pagination @size-change="sizeChange" @current-change="currentChange":current-page.sync="searchParm.currentPage" :page-sizes="[10, 20, 40, 80, 100]":page-size="searchParm.pageSize" layout="total, sizes, prev, pager, next, jumper":total="searchParm.total" background></el-pagination></div><!-- 新增 --><SystemDialog :title="dialog.title" :height="dialog.height" :width="dialog.width" :visible="dialog.visible"@on-close="onClose" @on-confirm="commit"><template v-slot:content><!-- 新增内容表单 --><el-form :model="addGoodsTypePram" ref="addRef" :rules="rules" label-width="80px" :inline="false"size="default"><el-form-item prop="categoryName" label="名称:"><el-input v-model="addGoodsTypePram.categoryName"></el-input></el-form-item><el-form-item prop="orderNum" label="优先级:"><el-input type="number" v-model="addGoodsTypePram.orderNum"></el-input></el-form-item></el-form></template></SystemDialog></el-main></template><script setup lang="ts">
import { nextTick, onMounted, reactive, ref } from 'vue';
import useDialog from '@/hooks/useDialog';
import { Title } from '@/type/BaseEnum';
import { ElMessage, FormInstance } from 'element-plus';
import { getGoodsTypeListApi, addGoodsTypeApi, editGoodsTypeApi, deleteGoodsTypeApi, getGoodsTypeSonListApi, deleteGoodsTypeSonApi, addGoodsTypeSonApi, editGoodsTypeSonApi } from '@/api/goods'
import SystemDialog from '@/components/SystemDialog/SystemDialog.vue';
import { GoodsType } from '@/api/goods/GoodsType';
import useInstance from '@/hooks/useInstance';
// 是否显示返回按钮
const isShowBack = ref(false);
// 返回一级分类
const back = () => {isShowBack.value = false;getList();
}
//获取当前点击对象的id
const id = ref<string>("0");
// 获取全局属性
const { golbal } = useInstance();
// 获取弹框属性
const { dialog, onClose } = useDialog();
// 表单 ref 属性
const addRef = ref<FormInstance>();
// 搜索绑定的对象 列表查询参数
const searchParm = reactive({currentPage: 1,pageSize: 10,searchName: "",total: 0
})
// 标识我们是提交操作还是修改操作
const tags = ref();
// 新增按钮
const addBtn = () => {tags.value = '0';// 设置弹框标题dialog.title = Title.ADDdialog.height = 120;dialog.visible = true;// 清空表单addRef.value?.resetFields()
}
// 点击跳转分类详情
const lookInfo = async (id_: string) => {if (!isShowBack.value) {id.value = id_;let res = await getGoodsTypeSonListApi(searchParm, id_);if (res && res.code == 200) {// res.data.records.forEach((x: { status: number; }) => x.status == 0 ? "true" : "false")tableList.value = res.data.records;searchParm.total = res.data.total;isShowBack.value = true;}}}// 搜索
const searchBtn = () => {getList();
}
// 重置
const resetBtn = () => {searchParm.searchName = '';getList();
}
// 表格数据
const tableList = ref([]);
// 表格高度
const tableHeight = ref(0);
// 列表查询
const getList = async () => {let res = await getGoodsTypeListApi(searchParm);if (res && res.code == 200) {// res.data.records.forEach((x: { status: number; }) => x.status == 0 ? "true" : "false")tableList.value = res.data.records;searchParm.total = res.data.total;}
}
// 新增表单内容
const addGoodsTypePram = reactive({categoryId: "",categoryName: "",orderNum: ""
})
// 新增表单内容
const addGoodsTypeSonPram = reactive({categoryId: "",categoryName: "",orderNum: "",categoryFatherId: ""
})// 表单验证规则
const rules = {categoryName: [{ required: true, message: '请填写商品分类', trigger: 'blur' },{ min: 0, max: 12, message: 'Length should be 0 to 12', trigger: 'blur' },],orderNum: [{ required: true, message: '请输入分类序号', trigger: 'blur' }],
}
// 提交表单
const commit = () => {addRef.value?.validate(async (valid) => {let res = null;if (valid) {addGoodsTypeSonPram.categoryId = addGoodsTypePram.categoryId;addGoodsTypeSonPram.categoryName = addGoodsTypePram.categoryName;addGoodsTypeSonPram.orderNum = addGoodsTypePram.orderNum;addGoodsTypeSonPram.categoryFatherId = id.value;if (tags.value == '0') {// 提交数据if (isShowBack.value) {res = await addGoodsTypeSonApi(addGoodsTypeSonPram);} else {res = await addGoodsTypeApi(addGoodsTypePram);}} else {// 提交数据if (!isShowBack.value) {res = await editGoodsTypeApi(addGoodsTypePram);}else {res = await editGoodsTypeSonApi(addGoodsTypeSonPram);}}if (res && res.code == 200) {// 重新拉取数据用户if (isShowBack.value) {isShowBack.value = false;lookInfo(id.value);isShowBack.value = true;} else {getList();}// 信息提示ElMessage.success(res.msg);// 提交成功 关闭弹框dialog.visible = false;}}});
}
// 编辑
const editBtn = (row: GoodsType) => {tags.value = '1';console.log(row);// 设置弹框标题dialog.title = Title.EDITdialog.height = 320;dialog.visible = true;// 设置数据回显nextTick(() => {Object.assign(addGoodsTypePram, row);})}
// 删除
const deleteBtn = async (row: GoodsType) => {console.log(row);const confirm = await golbal.$myConfirm("确定删除该数据吗?")if (confirm) {let res;if (!isShowBack.value) {res = await deleteGoodsTypeApi(row.categoryId);} else {res = await deleteGoodsTypeSonApi(row.categoryId);isShowBack.value = false;}if (res && res.code == 200) {// 重新拉取数据用户getList();// 信息提示ElMessage.success(res.msg);}// 设置数据回显nextTick(() => {Object.assign(addGoodsTypePram, row);})}
}
// 页容量改变时触发
const sizeChange = (size: number) => {searchParm.pageSize = size;getList();
}
// 页数改变时触发
const currentChange = (page: number) => {searchParm.currentPage = page;getList();
}
onMounted(() => {tableHeight.value = window.innerHeight - 200;getList();
})
</script><style lang="scss" scoped>
.tips {float: left;color: red;z-index: 99999;
}.page-helper {margin-top: 20px;display: flex;justify-content: flex-end;
}
</style>

4.2 GoodsType.ts


/** @Date: 2024-03-31 13:09:13* @LastEditors: zhong* @LastEditTime: 2024-03-31 13:10:56* @FilePath: \app-admin\src\api\goods\GoodsType.ts*/
// 定义商品分类数据
export type GoodsType = {categoryId: string,categoryName: string,orderNum: string,
}
// 二级商品分类数据
export type GoodsTypeSon = {categoryId: string,categoryName: string,orderNum: string,categoryFatherId: string
}

4.3 goods\index.ts


/** @Date: 2024-03-31 13:02:30* @LastEditors: zhong* @LastEditTime: 2024-04-11 17:23:15* @FilePath: \app-admin\src\api\goods\index.ts*/
import http from "@/http";
import { PageQueryPram } from "../PaginationQueryModel";
import { GoodsType, GoodsTypeSon } from './GoodsType'// 新增
export const addGoodsTypeApi = (parm: GoodsType) => {return http.post("/api/goodsCategory", parm);
}
// 查询所有
export const getGoodsTypeListApi = (parm: PageQueryPram) => {return http.get("/api/goodsCategory/getList", parm);
}
// 编辑
export const editGoodsTypeApi = (parm: GoodsType) => {return http.put("/api/goodsCategory", parm);
}
// 删除
export const deleteGoodsTypeApi = (categoryId: string) => {return http.delete(`/api/goodsCategory/${categoryId}`);
}// 查询所有子分类
export const getGoodsTypeSonListApi = (parm: PageQueryPram, id: string) => {return http.get(`/api/goodsCategory/getInfo/${id}`, parm);
}
// 删除子分类
export const deleteGoodsTypeSonApi = (categoryId: string) => {return http.delete(`/api/goodsCategory/son/${categoryId}`);
}
// 新增子分类
export const addGoodsTypeSonApi = (parm: GoodsTypeSon) => {return http.post("/api/goodsCategory/son", parm);
}// 编辑
export const editGoodsTypeSonApi = (parm: GoodsTypeSon) => {console.log(parm);return http.put("/api/goodsCategory/son", parm);
}

4.4 PaginationQueryModel.ts


/** @Date: 2024-03-30 13:16:03* @LastEditors: zhong* @LastEditTime: 2024-03-31 13:31:27* @FilePath: \app-admin\src\api\PaginationQueryModel.ts*/
// 定义用户的数据类型export type PageQueryPram = {currentPage: number,pageSize: number,searchName: string,total?: number
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/306754.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

性能升级,INDEMIND机器人AI Kit助力产业再蜕变

随着机器人进入到越来越多的生产生活场景中&#xff0c;作业任务和环境变得更加复杂&#xff0c;机器人需要更精准、更稳定、更智能、更灵敏的自主导航能力。 自主导航技术作为机器人技术的核心&#xff0c;虽然经过了多年发展&#xff0c;取得了长足进步&#xff0c;但在实践…

QA测试开发工程师面试题满分问答11: web前端页面视频组件无法播放如何定位bug

当 web 前端页面的视频组件无法播放时&#xff0c;可以从以下维度进行分析和定位可能的 bug&#xff0c;分析维度包括但不限于&#xff1a;前端功能点、缓存、异常、后端功能点、资源占用、并发、网络等&#xff1a; 前端功能点&#xff1a; HTML5 视频支持&#xff1a;检查视频…

FPGA基于VCU的H265视频解压缩,解码后HDMI2.0输出,支持4K60帧,提供工程源码+开发板+技术支持

目录 1、前言免责声明 2、相关方案推荐我这里已有的视频图像编解码方案4K60帧HDMI2.0输入&#xff0c;H265视频压缩方案 3、详细设计方案设计框图FPGA开发板解压视频源Zynq UltraScale VCUVideo Frame Buffer ReadVideo MixerHDMI 1.4/2.0 Transmitter SubsystemVideo PHY Cont…

基于springboot+vue实现的计算机等级考试报名系统

作者主页&#xff1a;Java码库 主营内容&#xff1a;SpringBoot、Vue、SSM、HLMT、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、小程序、安卓app等设计与开发。 收藏点赞不迷路 关注作者有好处 文末获取源码 技术选型 【后端】&#xff1a;Java 【框架】&#xff1a;spring…

淘宝Api接口开发系列,商品详情数据,搜索商品列表数据,无货源采集上货模式,数据分析

淘宝API接口开发涉及多个方面&#xff0c;包括获取商品详情数据、搜索商品列表数据、无货源采集上货模式以及数据分析等。今天给大家介绍下通过封装商品ID获取淘宝商品详情数据接口方法&#xff0c;支持高并发请求。下面我将分别对这些方面进行简要介绍。 1. 商品详情数据接口…

低频电磁仿真 | 新能源汽车性能提升的利器

永磁同步电机 新能源汽车的心脏 近年来&#xff0c;全球变暖的趋势日益加剧&#xff0c;极端天气事件层出不穷&#xff0c;这些现象都反映出当前气候形势的严峻性。为了应对这一全球性挑战&#xff0c;各国纷纷采取行动&#xff0c;制定了一系列降碳、减碳的措施。中国在2020年…

第十二届蓝桥杯大赛软件赛省赛Java 大学 B 组题解

1、ASC public class Main {public static void main(String[] args) {System.out.println(

如何使用 Grafana 监控文件系统状态

当 JuiceFS 文件系统部署完成并投入生产环境&#xff0c;接下来就需要着手解决一个非常重要的问题 —— 如何实时监控它的运行状态&#xff1f;毕竟&#xff0c;它可能正在为关键的业务应用或容器工作负载提供持久化存储支持&#xff0c;任何小小的故障或性能下降都可能造成不利…

基于jmeter的性能全流程测试

01、做性能测试的步骤 1、服务器性能监控 首先要在对应服务器上面安装性能监控工具&#xff0c;比如linux系统下的服务器&#xff0c;可以选择nmon或者其他的监控工具&#xff0c;然后在jmeter模拟场景跑脚本的时候&#xff0c;同时启动监控工具&#xff0c;这样就可以获得jm…

[lesson21]对象的构造顺序

对象的构造顺序 对象的构造顺序一 对于局部对象 当程序执行流到达对象的定义语句时进行构造 对象的构造顺序二 对于堆对象 当程序执行流到达new语句时创建对象使用new创建对象将自动触发构造函数的调用 s/20230724024159.png?origin_urlimage-2.png&pos_idimg-HTOH6…

纯小白蓝桥杯备赛笔记--DAY4(数学数据结构图论)

文章目录 数学质因数分解辗转相除法求最大公约数最小公倍数&#xff1a;快速幂乘法逆元费马小定理 逆元乘法逆元素数判定与埃式筛法朴素素数判定法埃式筛法 图论并查集T3:真题--合根植物DijkstraFloyd 基础算法递归&#xff0c;循环&#xff0c;前缀和&#xff0c;差分STL 数学…

ETL结合飞书快速实现业务信息同步

一、ETL工具介绍 ETLCloud数据集成平台是一款针对IT以及数据工程师推出的全域数据集成平台产品。它是集实时数据集成和离线数据集成以及API发布为一体的数据集成平台。与其他开源数据集成工具相比&#xff0c;系统采用轻量化架构、具有更快的部署速度、更快的数据传输速度、更…

什么是RMVB视频?如何把视频转成RMVB格式?视频格式转换的方法

一&#xff0c;什么是RMVB视频格式 RMVB是一种视频文件格式&#xff0c;它基于RealNetworks公司开发的RealMedia编解码器&#xff0c;被广泛应用于互联网上的视频流媒体传输和下载。RMVB文件通常具有较小的文件大小&#xff0c;同时保持较高的视频质量&#xff0c;因此在网络传…

【Kafka】Zookeeper集群 + Kafka集群

Zookeeper 概述 Zookeeper是一个开源的分布式的&#xff0c;为分布式框架提供协调服务的Apache项目。 Zookeeper 工作机制★★★ Zookeeper从设计模式角度来理解&#xff1a; 1&#xff09;是一个基于观察者模式设计的分布式服务管理框架&#xff1b; 它负责存储和管理大家都关…

TDengine too many open files

too many open files 是比较常见的报错&#xff0c;尤其使用TDengine 3.0 集群时&#xff0c;大概率会遇到。这个报错很简单&#xff0c;但要想顺利解决&#xff0c;却涉及到很多知识点。 目录 知识点&#xff1a;fs.nr_open知识点&#xff1a;file-max & fs.file-nr知识点…

Intrigue Core:一款功能强大的攻击面枚举引擎

关于Intrigue Core Intrigue Core是一款功能强大的开源攻击面枚举引擎&#xff0c;该工具可以帮助广大研究人员更好地管理应用程序的攻击面。 Intrigue Core集成了各种各样的安全数据源&#xff0c;可以将这些数据提取到标准化的对象模型中&#xff0c;并通过图形数据库跟踪关…

2024认证杯数学建模A题保暖纤维保暖能力原创论文讲解(含完整python代码)

大家好呀&#xff0c;从发布赛题一直到现在&#xff0c;总算完成了认证杯数学中国数学建模网络挑战赛第一阶段A题目保暖纤维的保暖能力完整的成品论文。 本论文可以保证原创&#xff0c;保证高质量。绝不是随便引用一大堆模型和代码复制粘贴进来完全没有应用糊弄人的垃圾半成品…

C++高级特性:柯里化过程与std::bind(六)

1、柯里化过程 1.1、operator()的引入 现在需要完成这样一个需求&#xff1a;有一个函数每次调用返回的结果不一样。例如&#xff1a;两次调用的返回值都不一样那么就可以达到这种目的 1.1.1、简单点的写法 可以给一个全局的变量&#xff08;静态变量&#xff09;&#xff…

SCI一区 | Matlab实现INFO-TCN-BiGRU-Attention向量加权算法优化时间卷积双向门控循环单元注意力机制多变量时间序列预测

SCI一区 | Matlab实现INFO-TCN-BiGRU-Attention向量加权算法优化时间卷积双向门控循环单元注意力机制多变量时间序列预测 目录 SCI一区 | Matlab实现INFO-TCN-BiGRU-Attention向量加权算法优化时间卷积双向门控循环单元注意力机制多变量时间序列预测预测效果基本介绍模型描述程…

实践笔记-linux内核版本升级(centos7)

linux内核版本升级 1.查看当前内核版本信息2.采用yum方式进行版本升级2.1导入仓库源2.2选择 ML 或 LT 版本安装2.3设置内核启动 3.删除旧版本内核 1.查看当前内核版本信息 #查看操作系统版本 cat /etc/redhat-release #查看系统内核 uname -r2.采用yum方式进行版本升级 2.1导…