完成导航管理及统一异常处理

master
barney 2 years ago
parent 55667fe45c
commit 377d9214e3
  1. 20
      src/main/java/cc/bnblogs/config/ExceptionConfig.java
  2. 6
      src/main/java/cc/bnblogs/controller/AdminController.java
  3. 5
      src/main/java/cc/bnblogs/controller/BannerController.java
  4. 7
      src/main/java/cc/bnblogs/controller/CategoryController.java
  5. 83
      src/main/java/cc/bnblogs/controller/NavigationController.java
  6. 2
      src/main/java/cc/bnblogs/mapper/BannerMapper.java
  7. 24
      src/main/java/cc/bnblogs/mapper/NavigationMapper.java
  8. 37
      src/main/java/cc/bnblogs/pojo/Navigation.java
  9. 2
      src/main/java/cc/bnblogs/service/ArticleService.java
  10. 1
      src/main/java/cc/bnblogs/service/CategoryService.java
  11. 72
      src/main/java/cc/bnblogs/service/NavigationService.java
  12. 4
      src/main/resources/templates/admin/banner.html
  13. 2
      src/main/resources/templates/admin/common.html
  14. 276
      src/main/resources/templates/admin/navigation.html

@ -0,0 +1,20 @@
package cc.bnblogs.config;
import cc.bnblogs.common.Result;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
/**
* @author zfp@bnblogs.cc
* @createTime: 2022/10/19
*/
@ControllerAdvice
public class ExceptionConfig {
@ResponseBody
@ExceptionHandler(Exception.class)
public Result<String> defaultException() {
return Result.error();
}
}

@ -4,7 +4,6 @@ import cc.bnblogs.pojo.Article;
import cc.bnblogs.pojo.Category; import cc.bnblogs.pojo.Category;
import cc.bnblogs.service.ArticleService; import cc.bnblogs.service.ArticleService;
import cc.bnblogs.service.CategoryService; import cc.bnblogs.service.CategoryService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;
import org.springframework.ui.Model; import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
@ -61,6 +60,11 @@ public class AdminController {
return "admin/comment"; return "admin/comment";
} }
@GetMapping("/navigation.html")
public String navigation() {
return "admin/navigation";
}
// 打开编辑文章界面可以带一个id参数 // 打开编辑文章界面可以带一个id参数
@GetMapping("/write.html") @GetMapping("/write.html")
public String write(@RequestParam(required = false)Integer id, Model model) { public String write(@RequestParam(required = false)Integer id, Model model) {

@ -73,6 +73,11 @@ public class BannerController {
return Result.success(); return Result.success();
} }
/**
* 对轮播图排序
* @param ids 编码后的轮播图的id和顺序值:id----ordered;
* @return 重新排序后的轮播图
*/
@PostMapping("/order") @PostMapping("/order")
public Result<String> ordered(String ids) { public Result<String> ordered(String ids) {
Arrays.stream(ids.split(";")).map(x -> x.split("----")). Arrays.stream(ids.split(";")).map(x -> x.split("----")).

@ -67,11 +67,4 @@ public class CategoryController {
categoryService.delete(id); categoryService.delete(id);
return Result.success(); return Result.success();
} }
} }

@ -0,0 +1,83 @@
package cc.bnblogs.controller;
import cc.bnblogs.common.Result;
import cc.bnblogs.enums.ResultEnum;
import cc.bnblogs.pojo.Navigation;
import cc.bnblogs.service.NavigationService;
import org.springframework.web.bind.annotation.*;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
/**
* @author zfp@bnblogs.cc
* @createTime: 2022/10/19
*/
@RestController
@RequestMapping("/admin/navigation")
public class NavigationController {
private final NavigationService navigationService;
public NavigationController(NavigationService navigationService) {
this.navigationService = navigationService;
}
/**
* 请求所有导航条的接口
* @return 返回所有导航条
*/
@GetMapping("/")
public Result<List<Navigation>> list() {
return Result.success(navigationService.list());
}
/**
* 请求导航条详情的接口
* @param id 导航条id
* @return 返回导航条的详情
*/
@GetMapping("/{id}")
public Result<Navigation> detail(@PathVariable Integer id) {
Navigation navigation = navigationService.detail(id);
if (Objects.isNull(navigation)) {
return Result.error(ResultEnum.RESULT_NOT_FOUND);
} else {
return Result.success(navigation);
}
}
/**
* 保存修改后的导航条数据
* @param navigation 修改的导航条
* @return 修改结果
*/
@PostMapping("/")
public Result<String> save(Navigation navigation) {
navigationService.save(navigation);
return Result.success();
}
/**
* 删除一个导航条
* @param id 删除的导航条id
* @return 删除结果
*/
@DeleteMapping("/{id}")
public Result<String> delete(@PathVariable Integer id) {
navigationService.delete(id);
return Result.success();
}
/**
* 对导航条排序
* @param ids 编码后的导航条的id和顺序值:id----ordered;
* @return 排序后的导航条
*/
@PostMapping("/order")
public Result<String> ordered(String ids) {
Arrays.stream(ids.split(";")).map(x -> x.split("----")).
forEach(x -> navigationService.order(Integer.parseInt(x[0]), Integer.parseInt(x[1])));
return Result.success();
}
}

@ -17,7 +17,7 @@ public interface BannerMapper extends JpaRepository<Banner,Integer> {
* @param id 轮播图id * @param id 轮播图id
* @param ordered 更新后的轮播图顺序值 * @param ordered 更新后的轮播图顺序值
*/ */
@Transactional @Transactional(rollbackOn = {Exception.class})
@Modifying @Modifying
@Query("update Banner set ordered = ?2 where id = ?1") @Query("update Banner set ordered = ?2 where id = ?1")
void ordered(Integer id, Integer ordered); void ordered(Integer id, Integer ordered);

@ -0,0 +1,24 @@
package cc.bnblogs.mapper;
import cc.bnblogs.pojo.Navigation;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import javax.transaction.Transactional;
/**
* @author zfp@bnblogs.cc
* @createTime: 2022/10/19
*/
public interface NavigationMapper extends JpaRepository<Navigation,Integer> {
/**
* 更新对应id的导航栏的顺序值
* @param id 导航栏id
* @param ordered 更新后的导航栏顺序值
*/
@Transactional(rollbackOn = {Exception.class})
@Modifying
@Query("update Navigation set ordered = ?2 where id = ?1")
void ordered(Integer id, Integer ordered);
}

@ -0,0 +1,37 @@
package cc.bnblogs.pojo;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.persistence.*;
/**
* @author zfp@bnblogs.cc
* @createTime: 2022/10/19
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
@Entity
@Table(name = "blog_navigation")
public class Navigation {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
@Column(unique = true)
// 名称
private String name;
// 图标
private String icon;
// 跳转链接
private String link;
// true: 新标签页打开 false: 当前页打开
private Boolean linkMode;
// 是否启用
private Boolean enable;
// 顺序
private Integer ordered;
}

@ -67,7 +67,7 @@ public class ArticleService {
* 保存文章 * 保存文章
* @param article 待保存的文章对象 * @param article 待保存的文章对象
*/ */
@Transactional @Transactional(rollbackFor = {Exception.class})
public void save(Article article) { public void save(Article article) {
// 修改更新时间 // 修改更新时间
article.setUpdated(new Date()); article.setUpdated(new Date());

@ -49,6 +49,7 @@ public class CategoryService {
* @param category 待保存的分类对象 * @param category 待保存的分类对象
*/ */
public void save(Category category) { public void save(Category category) {
System.out.println(category);
categoryMapper.save(category); categoryMapper.save(category);
} }

@ -0,0 +1,72 @@
package cc.bnblogs.service;
import cc.bnblogs.mapper.NavigationMapper;
import cc.bnblogs.pojo.Navigation;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* @author zfp@bnblogs.cc
* @createTime: 2022/10/19
*/
@Service
public class NavigationService {
private final NavigationMapper navigationMapper;
public NavigationService(NavigationMapper navigationMapper) {
this.navigationMapper = navigationMapper;
}
/**
* 获取所有导航条
* @return 导航条列表
*/
public List<Navigation> list() {
return navigationMapper.findAll(Sort.by(Sort.Direction.ASC,"ordered"));
}
/**
* 获取导航条总数
* @return 导航条总数
*/
public long count() {
return navigationMapper.count();
}
/**
* 根据id查询导航条对象
* @param id 导航条id
* @return id对应的导航条对象
*/
public Navigation detail(Integer id) {
return navigationMapper.findById(id).orElse(null);
}
/**
* 保存导航条
* @param navigation 待保存的导航条对象
*/
public void save(Navigation navigation) {
navigationMapper.save(navigation);
}
/**
* 根据id删除导航条对象
* @param id 待删除导航条的id
*/
public void delete(Integer id) {
navigationMapper.deleteById(id);
}
/**
* 对导航条进行排序
* @param id 导航条id
* @param ordered 导航条顺序值
*/
public void order(Integer id, Integer ordered) {
navigationMapper.ordered(id,ordered);
}
}

@ -58,7 +58,7 @@
<div class="form-group"> <div class="form-group">
<label>顺序</label> <label>顺序</label>
<input type="number" name="ordered" class="form-control" <input type="number" name="ordered" class="form-control" min="0"
placeholder="请输入顺序..."> placeholder="请输入顺序...">
</div> </div>
@ -120,7 +120,7 @@
align: "center", align: "center",
field: "ordered", field: "ordered",
formatter: (value, row) => { formatter: (value, row) => {
return `<input class="form-control sortedBySave" style="width: 60px" type="number" return `<input class="form-control sortedBySave" style="width: 60px" type="number" min="0"
data-id="${row.id}" value="${value}">` data-id="${row.id}" value="${value}">`
} }
}, },

@ -41,9 +41,9 @@
<li th:class="${active eq 'article'} ? 'active': ''"><a th:href="@{/admin/article.html}">文章管理</a></li> <li th:class="${active eq 'article'} ? 'active': ''"><a th:href="@{/admin/article.html}">文章管理</a></li>
<li th:class="${active eq 'category'} ? 'active': ''"><a th:href="@{/admin/category.html}">分类管理</a></li> <li th:class="${active eq 'category'} ? 'active': ''"><a th:href="@{/admin/category.html}">分类管理</a></li>
<li th:class="${active eq 'banner'} ? 'active': ''"><a th:href="@{/admin/banner.html}">轮播图管理</a></li> <li th:class="${active eq 'banner'} ? 'active': ''"><a th:href="@{/admin/banner.html}">轮播图管理</a></li>
<li><a href="#">页面管理</a></li>
<li th:class="${active eq 'friends'} ? 'active': ''"><a th:href="@{/admin/friends.html}">友链管理</a></li> <li th:class="${active eq 'friends'} ? 'active': ''"><a th:href="@{/admin/friends.html}">友链管理</a></li>
<li th:class="${active eq 'comment'} ? 'active': ''"><a th:href="@{/admin/comment.html}">评论管理</a></li> <li th:class="${active eq 'comment'} ? 'active': ''"><a th:href="@{/admin/comment.html}">评论管理</a></li>
<li th:class="${active eq 'navigation'} ? 'active': ''"><a th:href="@{/admin/navigation.html}">导航管理</a></li>
</ul> </ul>
<ul class="nav navbar-nav navbar-right"> <ul class="nav navbar-nav navbar-right">
<li><a href="#">退出登录</a></li> <li><a href="#">退出登录</a></li>

@ -0,0 +1,276 @@
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org" lang="en">
<head th:replace="admin/common::header(~{::title},~{},~{})">
<title>导航管理</title>
</head>
<body>
<th:block th:include="admin/common::nav('navigation')"></th:block>
<div class="container lw-main lw-banner">
<div class="btn-group" role="group" style="margin-bottom: 20px" aria-label="...">
<button type="button" id="create-navigation-btn" class="btn btn-default"><i class="fa fa-plus"></i>
新增
</button>
<button type="button" id="refresh-ordered-btn" class="btn btn-default"><i class="fa fa-refresh"></i>
保存顺序
</button>
</div>
<table id="data-table" style="user-select: none"></table>
</div>
<!-- 编辑窗口 -->
<div class="modal fade" id="save-window" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
<div class="modal-dialog" role="document">
<div class="modal-content">
<form id="data-form">
<input type="hidden" name="id">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span
aria-hidden="true">&times;</span></button>
<h4 class="modal-title" id="window-title">Modal Title</h4>
</div>
<div class="modal-body">
<div class="form-group">
<label>名称</label>
<input type="text" name="name" required class="form-control"
placeholder="请输入名称...">
</div>
<div class="form-group">
<label>图标</label>
<input type="text" name="icon" class="form-control"
placeholder="请输入图标...">
</div>
<div class="form-group">
<label>跳转链接</label>
<input type="url" name="link" required class="form-control"
placeholder="请输入跳转链接...">
</div>
<div class="form-group">
<label>顺序</label>
<input type="number" min="0" name="ordered" required class="form-control" placeholder="请输入顺序...">
</div>
<div class="form-group">
<label>打开方式</label>
<select required name="linkMode" class="form-control">
<option value="true">在新页面打开</option>
<option value="false">在当前页打开</option>
</select>
</div>
<div class="form-group">
<label>是否启用</label>
<select required name="enable" class="form-control">
<option value="true">启用</option>
<option value="false">禁止</option>
</select>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">关闭</button>
<button type="submit" class="btn btn-primary">保存</button>
</div>
</form>
</div>
</div>
</div>
<th:block th:include="admin/common::footer"></th:block>
<script>
$(function () {
// 显示表单所有导航条数据
$('#data-table').bootstrapTable({
url: "/admin/navigation/",
responseHandler: function (res) {
return res.data
},
columns: [
{
title: "序号",
width: 50,
align: 'center',
// 生成自增的序号
formatter: function (value, row, index) {
return index + 1
}
},
{
title: "名称",
align: 'center',
field: "name",
formatter: function (value, row) {
return `<a href="${row.link}" target="_blank">${value}</a>`
}
},
{
title: "图标",
align: 'center',
width: 20,
field: "icon",
formatter: value => {
return `<i class="fa fa-${value}"></i>`
}
},
{
title: '顺序',
width: 40,
align: 'center',
field: 'ordered',
formatter: function (value, row) {
return `<input class="form-control sortedBySave" style="width: 60px" type="number" min="0"
data-id="${row.id}" value="${value}">`
}
},
{
title: "跳转方式",
field: "linkMode",
align: 'center',
formatter: value => {
return value ? '新页面打开' : '当前页面打开';
}
},
{
title: "是否启用",
field: "enable",
align: 'center',
formatter: function (value) {
return value ? `<i class="fa fa-check"></i>` : `<i class="fa fa-close"></i>`
}
},
{
field: "id",
title: '操作',
align: "center",
width: 180,
formatter: function (value) {
return `<button type="button" data-id="${value}" class="btn btn-info btn-sm navigation-edit-btn" style="margin-right: 10px"><i class="fa fa-edit"></i> 编辑</button><button type="button" data-id="${value}" class="btn btn-danger btn-sm navigation-delete-btn"><i class="fa fa-trash"></i> 删除</button>`
}
}
]
})
// 编辑对应导航条
$("#data-table").on("click", ".navigation-edit-btn", function () {
let id = $(this).data("id")
$.ajax({
url: "/admin/navigation/" + id,
method: 'GET',
dataType: 'json',
success: res => {
if (res.code === 200) {
res.data['linkMode'] = res.data['linkMode'] + ""
res.data['enable'] = res.data['enable'] + ""
$("#window-title").text('编辑导航条')
$("#data-form").initForm(res.data)
$('#save-window').modal('show')
} else {
layer.msg(res.message, {icon: 2})
}
}
})
})
// 新增导航条
$("#create-navigation-btn").on("click", function () {
$("#window-title").text('新增导航条')
// 清空之前表单的数据
$("#data-form").initForm({
id: "",
name: "",
icon: "",
link: "",
ordered: "",
linkMode: "true",
enable: "true",
})
$('#save-window').modal('show')
})
// 删除导航条
$("#data-table").on("click", ".navigation-delete-btn", function () {
let id = $(this).data('id')
let idx = layer.confirm('是否要删除该数据?', {
btn: ['确认', '取消'] //按钮
}, function () { // 点击确认后删除
$.ajax({
url: '/admin/navigation/' + id,
method: 'delete',
dataType: 'json',
success: res => {
if (res.code === 200) {
layer.msg("删除成功", {icon: 1, time: 700})
$('#data-table').bootstrapTable('refresh', {silent: true})
} else {
layer.msg(res.message, {icon: 2})
}
}
})
layer.close(idx); // 关闭提示框
})
})
// 更新导航条数据
$("#data-form").on("submit", function () {
let data = $(this).serialize();
$.ajax({
url: "/admin/navigation/",
method: "POST",
data: data,
dataType: "json",
success: res => {
if (res.code === 200) {
// 显示成功信息
layer.msg("保存成功", {icon: 1, time: 600}, function () {
// 关闭模态框
$('#save-window').modal('hide')
// 重载表格数据
$('#data-table').bootstrapTable('refresh', {silent: true})
})
} else {
layer.msg(res.message, {icon: 2})
}
}
})
return false; // 阻止表单的提交行为
})
// 实现按照ordered排序
$('#refresh-ordered-btn').on('click', function () {
console.log("id----ordered")
// 返回数据的格式,依次获得所有表格项的id和顺序值并组成下面的格式
// id1----顺序1;id2----顺序2;id3----顺序13
let ids = ""
$('#data-table .sortedBySave').each((index, ele) => ids += $(ele).data('id') + "----" + $(ele).val() + ";")
console.log(ids);
$.ajax({
url: "/admin/navigation/order",
method: "POST",
data: {
ids: ids
},
dataType: "json",
success: res => {
if (res.code === 200) {
layer.msg("保存成功", {icon: 1, time: 600}, function () {
$('#data-table').bootstrapTable('refresh', {silent: true})
});
} else {
layer.msg(res.message, {icon: 2});
}
}
})
})
})
</script>
</body>
</html>
Loading…
Cancel
Save