产品分类后台管理完成

main
王宇航 2024-07-31 17:31:06 +08:00
parent bc658a2a23
commit 17c55f93d4
18 changed files with 217 additions and 108 deletions

4
.gitignore vendored Normal file
View File

@ -0,0 +1,4 @@
logs
.idea
*.log
ZJ-javaimage

View File

@ -1,16 +1,14 @@
package com.wyh.admin.controller; package com.wyh.admin.controller.goods;
import com.alibaba.fastjson2.JSONArray;
import com.wyh.admin.aop.Log; import com.wyh.admin.aop.Log;
import com.wyh.admin.service.IGoodsCateService; import com.wyh.admin.service.IGoodsCateService;
import com.wyh.admin.validate.commons.IdValidate; import com.wyh.admin.validate.commons.IdValidate;
import com.wyh.admin.validate.GoodsCateCreateValidate; import com.wyh.admin.validate.GoodsCateCreateValidate;
import com.wyh.admin.validate.GoodsCateUpdateValidate; import com.wyh.admin.validate.GoodsCateUpdateValidate;
import com.wyh.admin.validate.GoodsCateSearchValidate; import com.wyh.admin.validate.GoodsCateSearchValidate;
import com.wyh.admin.validate.commons.PageValidate;
import com.wyh.admin.vo.GoodsCateListedVo;
import com.wyh.admin.vo.GoodsCateDetailVo; import com.wyh.admin.vo.GoodsCateDetailVo;
import com.wyh.common.core.AjaxResult; import com.wyh.common.core.AjaxResult;
import com.wyh.common.core.PageResult;
import com.wyh.common.validator.annotation.IDMust; import com.wyh.common.validator.annotation.IDMust;
import io.swagger.annotations.Api; import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiOperation;
@ -29,9 +27,8 @@ public class GoodsCateController {
@GetMapping("/list") @GetMapping("/list")
@ApiOperation(value="产品分类列表") @ApiOperation(value="产品分类列表")
public AjaxResult<PageResult<GoodsCateListedVo>> list(@Validated PageValidate pageValidate, public AjaxResult<JSONArray> list(@Validated GoodsCateSearchValidate searchValidate) {
@Validated GoodsCateSearchValidate searchValidate) { JSONArray list = iGoodsCateService.list(searchValidate);
PageResult<GoodsCateListedVo> list = iGoodsCateService.list(pageValidate, searchValidate);
return AjaxResult.success(list); return AjaxResult.success(list);
} }

View File

@ -1,12 +1,10 @@
package com.wyh.admin.service; package com.wyh.admin.service;
import com.wyh.admin.validate.commons.PageValidate; import com.alibaba.fastjson2.JSONArray;
import com.wyh.admin.validate.GoodsCateCreateValidate; import com.wyh.admin.validate.GoodsCateCreateValidate;
import com.wyh.admin.validate.GoodsCateUpdateValidate; import com.wyh.admin.validate.GoodsCateUpdateValidate;
import com.wyh.admin.validate.GoodsCateSearchValidate; import com.wyh.admin.validate.GoodsCateSearchValidate;
import com.wyh.admin.vo.GoodsCateListedVo;
import com.wyh.admin.vo.GoodsCateDetailVo; import com.wyh.admin.vo.GoodsCateDetailVo;
import com.wyh.common.core.PageResult;
/** /**
* *
@ -18,11 +16,10 @@ public interface IGoodsCateService {
* *
* *
* @author LikeAdmin * @author LikeAdmin
* @param pageValidate
* @param searchValidate * @param searchValidate
* @return PageResult<GoodsCateListedVo> * @return JSONArray
*/ */
PageResult<GoodsCateListedVo> list(PageValidate pageValidate, GoodsCateSearchValidate searchValidate); JSONArray list(GoodsCateSearchValidate searchValidate);
/** /**
* *

View File

@ -1,10 +1,8 @@
package com.wyh.admin.service.impl; package com.wyh.admin.service.impl;
import com.alibaba.fastjson2.JSONArray;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.yulichang.query.MPJQueryWrapper; import com.github.yulichang.query.MPJQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.wyh.admin.validate.commons.PageValidate;
import com.wyh.admin.service.IGoodsCateService; import com.wyh.admin.service.IGoodsCateService;
import com.wyh.admin.validate.GoodsCateCreateValidate; import com.wyh.admin.validate.GoodsCateCreateValidate;
import com.wyh.admin.validate.GoodsCateUpdateValidate; import com.wyh.admin.validate.GoodsCateUpdateValidate;
@ -12,7 +10,6 @@ import com.wyh.admin.validate.GoodsCateSearchValidate;
import com.wyh.admin.vo.GoodsCateListedVo; import com.wyh.admin.vo.GoodsCateListedVo;
import com.wyh.admin.vo.GoodsCateDetailVo; import com.wyh.admin.vo.GoodsCateDetailVo;
import com.wyh.common.config.GlobalConfig; import com.wyh.common.config.GlobalConfig;
import com.wyh.common.core.PageResult;
import com.wyh.common.entity.GoodsCate; import com.wyh.common.entity.GoodsCate;
import com.wyh.common.mapper.GoodsCateMapper; import com.wyh.common.mapper.GoodsCateMapper;
import com.wyh.common.util.ListUtils; import com.wyh.common.util.ListUtils;
@ -39,37 +36,35 @@ public class GoodsCateServiceImpl implements IGoodsCateService {
* *
* *
* @author LikeAdmin * @author LikeAdmin
* @param pageValidate
* @param searchValidate * @param searchValidate
* @return PageResult<GoodsCateListedVo> * @return JSONArray
*/ */
@Override @Override
public PageResult<GoodsCateListedVo> list(PageValidate pageValidate, GoodsCateSearchValidate searchValidate) { public JSONArray list(GoodsCateSearchValidate searchValidate) {
Integer page = pageValidate.getPageNo();
Integer limit = pageValidate.getPageSize();
QueryWrapper<GoodsCate> queryWrapper = new QueryWrapper<>(); MPJQueryWrapper<GoodsCate> mpjQueryWrapper = new MPJQueryWrapper<>();
queryWrapper.eq("is_delete", 0); mpjQueryWrapper.selectAll(GoodsCate.class);
queryWrapper.orderByDesc(Arrays.asList("sort", "id")); mpjQueryWrapper.eq("is_delete", 0);
mpjQueryWrapper.orderByDesc(Arrays.asList("sort", "id"));
goodsCateMapper.setSearch(queryWrapper, searchValidate, new String[]{ goodsCateMapper.setSearch(mpjQueryWrapper, searchValidate, new String[]{
"like:name:str", "like:name:str",
"=:pid:str",
"=:sort:str", "=:sort:str",
"=:status:long", "=:isShow@is_show:int",
}); });
IPage<GoodsCate> iPage = goodsCateMapper.selectPage(new Page<>(page, limit), queryWrapper); List<GoodsCateListedVo> array = goodsCateMapper.selectJoinList(
GoodsCateListedVo.class,
mpjQueryWrapper);
List<GoodsCateListedVo> list = new LinkedList<>(); for(GoodsCateListedVo item : array) {
for(GoodsCate item : iPage.getRecords()) { item.setCreateTime(TimeUtils.timestampToDate(item.getCreateTime()));
GoodsCateListedVo vo = new GoodsCateListedVo(); item.setUpdateTime(TimeUtils.timestampToDate(item.getUpdateTime()));
BeanUtils.copyProperties(item, vo);
vo.setCreateTime(TimeUtils.timestampToDate(item.getCreateTime()));
vo.setUpdateTime(TimeUtils.timestampToDate(item.getUpdateTime()));
list.add(vo);
} }
return PageResult.iPageHandle(iPage.getTotal(), iPage.getCurrent(), iPage.getSize(), list); JSONArray jsonArray = JSONArray.parseArray(JSONArray.toJSONString(array));
return ListUtils.listToTree(jsonArray, "id", "pid", "children");
} }
/** /**
@ -104,10 +99,11 @@ public class GoodsCateServiceImpl implements IGoodsCateService {
public void add(GoodsCateCreateValidate createValidate) { public void add(GoodsCateCreateValidate createValidate) {
GoodsCate model = new GoodsCate(); GoodsCate model = new GoodsCate();
model.setName(createValidate.getName()); model.setName(createValidate.getName());
model.setPid(createValidate.getPid());
model.setCreateTime(System.currentTimeMillis() / 1000); model.setCreateTime(System.currentTimeMillis() / 1000);
model.setUpdateTime(System.currentTimeMillis() / 1000); model.setUpdateTime(System.currentTimeMillis() / 1000);
model.setSort(createValidate.getSort()); model.setSort(createValidate.getSort());
model.setStatus(createValidate.getStatus()); model.setIsShow(createValidate.getIsShow());
goodsCateMapper.insert(model); goodsCateMapper.insert(model);
} }
@ -129,9 +125,10 @@ public class GoodsCateServiceImpl implements IGoodsCateService {
model.setId(updateValidate.getId()); model.setId(updateValidate.getId());
model.setName(updateValidate.getName()); model.setName(updateValidate.getName());
model.setPid(updateValidate.getPid());
model.setUpdateTime(System.currentTimeMillis() / 1000); model.setUpdateTime(System.currentTimeMillis() / 1000);
model.setSort(updateValidate.getSort()); model.setSort(updateValidate.getSort());
model.setStatus(updateValidate.getStatus()); model.setIsShow(updateValidate.getIsShow());
goodsCateMapper.updateById(model); goodsCateMapper.updateById(model);
} }

View File

@ -54,7 +54,7 @@ public class SettingDictDataServiceImpl implements ISettingDictDataService {
queryWrapper.select("id,type_id,name,value,remark,sort,status,create_time,update_time"); queryWrapper.select("id,type_id,name,value,remark,sort,status,create_time,update_time");
queryWrapper.eq("is_delete", 0); queryWrapper.eq("is_delete", 0);
queryWrapper.eq("type_id", dictType.getId()); queryWrapper.eq("type_id", dictType.getId());
queryWrapper.orderByDesc("id"); queryWrapper.orderByDesc("sort").orderByDesc("id");
dictDataMapper.setSearch(queryWrapper, params, new String[]{ dictDataMapper.setSearch(queryWrapper, params, new String[]{
"like:name:str", "like:name:str",
@ -101,7 +101,8 @@ public class SettingDictDataServiceImpl implements ISettingDictDataService {
queryWrapper.select("id,type_id,name,value,remark,sort,status,create_time,update_time"); queryWrapper.select("id,type_id,name,value,remark,sort,status,create_time,update_time");
queryWrapper.eq("type_id", dictType.getId()); queryWrapper.eq("type_id", dictType.getId());
queryWrapper.eq("is_delete", 0); queryWrapper.eq("is_delete", 0);
queryWrapper.orderByDesc("id"); queryWrapper.orderByDesc("sort").orderByDesc("id");
dictDataMapper.setSearch(queryWrapper, params, new String[]{ dictDataMapper.setSearch(queryWrapper, params, new String[]{
"like:name:str", "like:name:str",

View File

@ -16,12 +16,16 @@ public class GoodsCateCreateValidate implements Serializable {
@ApiModelProperty(value = "产品分类名称") @ApiModelProperty(value = "产品分类名称")
private String name; private String name;
@NotNull(message = "pid参数缺失")
@ApiModelProperty(value = "上级菜单")
private String pid;
@NotNull(message = "sort参数缺失") @NotNull(message = "sort参数缺失")
@ApiModelProperty(value = "排序编号") @ApiModelProperty(value = "排序编号")
private String sort; private String sort;
@NotNull(message = "status参数缺失") @NotNull(message = "isShow参数缺失")
@ApiModelProperty(value = "是否禁用: 0=否, 1=是") @ApiModelProperty(value = "是否显示: 0=否, 1=是")
private Long status; private String isShow;
} }

View File

@ -14,10 +14,13 @@ public class GoodsCateSearchValidate implements Serializable {
@ApiModelProperty(value = "产品分类名称") @ApiModelProperty(value = "产品分类名称")
private String name; private String name;
@ApiModelProperty(value = "上级菜单")
private String pid;
@ApiModelProperty(value = "排序编号") @ApiModelProperty(value = "排序编号")
private String sort; private String sort;
@ApiModelProperty(value = "是否禁用: 0=否, 1=是") @ApiModelProperty(value = "是否显示: 0=否, 1=是")
private Long status; private String isShow;
} }

View File

@ -25,12 +25,16 @@ public class GoodsCateUpdateValidate implements Serializable {
@ApiModelProperty(value = "产品分类名称") @ApiModelProperty(value = "产品分类名称")
private String name; private String name;
@NotNull(message = "pid参数缺失")
@ApiModelProperty(value = "上级菜单")
private String pid;
@NotNull(message = "sort参数缺失") @NotNull(message = "sort参数缺失")
@ApiModelProperty(value = "排序编号") @ApiModelProperty(value = "排序编号")
private String sort; private String sort;
@NotNull(message = "status参数缺失") @NotNull(message = "isShow参数缺失")
@ApiModelProperty(value = "是否禁用: 0=否, 1=是") @ApiModelProperty(value = "是否显示: 0=否, 1=是")
private Long status; private String isShow;
} }

View File

@ -18,11 +18,14 @@ public class GoodsCateDetailVo implements Serializable {
@ApiModelProperty(value = "产品分类名称") @ApiModelProperty(value = "产品分类名称")
private String name; private String name;
@ApiModelProperty(value = "上级菜单")
private String pid;
@ApiModelProperty(value = "排序编号") @ApiModelProperty(value = "排序编号")
private String sort; private String sort;
@ApiModelProperty(value = "是否禁用: 0=否, 1=是") @ApiModelProperty(value = "是否显示: 0=否, 1=是")
private Long status; private String isShow;
} }

View File

@ -18,6 +18,9 @@ public class GoodsCateListedVo implements Serializable {
@ApiModelProperty(value = "产品分类名称") @ApiModelProperty(value = "产品分类名称")
private String name; private String name;
@ApiModelProperty(value = "上级菜单")
private String pid;
@ApiModelProperty(value = "创建时间") @ApiModelProperty(value = "创建时间")
private String createTime; private String createTime;
@ -27,8 +30,8 @@ public class GoodsCateListedVo implements Serializable {
@ApiModelProperty(value = "排序编号") @ApiModelProperty(value = "排序编号")
private String sort; private String sort;
@ApiModelProperty(value = "是否禁用: 0=否, 1=是") @ApiModelProperty(value = "是否显示: 0=否, 1=是")
private Long status; private String isShow;
} }

View File

@ -21,6 +21,9 @@ public class GoodsCate implements Serializable {
@ApiModelProperty(value = "产品分类名称") @ApiModelProperty(value = "产品分类名称")
private String name; private String name;
@ApiModelProperty(value = "上级菜单")
private String pid;
@ApiModelProperty(value = "是否删除: 0=否, 1=是") @ApiModelProperty(value = "是否删除: 0=否, 1=是")
private Integer isDelete; private Integer isDelete;
@ -36,7 +39,7 @@ public class GoodsCate implements Serializable {
@ApiModelProperty(value = "排序编号") @ApiModelProperty(value = "排序编号")
private String sort; private String sort;
@ApiModelProperty(value = "是否禁用: 0=否, 1=是") @ApiModelProperty(value = "是否显示: 0=否, 1=是")
private Long status; private String isShow;
} }

View File

@ -18,8 +18,8 @@ public class SwaggerConfig {
@Value("${ZJ-java.knife4j.swagger-ui.enabled}") @Value("${ZJ-java.knife4j.swagger-ui.enabled}")
private boolean enabled; private boolean enabled;
@Value("${ZJ-java.knife4j.swagger-ui.path}") // @Value("${ZJ-java.knife4j.swagger-ui.path}")
private String pathMapping; // private String pathMapping;
@Bean @Bean
public Docket createRestApi(){ public Docket createRestApi(){
@ -29,8 +29,7 @@ public class SwaggerConfig {
.select() .select()
.apis(RequestHandlerSelectors.basePackage("com.wyh.front")) .apis(RequestHandlerSelectors.basePackage("com.wyh.front"))
.build() .build()
.groupName("中将业务接口【前台】") .groupName("中将业务接口【前台】");
.pathMapping(pathMapping);
} }
private ApiInfo apiInfo(){ private ApiInfo apiInfo(){
@ -45,5 +44,4 @@ public class SwaggerConfig {
.contact(new Contact(author, url, email)) .contact(new Contact(author, url, email))
.build(); .build();
} }
} }

View File

@ -5,11 +5,13 @@ import com.wyh.common.core.AjaxResult;
import com.wyh.front.service.IWechatService; import com.wyh.front.service.IWechatService;
import io.swagger.annotations.Api; import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiOperation;
import org.checkerframework.checker.units.qual.A;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import springfox.documentation.annotations.ApiIgnore;
import javax.annotation.Resource; import javax.annotation.Resource;
import javax.validation.constraints.NotEmpty; import javax.validation.constraints.NotEmpty;
@ -18,6 +20,7 @@ import java.util.Map;
@RestController @RestController
@RequestMapping("api/wechat") @RequestMapping("api/wechat")
@Api(tags = "微信管理") @Api(tags = "微信管理")
@ApiIgnore
public class WechatController { public class WechatController {
@Resource @Resource

View File

@ -12,7 +12,7 @@ ZJ-java:
knife4j: knife4j:
swagger-ui: swagger-ui:
enabled: true enabled: true
path: /doc.html # path: /doc.html
# 服务配置 # 服务配置
server: server:

3
admin/.vscode/extensions.json vendored Normal file
View File

@ -0,0 +1,3 @@
{
"recommendations": ["Vue.volar", "Vue.vscode-typescript-vue-plugin"]
}

11
admin/.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,11 @@
{
"editor.detectIndentation": false,
"editor.tabSize": 4,
"editor.formatOnSave": true,
"editor.codeActionsOnSave": {
"source.fixAll.eslint": "explicit"
},
"css.validate": false,
"less.validate": false,
"scss.validate": false
}

View File

@ -10,17 +10,31 @@
@close="handleClose" @close="handleClose"
> >
<el-form ref="formRef" :model="formData" label-width="110px" :rules="formRules"> <el-form ref="formRef" :model="formData" label-width="110px" :rules="formRules">
<el-form-item label="上级菜单" prop="pid">
<el-tree-select
class="flex-1"
v-model="formData.pid"
:data="treeList"
clearable
node-key="id"
:props="{ label: 'name', value: 'id', children: 'children' }"
:default-expand-all="true"
placeholder="请选择上级菜单"
check-strictly
/>
</el-form-item>
<el-form-item label="产品分类名称" prop="name"> <el-form-item label="产品分类名称" prop="name">
<el-input v-model="formData.name" placeholder="请输入产品分类名称" /> <el-input v-model="formData.name" placeholder="请输入产品分类名称" />
</el-form-item> </el-form-item>
<el-form-item label="产品分类排序" prop="menuSort"> <el-form-item label="菜单排序" prop="menuSort">
<div> <div>
<el-input-number v-model="formData.sort" :max="9999" /> <el-input-number v-model="formData.sort" :max="9999" />
<div class="form-tips">数值越大越排前</div> <div class="form-tips">数值越大越排前</div>
</div> </div>
</el-form-item> </el-form-item>
<el-form-item label="是否禁用" prop="status"> <el-form-item label="是否显示" prop="status">
<el-radio-group v-model="formData.status" placeholder="请选择是否禁用"> <el-radio-group v-model="formData.isShow" placeholder="请选择是否显示">
<el-radio <el-radio
v-for="(item, index) in dictData.Boolean" v-for="(item, index) in dictData.Boolean"
:key="index" :key="index"
@ -37,7 +51,7 @@
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import type { FormInstance } from 'element-plus' import type { FormInstance } from 'element-plus'
import { cateEdit, cateAdd, cateDetail } from '@/api/cate' import { cateLists, cateEdit, cateAdd, cateDetail } from '@/api/cate'
import Popup from '@/components/popup/index.vue' import Popup from '@/components/popup/index.vue'
import feedback from '@/utils/feedback' import feedback from '@/utils/feedback'
import type { PropType } from 'vue' import type { PropType } from 'vue'
@ -50,6 +64,7 @@ defineProps({
const emit = defineEmits(['success', 'close']) const emit = defineEmits(['success', 'close'])
const formRef = shallowRef<FormInstance>() const formRef = shallowRef<FormInstance>()
const popupRef = shallowRef<InstanceType<typeof Popup>>() const popupRef = shallowRef<InstanceType<typeof Popup>>()
const treeList = ref<any[]>([])
const mode = ref('add') const mode = ref('add')
const popupTitle = computed(() => { const popupTitle = computed(() => {
return mode.value == 'edit' ? '编辑产品分类' : '新增产品分类' return mode.value == 'edit' ? '编辑产品分类' : '新增产品分类'
@ -58,8 +73,9 @@ const popupTitle = computed(() => {
const formData = reactive({ const formData = reactive({
id: '', id: '',
name: '', name: '',
pid: '',
sort: '', sort: '',
status: '', isShow: '',
}) })
const formRules = { const formRules = {
@ -77,6 +93,13 @@ const formRules = {
trigger: ['blur'] trigger: ['blur']
} }
], ],
pid: [
{
required: true,
message: '请输入上级菜单',
trigger: ['blur']
}
],
sort: [ sort: [
{ {
required: true, required: true,
@ -84,10 +107,10 @@ const formRules = {
trigger: ['blur'] trigger: ['blur']
} }
], ],
status: [ isShow: [
{ {
required: true, required: true,
message: '请选择是否禁用: 0=否, 1=是', message: '请输入是否显示: 0=否, 1=是',
trigger: ['blur'] trigger: ['blur']
} }
], ],
@ -127,6 +150,15 @@ const handleClose = () => {
emit('close') emit('close')
} }
const getLists = async () => {
const data: any = await cateLists()
const item = { id: 0, name: '顶级', children: [] }
item.children = data
treeList.value.push(item)
}
getLists()
defineExpose({ defineExpose({
open, open,
setFormData, setFormData,

View File

@ -1,13 +1,13 @@
<template> <template>
<div class="index-lists"> <div class="index-tree">
<el-card class="!border-none" shadow="never"> <el-card class="!border-none mb-4" shadow="never">
<el-form ref="formRef" class="mb-[-16px]" :model="queryParams" :inline="true"> <el-form ref="formRef" class="mb-[-16px]" :model="queryParams" :inline="true">
<el-form-item label="产品分类名称" prop="name"> <el-form-item label="产品分类名称" prop="name">
<el-input class="w-[280px]" v-model="queryParams.name" /> <el-input class="w-[280px]" v-model="queryParams.name" />
</el-form-item> </el-form-item>
<el-form-item label="是否禁用" prop="status"> <el-form-item label="是否显示" prop="status">
<el-select <el-select
v-model="queryParams.status" v-model="queryParams.isShow"
class="w-[280px]" class="w-[280px]"
clearable clearable
> >
@ -21,12 +21,12 @@
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
<el-button type="primary" @click="resetPage"></el-button> <el-button type="primary" @click="getLists"></el-button>
<el-button @click="resetParams"></el-button> <el-button @click="resetParams"></el-button>
</el-form-item> </el-form-item>
</el-form> </el-form>
</el-card> </el-card>
<el-card class="!border-none mt-4" shadow="never"> <el-card class="!border-none" shadow="never">
<div> <div>
<el-button v-perms="['cate:add']" type="primary" @click="handleAdd()"> <el-button v-perms="['cate:add']" type="primary" @click="handleAdd()">
<template #icon> <template #icon>
@ -34,27 +34,38 @@
</template> </template>
新增 新增
</el-button> </el-button>
<el-button @click="handleExpand"> / </el-button>
</div> </div>
<el-table <el-table
v-loading="loading"
ref="tableRef"
class="mt-4" class="mt-4"
size="large" size="large"
v-loading="pager.loading" :data="lists"
:data="pager.lists" row-key="id"
:tree-props="{ children: 'children', hasChildren: 'hasChildren' }"
> >
<el-table-column label="产品分类名称" prop="name" min-width="100" /> <el-table-column label="产品分类名称" prop="name" min-width="100" />
<el-table-column label="排序编号" prop="sort" min-width="100" /> <el-table-column label="上级菜单" prop="pid" min-width="100" />
<el-table-column label="是否禁用" prop="status" min-width="100">
<template #default="{ row }">
<dict-value :options="dictData.Boolean" :value="row.status" />
</template>
</el-table-column>
<el-table-column label="创建时间" prop="createTime" min-width="100" /> <el-table-column label="创建时间" prop="createTime" min-width="100" />
<el-table-column label="更新时间" prop="updateTime" min-width="100" /> <el-table-column label="更新时间" prop="updateTime" min-width="100" />
<el-table-column label="排序编号" prop="sort" min-width="100" />
<el-table-column label="是否显示" prop="isShow" min-width="100">
<el-table-column label="操作" width="120" fixed="right">
<template #default="{ row }"> <template #default="{ row }">
<dict-value :options="dictData.Boolean" :value="row.isShow" />
</template>
</el-table-column>
<el-table-column label="操作" width="160" fixed="right">
<template #default="{ row }">
<el-button
v-perms="['cate:add']"
type="primary"
link
@click="handleAdd(row.id)"
>
新增
</el-button>
<el-button <el-button
v-perms="['cate:edit']" v-perms="['cate:edit']"
type="primary" type="primary"
@ -74,9 +85,6 @@
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
<div class="flex justify-end mt-4">
<pagination v-model="pager" @change="getLists" />
</div>
</el-card> </el-card>
<edit-popup <edit-popup
v-if="showEdit" v-if="showEdit"
@ -90,30 +98,54 @@
<script lang="ts" setup name="cate"> <script lang="ts" setup name="cate">
import { cateDelete, cateLists } from '@/api/cate' import { cateDelete, cateLists } from '@/api/cate'
import { useDictData } from '@/hooks/useDictOptions' import { useDictData } from '@/hooks/useDictOptions'
import { usePaging } from '@/hooks/usePaging'
import feedback from '@/utils/feedback'
import EditPopup from './edit.vue' import EditPopup from './edit.vue'
import feedback from '@/utils/feedback'
import type { ElTable, FormInstance } from 'element-plus'
const tableRef = shallowRef<InstanceType<typeof ElTable>>()
const editRef = shallowRef<InstanceType<typeof EditPopup>>() const editRef = shallowRef<InstanceType<typeof EditPopup>>()
const formRef = shallowRef<FormInstance>()
let isExpand = false
const showEdit = ref(false) const showEdit = ref(false)
const loading = ref(false)
const lists = ref<any[]>([])
const queryParams = reactive({ const queryParams = reactive({
name: '', name: '',
pid: '',
sort: '', sort: '',
status: '', isShow: '',
}) })
const { pager, getLists, resetPage, resetParams } = usePaging({
fetchFun: cateLists,
params: queryParams
})
const { dictData } = useDictData<{ const { dictData } = useDictData<{
Boolean: any[] Boolean: any[]
}>(['Boolean']) }>(['Boolean'])
const getLists = async () => {
loading.value = true
try {
const data = await cateLists(queryParams)
lists.value = data
loading.value = false
} catch (error) {
loading.value = false
}
}
const resetParams = () => {
formRef.value?.resetFields()
getLists()
}
const handleAdd = async () => {
const handleAdd = async (id?: number) => {
showEdit.value = true showEdit.value = true
await nextTick() await nextTick()
if (id) {
editRef.value?.setFormData({
pid: id
})
}
editRef.value?.open('add') editRef.value?.open('add')
} }
@ -131,5 +163,19 @@ const handleDelete = async (id: number) => {
getLists() getLists()
} }
const handleExpand = () => {
isExpand = !isExpand
toggleExpand(lists.value, isExpand)
}
const toggleExpand = (children: any[], unfold = true) => {
for (const key in children) {
tableRef.value?.toggleRowExpansion(children[key], unfold)
if (children[key].children) {
toggleExpand(children[key].children!, unfold)
}
}
}
getLists() getLists()
</script> </script>