Merge remote-tracking branch 'origin/master' into songpengmaster

# Conflicts:
#	sparchetype/src/main/java/com/songpeng/sparchetype/system/controller/client/SysLoginController.java
#	sparchetype/src/main/java/com/songpeng/sparchetype/system/service/impl/SysMenuServiceImpl.java
#	sparchetype/src/main/resources/templates/login.ftl
pull/1/head
wangziyangyang 2020-03-06 09:31:22 +08:00
commit c5e4274455
22 changed files with 505 additions and 227 deletions

View File

@ -37,6 +37,12 @@
* http://www.fontawesome.com.cn/faicons/
* 后端
* Hutool 是一个小而全的Java工具类库通过静态方法封装降低相关API的学习成本提高工作效率使Java拥有函数式语言般的优雅让Java语言也可以“甜甜的”。
* 枚举
* 公共枚举类com.songpeng.sparchetype.common.enums.CommonEnum
* 不同模块下的枚举:如 com.songpeng.sparchetype.system.enums
* 请求参数
* 每张表的分页查询参数严格按照一张表对应一个请求参数对象进行开发如系统用户分页查询参数com.songpeng.sparchetype.system.request.SysUserPageReq
*
#### 安装教程

View File

@ -0,0 +1,45 @@
package com.songpeng.sparchetype.common.enums;
/**
*
*
* @author SongPeng
* @date 2019/10/17 9:45
*/
public enum CommonEnum {
/**
* 0 1 2
*/
FIELD_NAME_IS_DELETED("is_deleted", "数据库删除标记字段名"),
FIELD_NAME_CREATE_TIME("create_time", "数据库创建时间字段名"),
FIELD_NAME_CREATE_USERNAME("create_username", "数据库创建用户名字段名"),
FIELD_NAME_UPDATE_TIME("update_time", "数据库更新时间字段名"),
FIELD_NAME_UPDATE_USERNAME("update_username", "数据库更新用户名字段名");
/**
* The Code
*/
String code;
/**
* The Desc
*/
String desc;
public String getCode() {
return code;
}
public String getDesc() {
return desc;
}
CommonEnum(String code, String desc) {
this.code = code;
this.desc = desc;
}
}

View File

@ -0,0 +1,152 @@
package com.songpeng.sparchetype.common.util;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.util.Random;
/**
*
*
* @author SongPeng
* @date 2020/3/6
*/
public class RandomVerificationCodeUtil {
private static final Logger log = LoggerFactory.getLogger(RandomVerificationCodeUtil.class);
/**
* sessionkey
*/
public static final String RANDOM_CODE_KEY = "RANDOMVALIDATECODEKEY";
/**
*
*/
public static final String FONT_NAME = "Fixedsys";
/**
*
*/
private String randString = "0123456789";
/**
*
*/
private int width = 95;
/**
*
*/
private int height = 25;
/**
* 线
*/
private int lineSize = 40;
/**
*
*/
private int stringNum = 4;
private Random random = new Random();
/**
*
*/
private Font getFont() {
return new Font(FONT_NAME, Font.CENTER_BASELINE, 18);
}
/**
*
*/
private Color getRandColor(int fc, int bc) {
if (fc > 255) {
fc = 255;
}
if (bc > 255) {
bc = 255;
}
int r = fc + random.nextInt(bc - fc - 16);
int g = fc + random.nextInt(bc - fc - 14);
int b = fc + random.nextInt(bc - fc - 18);
return new Color(r, g, b);
}
/**
*
*/
public void getRandcode(HttpServletRequest request, HttpServletResponse response) {
HttpSession session = request.getSession();
// BufferedImage类是具有缓冲区的Image类,Image类是用于描述图像信息的类
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_BGR);
// 产生Image对象的Graphics对象,改对象可以在图像上进行各种绘制操作
Graphics g = image.getGraphics();
// 图片大小
g.fillRect(0, 0, width, height);
// 字体大小
g.setFont(new Font("Default", Font.ROMAN_BASELINE, 18));
// 字体颜色
g.setColor(getRandColor(110, 133));
// 绘制干扰线
for (int i = 0; i <= lineSize; i++) {
drowLine(g);
}
// 绘制随机字符
String randomString = "";
for (int i = 1; i <= stringNum; i++) {
randomString = drowString(g, randomString, i);
}
log.info(randomString);
// 将生成的随机字符串保存到session中
session.removeAttribute(RANDOM_CODE_KEY);
session.setAttribute(RANDOM_CODE_KEY, randomString);
g.dispose();
try {
// 将内存中的图片通过流动形式输出到客户端
ImageIO.write(image, "JPEG", response.getOutputStream());
} catch (Exception e) {
log.error("将内存中的图片通过流形式输出到客户端失败", e);
}
}
/**
*
*/
private String drowString(Graphics g, String randomString, int i) {
g.setFont(getFont());
g.setColor(new Color(random.nextInt(101), random.nextInt(111), random
.nextInt(121)));
String rand = String.valueOf(getRandomString(random.nextInt(randString
.length())));
randomString += rand;
g.translate(random.nextInt(3), random.nextInt(3));
g.drawString(rand, 13 * i, 16);
return randomString;
}
/**
* 线
*/
private void drowLine(Graphics g) {
int x = random.nextInt(width);
int y = random.nextInt(height);
int xl = random.nextInt(13);
int yl = random.nextInt(15);
g.drawLine(x, y, x + xl, y + yl);
}
/**
*
*/
public String getRandomString(int num) {
return String.valueOf(randString.charAt(num));
}
}

View File

@ -80,7 +80,7 @@ public class ShiroConfig {
shiroFilterFactoryBean.setUnauthorizedUrl("/403");
LinkedHashMap<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
filterChainDefinitionMap.put("/login", "anon");
filterChainDefinitionMap.put("/getVerify", "anon");
filterChainDefinitionMap.put("/verification/code", "anon");
filterChainDefinitionMap.put("/css/**", "anon");
filterChainDefinitionMap.put("/image/**", "anon");
filterChainDefinitionMap.put("/js/**", "anon");

View File

@ -2,11 +2,11 @@ package com.songpeng.sparchetype.system.controller.admin;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.songpeng.sparchetype.common.BaseController;
import com.songpeng.sparchetype.common.Result;
import com.songpeng.sparchetype.system.entity.SysDepartment;
import com.songpeng.sparchetype.system.entity.SysDict;
import com.songpeng.sparchetype.system.request.SysDepartmentPageReq;
import com.songpeng.sparchetype.system.service.ISysDepartmentService;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
@ -46,10 +46,12 @@ public class SysDepartmentController extends BaseController {
return "admin/system/department/list";
}
@ApiOperation("系统部门信息分页列表")
@ApiImplicitParams({@ApiImplicitParam(name = "page", value = "模型", defaultValue = "模型")})
@PostMapping("/page")
@ResponseBody
public Result page(Page page) {
IPage result = sysDepartmentService.page(page);
public Result page(SysDepartmentPageReq req) {
IPage result = sysDepartmentService.page(req);
return Result.success(result);
}

View File

@ -2,10 +2,10 @@ package com.songpeng.sparchetype.system.controller.admin;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.songpeng.sparchetype.common.BaseController;
import com.songpeng.sparchetype.common.Result;
import com.songpeng.sparchetype.system.entity.SysDict;
import com.songpeng.sparchetype.system.request.SysDictPageReq;
import com.songpeng.sparchetype.system.service.ISysDictService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
@ -49,8 +49,8 @@ public class SysDictController extends BaseController {
@PostMapping("/page")
@ResponseBody
public Result page(Page page) {
IPage result = sysDictService.page(page);
public Result page(SysDictPageReq req) {
IPage result = sysDictService.page(req);
return Result.success(result);
}

View File

@ -1,9 +1,7 @@
package com.songpeng.sparchetype.system.controller.admin;
import com.songpeng.sparchetype.common.Result;
import com.songpeng.sparchetype.system.entity.SysMenu;
import com.songpeng.sparchetype.system.service.ISysMenuService;
import com.songpeng.sparchetype.system.vo.TreeVO;
import io.swagger.annotations.ApiOperation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -14,7 +12,6 @@ import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import java.util.List;
import java.util.Map;
/**

View File

@ -2,10 +2,10 @@ package com.songpeng.sparchetype.system.controller.admin;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.songpeng.sparchetype.common.BaseController;
import com.songpeng.sparchetype.common.Result;
import com.songpeng.sparchetype.system.entity.SysMenu;
import com.songpeng.sparchetype.system.request.SysMenuPageReq;
import com.songpeng.sparchetype.system.service.ISysMenuService;
import com.songpeng.sparchetype.system.vo.TreeVO;
import io.swagger.annotations.ApiOperation;
@ -42,8 +42,8 @@ public class SysMenuController extends BaseController {
@PostMapping("/page")
@ResponseBody
public Result page(Page page) {
IPage result = sysMenuService.page(page);
public Result page(SysMenuPageReq req) {
IPage result = sysMenuService.page(req);
return Result.success(result);
}

View File

@ -3,7 +3,6 @@ package com.songpeng.sparchetype.system.controller.admin;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.songpeng.sparchetype.common.BaseController;
import com.songpeng.sparchetype.common.Result;
import com.songpeng.sparchetype.system.entity.SysRole;
@ -40,10 +39,10 @@ public class SysRoleController extends BaseController {
@PostMapping("/page")
@ResponseBody
public Result page(Page page, SysRolePageReq req) {
public Result page(SysRolePageReq req) {
QueryWrapper qw = new QueryWrapper();
qw.orderByDesc(req.getOrderBy());
IPage result = sysRoleService.page(page, qw);
IPage result = sysRoleService.page(req, qw);
return Result.success(result);
}

View File

@ -1,6 +1,5 @@
package com.songpeng.sparchetype.system.controller.admin;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.songpeng.sparchetype.common.BaseController;

View File

@ -1,7 +1,9 @@
package com.songpeng.sparchetype.system.controller.client;
import com.songpeng.sparchetype.common.Result;
import com.songpeng.sparchetype.common.util.RandomVerificationCodeUtil;
import com.songpeng.sparchetype.system.config.shiro.SpUsernamePasswordToken;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.crypto.hash.Md5Hash;
@ -15,10 +17,9 @@ import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
*
*
* @author SongPeng
* @date 2019/9/27 16:05
*/
@ -38,6 +39,26 @@ public class SysLoginController {
return "redirect:/admin/index";
}
/**
*
*/
@GetMapping(value = "/verification/code")
public void getVerify(HttpServletRequest request, HttpServletResponse response) {
try {
// 设置相应类型,告诉浏览器输出的内容为图片
response.setContentType("image/jpeg");
// 设置响应头信息,告诉浏览器不要缓存此内容
response.setHeader("Pragma", "No-cache");
response.setHeader("Cache-Control", "no-cache");
response.setDateHeader("Expire", 0);
RandomVerificationCodeUtil randomValidateCode = new RandomVerificationCodeUtil();
// 输出验证码图片方法
randomValidateCode.getRandcode(request, response);
} catch (Exception e) {
log.error("获取验证码失败", e);
}
}
/**
*
*
@ -52,6 +73,16 @@ public class SysLoginController {
@PostMapping("/login")
@ResponseBody
public Result login(String username, String password, String captcha, String rememberMe, HttpServletRequest request) {
//从session中获取随机数
String random = (String) request.getSession().getAttribute(RandomVerificationCodeUtil.RANDOM_CODE_KEY);
if (StringUtils.isBlank(captcha)) {
return Result.failure("请输入验证码");
}
if (!random.equals(captcha)) {
return Result.failure("请输入正确的验证码");
}
// TODO loginType 字段用于后期拓展用
UsernamePasswordToken token = new SpUsernamePasswordToken(username, password, "UserLogin");
Subject subject = SecurityUtils.getSubject();

View File

@ -0,0 +1,15 @@
package com.songpeng.sparchetype.system.request;
import com.songpeng.sparchetype.common.BasePageReq;
/**
* <p>
*
* </p>
*
* @author SongPeng
* @since 2019-10-15
*/
public class SysDepartmentPageReq extends BasePageReq {
}

View File

@ -0,0 +1,15 @@
package com.songpeng.sparchetype.system.request;
import com.songpeng.sparchetype.common.BasePageReq;
/**
* <p>
*
* </p>
*
* @author SongPeng
* @since 2019-10-15
*/
public class SysDictPageReq extends BasePageReq {
}

View File

@ -3,6 +3,7 @@ package com.songpeng.sparchetype.system.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.songpeng.sparchetype.system.dto.SysRoleDTO;
import com.songpeng.sparchetype.system.dto.SysUserDTO;
import com.songpeng.sparchetype.system.entity.SysRole;
import java.util.List;
@ -25,4 +26,12 @@ public interface ISysRoleService extends IService<SysRole> {
* @throws Exception
*/
List<SysRoleDTO> listByUserId(String userId) throws Exception;
/**
*
*
* @param sysUserDTO DTO
* @throws Exception
*/
void rebuild(SysUserDTO sysUserDTO) throws Exception;
}

View File

@ -1,10 +1,8 @@
package com.songpeng.sparchetype.system.service;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.IService;
import com.songpeng.sparchetype.system.dto.SysUserDTO;
import com.songpeng.sparchetype.system.entity.SysUser;
import com.songpeng.sparchetype.system.request.SysUserPageReq;
/**
* <p>

View File

@ -1,9 +1,7 @@
package com.songpeng.sparchetype.system.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.songpeng.sparchetype.system.entity.SysRole;
import com.songpeng.sparchetype.system.entity.SysRoleMenu;
import com.songpeng.sparchetype.system.mapper.SysRoleMapper;
import com.songpeng.sparchetype.system.mapper.SysRoleMenuMapper;
import com.songpeng.sparchetype.system.service.ISysRoleMenuService;
import org.springframework.stereotype.Service;

View File

@ -2,11 +2,17 @@ package com.songpeng.sparchetype.system.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.songpeng.sparchetype.common.enums.CommonEnum;
import com.songpeng.sparchetype.system.dto.SysRoleDTO;
import com.songpeng.sparchetype.system.dto.SysUserDTO;
import com.songpeng.sparchetype.system.entity.SysRole;
import com.songpeng.sparchetype.system.entity.SysUserRole;
import com.songpeng.sparchetype.system.enums.SysRoleEnum;
import com.songpeng.sparchetype.system.mapper.SysRoleMapper;
import com.songpeng.sparchetype.system.service.ISysRoleService;
import com.songpeng.sparchetype.system.service.ISysUserRoleService;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@ -28,6 +34,9 @@ public class SysRoleServiceImpl extends ServiceImpl<SysRoleMapper, SysRole> impl
@Autowired
private SysRoleMapper sysRoleMapper;
@Autowired
private ISysUserRoleService sysUserRoleService;
/**
* ID
*
@ -42,7 +51,7 @@ public class SysRoleServiceImpl extends ServiceImpl<SysRoleMapper, SysRole> impl
List<SysRole> sysRoles = sysRoleMapper.listByUserId(userId);
QueryWrapper<SysRole> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("delete", SysRoleEnum.DELETED_NORMAL.getCode());
queryWrapper.eq(CommonEnum.FIELD_NAME_IS_DELETED.getCode(), SysRoleEnum.DELETED_NORMAL.getCode());
List<SysRole> sysRolesAll = sysRoleMapper.selectList(null);
for (SysRole role : sysRolesAll) {
@ -57,4 +66,30 @@ public class SysRoleServiceImpl extends ServiceImpl<SysRoleMapper, SysRole> impl
}
return result;
}
/**
*
*
* @param sysUserDTO DTO
* @throws Exception
*/
@Override
public void rebuild(SysUserDTO sysUserDTO) throws Exception {
if (StringUtils.isNotEmpty(sysUserDTO.getId())) {
QueryWrapper<SysUserRole> deleteWrapper = new QueryWrapper<>();
deleteWrapper.eq("user_id", sysUserDTO.getId());
sysUserRoleService.remove(deleteWrapper);
}
if (ArrayUtils.isNotEmpty(sysUserDTO.getSysRoleIds())) {
for (String roleId : sysUserDTO.getSysRoleIds()) {
if (StringUtils.isEmpty(roleId)) {
continue;
}
SysUserRole sysUserRole = new SysUserRole();
sysUserRole.setUserId(sysUserDTO.getId());
sysUserRole.setRoleId(roleId);
sysUserRoleService.save(sysUserRole);
}
}
}
}

View File

@ -1,9 +1,7 @@
package com.songpeng.sparchetype.system.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.songpeng.sparchetype.system.entity.SysUser;
import com.songpeng.sparchetype.system.entity.SysUserRole;
import com.songpeng.sparchetype.system.mapper.SysUserMapper;
import com.songpeng.sparchetype.system.mapper.SysUserRoleMapper;
import com.songpeng.sparchetype.system.service.ISysUserRoleService;
import org.springframework.stereotype.Service;

View File

@ -1,21 +1,15 @@
package com.songpeng.sparchetype.system.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.songpeng.sparchetype.system.dto.SysMenuDTO;
import com.songpeng.sparchetype.system.dto.SysRoleDTO;
import com.songpeng.sparchetype.system.dto.SysUserDTO;
import com.songpeng.sparchetype.system.entity.SysUser;
import com.songpeng.sparchetype.system.entity.SysUserRole;
import com.songpeng.sparchetype.system.mapper.SysUserMapper;
import com.songpeng.sparchetype.system.request.SysUserPageReq;
import com.songpeng.sparchetype.system.service.ISysMenuService;
import com.songpeng.sparchetype.system.service.ISysUserRoleService;
import com.songpeng.sparchetype.system.service.ISysRoleService;
import com.songpeng.sparchetype.system.service.ISysUserService;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@ -40,7 +34,7 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
private ISysMenuService sysMenuService;
@Autowired
private ISysUserRoleService sysUserRoleService;
private ISysRoleService sysRoleService;
/**
*
@ -52,18 +46,7 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
@Override
public void save(SysUserDTO record) throws Exception {
sysUserMapper.insert(record);
// rebuild
if (ArrayUtils.isNotEmpty(record.getSysRoleIds())) {
for (String roleId : record.getSysRoleIds()) {
if (StringUtils.isEmpty(roleId)) {
continue;
}
SysUserRole sysUserRole = new SysUserRole();
sysUserRole.setUserId(record.getId());
sysUserRole.setRoleId(roleId);
sysUserRoleService.save(sysUserRole);
}
}
sysRoleService.rebuild(record);
}
/**
@ -76,20 +59,7 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
@Override
public void update(SysUserDTO record) throws Exception {
sysUserMapper.updateById(record);
QueryWrapper<SysUserRole> deleteWrapper = new QueryWrapper<>();
deleteWrapper.eq("user_id", record.getId());
sysUserRoleService.remove(deleteWrapper);
if (ArrayUtils.isNotEmpty(record.getSysRoleIds())) {
for (String roleId : record.getSysRoleIds()) {
if (StringUtils.isEmpty(roleId)) {
continue;
}
SysUserRole sysUserRole = new SysUserRole();
sysUserRole.setUserId(record.getId());
sysUserRole.setRoleId(roleId);
sysUserRoleService.save(sysUserRole);
}
}
sysRoleService.rebuild(record);
}
/**

View File

@ -135,7 +135,7 @@
<input type="checkbox" name="rememberMe" value="true" lay-skin="primary" title="记住密码">
</div>
<div class="layui-form-item">
<button class="layui-btn layui-btn-fluid layui-btn-normal" lay-submit="" lay-filter="login">登 入</button>
<button class="layui-btn layui-btn-fluid" lay-submit="" lay-filter="login">登 入</button>
</div>
</form>
</div>
@ -174,6 +174,15 @@
return false;
});
/**
* 获取图形验证码
*/
$('#captchaPic').click(function () {
this.src = "${request.contextPath}/verification/code?" + Math.random();
});
$("#captchaPic").click();
});
</script>