当前位置 : 主页 > 编程语言 > java >

016-管理后台导航功能开发

来源:互联网 收集:自由互联 发布时间:2023-09-03
1.功能分析 1.1. 查询列表 1.1.1. 页面效果 1.1.2. 功能要求 分页查询默认查询10条每页从第1页开始查询 默认导航信息只提供查询按钮 非默认导航提供查询,修改,删除按钮 点击新增按钮弹出

1.功能分析

1.1. 查询列表

1.1.1. 页面效果

016-管理后台导航功能开发_搜索

1.1.2. 功能要求

  • 分页查询默认查询10条每页从第1页开始查询
  • 默认导航信息只提供查询按钮
  • 非默认导航提供查询,修改,删除按钮
  • 点击新增按钮弹出新增导航页面
  • 搜索条件
  • 导航名称:支持模糊搜索
  • 点击搜索按钮是按照录入的搜索条件进行查询数据并渲染
  • 点击重置按钮的时候清空搜索条件,并重新渲染数据

1.2. 新增导航

1.2.1. 页面效果

016-管理后台导航功能开发_搜索_02

1.2.2. 功能要求

  • 导航名称,导航链接为必填项
  • 导航名称需做唯一性校验
  • 导航链接需要做唯一性校验
  • 导航图标如果不填则默认填充一个系统定义的默认图标
  • 导航排序如果不填写则默认填写为999(最大放到最后)
  • 导航排序填写范围为[0-999]
  • 是否显示默认选中显示
  • 是否默认导航默认选中否
  • 成功添加数据后列表页进行刷新

1.3. 修改导航

1.3.1. 页面效果

016-管理后台导航功能开发_导航_03

1.3.2. 功能要求

  • 导航名称,默认导航不可修改仅查看
  • 导航链接需做唯一性验证
  • 成功修改数据后列表页进行刷新

1.4. 删除导航

1.4.1. 功能要求

  • 点击删除按钮需给出提示框进行二次确认,当二次确认后可进行删除操作
  • 成功删除数据后列表页进行刷新

1.5. 查询明细

1.5.1. 页面效果

016-管理后台导航功能开发_搜索_04

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. 测试查询列表

016-管理后台导航功能开发_bootstrap_05

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测试新增

016-管理后台导航功能开发_导航_06


016-管理后台导航功能开发_bc_07

016-管理后台导航功能开发_bootstrap_08

016-管理后台导航功能开发_bootstrap_09

016-管理后台导航功能开发_导航_10

016-管理后台导航功能开发_bootstrap_11

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();
}



上一篇:017-管理后台通用js提取
下一篇:没有了
网友评论