pom.xml
@@ -19,18 +19,18 @@ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <mybatis.plus.version>3.3.1</mybatis.plus.version> <hutool.version>5.3.1</hutool.version> <swagger.ui>2.9.2</swagger.ui> <tomcat.version>9.0.31</tomcat.version> <hutool.version>5.3.1</hutool.version> </properties> <dependencies> <dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-all</artifactId> <version>${hutool.version}</version> </dependency> <!-- Spring系列 --> <dependency> <groupId>org.springframework.boot</groupId> src/main/java/cc/mrbird/febs/common/entity/DeptTree.java
@@ -28,7 +28,7 @@ private boolean hasParent = false; private boolean hasChild = false; private Dept data; private T data; public void initChildren(){ this.children = new ArrayList<>(); src/main/java/cc/mrbird/febs/video/controller/AdminVideoController.java
New file @@ -0,0 +1,70 @@ package cc.mrbird.febs.video.controller; import cc.mrbird.febs.common.annotation.ControllerEndpoint; import cc.mrbird.febs.common.entity.DeptTree; import cc.mrbird.febs.common.entity.FebsResponse; import cc.mrbird.febs.system.entity.Dept; import cc.mrbird.febs.video.entity.VideoCategoryEntity; import cc.mrbird.febs.video.service.IVideoCategoryService; import com.baomidou.mybatisplus.core.toolkit.StringPool; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.apache.shiro.authz.annotation.RequiresPermissions; import org.springframework.web.bind.annotation.*; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.StrUtil; import javax.validation.constraints.NotBlank; import java.util.Date; import java.util.List; /** * @author wzy * @date 2021-12-13 **/ @Slf4j @RestController @RequiredArgsConstructor @RequestMapping("video") public class AdminVideoController { private final IVideoCategoryService videoCategoryService; @GetMapping("/allCategory") public List<DeptTree<VideoCategoryEntity>> allCategory() { return this.videoCategoryService.findVideoCategory(); } @GetMapping("/categoryTree") @ControllerEndpoint(exceptionMessage = "获取视频分类失败") public FebsResponse categoryTree(VideoCategoryEntity category) { List<DeptTree<VideoCategoryEntity>> depts = this.videoCategoryService.categoryTree(category); return new FebsResponse().success().data(depts); } @PostMapping("/addCate") @RequiresPermissions("category:add") @ControllerEndpoint(operation = "新增分类", exceptionMessage = "新增分类失败") public FebsResponse addCate(VideoCategoryEntity category) { this.videoCategoryService.save(category); return new FebsResponse().success(); } @PostMapping("/updateCate") @RequiresPermissions("category:update") @ControllerEndpoint(operation = "修改分类", exceptionMessage = "修改分类失败") public FebsResponse updateCate(VideoCategoryEntity category) { category.setUpdatedTime(new Date()); this.videoCategoryService.updateById(category); return new FebsResponse().success(); } @GetMapping("/delCate/{cateIds}") @RequiresPermissions("category:update") @ControllerEndpoint(operation = "修改分类", exceptionMessage = "修改分类失败") public FebsResponse delCate(@NotBlank(message = "{required}") @PathVariable String cateIds) { List<String> ids = StrUtil.split(cateIds, ','); this.videoCategoryService.removeByIds(ids); return new FebsResponse().success(); } } src/main/java/cc/mrbird/febs/video/controller/ViewController.java
New file @@ -0,0 +1,20 @@ package cc.mrbird.febs.video.controller; import cc.mrbird.febs.common.entity.FebsConstant; import cc.mrbird.febs.common.utils.FebsUtil; import lombok.RequiredArgsConstructor; import org.apache.shiro.authz.annotation.RequiresPermissions; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; @Controller("videoView") @RequiredArgsConstructor public class ViewController { @GetMapping(FebsConstant.VIEW_PREFIX + "video/category") @RequiresPermissions("category:view") public String systemMenu() { return FebsUtil.view("video/video/category"); } } src/main/java/cc/mrbird/febs/video/entity/VideoCategoryEntity.java
@@ -11,4 +11,6 @@ private String name; private Long parentId; private Integer seq; } src/main/java/cc/mrbird/febs/video/mapper/VideoCategoryMapper.java
New file @@ -0,0 +1,11 @@ package cc.mrbird.febs.video.mapper; import cc.mrbird.febs.video.entity.VideoCategoryEntity; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import java.util.List; public interface VideoCategoryMapper extends BaseMapper<VideoCategoryEntity> { List<VideoCategoryEntity> selectAllCategory(); } src/main/java/cc/mrbird/febs/video/service/IVideoCategoryService.java
New file @@ -0,0 +1,14 @@ package cc.mrbird.febs.video.service; import cc.mrbird.febs.common.entity.DeptTree; import cc.mrbird.febs.video.entity.VideoCategoryEntity; import com.baomidou.mybatisplus.extension.service.IService; import java.util.List; public interface IVideoCategoryService extends IService<VideoCategoryEntity> { List<DeptTree<VideoCategoryEntity>> findVideoCategory(); List<DeptTree<VideoCategoryEntity>> categoryTree(VideoCategoryEntity category); } src/main/java/cc/mrbird/febs/video/service/impl/VideoCategoryServiceImpl.java
New file @@ -0,0 +1,60 @@ package cc.mrbird.febs.video.service.impl; import cc.mrbird.febs.common.entity.DeptTree; import cc.mrbird.febs.common.utils.TreeUtil; import cc.mrbird.febs.system.entity.Dept; import cc.mrbird.febs.video.entity.VideoCategoryEntity; import cc.mrbird.febs.video.mapper.VideoCategoryMapper; import cc.mrbird.febs.video.service.IVideoCategoryService; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.springframework.stereotype.Service; import java.util.ArrayList; import java.util.List; /** * @author wzy * @date 2021-12-14 **/ @Slf4j @Service @RequiredArgsConstructor public class VideoCategoryServiceImpl extends ServiceImpl<VideoCategoryMapper, VideoCategoryEntity> implements IVideoCategoryService { @Override public List<DeptTree<VideoCategoryEntity>> findVideoCategory() { List<VideoCategoryEntity> list = this.baseMapper.selectList(null); return convertTree(list); } @Override public List<DeptTree<VideoCategoryEntity>> categoryTree(VideoCategoryEntity category) { QueryWrapper<VideoCategoryEntity> queryWrapper = new QueryWrapper<>(); if (StringUtils.isNotBlank(category.getName())) { queryWrapper.lambda().eq(VideoCategoryEntity::getName, category.getName()); } queryWrapper.lambda().orderByAsc(VideoCategoryEntity::getSeq); List<VideoCategoryEntity> list = this.baseMapper.selectList(null); List<DeptTree<VideoCategoryEntity>> trees = convertTree(list); return TreeUtil.buildDeptTree(trees); } private List<DeptTree<VideoCategoryEntity>> convertTree(List<VideoCategoryEntity> list) { List<DeptTree<VideoCategoryEntity>> trees = new ArrayList<>(); list.forEach(category -> { DeptTree<VideoCategoryEntity> tree = new DeptTree<>(); tree.setId(String.valueOf(category.getId())); tree.setParentId(String.valueOf(category.getParentId())); tree.setName(category.getName()); tree.setData(category); trees.add(tree); }); return trees; } } src/main/resources/mapper/video/VideoCategoryMapper.xml
New file @@ -0,0 +1,8 @@ <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="cc.mrbird.febs.video.mapper.VideoCategoryMapper"> <select id="selectAllCategory" resultType="cc.mrbird.febs.video.entity.VideoCategoryEntity"> select * from video_category </select> </mapper> src/main/resources/templates/febs/views/video/test
src/main/resources/templates/febs/views/video/video/category.html
New file @@ -0,0 +1,237 @@ <div class="layui-fluid layui-anim febs-anim" id="febs-category" lay-title="视频分类管理"> <div class="layui-row layui-col-space8 febs-container"> <div class="layui-col-md6 layui-col-sm6 layui-col-xs12"> <div class="layui-card"> <div class="layui-card-body febs-table-full"> <form class="layui-form layui-table-form" lay-filter="dept-table-form" id="dept-table-form"> <div class="layui-row"> <div class="layui-col-md8 layui-col-sm9 layui-col-xs9"> <div class="layui-form-item"> <div class="layui-inline"> <label class="layui-form-label layui-form-label-sm">名称</label> <div class="layui-input-inline"> <input type="text" name="name" autocomplete="off" class="layui-input"> </div> </div> </div> </div> <div class="layui-col-md4 layui-col-sm12 layui-col-xs12 table-action-area"> <div class="layui-btn layui-btn-sm layui-btn-primary febs-button-blue-plain table-action" id="query"> <i class="layui-icon"></i> </div> <div class="layui-btn layui-btn-sm layui-btn-primary febs-button-green-plain table-action" id="reset"> <i class="layui-icon"></i> </div> <div class="layui-btn layui-btn-sm layui-btn-primary table-action action-more" shiro:hasAnyPermissions="category:add,category:del"> <i class="layui-icon"></i> </div> </div> </div> </form> <div class="dept-tree" lay-filter="cateTree" style="margin-left: 1rem"></div> </div> </div> </div> <div class="layui-col-md6 layui-col-sm6 layui-col-xs12"> <div class="layui-card"> <div class="layui-card-header" id="form-header">新增分类</div> <div class="layui-card-body febs-table-full"> <form class="layui-form layui-table-form" action="" lay-filter="cate-form"> <div class="layui-form-item febs-hide"> <label class="layui-form-label febs-form-item-require">ID:</label> <div class="layui-input-block"> <input type="text" name="id" class="layui-input"> </div> </div> <div class="layui-form-item"> <label class="layui-form-label">上级ID:</label> <div class="layui-input-block"> <input type="text" value="" name="parentId" readonly autocomplete="off" class="layui-input"> </div> </div> <div class="layui-form-item"> <label class="layui-form-label febs-form-item-require">分类名称:</label> <div class="layui-input-block"> <input type="text" name="name" autocomplete="off" class="layui-input" minlength="2" maxlength="10" lay-verify="range"> </div> </div> <div class="layui-form-item"> <label class="layui-form-label">分类排序:</label> <div class="layui-input-block"> <input type="text" name="seq" autocomplete="off" class="layui-input" lay-verify="number"> </div> </div> <button type="reset" class="layui-btn febs-hide" id="reset-form"></button> <button class="layui-btn febs-hide" lay-submit="" lay-filter="cate-form-submit" id="submit-form"></button> </form> </div> <div class="layui-card-footer"> <button class="layui-btn layui-btn-normal" id="submit">保存</button> </div> </div> </div> </div> </div> <script data-th-inline="javascript" type="text/javascript"> layui.use(['dropdown', 'jquery', 'validate', 'febs', 'form', 'eleTree'], function () { var $ = layui.jquery, febs = layui.febs, form = layui.form, validate = layui.validate, eleTree = layui.eleTree, dropdown = layui.dropdown, $view = $('#febs-category'), $query = $view.find('#query'), $reset = $view.find('#reset'), $submit = $view.find('#submit'), $header = $view.find('#form-header'), $searchForm = $view.find('#dept-table-form'), $name = $searchForm.find('input[name="name"]'), _currentDeptData, _cateTree; form.verify(validate); form.render(); renderCateTree(); eleTree.on("nodeClick(cateTree)", function (d) { $header.text('修改分类'); var data = d.data.currentData.data; _currentDeptData = data; form.val("cate-form", { "name": data.name, "seq": data.seq, "parentId": data.parentId, "id": data.id }); }); dropdown.render({ elem: $view.find('.action-more'), click: function (name, elem, event) { if (name === 'add') { reset(); var selected = _cateTree.getChecked(false, true); if (selected.length > 1) { febs.alert.warn('只能选择一个节点作为父级!'); return; } form.val("cate-form", { "parentId": selected[0] ? selected[0].id : '' }); } if (name === 'delete') { var checked = _cateTree.getChecked(false, true); if (checked.length < 1) { febs.alert.warn('请勾选需要删除的部门'); return; } var cateIds = []; layui.each(checked, function (key, item) { cateIds.push(item.id) }); febs.modal.confirm('提示', '当您点击确定按钮后,这些记录将会被彻底删除,如果其包含子记录,也将一并删除!', function () { febs.get(ctx + 'video/delCate/' + cateIds.join(','), null, function () { febs.alert.success('删除成功!'); reloadCateTree(); reset(); }) }); } }, options: [{ name: 'add', title: '新增分类', perms: 'category:add' }, { name: 'delete', title: '删除分类', perms: 'category:del' }] }); $view.on('click', '#submit', function () { $view.find('#submit-form').trigger('click'); }); $reset.on('click', function () { $name.val(''); reloadCateTree(); reset(); }); $query.on('click', function () { reloadCateTree(); }); function getQueryParams() { return { "name": $name.val().trim() } } function reset() { $header.text('新增分类'); $view.find('#reset-form').trigger('click'); } function renderCateTree() { _cateTree = eleTree.render({ elem: '.dept-tree', url: ctx + 'video/categoryTree', accordion: true, highlightCurrent: true, showCheckbox: true, checkStrictly: true, renderAfterExpand: false, where: { "name": $name.val().trim(), "invalidate_ie_cache": new Date() }, request: { name: 'name', key: "id", checked: "checked", data: 'data' }, response: { statusName: "code", statusCode: 200, dataName: "data" } }); return _cateTree; } function reloadCateTree() { _cateTree = renderCateTree(); } form.on('submit(cate-form-submit)', function (data) { if (data.field.id && $header.text().indexOf('修改') !== -1) { if (febs.nativeEqual(data.field, _currentDeptData)) { febs.alert.warn('数据未作任何修改!'); return false; } febs.post(ctx + 'video/updateCate', data.field, function () { febs.alert.success('修改成功'); reloadCateTree(); reset(); }) } else { febs.post(ctx + 'video/addCate', data.field, function () { febs.alert.success('新增成功'); reloadCateTree(); reset(); }) } return false; }); }); </script>