六、模块实现:用户管理模块(1)

    1. 用户管理模块
      1. 配置类

首先,在包“com.example.demo”中新建一个“MybatisPlusConfig”类(在这个类中还可以对mybatis-plus进一步进行配置,本例中启用了分页插件),代码如下:

package com.example.demo;

 

import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.Configuration;

import org.springframework.transaction.annotation.EnableTransactionManagement;

 

import com.baomidou.mybatisplus.plugins.PaginationInterceptor;

 

@EnableTransactionManagement

@Configuration

public class MybatisPlusConfig {

   

     /**

     * 分页插件

     */

    @Bean

    public PaginationInterceptor paginationInterceptor() {

        return new PaginationInterceptor();

    }

 

}

相关知识点:

(1)@EnableTransactionManagement注解

@EnableTransactionManagement 开启事务支持后,然后在访问数据库的Service方法上添加注解 @Transactional 便可。

(2)@Configuration注解

@Configuration用于类,表明这个类是beans定义的源,可以定义bean。在 @Component 注解的类中不能定义类内依赖的@Bean注解的方法,而@Configuration可以。

(3)@Bean注解

用@Bean注解的方法:会实例化、配置并初始化一个新的对象,这个对象会由spring IoC 容器管理。

接着,在包“com.example.demo”中新建一个“WebConfig”类(用来映射用户上传的文件以及后面实现登录拦截器的设置),代码如下:

package com.example.demo;

 

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.beans.factory.annotation.Value;

import org.springframework.context.annotation.Configuration;

import org.springframework.web.servlet.config.annotation.InterceptorRegistration;

import org.springframework.web.servlet.config.annotation.InterceptorRegistry;

import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;

import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

 

@Configuration

public class WebConfig implements WebMvcConfigurer {

   

    //图片存放根路径,从application.yml中读取upload

    @Value("${upload}")

    private String UPLOAD_PATH;

   

    /**

     * 文件上传

     */

    @Override

    public void addResourceHandlers(ResourceHandlerRegistry registry) {

    //外部静态资源映射路径,用来上传文件

    String filePath = "file:" + UPLOAD_PATH;

        registry.addResourceHandler("/upload/**").addResourceLocations(filePath);

    }

}

@Value("${upload}")表示从配置文件application.yml中读入配置信息,“upload”为配置的属性名称。registry.addResourceHandler("/upload/**"),把上传路径映射到“/upload/”的url路径中,可以通过url地址访问到文件。

      1. 用户model

在包“com.example.demo.model”中新建一个“User”类(如果自己添加model类时,只须定义好属性,然后利用eclipse的生成getter和setter功能,直接生成代码),代码如下:

package com.example.demo.model;

import java.sql.Timestamp;

 

/**

 * 与数据库中的物理表映射,增删改一般都用这个模型实现

 */

import com.baomidou.mybatisplus.annotations.TableId;

import com.baomidou.mybatisplus.annotations.TableName;

import com.fasterxml.jackson.annotation.JsonFormat;

 

@TableName("t_sys_user")//数据库对应表名

public class User {

   

    @TableId

    private String id;//@TableId表示主键,与字段名称大小写一致

   

    private String username;//与字段名称大小写一致

    private String password;//与字段名称大小写一致

   

    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")

    private Timestamp birthday;//与字段名称大小写一致

   

    private String photo;//与字段名称大小写一致

    private String introduce;//与字段名称大小写一致

    private String usertype;//与字段名称大小写一致

   

    public String getUsertype() {

         return usertype;

    }

    public void setUsertype(String usertype) {

         this.usertype = usertype;

    }

    public Timestamp getBirthday() {

         return birthday;

    }

    public void setBirthday(Timestamp birthday) {

         this.birthday = birthday;

    }

    public String getPhoto() {

         return photo;

    }

    public void setPhoto(String photo) {

         this.photo = photo;

    }

    public String getIntroduce() {

         return introduce;

    }

    public void setIntroduce(String introduce) {

         this.introduce = introduce;

    }

    public String getId() {

         return id;

    }

    public void setId(String id) {

         this.id = id;

    }

    public String getUsername() {

         return username;

    }

    public void setUsername(String username) {

         this.username = username;

    }

    public String getPassword() {

         return password;

    }

    public void setPassword(String password) {

         this.password = password;

    }

   

}

相关知识点:

(1)@TableName注解

Mybatis plus插件中的注解,指明model与数据库中关联的表名。

(2)@TableId注解

@TableId表示主键,与字段名称大小写一致。在设计表时字段名称建议不要使用大写字母,否则定义model属性时,生成gettersetter后看起来比较乱。

(3)@JsonFormat注解

@JsonFormat注解来源于jackson,Jackson是一个简单基于Java应用库,Jackson可以轻松的将Java对象转换成json对象和xml文档,同样也可以将json、xml转换成Java对象。

      1. 用户vo

在包“com.example.demo.vo”中新建一个“UserVO”类(如果自己添加类时,只须定义好属性,然后利用eclipse的生成getter和setter功能,直接生成代码),代码如下:

package com.example.demo.vo;

 

import java.sql.Timestamp;

 

/**

 * 展示模型(一般不做修改操作),不一定与物理表字段一致,可以是几张关联表的字段组合

 * @author gjq

 *

 */

public class UserVO{

 

    private String id;

   

    private String username;

    private String password;

   

    private Timestamp birthday;

   

    private String photo;

    private String introduce;

    private String usertype;

   

//  private String rolename;//关联角色表中的name字段,用来存放角色名

 

    public String getUsertype() {

         return usertype;

    }

 

    public void setUsertype(String usertype) {

         this.usertype = usertype;

    }

   

    public String getId() {

         return id;

    }  

 

    public void setId(String id) {

         this.id = id;

    }

 

    public String getUsername() {

         return username;

    }

 

    public void setUsername(String username) {

         this.username = username;

    }

 

    public String getPassword() {

         return password;

    }

 

    public void setPassword(String password) {

         this.password = password;

    }

 

    public Timestamp getBirthday() {

         return birthday;

    }

 

    public void setBirthday(Timestamp birthday) {

         this.birthday = birthday;

    }

 

    public String getPhoto() {

         return photo;

    }

 

    public void setPhoto(String photo) {

         this.photo = photo;

    }

 

    public String getIntroduce() {

         return introduce;

    }

 

    public void setIntroduce(String introduce) {

         this.introduce = introduce;

    }

 

//  public String getRolename() {

//       return rolename;

//  }

//

//  public void setRolename(String rolename) {

//       this.rolename = rolename;

//  }

   

   

}

VO类与model类的区别:VO主要与前端展示结合使用,可以是多张表的组合数据,以显示功能为主;而model与表是一一对应的,model一般属性与表中的字段一致,实现表数据的增删改查功能,是更底层的数据模型。

      1. 用户mapper类以及xml文件

在包“com.example.demo.mapper”中新建一个“UserMapper”接口,代码如下:

package com.example.demo.mapper;

 

import java.util.List;

 

import org.apache.ibatis.annotations.Mapper;

import com.baomidou.mybatisplus.mapper.BaseMapper;

import com.baomidou.mybatisplus.plugins.pagination.Pagination;

import com.example.demo.model.User;

import com.example.demo.vo.UserVO;

 

@Mapper

public interface  UserMapper  extends BaseMapper<User>{

//  Integer listCount();

//  User findUserByUsername(String username);

     List<UserVO> selectUserListPage(Pagination page ,UserVO userVO);

}

通过继承BaseMapper<User>,拥有了通用mapper的基本增删改查功能,因此用户表的基本增删改查功能不必再实现,这里定义的“selectUserListPage”是调用xml文件中的自定义查询,主要是可以实现多表连接查询和多条件查询(本例中较为简单,没有用到连接查询),扩展通用mapper没有的功能。

在“src/main/resources” 中的“mapper”文件夹中,新建一个文件,命名为“UserMapper.xml”,代码如下:

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE mapper PUBLIC "-//mybatis.org/DTD Mapper 3.0" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

 

<!-- 指明当前xml对应的Mapper -->

<mapper namespace="com.example.demo.mapper.UserMapper">

    <!-- 多表查询,Select as后面的名称必须与UserVO属性名大小写一致  -->

    <select id="selectUserListPage" parameterType="com.example.demo.vo.UserVO" resultType="com.example.demo.vo.UserVO">

        SELECT

            u.id as id,

            u.username as username,

            u.password as password,

            u.birthday as birthday,

            u.photo as photo,

            u.usertype as usertype,

            u.introduce as introduce

<!--             r.name as rolename -->

        FROM

            t_sys_user u

<!--         LEFT JOIN t_sys_role_user ru ON u.id = ru.sys_user_id

        LEFT JOIN t_sys_role r ON ru.sys_role_id = r.id -->

        WHERE 1=1

        <if test="username != null">

            and u.username like  concat('%',#{username},'%')

        </if>

<!--         <if test="rolename != null">

            and r.name like  concat('%',#{rolename},'%')

        </if> -->

      

    </select>

<!-- 以下为示例 -->

<!--     <select id="listCount" resultType="Integer">

        SELECT COUNT(*) FROM t_sys_user;

    </select>

    <select id="findUserByUsername" parameterType="String" resultType="User">

        SELECT * FROM t_sys_user WHERE username=#{username}

    </select> -->

   

</mapper>

Xml文件采用mybatis语法格式来定义查询语句,namespace="com.example.demo.mapper.UserMapper"表示关联的mapper类,包名必须与自己源码中的包名一致,id="selectUserListPage"、parameterType="com.example.demo.vo.UserVO"、resultType="com.example.demo.vo.UserVO"分别与mapper中自定义的selectUserListPage函数名称、参数类型(Pagination是分页参数)、返回值类型一致,as语句后面的名称必须与返回值类型UserVO的属性名称大小写一致,test="username != null"中的“username”是参数类型UserVO中的属性名称,如果“username”值不为空,则按照该值进行模糊查询。其他查询语句的定义可以参考注释部分的代码,也可以访问官方网址:http://www.mybatis.org/mybatis-3/zh/sqlmap-xml.html

      1. 用户service

在包“com.example.demo.service”中新建一个“UserService”类,代码如下:

package com.example.demo.service;

 

import java.util.List;

 

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Service;

import org.springframework.transaction.annotation.Transactional;

import org.springframework.util.StringUtils;

import com.baomidou.mybatisplus.mapper.EntityWrapper;

import com.baomidou.mybatisplus.plugins.Page;

import com.example.demo.mapper.UserMapper;

import com.example.demo.model.User;

import com.example.demo.util.Convert;

import com.example.demo.util.SnowflakeIdWorker;

import com.example.demo.vo.DataTableResult;

import com.example.demo.vo.UserVO;

 

 

@Service

public class UserService {

   

   

    @Autowired

    private UserMapper userMapper;//注入mapper进行数据操作

   

    /**

     * 自定义xml形式的查询

     * @return

     */

//  public Integer listCount() {

//      

//       return userMapper.listCount();

//      

//  }

    /**

     * 自定义xml形式的查询

     * @param username

     * @return

     */

//  public User findUserByUsername(String username) {

//       return userMapper.findUserByUsername(username);

//  }

   

    //对于执行数据修改的方法加上事务处理

    @Transactional

    public int delete(String ids) {

         //ids,逗号隔开的主键

         List<String> listid=Convert.toListStrArray(ids);

         return userMapper.deleteBatchIds(listid);

    }

   

    public User selectById(String id) {  

         //userMapper.selectOne(user),selectOne可以按照其他字段来查询一条记录

         return userMapper.selectById(id);

    }

   

    public User selectByUser(User user) {

         return userMapper.selectOne(user);

    }

   

    //对于执行数据修改的方法加上事务处理

    @Transactional

    public int updateById(User user) {

         return userMapper.updateById(user);

    }

   

    //对于执行数据修改的方法加上事务处理

    @Transactional

    public int insert(User user) {

         //添加雪花主键id

         user.setId(SnowflakeIdWorker.getUUID());

         int n = userMapper.insert(user);

         //密码安全一点的话,不能原文保存,应该用MD5,也可以加盐处理

//       n=1/0; //事务测试

         return n;

    }

    /**

     * 采用集成的查询方法

     * @param username

     * @return

     */

    public List<User> selectList(String username) {

         EntityWrapper<User> wrapper = new EntityWrapper<User>();

        wrapper.like("username", username);

         return userMapper.selectList(wrapper);

    }

   

    /**

     * 分页查询

     * @param user

     * @return

     */

    public DataTableResult selectUserListPage(UserVO userVO,int start,int length,String orderField,String orderDir) {

         Page<UserVO> page = null;

         //排序

         if(!StringUtils.isEmpty(orderDir)&&!StringUtils.isEmpty(orderField)) {

             if(orderDir.equals("asc")) {

                  page = new Page<>(start/length + 1, length,orderField,true);// 当前页,每页总条数 构造 page 对象

             }else {

                  page = new Page<>(start/length + 1, length,orderField,false);// 当前页,每页总条数 构造 page 对象

             }

            

         }else {

             page = new Page<>(start/length + 1, length,"id",false);//默认id降序

         }

        page.setRecords(userMapper.selectUserListPage(page, userVO));

       

        DataTableResult result = new DataTableResult();

         result.setRecordsTotal(page.getTotal());

         result.setRecordsFiltered(page.getTotal());

         result.setData(page.getRecords());

         return result;

    }

 

}

Service类实现业务层的代码,是最为复杂的部分,通过调用mapper类的方法实现对数据的增删改查操作,基本方法都比较固定,学会套用即可,类中用到的注解如下:

(1)@Service注解:如果一个类带了@Service注解,将自动注册到Spring容器,默认名称是类名(头字母小写),可以@Service(“xxxx”)这样来指定。

(2)@Autowired注解:@Autowired表示被修饰的类需要注入对象,spring会扫描所有被@Autowired标注的类,然后根据类型在ioc容器中找到匹配的类注入。

(3)@Transactional注解:@Transactional可以作用于接口、接口方法、类以及类方法上;当作用于类上时,该类的所有 public 方法将都具有该类型的事务属性,同时,我们也可以在方法级别使用该标注来覆盖类级别的定义。

      1. 用户controller

在包“com.example.demo.controller”中新建一个“UserController”类,代码如下:

package com.example.demo.controller;

 

import java.io.File;

import java.io.IOException;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpSession;

 

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.beans.factory.annotation.Value;

import org.springframework.stereotype.Controller;

import org.springframework.ui.Model;

import org.springframework.util.StringUtils;

import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.web.bind.annotation.RequestParam;

import org.springframework.web.bind.annotation.ResponseBody;

import org.springframework.web.multipart.MultipartFile;

 

import com.example.demo.model.User;

import com.example.demo.service.UserService;

import com.example.demo.util.SnowflakeIdWorker;

import com.example.demo.vo.DataTableResult;

import com.example.demo.vo.Json;

import com.example.demo.vo.UserVO;

import com.google.code.kaptcha.Constants;

 

@Controller

@RequestMapping("/UserController")

public class UserController {

 

    private final Logger logger = LoggerFactory.getLogger(this.getClass());

 

    private String prefix = "admin/user";// 页面的路径,注意admin前面不要有/

 

    // 图片存放根路径,从application.yml中读取upload

    @Value("${upload}")

    private String UPLOAD_PATH;

 

    @Autowired

    private UserService userService;// 注入业务层的service

 

    // 未加入@ResponseBody用来返回数据给页面

    @RequestMapping("view")

    public String view(Model model) {

         return prefix + "/view";

    }

 

    // @ResponseBody,直接通过js异步返回数据给页面

    @RequestMapping("list")

    @ResponseBody

    public DataTableResult list(HttpServletRequest request, UserVO userVO) {

        // DataTableResult返回给datatables控件的数据格式

         DataTableResult result = new DataTableResult();

         // 获取分页参数

         int start = Integer.parseInt(request.getParameter("start"));

         int length = Integer.parseInt(request.getParameter("length"));

         // 获取排序字段

         String orderIdx = request.getParameter("order[0][column]");

         // 获取排序字段名

         String orderField = request.getParameter("columns[" + orderIdx + "][name]");

         // 获取排序方式,降序desc或者升序asc

         String orderDir = request.getParameter("order[0][dir]");

         // 调用分页查询方法

         result = userService.selectUserListPage(userVO, start, length, orderField, orderDir);

//       result.setDraw(userVO.getDraw());

         return result;

    }

    // @ResponseBody,直接通过js异步返回数据给页面

    @RequestMapping("insert")

    @ResponseBody

    public Json insert(User user) {

         Json j = new Json();

         if (userService.insert(user) > 0) {

             j.setSuccess(true);

             j.setMsg("添加成功!");

         } else {

             j.setSuccess(false);

             j.setMsg("添加失败!");

         }

         return j;

    }

 

    // @ResponseBody,直接通过js异步返回数据给页面

    @RequestMapping("update")

    @ResponseBody

    public Json updateById(User user) {

         Json j = new Json();

         if (userService.updateById(user) > 0) {

             j.setSuccess(true);

             j.setMsg("修改成功!");

         } else {

             j.setSuccess(false);

             j.setMsg("修改失败!");

         }

         return j;

    }

 

    // @ResponseBody,直接通过js异步返回数据给页面

    @RequestMapping("select")

    @ResponseBody

    public Json selectById(User user) {

         Json j = new Json();

         j.setSuccess(true);

         j.setObj(userService.selectById(user.getId()));

         return j;

    }

 

    // @ResponseBody,直接通过js异步返回数据给页面

    @RequestMapping("delete")

    @ResponseBody

    public Json delete(HttpServletRequest request) {

         Json j = new Json();

         String ids = request.getParameter("ids");

         if (!StringUtils.isEmpty(ids)) {

             j.setSuccess(true);

             j.setObj("成功删除" + userService.delete(ids) + "条记录");

         } else {

             j.setSuccess(false);

             j.setMsg("没有需要删除的记录!");

         }

         return j;

    }

 

    // @ResponseBody,直接通过js异步返回数据给页面

    // @RequestParam("file[]") MultipartFile[] file 多个文件

    @RequestMapping("upload")

    @ResponseBody

    public Json upload(HttpServletRequest request, @RequestParam("file") MultipartFile file) {

         Json j = new Json();

         if (!file.isEmpty()) {

             try {

                  String originalFilename = file.getOriginalFilename();

                  // 随机文件名

                  String newFileName = SnowflakeIdWorker.getUUID()

                          + originalFilename.substring(originalFilename.lastIndexOf("."));

                  // 上传文件路径

                  File upload = new File(UPLOAD_PATH, "images/");

                  if (!upload.exists())

                      upload.mkdirs();

                  String uploadPath = upload + "\\";

                  logger.info("uploadPath = " + uploadPath);

                  File uploadfile = new File(uploadPath + newFileName);

                  // 将上传文件保存到一个目标文件当中

                  file.transferTo(uploadfile);

                  j.setSuccess(true);

                  j.setObj("/upload/images/" + newFileName);

             } catch (IllegalStateException | IOException e) {

                  // TODO Auto-generated catch block

                  e.printStackTrace();

                  j.setSuccess(false);

                  j.setObj("上传异常");

             }

 

         } else {

             j.setSuccess(false);

             j.setObj("上传失败");

         }

         return j;

    }

 

}

Controller类负责数据的传入与传出,可以做一些数据校验,但尽量不涉及底层的数据库操作,应该交给service来实现,相关知识点如下:

(1)@Controller用于标记在一个类上,使用它标记的类就是一个SpringMVC Controller 对象。

(2)@RequestMapping是一个用来处理请求地址映射的注解,可用于类或方法上。用于类上,表示类中的所有响应请求的方法都是以该地址作为父路径。

(3)@ResponseBody这个注解通常使用在控制层(controller)的方法上,其作用是将方法的返回值以特定的格式写入到response的body区域,进而将数据返回给客户端,例如JSON数据,常用在AJAX中的异步请求调用。当方法上面没有写ResponseBody,底层会将方法的返回值封装为ModelAndView对象,返回页面地址。

(4)@Value("${upload}")表示从配置文件application.yml中读入配置信息,“upload”为配置的属性名称。

(5)logger用来打印日志,在控制台或者logs文件夹下面的日志文件中显示信息,常用来调试和跟踪变量的值,要学会使用,例如logger.info()方法等。

(6)方法中如何获取页面传递过来的参数:一种是通过定义HttpServletRequest参数request,来获取参数,该方法可以获取各种参数,但是需要自己一一获取,常用在一些特殊参数值的获取;另一种是通过对象,如User类型参数user,如果参数名与类中的属性名大小写相同,则直接自动赋值,该方法比较常用。

(7)返回值:一种是String类型,一般是用来返回页面地址;另一种是对象类型,如Json,是自定义的数据类型,用来封装异步返回的数据。

(8)文件上传:利用了MultipartFile类型的参数file获取文件对象,通过file.transferTo()方法保存到配置文件的上传路径中

简单测试一下接口:

(1)运行项目

(2)测试

打开浏览器,建议用chrome或者360浏览器的极速模式,输入地址http://127.0.0.1:8080/UserController/select?id=1,看到数据就表示访问成功:

uploading.gif转存失败重新上传取消uploading.gif正在上传…重新上传取消uploading.gif正在上传…重新上传取消uploading.gif正在上传…重新上传取消uploading.gif正在上传…重新上传取消uploading.gif正在上传…重新上传取消

      1. 后台管理主界面及首页

后台管理界面采用了开源项目“hAdmin”,GitHub地址:https://github.com/huangyaoxin/hAdmin。hAdmin是一个免费的后台管理模版,该模版基于bootstrap(https://v3.bootcss.com/components/)与jQuery(https://www.runoob.com/jquery/jquery-tutorial.html)制作,集成了众多常用插件。

Spring Boot 中推荐使用Thymeleaf作为模板引擎,因为 Thymeleaf 提供了完美的 Spring MVC支持。Thymeleaf是一个跟 Velocity、FreeMarker类似的模板引擎,它可以完全替代JSP。官方的使用教程地址:https://www.thymeleaf.org/doc/tutorials/3.0/usingthymeleaf.html。中文版教程:https://www.e-learn.cn/thymeleaf

后台页面采用bootstrap与jQuery框架,结合Thymeleaf模板引擎实现,模板文件为带Thymeleaf标签的html文件,统一放在templates文件夹里面。

在templates文件夹新建一个文件夹“admin”,因为controller的转发路径都以admin开头。

添加主界面文件,在“admin”文件夹-> 右键->new->file,输入“index.html”,代码如下:

<!DOCTYPE html>

<html xmlns:th="http://www.thymeleaf.org">

<head>

    <meta charset="utf-8">

    <meta name="viewport" content="width=device-width, initial-scale=1.0">

    <meta name="renderer" content="webkit">

    <title> hAdmin- 主页</title>

    <meta name="keywords" content="">

    <meta name="description" content="">

    <!--[if lt IE 9]>

    <meta http-equiv="refresh" content="0;ie.html" />

    <![endif]-->

    <link rel="shortcut icon" href="favicon.ico">

    <link th:href="@{/static/css/bootstrap.min.css?v=3.3.6}" rel="stylesheet">

    <link th:href="@{/static/css/font-awesome.min.css?v=4.4.0}" rel="stylesheet">

    <link th:href="@{/static/css/animate.css}" rel="stylesheet">

    <link th:href="@{/static/css/style.css?v=4.1.0}" rel="stylesheet">

</head>

<body class="fixed-sidebar full-height-layout gray-bg" style="overflow:hidden">

    <div id="wrapper">

        <!--左侧导航开始-->

        <nav class="navbar-default navbar-static-side" role="navigation">

            <div class="nav-close"><i class="fa fa-times-circle"></i>

            </div>

            <div class="sidebar-collapse">

                <ul class="nav" id="side-menu">

                    <li class="nav-header">

                        <div class="dropdown profile-element">

                            <a data-toggle="dropdown" class="dropdown-toggle" href="#">

                                <span class="clear">

                                    <span class="block m-t-xs" style="font-size:20px;">

                                        <i class="fa fa-bank"></i>

                                        <strong class="font-bold">管理系统</strong>

                                    </span>

                                </span>

                            </a>

                        </div>

                        <div class="logo-element">管理系统

                        </div>

                    </li>

                    <li>

                        <a class="J_menuItem" href="/home">

                            <i class="fa fa-home"></i>

                            <span class="nav-label">主页</span>

                        </a>

                    </li>

                    <li>

                        <a href="#">

                            <i class="fa fa-desktop"></i>

                            <span class="nav-label">系统设置</span>

                            <span class="fa arrow"></span>

                        </a>

                        <ul class="nav nav-second-level">

                            <li>

                                <a class="J_menuItem" href="/UserController/view">用户管理</a>

                            </li>

                            <li>

                                <a class="J_menuItem" href="/PermissionController/view">权限管理</a>

                            </li>

                            <li>

                                <a class="J_menuItem" href="/RoleController/view">角色管理</a>

                            </li>                           

                        </ul>

                    </li>

                   

                    <li>

                        <a href="#">

                            <i class="fa fa-file-o"></i>

                            <span class="nav-label">测试分类</span>

                            <span class="fa arrow"></span>

                        </a>

                        <ul class="nav nav-second-level">

                            <li>

                                <a class="J_menuItem" href="graph_echarts.html">测试页面</a>

                            </li>

                          

                        </ul>

                    </li>

 

                </ul>

            </div>

        </nav>

        <!--左侧导航结束-->

        <!--右侧部分开始-->

        <div id="page-wrapper" class="gray-bg dashbard-1">

            <div class="row border-bottom">

                <nav class="navbar navbar-static-top" role="navigation" style="margin-bottom: 0">

                    <div class="navbar-header"><a class="navbar-minimalize minimalize-styl-2 btn btn-info " href="#"><i class="fa fa-bars"></i> </a>

                        <form role="search" class="navbar-form-custom" method="post" action="search_results.html">

                            <div class="form-group">

                                <input type="text" placeholder="请输入您需要查找的内容 …" class="form-control" name="top-search" id="top-search">

                            </div>

                        </form>

                    </div>

                    <ul class="nav navbar-top-links navbar-right">

                        <li>

                           <span th:text="${username}"></span><span><a href="/UserController/logout">注销</a></span>

                        </li>

                        <li class="dropdown">

                            <a class="dropdown-toggle count-info" data-toggle="dropdown" href="#">

                                <i class="fa fa-envelope"></i> <span class="label label-warning">16</span>

                            </a>

                            <ul class="dropdown-menu dropdown-messages">

                                <li class="m-t-xs">

                                    <div class="dropdown-messages-box">

                                        <a href="profile.html" class="pull-left">

                                            <img alt="image" class="img-circle" th:src="@{/static/img/a7.jpg}">

                                        </a>

                                        <div class="media-body">

                                            <small class="pull-right">46小时前</small>

                                            <strong>小四</strong> 是不是只有我死了,你们才不骂爵迹

                                            <br>

                                            <small class="text-muted">3天前 2014.11.8</small>

                                        </div>

                                    </div>

                                </li>

                                <li class="divider"></li>

                                <li>

                                    <div class="dropdown-messages-box">

                                        <a href="profile.html" class="pull-left">

                                            <img alt="image" class="img-circle" th:src="@{/static/img/a4.jpg}">

                                        </a>

                                        <div class="media-body ">

                                            <small class="pull-right text-navy">25小时前</small>

                                            <strong>二愣子</strong> 呵呵

                                            <br>

                                            <small class="text-muted">昨天</small>

                                        </div>

                                    </div>

                                </li>

                                <li class="divider"></li>

                                <li>

                                    <div class="text-center link-block">

                                        <a class="J_menuItem" href="mailbox.html">

                                            <i class="fa fa-envelope"></i> <strong> 查看所有消息</strong>

                                        </a>

                                    </div>

                                </li>

                            </ul>

                        </li>

                        <li class="dropdown">

                            <a class="dropdown-toggle count-info" data-toggle="dropdown" href="#">

                                <i class="fa fa-bell"></i> <span class="label label-primary">8</span>

                            </a>

                            <ul class="dropdown-menu dropdown-alerts">

                                <li>

                                    <a href="mailbox.html">

                                        <div>

                                            <i class="fa fa-envelope fa-fw"></i> 您有16条未读消息

                                            <span class="pull-right text-muted small">4分钟前</span>

                                        </div>

                                    </a>

                                </li>

                                <li class="divider"></li>

                                <li>

                                    <a href="profile.html">

                                        <div>

                                            <i class="fa fa-qq fa-fw"></i> 3条新回复

                                            <span class="pull-right text-muted small">12分钟钱</span>

                                        </div>

                                    </a>

                                </li>

                                <li class="divider"></li>

                                <li>

                                    <div class="text-center link-block">

                                        <a class="J_menuItem" href="notifications.html">

                                            <strong>查看所有 </strong>

                                            <i class="fa fa-angle-right"></i>

                                        </a>

                                    </div>

                                </li>

                            </ul>

                        </li>

                    </ul>

                </nav>

            </div>

            <div class="row J_mainContent" id="content-main">

                <iframe id="J_iframe" width="100%" height="100%" src="/home" frameborder="0" data-id="/home" seamless></iframe>

            </div>

        </div>

        <!--右侧部分结束-->

    </div>

 

    <!-- 全局js -->

    <script th:src="@{/static/js/jquery.min.js?v=2.1.4}"></script>

    <script th:src="@{/static/js/bootstrap.min.js?v=3.3.6}"></script>

    <script th:src="@{/static/js/plugins/metisMenu/jquery.metisMenu.js}"></script>

    <script th:src="@{/static/js/plugins/slimscroll/jquery.slimscroll.min.js}"></script>

    <script th:src="@{/static/js/plugins/layer/layer.min.js}"></script>

 

    <!-- 自定义js -->

    <script th:src="@{/static/js/hAdmin.js?v=4.1.0}"></script>

    <script type="text/javascript" th:src="@{/static/js/index.js}"></script>

 

    <!-- 第三方插件 -->

    <script th:src="@{/static/js/plugins/pace/pace.min.js}"></script>

</body>

</html>

 

在html标签中需要加入“<html xmlns:th="http://www.thymeleaf.org">”表示是Thymeleaf模板文件,在页面中以“th:”开头的也都是Thymeleaf标签,本项目中只是简单用了一些标签,大部分效果还是通过jquery来控制。

 

添加首页文件,在“admin”文件夹-> 右键->new->file,输入“home.html”,代码如下:

<!DOCTYPE html>

<html xmlns:th="http://www.thymeleaf.org">

<head>

    <meta charset="utf-8">

    <meta name="viewport" content="width=device-width, initial-scale=1.0">

    <meta name="renderer" content="webkit">

    <title>主页</title>

    <meta name="keywords" content="">

    <meta name="description" content="">

    <!--[if lt IE 9]>

    <meta http-equiv="refresh" content="0;ie.html" />

    <![endif]-->

    <link rel="shortcut icon" href="favicon.ico">

    <link th:href="@{/static/css/bootstrap.min.css?v=3.3.6}" rel="stylesheet">

    <link th:href="@{/static/css/font-awesome.min.css?v=4.4.0}" rel="stylesheet">

    <link th:href="@{/static/css/animate.css}" rel="stylesheet">

    <link th:href="@{/static/css/style.css?v=4.1.0}" rel="stylesheet">

</head>

 

<body class="gray-bg">

    <div class="row wrapper border-bottom white-bg page-heading">

        <div class="col-sm-4">

            <h2>主页</h2>

        </div>

    </div>

 

    <div class="wrapper wrapper-content">

        <div class="row">

            <div class="col-sm-12">

                <div class="middle-box text-center animated fadeInRightBig">

                    <h3 class="font-bold">这里是主页</h3>

                </div>

            </div>

        </div>

    </div>

   

    <!-- 全局js -->

    <script th:src="@{/static/js/jquery.min.js?v=2.1.4}"></script>

    <script th:src="@{/static/js/bootstrap.min.js?v=3.3.6}"></script>

    <script th:src="@{/static/js/plugins/layer/layer.min.js}"></script>

    <!-- 自定义js -->

    <script th:src="@{/static/js/content.js}"></script>

</body>

</html>

Home页面以iframe形式嵌入到index.html页面中。

模板文件不能直接访问,必须通过后台转发,因此在包“com.example.demo.controller”中新建一个“HomeController”类来转发上面的地址,代码如下:

package com.example.demo.controller;

 

import javax.servlet.http.HttpServletRequest;

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

import org.springframework.stereotype.Controller;

import org.springframework.ui.Model;

import org.springframework.web.bind.annotation.RequestMapping;

 

@Controller

public class HomeController {

 

    private final Logger logger = LoggerFactory.getLogger(this.getClass());

   

    // 未加入@ResponseBody用来返回数据给页面

    @RequestMapping("/index")

    public String index(HttpServletRequest request,Model model) {

         return "admin/index";

    }

 

    // 未加入@ResponseBody用来返回数据给页面

    @RequestMapping("/home")

    public String home(Model model) {

         return "admin/home";

    }

 

}

确保项目在运行中,如果停止了,通过 启动,打开浏览器,输入地址:http://127.0.0.1:8080/index,可以看到以下效果:

url地址中的index是@RequestMapping("/index")映射的地址,会按照返回值转化为templates路径中的“admin/index.html”,扩展名可以省略。

      1. 用户管理界面

添加用户管理界面,在“admin”文件夹中新建一个文件夹“user”,在“user”文件夹-> 右键->new->file,输入“view.html”(这里的路径主要是由controller的转发方法决定,保持一致即可),代码如下:

<!DOCTYPE html>

<html xmlns:th="http://www.thymeleaf.org">

<head>

<meta charset="utf-8">

<meta name="viewport" content="width=device-width, initial-scale=1.0">

<meta name="renderer" content="webkit">

<title>用户管理</title>

<meta name="keywords" content="">

<meta name="description" content="">

<!--[if lt IE 9]>

    <meta http-equiv="refresh" content="0;ie.html" />

    <![endif]-->

<link rel="shortcut icon" href="favicon.ico">

<link th:href="@{/static/css/bootstrap.min.css?v=3.3.6}"

    rel="stylesheet">

<link th:href="@{/static/css/font-awesome.min.css?v=4.4.0}"

    rel="stylesheet">

<link th:href="@{/static/css/animate.css}" rel="stylesheet">

<link th:href="@{/static/css/style.css?v=4.1.0}" rel="stylesheet">

<!-- Data Tables -->

<link

    th:href="@{/static/css/plugins/dataTables/dataTables.bootstrap.css}"

    rel="stylesheet">

<!-- Ztree -->  

<link rel="stylesheet" th:href="@{/static/css/plugins/ztree/zTreeStyle/zTreeStyle.css}" type="text/css">

<!-- toastr -->

<link th:href="@{/static/css/plugins/toastr/toastr.min.css}" rel="stylesheet">  

<!-- summernote -->

<link th:href="@{/static/css/plugins/summernote/summernote.css}" rel="stylesheet">

<link th:href="@{/static/css/plugins/summernote/summernote-bs3.css}" rel="stylesheet">

<!-- dropzone -->

<link th:href="@{/static/css/plugins/dropzone/basic.css}" rel="stylesheet">

<link th:href="@{/static/css/plugins/dropzone/dropzone.css}" rel="stylesheet">

           

</head>

 

<body class="gray-bg">

    <div class="wrapper wrapper-content animated fadeInRight">

        <div class="row">

            <div class="col-sm-12">

                <div class="ibox float-e-margins">

                    <div class="ibox-title">

                        <h5>用户管理</h5>

                        <div class="ibox-tools">

                            <a class="collapse-link">

                                <i class="fa fa-chevron-up"></i>

                            </a>

                            <a class="dropdown-toggle" data-toggle="dropdown" href="table_data_tables.html#">

                                <i class="fa fa-wrench"></i>

                            </a>

                            <ul class="dropdown-menu dropdown-user">

                                <li><a href="table_data_tables.html#">选项1</a>

                                </li>

                                <li><a href="table_data_tables.html#">选项2</a>

                                </li>

                            </ul>

                            <a class="close-link">

                                <i class="fa fa-times"></i>

                            </a>

                        </div>

                    </div>

                    <div class="ibox-content">

                        <div class="form-horizontal">

                            <div class="form-group">

                                            <div class="col-sm-4">

                                                <button id="btn_add" class="btn btn-primary btn-sm" ><i class="fa fa-plus"></i>&nbsp;添加</button>

                                                <button id="btn_del" class="btn btn-danger btn-sm m-l-sm" ><i class="fa fa-remove"></i>&nbsp;删除</button>

                                                <button id="btn_export" class="btn btn-primary btn-sm m-l-sm" onclick="$('#table').tableExport({type:'excel',escape:'false',tableName:'导出表格',ignoreColumn:[0,4]});"><i class="fa fa-file-excel-o"></i>&nbsp;导出</button>

                                            </div>

                                            <label class="col-sm-1 control-label">搜索:</label>

                                            <div class="col-sm-2">

                                                <select id="searchfield" class="form-control">

                                                     <!-- value为查找字段名称 -->

                                                     <option value="username">用户名</option>

                                                </select>

                                               

                                            </div>

                                            <div class="col-sm-3">

                                                <input id="keyword" type="search" class="form-control" placeholder="关键字" />

                                            </div>

                                            <div class="col-sm-2">

                                                <button id="btn_search" class="btn btn-primary btn-sm m-l-sm" ><i class="fa fa-search"></i>&nbsp;搜索</button>

                                            </div>

                                           

                                 </div>

                          </div>

                        <table class="table table-striped table-bordered table-hover" id="table">

                            <thead>

                                       <tr>

                                            <th style="padding-left: 10px;">

                                                <input type="checkbox" id="cb_selectAll" class="input-lg" style="width:20px;height:20px;"/>

                                            </th>

                                            <th>id</th>

                                            <th>用户名</th>

                                            <th>用户类型</th>

                                            <th>操作</th>

                                       </tr>

                               </thead>

                        </table>

                    </div>

                </div>

            </div>

        </div>

       

    </div>

 

   

 <!-- 模态窗口 -->  

<div class="modal fade" data-backdrop="static" id="modal" tabindex="-1" role="dialog" aria-hidden="true">

    <div class="modal-dialog modal-lg">

         <div class="modal-content">

             <div class="modal-header">

                  <button type="button" class="close" data-dismiss="modal">

                      <span aria-hidden="true">&times;</span><span class="sr-only">Close</span>

                  </button>

                  <h2 class="modal-title" id="modaltitle"></h2>

             </div>

             <div class="modal-body">

                  <div class="row">

                      <!-- 表单布局 -->

                      <form id="form">

                               <div class="col-md-12">

                                   <div class="form-group">

                                       <label class="col-sm-3 control-label"><font color="#FF0000">*</font>用户名称:</label>

                                       <div class="col-sm-9">

                                           <!-- 保存修改的主键值 -->

                                           <input type="hidden" name="id" id="id">

                                            <input class="form-control" type="text" name="username" id="username"

                                                placeholder="请输入用户名" >

                                            <span class="help-block m-b-none"></span>

                                       </div>

                                   </div>

                               </div>

                               <div class="col-md-12">

                                  <div class="form-group">

                                   <label class="col-sm-3 control-label"><font color="#FF0000">*</font>用户密码:</label>

                                   <div class="col-sm-3">

                                       <input  class="form-control" type="password" name="password" id="password"

                                            placeholder="请输入用户密码" >

                                       <span class="help-block m-b-none"></span>

                                   </div>

                                   <label class="col-sm-3 control-label"><font color="#FF0000">*</font>确认密码:</label>

                                   <div class="col-sm-3">

                                       <input class="form-control" type="password" name="repassword" id="repassword"

                                            placeholder="确认密码" >

                                       <span class="help-block m-b-none"></span>

                                   </div>

                                </div>

                            </div>

                            <div class="col-md-12">

                                   <div class="form-group">

                                       <label class="col-sm-3 control-label">用户类型:</label>

                                       <div class="col-sm-9">

                                            <select id="usertype" class="form-control">

                                                <option value="普通用户">普通用户</option>

                                                <option value="超级管理员">超级管理员</option>

                                            </select>

                                            <span class="help-block m-b-none"></span>

                                       </div>

                                   </div>

                            </div>

                            <div class="col-md-12">

                                   <div class="form-group">

                                       <label class="col-sm-3 control-label">出生日期:</label>

                                       <div class="col-sm-9">

                                            <input class="form-control layer-date" name="birthday" id="birthday" placeholder="YYYY-MM-DD hh:mm:ss" onclick="laydate({istime: true, format: 'YYYY-MM-DD hh:mm:ss'})">

                                            <label class="laydate-icon"></label>

                                            <span class="help-block m-b-none"></span>

                                       </div>

                                   </div>

                               </div>

                               <div class="col-md-12">

                                   <div class="form-group">

                                       <label class="col-sm-3 control-label">头像:</label>

                                       <div class="col-sm-9">

                                            <img alt="image" id="photo" style="width: 150px; height: 150px;" class="img-circle" th:src="@{/static/img/a7.jpg}">

                                       </div>                                     

                                   </div>

                               </div>

                               <div class="col-md-12">

                                   <div id="fileupload" class="dropzone">

                                      

                                   </div>

                               </div>

                               <div class="col-md-12">

                                   <div class="form-group">

                                       <label class="col-sm-3 control-label">个人简介:</label>

                                       <div class="col-sm-9">

                                                <div class="summernote" id="introduce">

                                                 

                                              </div>

                                             

                                            <span class="help-block m-b-none"></span>

                                       </div>

                                   </div>

                               </div>

                      </form>

                      <!-- 表单布局结束 -->

                  </div>

             </div>

             <div class="modal-footer">

                  <button type="button" class="btn btn-white"

                      data-dismiss="modal">关闭</button>

                  <button type="button" class="btn btn-primary" id="btn_save">保存</button>

             </div>

         </div>

    </div>

</div>

<!-- 模态窗口结束 -->

 

 

<!-- 分配角色模态窗口 -->  

<div class="modal fade" data-backdrop="static" id="rolemodal" tabindex="-1" role="dialog" aria-hidden="true">

    <div class="modal-dialog modal-lg">

         <div class="modal-content">

             <div class="modal-header">

                  <button type="button" class="close" data-dismiss="modal">

                      <span aria-hidden="true">&times;</span><span class="sr-only">Close</span>

                  </button>

                  <h2 class="modal-title" id="rolemodaltitle">分配角色</h2>

             </div>

             <div class="modal-body">

                  <div class="row">

                      <!-- 表单布局 -->

                      <form id="roleform">

                               <div class="col-md-12">

                               <!-- 保存修改的主键值 -->

                              <input type="hidden" name="userid" id="userid">

                              <ul id="tree" class="ztree"></ul>

                               </div>

                      </form>

                      <!-- 表单布局结束 -->

                  </div>

             </div>

             <div class="modal-footer">

                  <button type="button" class="btn btn-white"

                      data-dismiss="modal">关闭</button>

                  <button type="button" class="btn btn-primary" id="btn_rolesave">保存</button>

             </div>

         </div>

    </div>

</div>

<!-- 模态窗口结束 -->

 

    <!-- 全局js -->

    <script th:src="@{/static/js/jquery.min.js?v=2.1.4}"></script>

    <script th:src="@{/static/js/bootstrap.min.js?v=3.3.6}"></script>

    <script th:src="@{/static/js/plugins/layer/layer.min.js}"></script>

 

    <!-- 自定义js -->

    <script th:src="@{/static/js/content.js}"></script>

 

    <!-- Data Tables -->

    <script th:src="@{/static/js/plugins/dataTables/jquery.dataTables.js}"></script>

    <script

         th:src="@{/static/js/plugins/dataTables/dataTables.bootstrap.js}"></script>

   

    <!-- tableexport -->

    <!--   前端直接导出excel有一定的缺陷,使用后台导出功能更强大

        后台导出:阿里巴巴项目组提供了easyexcel工具类,github地址:https://github.com/alibaba/easyexcel -->

    <script th:src="@{/static/js/plugins/tableexport/tableExport.js}"></script>

    <script th:src="@{/static/js/plugins/tableexport/jquery.base64.js}"></script>

   

    <!-- ztree -->

    <script th:src="@{/static/js/plugins/ztree/jquery.ztree.core.min.js}"></script>

    <script th:src="@{/static/js/plugins/ztree/jquery.ztree.excheck.min.js}"></script>

    <!-- Toastr script -->

    <script th:src="@{/static/js/plugins/toastr/toastr.min.js}"></script>

    <!-- jQuery Validation plugin javascript-->

    <script th:src="@{/static/js/plugins/validate/jquery.validate.min.js}"></script>

    <script th:src="@{/static/js/plugins/validate/messages_zh.min.js}"></script>

   

    <!-- layerDate plugin javascript -->

    <script th:src="@{/static/js/plugins/layer/laydate/laydate.js}"></script>

   

    <!-- SUMMERNOTE -->

    <script th:src="@{/static/js/plugins/summernote/summernote.min.js}"></script>

    <script th:src="@{/static/js/plugins/summernote/summernote-zh-CN.js}"></script>

   

    <!-- DROPZONE -->

    <script th:src="@{/static/js/plugins/dropzone/dropzone.js}"></script>

   

    <!-- Page-Level Scripts -->

    <script>

        //表格行中的按钮点击事件

        function edit(id){

        //异步获取数据

        $.ajax({

              type: "get",

              data: {

                 id:id,//第一个id为参数名,第二个为参数值

              },

              url: "/UserController/select",//后台处理地址

              success: function (data) {

                 //console.log(data);

                 if(data.success){

                      //设置数据

                      $("#id").val(data.obj.id);//修改数据必须有主键值

                      

                 $("#username").val(data.obj.username);

                 $("#password").val(data.obj.password);

                 $("#repassword").val(data.obj.password);

                 $("#usertype").val(data.obj.usertype);

                 $("#birthday").val(data.obj.birthday);

                 $('#photo').attr("src",data.obj.photo);

                 $('#introduce').summernote("code", data.obj.introduce);

                 $("#modaltitle").text("修改用户");

                 $("#modal").modal("show");

                 }else{

                      toastr.error(data.msg, '错误!');

                 }

              }

        }); // end ajax

       

        }//end edit

       

        //表格行中的按钮点击事件

        function role(id){

        //异步获取数据

        $.ajax({

              type: "get",

              data: {

                 id:id,//第一个id为参数名,第二个为参数值

              },

              url: "/RoleController/tree",//后台处理地址

              success: function (data) {

                  //ztree

                   var setting = {

                           check: {

                                enable: true

                           },

                           data: {

                                simpleData: {

                                    enable: true

                                }

                           }

                   };

                   $.fn.zTree.init($("#tree"), setting, data);

                   $("#userid").val(id);//通过隐藏input保存用户id

             $("#rolemodal").modal("show");

              }

        }); // end ajax

 

        }

       

        $(document).ready(function () {

        //datatable

        var datatable= $('#table').DataTable({

              "processing": true,

                "serverSide": true,

                "ajax": {

                   url: "/UserController/list",

                   type:"post",

                   data: function (d) {

                     //把字段名和关键词发送给controller进行查询,自动映射到vo模型的相应属性中

                     d[$('#searchfield').val()]=$('#keyword').val()

                   }

                },  

                "language": {

                     "lengthMenu": "每页 _MENU_ ",

                     "info": " _START_ _END_,共 _TOTAL_ 记录",

                     "zeroRecords": "没有找到记录",

                     "infoEmpty": "暂无记录",

                     "infoFiltered": "( _MAX_ 条记录过滤)",

                     "paginate": {

                         "previous": "上一页",

                         "next": "下一页",

 

                     },

                     "processing": "正在加载..."

                 },

                 "autoWidth": false,

                 "pageLength": 2,

                 "lengthChange": false,

                 "searching": false,

                 "columns": [

 

                      {"data":"id","orderable": false,

                          "render": function ( data, type, full, meta ) {

                                   return '<input type="checkbox" value="'+data+'" class="input-lg" style="width:20px;height:20px;" />';

                               }

                      },

                      {"data":"id","name":"id"},

                      {"data":"username","name":"username"},

                      {"data":"usertype","name":"usertype"},

                      //有排序功能必须指定name为字段名称

                      {"data":"id","orderable": false,

                          "render": function ( data, type, full, meta ) {

                                   return '<button id="btn_edit" class="btn btn-primary btn-sm" οnclick="edit(\''+data+'\')"><i class="fa fa-edit"></i>&nbsp;查看修改</button> <button id="btn_role" class="btn btn-primary btn-sm" οnclick="role(\''+data+'\')"><i class="fa fa-users"></i>&nbsp;分配角色</button>';

                               }

                      },

                  ],

                  "order": [

                     [1, 'desc']

                  ]//默认排序

        });

       

        $("#btn_search").click(function(){

              datatable.ajax.reload();//根据关键词重新加载数据

        });

       

        //全选

        $("#cb_selectAll").click(function(){

              if ($("#cb_selectAll").get(0).checked) {

                    $("#table tbody :checkbox").prop("checked", true);

                }else{

                   $("#table tbody :checkbox").prop("checked", false);

                }              

        });

       

        //toastr选项

        toastr.options = {

           "positionClass": "toast-bottom-center",

        }

       

        //删除

        $("#btn_del").click(function(){

              //获取选中的复选框

              var checkboxlist=$("#table tbody :checked");

              if(checkboxlist.length>0){

                  if(!confirm("您确定删除数据吗?"))

                    {

                       return;

                    }

              }else{

                  toastr.error("请选择要删除的记录。", '错误!');

                  return;

              }

              var ids="";

              $.each(checkboxlist, function(n, cb) { 

                  ids+=cb.value+","

                });

              if(ids.length>0){

                ids=ids.substring(0,ids.length-1);

              }

              //异步删除数据

              $.ajax({

                  type: "post",

                  data: {

                     ids:ids,//第一个ids为参数名,第二个为参数值

                  },

                  url: "/UserController/delete",//后台处理地址

                  success: function (data) {

                     if(data.success){

                          toastr.success(data.msg, '删除成功!');

                          datatable.ajax.reload(null, false);//刷新当前页

                     }else{

                          toastr.error(data.msg, '错误!');

                     }

                  }

              }); // end ajax

 

        });//end btn_del

       

         $("#btn_add").click(function(){

              //清空数据

              $("#username").val("");

              $("#password").val("");

              $("#repassword").val("");

              $("#usertype").val("普通用户");

              $("#birthday").val("");

              $('#photo').attr("src","");

              $('#introduce').summernote("code", "");

              //validator.resetForm();//重置验证

              $("#modaltitle").text("添加用户");

              $("#modal").modal("show");

        });//end add

       

       

       

        //不用改,以下为修改jQuery Validation插件兼容Bootstrap的方法,没有直接写在插件中是为了便于插件升级

            $.validator.setDefaults({

                highlight: function (element) {

                    $(element).closest('.form-group').removeClass('has-success').addClass('has-error');

                },

                success: function (element) {

                    element.closest('.form-group').removeClass('has-error').addClass('has-success');

                },

                errorElement: "span",

                errorPlacement: function (error, element) {

                    if (element.is(":radio") || element.is(":checkbox")) {

                        error.appendTo(element.parent().parent().parent());

                    } else {

                        error.appendTo(element.parent());

                    }

                },

                errorClass: "help-block m-b-none",

                validClass: "help-block m-b-none"

            });

        //end setDefaults

           

            // validate form setting

            var icon = "<i class='fa fa-times-circle'></i> ";

            validator=$("#form").validate({

                rules: {

                    username: {

                        required: true,

                        minlength: 1

                    },

                    password: {

                        required: true,

                        minlength: 1

                    },

                    repassword: {

                        required: true,

                        minlength: 1,

                        equalTo: "#password"

                    },

                },

                messages: {

                    username: {

                        required: icon + "请输入您的用户名",

                        minlength: icon + "用户名必须1个字符以上"

                    },

                    password: {

                        required: icon + "请输入您的密码",

                        minlength: icon + "密码必须1个字符以上"

                    },

                    repassword: {

                        required: icon + "请再次输入密码",

                        minlength: icon + "密码必须1个字符以上",

                        equalTo: icon + "两次输入的密码不一致"

                    },

                }

            });//end validate

           

            $("#btn_save").click(function(){

              if($("#form").valid()){

                  //save

                  var markupStr = $('#introduce').summernote('code');

                  //alert(markupStr);

                  if($("#modaltitle").text()=="添加用户"){

                       //add

                       //异步添加数据

                       $.ajax({

                            type: "post",

                            data: {

                                username:$("#username").val(),

                                password:$("#password").val(),

                                usertype:$("#usertype").val(),

                                birthday:$("#birthday").val(),

                                photo:$('#photo').attr("src"),

                                introduce:$('#introduce').summernote("code"),

                            },

                            url: "/UserController/insert",//后台处理地址

                           success: function (data) {

                               if(data.success){

                                   toastr.success(data.msg, '添加成功!');

                                   $("#modal").modal('hide');

                                   datatable.ajax.reload(null, false);//刷新当前页

                               }else{

                                   toastr.error(data.msg, '错误!');

                               }

                            }

                       });  // end ajax

                  }else{

                       //update

                       //异步修改数据

                       $.ajax({

                            type: "post",

                            data: {

                                id:$("#id").val(),//主键,从隐藏input获取到

                                username:$("#username").val(),

                                password:$("#password").val(),

                                usertype:$("#usertype").val(),

                                birthday:$("#birthday").val(),

                                photo:$('#photo').attr("src"),

                                introduce:$('#introduce').summernote("code"),

                            },

                            url: "/UserController/update",//后台处理地址

                            success: function (data) {

                               if(data.success){

                                   toastr.success(data.msg, '修改成功!');

                                   $("#modal").modal('hide');

                                   datatable.ajax.reload(null, false);//刷新当前页

                               }else{

                                   toastr.error(data.msg, '错误!');

                               }

                            }

                       });  // end ajax

                  }                

                 

              }            

        });//end btn_save

       

        //summernote

         $('#introduce').summernote({

                 lang: 'zh-CN'

             });

       

         //Dropzone

         Dropzone.autoDiscover = false;// 禁止对所有元素的自动查找,由于Dropzone会自动查找classdropzone的元素

         var myDropzone = new Dropzone("#fileupload", {

                url: "/UserController/upload",

                method:"post"//也可用put

              paramName:"file", //后台接收文件参数名称,默认为file

              maxFiles:1,//一次性上传的文件数量上限

              maxFilesize: 2, //文件大小,单位:MB

              acceptedFiles: ".jpg,.gif,.png,.jpeg", //上传的类型

              addRemoveLinks: true,

              dictRemoveFile: "删除",

              dictCancelUpload: "取消",

              dictMaxFilesExceeded: "最多上传一个文件",

              dictFallbackMessage: '不好意思,您的浏览器不支持!',//如果浏览器不支持,默认消息将被替换为这个文本。默认为 “Your browser does not support drag'n'drop file uploads.”

              dictInvalidFileType: '该文件不允许上传',//如果文件类型不匹配时显示的错误消息。

              dictResponseError:'上传失败,请稍后重试',//如果服务器响应是无效的时候显示的错误消息。

              autoProcessQueue: true,

              //uploadMultiple:true,//允许多个文件上传

              clickable: true,

              init:function(){

                this.on("addedfile", function(file) {

                  //上传文件时触发的事件

                  console.log("addedfile");

                });

                this.on("success",function(file,data){

                  //上传成功触发的事件

                  console.log("success");

                  console.log(data);

                  if(data.success){

                   $('#photo').attr("src", data.obj);

                   toastr.success("上传头像成功!", '成功');

                   myDropzone.removeFile(file);//上传界面的预览删除

                  }

                  

                });

                this.on("error",function (file,data) {

                  //上传失败触发的事件

                  console.log("error");

                });

                this.on("removedfile",function(file){

                  //删除文件时触发的方法

                  console.log("removedfile");

                });

              },

         });// end Dropzone

         

         $("#btn_rolesave").click(function(){

               var treeObj = $.fn.zTree.getZTreeObj("tree");

               var nodes = treeObj.getCheckedNodes(true);

               ids="";

               for(i=0;i<nodes.length;i++){

                   if(i<nodes.length - 1){

                        ids = ids + nodes[i].id + ",";

                   }else{

                        ids = ids + nodes[i].id;

                   }                      

               }                 

               //console.log(ids);

               $.ajax({

                  type: "post",

                  data: {

                     id:$("#userid").val(),

                     ids:ids

                  },

                  url: "/RoleController/role",//后台处理地址

                  success: function (data) {

                       if(data.success){

                         toastr.success("分配角色成功!", '成功');

                         $("#rolemodal").modal("hide");

                          }

                  }

             }); // end ajax

               

         });//end rolesave

         

 

        });//end ready

 

    </script>

 

</body>

</html>

数据的增删改查都通过$.ajaxjson格式异步发送到controller中进行处理。本页面中还封装了表格、表单验证、在线编辑器、文件上传组件、树形组件(需要调用到角色表,等角色模块完成就可以正常使用)等扩展组件,注意阅读代码中的注释,代码基本以块形式出现,每个扩展都在相应的代码段中。因为涉及的组件较多,重点学会3步套用法即可(1、引入css2、引入js3、编写事件处理代码)。异步调用时,一定要学会用console.log()来打印数据进行调试与后台中的logger.info()方法类似。

点击用户管理菜单的效果(除了分配角色功能,其他的都已经实现):

  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
用户管理模块是书店销售管理系统的一个重要组成部分,其主要功能是管理系统中的用户信息,包括添加、修改、查询、删除用户等操作。下面是该模块实现步骤: 1. 数据库设计 用户管理模块需要建立如下数据库表: 1.1 用户表:用于存储用户信息,包括用户ID、用户名、密码、真实姓名、性别、出生日期、联系电话等字段。 1.2 角色表:用于存储角色信息,包括角色ID、角色名称、角色描述等字段。 1.3 权限表:用于存储权限信息,包括权限ID、权限名称、权限描述等字段。 1.4 用户角色表:用于存储用户和角色的关系。 1.5 角色权限表:用于存储角色和权限的关系。 2. 功能实现 2.1 添加用户管理员可以添加新用户,并分配角色和权限。用户注册时需要输入用户名、密码、真实姓名、性别、出生日期、联系电话等信息。 2.2 修改用户管理员可以修改用户信息,包括用户名、密码、真实姓名、性别、出生日期、联系电话等字段。同时,管理员还可以修改用户的角色和权限。 2.3 查询用户管理员可以根据用户ID、用户名、真实姓名等条件查询用户信息。查询结果以列表形式呈现,包括用户ID、用户名、真实姓名、性别、出生日期、联系电话等信息。 2.4 删除用户管理员可以删除用户信息,同时删除用户与角色、权限的关系。 2.5 分配角色和权限:管理员可以为用户分配角色和权限,以控制用户访问系统的权限。 3. 界面实现 用户管理模块需要提供如下界面: 3.1 用户列表界面:显示所有用户的列表信息,包括用户ID、用户名、真实姓名、性别、出生日期、联系电话等信息。 3.2 用户详情界面:显示某个用户的详细信息,包括用户ID、用户名、真实姓名、性别、出生日期、联系电话等信息,并允许修改用户信息。 3.3 添加用户界面:用于添加新用户,并分配角色和权限。 3.4 分配角色和权限界面:用于为用户分配角色和权限。 以上是书店销售管理系统用户管理模块实现步骤,希望能对你有所帮助。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值