1.功能分析 1.1. 查询列表 1.1.1. 页面效果 1.1.2. 功能要求 分页查询默认查询10条每页从第1页开始查询 默认导航信息只提供查询按钮 非默认导航提供查询,修改,删除按钮 点击新增按钮弹出
1.功能分析
1.1. 查询列表
1.1.1. 页面效果
1.1.2. 功能要求
- 分页查询默认查询10条每页从第1页开始查询
- 默认导航信息只提供查询按钮
- 非默认导航提供查询,修改,删除按钮
- 点击新增按钮弹出新增导航页面
- 搜索条件
- 导航名称:支持模糊搜索
- 点击搜索按钮是按照录入的搜索条件进行查询数据并渲染
- 点击重置按钮的时候清空搜索条件,并重新渲染数据
1.2. 新增导航
1.2.1. 页面效果
1.2.2. 功能要求
- 导航名称,导航链接为必填项
- 导航名称需做唯一性校验
- 导航链接需要做唯一性校验
- 导航图标如果不填则默认填充一个系统定义的默认图标
- 导航排序如果不填写则默认填写为999(最大放到最后)
- 导航排序填写范围为[0-999]
- 是否显示默认选中显示
- 是否默认导航默认选中否
- 成功添加数据后列表页进行刷新
1.3. 修改导航
1.3.1. 页面效果
1.3.2. 功能要求
- 导航名称,默认导航不可修改仅查看
- 导航链接需做唯一性验证
- 成功修改数据后列表页进行刷新
1.4. 删除导航
1.4.1. 功能要求
- 点击删除按钮需给出提示框进行二次确认,当二次确认后可进行删除操作
- 成功删除数据后列表页进行刷新
1.5. 查询明细
1.5.1. 页面效果
1.5.2. 功能要求
- 页面仅查看无法进行操作
1.6. 启用/禁用导航
1.6.1. 功能要求
无
2.功能实现
2.1. 初期准备
2.1.1. 创建数据库 zh_nav
CREATE TABLE `zh_nav` (
`id` int NOT NULL AUTO_INCREMENT,
`nav_name` varchar(255) DEFAULT NULL COMMENT '导航名称',
`nav_link` varchar(255) DEFAULT NULL COMMENT '导航连接',
`nav_icon` varchar(255) DEFAULT NULL COMMENT '导航图标',
`nav_sort` int DEFAULT NULL COMMENT '导航排序',
`nav_show` tinyint(1) DEFAULT NULL COMMENT '导航是否展示 0.否 1是',
`is_default` tinyint(1) DEFAULT NULL COMMENT '是否默认 0否 1是',
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
`create_user_code` varchar(255) DEFAULT NULL COMMENT '创建人编号',
`create_user_name` varchar(255) DEFAULT NULL COMMENT '创建时间',
`update_time` datetime DEFAULT NULL COMMENT '修改时间',
`update_user_code` varchar(255) DEFAULT NULL COMMENT '修改人编号',
`update_user_name` varchar(255) DEFAULT NULL COMMENT '修改人名称',
PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT COMMENT='导航';
2.1.2. 创建控制层NavController
package com.zhuhuo.modual.controller.manager;
import com.zhuhuo.modual.service.NavService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
@Controller
@RequestMapping(value = "/m/nav")
public class NavController {
@Autowired
private NavService navService;
}
2.1.3. 创建实体映射Nav
package com.zhuhuo.modual.entity;
import lombok.Data;
import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;
import javax.persistence.Table;
import java.io.Serializable;
import java.util.Date;
import javax.persistence.Id;
@Data
@AllArgsConstructor
@NoArgsConstructor
@Table(name = "zh_nav")
public class Nav implements Serializable {
private static final long serialVersionUID = 1L;
@Id
private Long id;
private String navName;
private String navLink;
private String navIcon;
private Integer navSort;
private String navType;
private Byte navShow;
private Long parentId;
private Byte isDefault;
private Date createTime;
private String createUserCode;
private String createUserName;
private Date updateTime;
private String updateUserCode;
private String updateUserName;
}
2.1.4. 创建NavMapper, NavMapper.xml
package com.zhuhuo.modual.mapper;
import com.zhuhuo.core.frame.mapper.BasicsMapper;
import com.zhuhuo.modual.entity.Nav;
public interface NavMapper extends BasicsMapper<Nav>{
}
<?xml versinotallow="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="com.zhuhuo.modual.mapper.NavMapper">
<resultMap id="BaseResultMap" type="com.zhuhuo.modual.entity.Nav">
<id column="id" property="id" jdbcType="BIGINT"/>
<result column="nav_name" property="navName" jdbcType="VARCHAR"/>
<result column="nav_link" property="navLink" jdbcType="VARCHAR"/>
<result column="nav_icon" property="navIcon" jdbcType="VARCHAR"/>
<result column="nav_sort" property="navSort" jdbcType="INTEGER"/>
<result column="nav_type" property="navType" jdbcType="VARCHAR"/>
<result column="nav_show" property="navShow" jdbcType="TINYINT"/>
<result column="is_default" property="isDefault" jdbcType="TINYINT"/>
<result column="parent_id" property="parentId" jdbcType="BIGINT"/>
<result column="create_time" property="createTime" jdbcType="TIMESTAMP"/>
<result column="create_user_code" property="createUserCode" jdbcType="VARCHAR"/>
<result column="create_user_name" property="createUserName" jdbcType="VARCHAR"/>
<result column="update_time" property="updateTime" jdbcType="TIMESTAMP"/>
<result column="update_user_code" property="updateUserCode" jdbcType="VARCHAR"/>
<result column="update_user_name" property="updateUserName" jdbcType="VARCHAR"/>
</resultMap>
<sql id="base_column_list">
id, nav_name, nav_link, nav_icon, nav_sort, nav_type, nav_show,is_default,
parent_id,create_time, create_user_code, create_user_name, update_time, update_user_code,
update_user_name
</sql>
</mapper>
2.1.5. 创建NavService ,NavServiceImpl
package com.zhuhuo.modual.service;
import com.zhuhuo.modual.entity.Nav;
public interface NavService {
}
package com.zhuhuo.modual.service.impl;
import com.zhuhuo.modual.entity.Nav;
import com.zhuhuo.modual.mapper.NavMapper;
import com.zhuhuo.modual.service.NavService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service("navService")
public class NavServiceImpl implements NavService {
@Autowired
private NavMapper navMapper;
}
2.2. 接口设计
请参考接口设计文档
2.3. 查询导航列表
2.3.1. 静态页面
2.3.1.1. 资源引入
1.引入表格插件bootstrap-table的 css和 js文件
2.3.1.2. 页面布局
<!DOCTYPE html>
<html lang="en">
<head>
<th:block th:replace="/manager/common/common :: core-head('导航列表','','')"></th:block>
<div th:replace="/manager/common/common :: core-css"></div>
<div th:replace="/manager/common/common :: lib-bootstrap-table-css"></div>
</head>
<body class="gray-bg">
<div class="wrapper wrapper-content">
<div class="panel">
<div class="panel-body">
<div class="btn-group-sm" id="toolbar" role="group">
<a class="btn btn-success" id="addBtn" >
<i class="fa fa-plus"></i> 新增
</a>
</div>
<div class="select-table table-striped">
<table id="bootstrap-table-list" ></table>
</div>
</div>
</div>
</div>
<div th:replace="/manager/common/common :: core-js"></div>
<div th:replace="/manager/common/common :: lib-bootstrap-table-js"></div>
</body>
</html>
2.3.1.3. 初始化表格js
$("#bootstrap-table-list").bootstrapTable({
url: "/m/nav/findNavList", // 请求后台的URL(*)
contentType: "application/x-www-form-urlencoded", // 编码类型
method: 'get', // 请求方式(*)
cache: false, // 是否使用缓存,默认为true,所以一般情况下需要设置一下这个属性(*)
// height: $(window).height()-56, // 表格的高度
striped: true, // 是否显示行间隔色
//排序相关属性
sortable: true, // 是否启用排序
sortStable: true, // 设置为 true 将获得稳定的排序
sortOrder: 'asc', // 排序方式 asc 或者 desc
//分页相关属性
pagination: true, // 是否开启分页
sidePagination: 'server', // 分页方式:client客户端分页,server服务端分页(*)
//工具栏相关属性
toolbar: '#toolbar', // 指定工作栏
iconSize: 'undefined', // 图标大小:undefined默认的按钮尺寸 xs超小按钮sm小按钮lg大按钮
showFullscreen: true, // 是否显示全屏按钮
showRefresh: true, // 是否显示刷新按钮
showToggle: true, // 是否显示详细视图和列表视图的切换按钮
showColumns: true, // 是否显示所有的列(选择显示的列)
//加载相关属性
showLoading: false, // 是否启用加载框
//搜索相关属性
clickToSelect: true, // 是否启用点击选中行
uniqueId: 'id', // 唯一标识符
pageNumber: 1, //初始化加载第一页,默认第一页
pageSize: 10, //每页的记录行数(*)
pageList: [10, 25, 50, 100], //可供选择的每页的行数(*)
showSearch:true,
// 在加载服务器发送来的数据之前处理函数
responseHandler: function(res){
if(res == null || res == 'undefined'){
console.log('resp', res)
}else {
if (res.responseCode == '200') {
return {rows: res.responseData, total: res.total};
} else {
$.modal.msg(res.responseMessage,'warning');
return {rows: [], total: 0};
}
}
},
queryParams:function (params){
var param = {
pageSize:params.limit,
pageNum: params.offset / params.limit + 1,
navName: $("#navName").val(),
};
return param;
},
queryParamsType:'limit',
onLoadSuccess: function (res){
console.log('data', res);
},
onLoadError: function (res){
console.log('res', res);
},
columns: [
{
checkbox: true
},
{
field: 'id',
title: 'id'
},
{
field: 'navName',
title: '导航名称'
},
{
field: 'isDefault',
title: '默认导航',
formatter: function (value, item, index) {
if (item.isDefault == '1') {
return '是';
} else {
return '否';
}
}
},
{
field: 'navShow',
title: '是否展示',
align: 'center',
formatter: function (value, item, index) {
return statusTools(item);
}
},
{
field: 'navLink',
title: '导航链接'
},
{
title: '操作',
align: 'center',
formatter: function actionFormatter(value, item) {
if(item.isDefault == '1'){
return [
'<button type="button" class="btn btn-sm btn-secondary" data-toggle="tooltip" title="查看明细" data-width="720" data-height="450" notallow="viewPage('+item.id+')"><i class="fa fa-search"></i></button>',
].join(' ')
}
else {
let btnArr = [];
btnArr.push('<button type="button" class="btn btn-sm btn-secondary" data-toggle="tooltip" title="查看明细" data-width="720" data-height="450" notallow="viewPage('+item.id+')"><i class="fa fa-search"></i></button>');
btnArr.push('<button type="button" class="btn btn-sm btn-secondary" data-toggle="tooltip" title="编辑" data-width="720" data-height="450" notallow="editPage('+item.id+')"><i class="fa fa-pencil"></i></button>');
btnArr.push('<button type="button" class="btn btn-sm btn-secondary" data-toggle="tooltip" title="删除" notallow="remove('+item.id+')"><i class="fa fa-times"></i></button>');
return btnArr.join(" ");
}
},
}
],
});
function statusTools(item) {
console.log(item)
if (item.navShow == 1) {
return '<i class=\"fa fa-toggle-off text-info fa-2x\" notallow="enable(\'' + item.id + '\')"></i> ';
} else {
return '<i class=\"fa fa-toggle-on text-danger fa-2x\" notallow="disable(\'' + item.id + '\')"></i> ';
}
}
2.3.1.3. sidebar修改
<li>
<a class="zh-menu-item" th:href="@{/m/nav/findNavPage}">
<i class="fa fa-paper-plane"></i>导航管理
</a>
</li>
2.3.2. 列表功能
2.3.2.1. 创建查询列表页面方法
/**
* 导航管理页面
* @return
*/
@GetMapping(value = "/findNavPage")
public String findNavPage(){
return "/manager/nav/list";
}
2.3.2.2.创建请求对象和响应对象
2.3.2.2.1. 请求对象 NavListBO
@Data
@NoArgsConstructor
@AllArgsConstructor
public class NavListBO {
/**
* 导航名称
*/
private String navName;
/**
* 分页数量
*/
private Integer pageNum;
/**
* 分页条数
*/
private Integer pageSize;
}
2.3.2.2.2. 响应对象 NavListDTO
@Data
@NoArgsConstructor
@AllArgsConstructor
public class NavListDTO {
/**
*
*/
private String id;
/**
* 导航名称
*/
private String navName;
/**
* 导航连接
*/
private String navLink;
/**
* 导航图标
*/
private String navIcon;
/**
* 导航排序
*/
private Integer navSort;
/**
* 导航是否展示 0.否 1是
*/
private Byte navShow;
/**
* 是否默认导航 0.否 1是
*/
private Byte isDefault;
}
2.3.2.3. 创建查询列表明细方法
2.3.2.3.1. controller
@ResponseBody
@GetMapping(value = "/findNavList")
public RespJsonPageData<NavListDTO> findNavList(NavListBO navListBO){
return navService.findNavList(navListBO);
}
2.3.2.3.2. service
RespJsonPageData<NavListDTO> findNavList(NavListBO navListBO);
2.3.2.3.3. serviceImpl
public RespJsonPageData<NavListDTO> findNavList(NavListBO navListBO) {
PageQuery query = new PageQuery(navListBO);
Page<Object> result = PageHelper.startPage(query.getPageNum(), query.getPageSize());
List<Nav> navList = navMapper.findNavList(MapUtils.objToMap(navListBO));
List<NavListDTO> navListDTOList = JacksonUtil.transformList(JacksonUtil.transformJSONCompact(navList), NavListDTO.class);
return RespJsonPageData.success(navListDTOList, result.getTotal());
}
2.3.2.3.4. mapper
List<Nav> findNavList(Map<String, Object> params);
2.3.2.3.5. xml
<select id="findNavList" parameterType="java.util.Map" resultMap="BaseResultMap">
select
<include refid="base_column_list"/>
from zh_nav
<include refid="search_list_condition"/>
order by nav_sort asc
</select>
<sql id="search_list_condition">
<where>
<if test="navName != null and navName != '' ">
and nav_name = like concat('%',#{navName},'%')
</if>
</where>
</sql>
2.3.2.3. 测试查询列表
2.3.3. 条件搜索/重置
2.3.3.1. 静态页面
<div class="panel">
<div class="panel-body">
<form role="search-form" class="form-inline" id="search-form">
<div class="form-group">
<label class="control-label">导航名称</label>
<input type="text" placeholder="请输导航名称" id="navName" name="navName" class="form-control">
</div>
<a class="btn btn-primary" id="searchBtn" notallow="search()">
<i class="fa fa-search"></i> 搜索
</a>
<a class="btn btn-warning" id="resetBtn" notallow="reset()">
<i class="fa fa-refresh"></i> 重置
</a>
</form>
</div>
</div>
2.3.3.1. 搜索/重置js
/**
* 搜索方法
*/
function search(){
var params = $("#bootstrap-table-list").bootstrapTable('getOptions');
params.navName = $("#navName").val();
$("#bootstrap-table-list").bootstrapTable('refresh', params);
}
/**
* 重置方法
*/
function reset(){
var params = $("#bootstrap-table-list").bootstrapTable('getOptions');
$("#navName").val('');
$("#bootstrap-table-list").bootstrapTable('refresh', params);
}
2.4. 新增导航
2.4.1. 静态页面
2.4.1.1. list页面add按钮弹出层
function add(){
let title = '新增导航';
let url = '/m/nav/addNavPage';
let width = 800;
let height = $(window).height();
let isFull = true;
//判断是否为移动端
if(navigator.userAgent.match(/(iPhone|iPad|Android|ios)/i)){
width = 'auto';
height = 'auto';
}
openAddWindow(title,url,width,height,isFull);
}
function openAddWindow(title, url, width, height,isFull){
var index = top.layer.open({
type: 2,
title: title,
area: [width + 'px', height + 'px'],
content: url, //要展示的内容,此处可以通过后台获取,也可以自定义
fix: false,
maxmin: true, //开启最大化最小化按钮
shade: 0.3, //弹层的遮罩 设置遮罩深色背景的透明度
btn: ['确定', '关闭'],
shadeClose: true, // 弹层外区域关闭
yes: function(index, layero) {
var iframeWin = layero.find('iframe')[0];
//监听当前页layer.open监听页面提交
iframeWin.contentWindow.submitHandler(index, layero);
},
cancel: function(index) {
return true;
},
success: function () {
$(':focus').blur();
}
});
if(isFull){
top.layer.full(index);
}
}
2.4.1.2. 页面布局
<!DOCTYPE html>
<html lang="en">
<head>
<div th:replace="/manager/common/common :: core-head('新增文章','','')"></div>
<div th:replace="/manager/common/common :: core-css"></div>
<div th:replace="/manager/common/common :: lib-bootstrap-table-css"></div>
</head>
<body class="gray-bg">
<div class="wrapper wrapper-content">
<div class="panel">
<div class="panel-body">
<!-- 表单信息-->
<form class="form-horizontal m" id="add-nav-form" style="padding-left: 20px;padding-right: 20px">
<div class="form-group">
<div class="col-md-12">
<div class="input-group m-b">
<span class="input-group-addon">导航名称</span>
<input type="text" class="form-control" placeholder="请输入导航名称" name="navName" id="navName">
</div>
</div>
</div>
<div class="form-group">
<div class="col-md-12">
<div class="input-group m-b">
<span class="input-group-addon">导航链接</span>
<input type="text" class="form-control" placeholder="请输入导航链接" name="navLink" id="navLink">
</div>
</div>
</div>
<div class="form-group">
<div class="col-md-12">
<div class="input-group m-b">
<span class="input-group-addon">导航图标</span>
<input type="text" class="form-control" placeholder="请输入导航图标" name="navIcon" id="navIcon">
</div>
</div>
</div>
<div class="form-group">
<div class="col-md-12">
<div class="input-group m-b">
<span class="input-group-addon">导航排序</span>
<input type="text" class="form-control" placeholder="请输入导航图标" name="navSort" id="navSort">
</div>
</div>
</div>
<div class="form-group">
<div class=" col-md-6">
<div class="input-group m-b ">
<span class="input-group-addon">是否显示</span>
<select class="form-control m-b" name="navShow" id="navShow">
<option value="1" selected>显示</option>
<option value="2">隐藏</option>
</select>
</div>
</div>
<div class=" col-md-6">
<div class="input-group m-b ">
<span class="input-group-addon">默认导航</span>
<select class="form-control m-b" name="isDefault" id="isDefault">
<option value="0" selected>否</option>
<option value="1">是</option>
</select>
</div>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
<div th:replace="/manager/common/common :: core-js"></div>
<div th:replace="/manager/common/common :: lib-bootstrap-table-js"></div>
<div th:replace="/manager/common/common :: lib-jquery-validate-js"></div>
</body>
</html>
2.4.1.3. 表单校验js
$('#add-nav-form').validate({
onkeyup: false,
rules: {
navName: {
required: true,
remote: {
url: "/m/nav/validataNavName",
type: "post",
dataType: "json",
data: {
"navName" : function() {
return trim($("#navName").val());
}
},
dataFilter: function(res) {
return uniqueCheck(res)
}
}
},
},
messages: {
navName: {
required: "请录入导航名称",
remote:"导航名称已存在,请重新录入",
},
},
focusCleanup: true
});
2.4.1.4. 表单提交js
function submitHandler(index) {
if($("#add-nav-form").validate().form()){
let requestData = formToJsonJq('add-nav-form');
$.ajax({
url:"/m/nav/addNav",
type:"post",
data:JSON.stringify(requestData),
dataType:"json",
contentType: "application/json",
success: function(result) {
var parent = activeWindow();
if(result.responseCode == "200"){
top.layer.close(index);
parent.layer.msg(content, { icon: $.modal.icon(1), time: 1000, shift: 5 });
parent.refreshData();
}else {
parent.layer.msg(content, { icon: $.modal.icon(2), time: 1000, shift: 5 });
}
}
})
}
}
function activeWindow(){
//获取上一层窗口
let topWindow = $(window.parent.document)
//获取tab选中的窗体信息
let checkedWindowId = $('.page-tabs-content',topWindow).find('.active').attr('data-id')
//判断是否选中tab窗体,如果未选中则直接返回父窗体
if(!checkedWindowId){
return window.parent
}
//返回上级选中的窗体
return $('.zh-iframe[data-id="'+checkedWindowId+'"]',topWindow)[0].contentWindow;
}
2.4.1.5. 工具js
/**
* form转json 通过formid传递
* @param formId 表单id
* @return {{}}
*/
function formToJsonJq (formId) {
var json = {};
$.each($("#" + formId).serializeArray(), function(i, field) {
if (json[field.name]) {
json[field.name] += ("," + field.value);
} else {
json[field.name] = field.value;
}
});
return json;
}
/**
* form转json 通过传递form
* @param form 表单信息
*/
function formToJsonNormal(form){
let formData = new FormData(form);
let json = {};
for (var [key, value] of formData.entries()) {
json[key] = value;
}
return JSON.stringify(json);
}
/**
* 剔除空格
* @param textval
* @return {string}
*/
function trim(textval){
if (textval == null) {
return "";
}
return textval.toString().replace(/(^\s*)|(\s*$)|\r|\n/g, "");
}
/**
* 校验是否为空
* @param textval 传入的文本
*/
function isEmpty(textval){
if (textval == null || this.trim(textval) == "" || textval == undefined || textval == "undefined") {
return true;
}
return false;
}
2.4.2. 新增功能
2.4.2.1. 创建新增请求对象BO
@Data
@NoArgsConstructor
@AllArgsConstructor
public class NavBO {
/**
*
*/
private Long id;
/**
* 导航名称
*/
private String navName;
/**
* 导航连接
*/
private String navLink;
/**
* 导航图标
*/
private String navIcon;
/**
* 导航排序
*/
private Integer navSort;
/**
* 导航是否展示 0.否 1是
*/
private Byte navShow;
/**
* 是否默认导航 0.否 1是
*/
private Byte isDefault;
}
2.4.2.2. 创建新增页面方法
@GetMapping(value = "/addNavPage")
public String addNavPage(){
return "/manager/nav/add";
}
2.4.2.3. 创建新增页面方法
2.4.2.3.1. controller
@GetMapping(value = "/addNavPage")
public String addNavPage(){
return "/manager/nav/add";
}
@ResponseBody
@PostMapping(value = "/addNav")
public RespJson addNav( @RequestBody NavBO navBO){
return navService.addNav(navBO);
}
2.4.2.3.2. service,serviceImpl
RespJson addNav(NavBO navBO);
public RespJson addNav(NavBO navBO) {
if(ObjectUtil.isEmpty(navBO.getNavName())){
return RespJson.fail(BizResponseCode.NAV_NAME_NOT_EMPTY.getResponseCode(),BizResponseCode.NAV_NAME_NOT_EMPTY.getResponseMessage());
}
if(ObjectUtil.isEmpty(navBO.getNavLink())){
return RespJson.fail(BizResponseCode.NAV_LINK_NOT_EMPTY.getResponseCode(),BizResponseCode.NAV_LINK_NOT_EMPTY.getResponseMessage());
}
//校验导航名称的唯一性
if(navMapper.findNavCountByNavName(navBO.getNavName()) > 0){
return RespJson.fail(BizResponseCode.NAV_NAME_ALREADY_EXISTS.getResponseCode(),BizResponseCode.NAV_NAME_ALREADY_EXISTS.getResponseMessage());
}
if(navMapper.findNavCountByNavLink(navBO.getNavLink()) > 0){
return RespJson.fail(BizResponseCode.NAV_LINK_ALREADY_EXISTS.getResponseCode(),BizResponseCode.NAV_LINK_ALREADY_EXISTS.getResponseMessage());
}
if(ObjectUtil.isNotEmpty(navBO.getNavSort()) && (navBO.getNavSort() > 999 || navBO.getNavSort() < 0 )){
return RespJson.fail(BizResponseCode.NAV_SORT_RANGE_ERROR.getResponseCode(),BizResponseCode.NAV_SORT_RANGE_ERROR.getResponseMessage());
}
Nav nav = new Nav();
nav.setNavName(navBO.getNavName());
nav.setNavLink(navBO.getNavLink());
nav.setNavShow(ObjectUtil.isEmpty(navBO.getNavShow()) ? 0:navBO.getNavShow());
nav.setIsDefault(ObjectUtil.isEmpty(navBO.getIsDefault())? 0:navBO.getIsDefault());
nav.setNavIcon(ObjectUtil.isEmpty(navBO.getNavIcon())? "fa fa-home":navBO.getNavIcon());
nav.setNavSort(ObjectUtil.isEmpty(navBO.getNavSort()) ? 999: navBO.getNavSort());
navMapper.insertSelective(nav);
return RespJson.success();
}
2.4.2.3.3. BizResponseCode
NAV_NAME_NOT_EMPTY("102001","导航名称不能为空"),
NAV_LINK_NOT_EMPTY("102002","导航链接不能为空"),
NAV_NAME_ALREADY_EXISTS("102003","导航名称已存在"),
NAV_LINK_ALREADY_EXISTS("102004","导航链接已存在"),
NAV_SORT_RANGE_ERROR("102005","导航排序范围只能为[0,999]"),
2.4.2.3.4. mapper,xml
/**
* <h2>根据导航名称查询数量</h2>
* @param navName
* @return
*/
int findNavCountByNavName(@Param("navName") String navName);
/**
* <h2>根据导航链接查询数量</h2>
* @param navLink
* @return
*/
int findNavCountByNavLink(@Param("navLink") String navLink);
<select id="findNavCountByNavName" parameterType="java.lang.String" resultType="java.lang.Integer">
select count(1) from zh_nav where nav_name = #{navName}
</select>
<select id="findNavCountByNavLink" parameterType="java.lang.String" resultType="java.lang.Integer">
select count(1) from zh_nav where nav_link = #{navLink}
</select>
2.4.2.4. postmant测试新增
2.5. 修改导航
2.5.1. 静态页面
2.5.1.1. list页面edit按钮弹出层
function edit(id){
let title = '修改导航';
let url = '/m/nav/editNavPage/'+id;
let width = 800;
let height = $(window).height();
let isFull = true;
//判断是否为移动端
if(navigator.userAgent.match(/(iPhone|iPad|Android|ios)/i)){
width = 'auto';
height = 'auto';
}
openEditWindow(title,url,width,height,isFull);
}
function openEditWindow(title, url, width, height,isFull){
var index = top.layer.open({
type: 2,
title: title,
area: [width + 'px', height + 'px'],
content: url, //要展示的内容,此处可以通过后台获取,也可以自定义
fix: false,
maxmin: true, //开启最大化最小化按钮
shade: 0.3, //弹层的遮罩 设置遮罩深色背景的透明度
btn: ['确定', '关闭'],
shadeClose: true, // 弹层外区域关闭
yes: function(index, layero) {
var iframeWin = layero.find('iframe')[0];
//监听当前页layer.open监听页面提交
iframeWin.contentWindow.submitHandler(index, layero);
},
cancel: function(index) {
return true;
},
success: function () {
$(':focus').blur();
}
});
if(isFull){
top.layer.full(index);
}
}
2.5.1.2. 页面布局
<!DOCTYPE html>
<html lang="en">
<head>
<div th:replace="/manager/common/common :: core-head('新增文章','','')"></div>
<div th:replace="/manager/common/common :: core-css"></div>
<div th:replace="/manager/common/common :: lib-bootstrap-table-css"></div>
</head>
<body class="gray-bg">
<div class="wrapper wrapper-content">
<div class="panel">
<div class="panel-body">
<!-- 表单信息-->
<form class="form-horizontal m" id="edit-nav-form" style="padding-left: 20px;padding-right: 20px" th:object="${editNav}">
<input name="id" type="hidden" th:field="*{id}" />
<div class="form-group">
<div class="col-md-12">
<div class="input-group m-b">
<span class="input-group-addon">导航名称</span>
<input type="text" class="form-control" placeholder="请输入导航名称" name="navName" id="navName" th:field="*{navName}" disabled>
</div>
</div>
</div>
<div class="form-group">
<div class="col-md-12">
<div class="input-group m-b">
<span class="input-group-addon">导航链接</span>
<input type="text" class="form-control" placeholder="请输入导航链接" name="navLink" id="navLink" th:field="*{navLink}">
</div>
</div>
</div>
<div class="form-group">
<div class="col-md-12">
<div class="input-group m-b">
<span class="input-group-addon">导航图标</span>
<input type="text" class="form-control" placeholder="请输入导航图标" name="navIcon" id="navIcon" th:field="*{navIcon}">
</div>
</div>
</div>
<div class="form-group">
<div class="col-md-12">
<div class="input-group m-b">
<span class="input-group-addon">导航排序</span>
<input type="text" class="form-control" placeholder="请输入导航排序" name="navSort" id="navSort" th:field="*{navSort}">
</div>
</div>
</div>
<div class="form-group" >
<div class=" col-md-6">
<div class="input-group m-b ">
<span class="input-group-addon">是否显示</span>
<select class="form-control m-b" name="navShow" id="navShow" th:field="*{navShow}">
<option value="1">显示</option>
<option value="0">隐藏</option>
</select>
</div>
</div>
<div class=" col-md-6">
<div class="input-group m-b ">
<span class="input-group-addon">默认导航</span>
<select class="form-control m-b" name="isDefault" id="isDefault" th:field="*{isDefault}" disabled>
<option value="0" selected>否</option>
<option value="1">是</option>
</select>
</div>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
<div th:replace="/manager/common/common :: core-js"></div>
<div th:replace="/manager/common/common :: lib-bootstrap-table-js"></div>
<div th:replace="/manager/common/common :: lib-jquery-validate-js"></div>
2.5.1.3. 表单校验js
$('#edit-nav-form').validate({
onkeyup: false,
rules: {
navLink: {
required: true,
},
},
messages: { // custom messages for radio buttons and checkboxes
navLink: {
required: "请录入导航链接",
},
},
focusCleanup: true
});
2.5.1.4. 表单提交js
function submitHandler(index) {
if($("#edit-nav-form").validate().form()){
let requestData = formToJsonJq('edit-nav-form');
$.ajax({
url:"/m/nav/editNav",
type:"post",
data:JSON.stringify(requestData),
dataType:"json",
contentType: "application/json",
success: function(result) {
var parent = activeWindow();
if(result.responseCode == "200"){
top.layer.close(index);
parent.layer.msg(content, { icon: $.modal.icon(1), time: 1000, shift: 5 });
parent.refreshData();
}else {
parent.layer.msg(content, { icon: $.modal.icon(2), time: 1000, shift: 5 });
}
}
})
}
}
function activeWindow(){
//获取上一层窗口
let topWindow = $(window.parent.document)
//获取tab选中的窗体信息
let checkedWindowId = $('.page-tabs-content',topWindow).find('.active').attr('data-id')
//判断是否选中tab窗体,如果未选中则直接返回父窗体
if(!checkedWindowId){
return window.parent
}
//返回上级选中的窗体
return $('.zh-iframe[data-id="'+checkedWindowId+'"]',topWindow)[0].contentWindow;
}
2.5.2. 修改功能
2.5.2.1. 创建修改明细响应对象DTO
@Data
public class NavDetailDTO {
private Long id;
/**
* 导航名称
*/
private String navName;
/**
* 导航链接
*/
private String navLink;
/**
* 导航图标
*/
private String navIcon;
/**
* 导航排序
*/
private Integer navSort;
/**
* 是否默认导航 0否 1是
*/
private Byte isDefault;
/**
* 导航是否展示 0隐藏 1显示
*/
private Byte navShow;
}
2.5.2.2. 创建修改页面方法
2.5.2.2.1 controller
@GetMapping(value = "/editNavPage/{id}")
public String editNavPage(@PathVariable("id") Long id,ModelMap modelMap){
return navService.editNavPage(id,modelMap);
}
2.5.2.2.2 service ,serviceImpl
String editNavPage(Long id, ModelMap modelMap);
@Override
public String editNavPage(Long id, ModelMap modelMap) {
Nav nav = navMapper.selectByPrimaryKey(id);
NavDetailDTO navDetailDTO = JacksonUtil.transformObject(JacksonUtil.transformJSONCompact(nav),NavDetailDTO.class);
modelMap.put("editNav",navDetailDTO);
return "/manager/nav/edit";
}
2.5.2.3. 创建修改页面方法
2.5.2.3.1. controller
@ResponseBody
@PostMapping(value = "/editNav")
public RespJson editNav(@RequestBody NavBO navBO){
return navService.editNav(navBO);
}
2.5.2.3.2. service,serviceImpl
RespJson editNav(NavBO navBO);
public RespJson editNav(NavBO navBO) {
//验证id是否存在
if(ObjectUtil.isEmpty(navBO.getId())){
return RespJson.fail(BizResponseCode.NAV_ID_NOT_EXIST.getResponseCode(),BizResponseCode.NAV_ID_NOT_EXIST.getResponseMessage());
}
//获取导航信息
Nav nav = navMapper.selectByPrimaryKey(navBO.getId());
if(ObjectUtil.isEmpty(navBO.getNavLink())){
return RespJson.fail(BizResponseCode.NAV_LINK_NOT_EMPTY.getResponseCode(),BizResponseCode.NAV_LINK_NOT_EMPTY.getResponseMessage());
}
//验证导航是否存在
if(ObjectUtil.isEmpty(nav)){
return RespJson.fail(BizResponseCode.NAV_NOT_EXIST.getResponseCode(),BizResponseCode.NAV_NOT_EXIST.getResponseMessage());
}
if(ObjectUtil.isNotEmpty(navBO.getNavLink()) && !(navBO.getNavLink().equals(nav.getNavLink()))){
if(navMapper.findNavCountByNavLink(navBO.getNavLink()) > 0){
return RespJson.fail(BizResponseCode.NAV_LINK_ALREADY_EXISTS.getResponseCode(),BizResponseCode.NAV_LINK_ALREADY_EXISTS.getResponseMessage());
}
}
if(ObjectUtil.isNotEmpty(navBO.getNavSort()) && (navBO.getNavSort() > 999 || navBO.getNavSort() < 0 )){
return RespJson.fail(BizResponseCode.NAV_SORT_RANGE_ERROR.getResponseCode(),BizResponseCode.NAV_SORT_RANGE_ERROR.getResponseMessage());
}
nav.setNavLink(navBO.getNavLink());
nav.setNavSort(navBO.getNavSort());
nav.setNavShow(navBO.getNavShow());
navMapper.updateByPrimaryKeySelective(nav);
return RespJson.success();
}
2.5.2.3.3. BizResponseCode
NAV_ID_NOT_EXIST("102006","导航id不存在,请检查"),
NAV_NOT_EXIST("102007","导航不存在"),
2.5.2.4. postmant测试修改
2.6. 查询导航明细
2.6.1. 静态页面
2.6.1.1. list页面查询按钮弹出层
function viewPage(id){
let title = '修改导航';
let url = '/m/nav/viewNavPage/'+id;
let width = 800;
let height = $(window).height();
let isFull = true;
//判断是否为移动端
if(navigator.userAgent.match(/(iPhone|iPad|Android|ios)/i)){
width = 'auto';
height = 'auto';
}
openViewWindow(title,url,width,height,isFull);
}
function openViewWindow(title, url, width, height,isFull){
var index = top.layer.open({
type: 2,
title: title,
area: [width + 'px', height + 'px'],
content: url, //要展示的内容,此处可以通过后台获取,也可以自定义
fix: false,
maxmin: true, //开启最大化最小化按钮
shade: 0.3, //弹层的遮罩 设置遮罩深色背景的透明度
btn: [ '关闭'],
shadeClose: true, // 弹层外区域关闭
cancel: function(index) {
return true;
},
success: function () {
$(':focus').blur();
}
});
if(isFull){
top.layer.full(index);
}
}
2.6.1.2. 页面布局
<!DOCTYPE html>
<html lang="en">
<head>
<div th:replace = "/manager/common/common :: core-head('查询导航','zhuhuo-blog,烛火博客,blog','')"></div>
<div th:replace = "/manager/common/common :: core-css"></div>
</head>
<body class="gray-bg">
<div class="wrapper wrapper-content">
<div class="panel">
<div class="panel-body">
<form class="form-horizontal m" id="view-form" style="padding-left: 20px;padding-right: 20px" th:object="${viewNav}">
<input type="hidden" name="id" th:field="*{id}">
<!-- 导航名称 -->
<div class="form-group">
<div class="col-md-12">
<div class="input-group m-b">
<span class="input-group-addon">导航名称</span>
<input type="text" placeholder="请输入导航名称" class="form-control" id="navName" name="navName" th:field="*{navName}" disabled>
</div>
</div>
</div>
<!-- 导航链接-->
<div class="form-group">
<div class="col-md-12">
<div class="input-group m-b">
<span class="input-group-addon">导航链接</span>
<input type="text" placeholder="请输入导航链接" class="form-control" id="navLink" name="navLink" th:field="*{navLink}">
</div>
</div>
</div>
<!-- 导航图标 fa fa-home -->
<div class="form-group">
<div class="col-md-12">
<div class="input-group m-b">
<span class="input-group-addon">导航图标</span>
<input type="text" placeholder="请输入导航图标" class="form-control" id="navIcon" name="navIcon" th:field="*{navIcon}">
</div>
</div>
</div>
<!-- 导航排序-->
<div class="form-group">
<div class="col-md-12">
<div class="input-group m-b">
<span class="input-group-addon">导航排序</span>
<input type="text" placeholder="请输入导航排序" class="form-control" id="navSort" name="navSort" th:field="*{navSort}">
</div>
</div>
</div>
<!-- 是否显示/是否默认导航-->
<div class="form-group">
<!-- 是否显示-->
<div class="col-md-6">
<div class="input-group m-b">
<span class="input-group-addon">是否显示</span>
<select class="form-control m-b" name="navShow" id="navShow" th:field="*{navShow}">
<option value="1" selected>显示</option>
<option value="0">隐藏</option>
</select>
</div>
</div>
<!-- 是否默认导航-->
<div class="col-md-6">
<div class="input-group m-b">
<span class="input-group-addon">默认导航</span>
<select class="form-control m-b" name="isDefault" id="isDefault" th:field="*{isDefault}" disabled>
<option value="0" selected>否</option>
<option value="1">是</option>
</select>
</div>
</div>
</div>
</form>
</div>
</div>
</div>
<div th:replace = "/manager/common/common :: core-js"></div>
</body>
</html>
2.6.2. 查询功能
2.6.2.1. 创建查询页面方法
2.6.2.2.1 controller
@GetMapping(value = "/viewNavPage/{id}")
public String viewNavPage(@PathVariable("id") Long id,ModelMap modelMap){
return navService.viewNavPage(id,modelMap);
}
2.6.2.2.2 service ,serviceImpl
String viewNavPage(Long id, ModelMap modelMap);
@Override
public String viewNavPage(Long id, ModelMap modelMap) {
Nav nav = navMapper.selectByPrimaryKey(id);
NavDetailDTO navDetailDTO = JacksonUtil.transformObject(JacksonUtil.transformJSONCompact(nav),NavDetailDTO.class);
modelMap.put("viewNav",navDetailDTO);
return "/manager/nav/view";
}
2.7. 删除导航
2.7.1. 静态页面
2.7.1.1. list页面remove操作
function remove(id){
layer.confirm('确定吗?', {
icon: 3,
title: "系统提示",
btn: ['确认', '取消']
},function(index){
// do something
var requestData = { "id": id };
$.ajax({
url:'/m/nav/deleteNav',
type:'post',
data: JSON.stringify(requestData),
dataType:'json',
contentType:'application/json',
success: function (res){
if(res.responseCode == '200'){
//2.给出响应的消息提示
layer.msg(res.responseMessage,{icon: 1})
//3.刷新bootstrap-table
refreshData();
}else {
//1.给出对应的消息提示
layer.msg(res.responseMessage, {icon: 2});
}
}
})
// …
layer.close(index);
});
}
2.7.2. 删除功能
2.7.2.1. 创建删除方法
2.7.2.2.1. controller
@ResponseBody
@PostMapping(value = "/deleteNav")
public RespJson deleteNav(@RequestBody NavBO navBO){
return navService.deleteNav(navBO);
}
2.7.2.2.2. service,serviceImpl
RespJson deleteNav(NavBO navBO);
@Override
public RespJson deleteNav(NavBO navBO) {
if(ObjectUtil.isEmpty(navBO.getId())){
return RespJson.fail(BizResponseCode.NAV_ID_NOT_EXIST.getResponseCode(),BizResponseCode.NAV_ID_NOT_EXIST.getResponseMessage());
}
navMapper.deleteByPrimaryKey(navBO.getId());
return RespJson.success();
}
2.8. 显示/隐藏导航
2.8.1. 静态页面
2.8.1.1. list页面enable操作
function enable(id){
layer.confirm('是否确认启用当前选中的数据', {icon: 3, title:'启用提示'}, function(index){
// do something
let requestData = {id:id}
$.ajax({
url:'/m/nav/enableNav',
type:'post',
data: JSON.stringify(requestData),
dataType:'json',
contentType:'application/json',
success: function (res){
if(res.responseCode == '200'){
//2.给出响应的消息提示
layer.msg(res.responseMessage,{icon: 1})
//3.刷新bootstrap-table
refreshData();
}else {
//1.给出对应的消息提示
layer.msg(res.responseMessage, {icon: 2});
}
}
})
// …
layer.close(index);
});
}
2.8.1.2. list页面disable操作
function disable(id){
layer.confirm('是否确认禁用当前选中的数据', {icon: 3, title:'禁用提示'}, function(index){
// do something
let requestData = {id:id}
$.ajax({
url:'/m/nav/disableNav',
type:'post',
data: JSON.stringify(requestData),
dataType:'json',
contentType:'application/json',
success: function (res){
if(res.responseCode == '200'){
//2.给出响应的消息提示
layer.msg(res.responseMessage,{icon: 1})
//3.刷新bootstrap-table
refreshData();
}else {
//1.给出对应的消息提示
layer.msg(res.responseMessage, {icon: 2});
}
}
})
// …
layer.close(index);
});
}
2.8.2. 显示/隐藏功能
2.8.2.1. 创建显示/启用方法
2.8.2.1.1. controller
@ResponseBody
@PostMapping(value = "/enableNav")
public RespJson enableNav(@RequestBody NavBO navBO){
return navService.enableNav(navBO);
}
2.8.2.1.2. service,serviceImpl
RespJson enableNav(NavBO navBO);
@Override
public RespJson enableNav(NavBO navBO) {
if(ObjectUtil.isEmpty(navBO.getId())){
return RespJson.fail(BizResponseCode.NAV_ID_NOT_EXIST.getResponseCode(),BizResponseCode.NAV_ID_NOT_EXIST.getResponseMessage());
}
Nav nav = navMapper.selectByPrimaryKey(navBO.getId());
if(ObjectUtil.isEmpty(nav)){
return RespJson.fail(BizResponseCode.NAV_NOT_EXIST.getResponseCode(),BizResponseCode.NAV_NOT_EXIST.getResponseMessage());
}
nav.setNavShow(ZhuHuoConstant.Status.ENABLE);
navMapper.updateByPrimaryKeySelective(nav);
return RespJson.success();
}
2.8.2.2. 创建隐藏/禁用方法
2.8.2.2.1. controller
@ResponseBody
@PostMapping(value = "/disableNav")
public RespJson disableNav(@RequestBody NavBO navBO){
return navService.disableNav(navBO);
}
2.8.2.2.2. service,serviceImpl
RespJson disableNav(NavBO navBO);
@Override
public RespJson disableNav(NavBO navBO) {
if(ObjectUtil.isEmpty(navBO.getId())){
return RespJson.fail(BizResponseCode.NAV_ID_NOT_EXIST.getResponseCode(),BizResponseCode.NAV_ID_NOT_EXIST.getResponseMessage());
}
Nav nav = navMapper.selectByPrimaryKey(navBO.getId());
if(ObjectUtil.isEmpty(nav)){
return RespJson.fail(BizResponseCode.NAV_NOT_EXIST.getResponseCode(),BizResponseCode.NAV_NOT_EXIST.getResponseMessage());
}
nav.setNavShow(ZhuHuoConstant.Status.DISABLE);
navMapper.updateByPrimaryKeySelective(nav);
return RespJson.success();
}