权限管理
authorqiaowei <jov123@163.com>
Mon, 29 Apr 2019 09:58:40 +0000 (17:58 +0800)
committerqiaowei <jov123@163.com>
Mon, 29 Apr 2019 09:58:45 +0000 (17:58 +0800)
25 files changed:
src/main/java/com/supwisdom/dlpay/framework/dao/FunctionDao.java
src/main/java/com/supwisdom/dlpay/framework/dao/ResourceDao.java
src/main/java/com/supwisdom/dlpay/framework/dao/RoleDao.java
src/main/java/com/supwisdom/dlpay/framework/dao/RoleFunctionDao.java
src/main/java/com/supwisdom/dlpay/framework/domain/TRoleFunction.java
src/main/java/com/supwisdom/dlpay/framework/security/MyPermissionEvaluator.java [new file with mode: 0644]
src/main/java/com/supwisdom/dlpay/framework/util/PermissionConstants.java [new file with mode: 0644]
src/main/java/com/supwisdom/dlpay/system/bean/FunctionSearchBean.java [new file with mode: 0644]
src/main/java/com/supwisdom/dlpay/system/bean/PageBean.java [new file with mode: 0644]
src/main/java/com/supwisdom/dlpay/system/controller/FunctionController.java [new file with mode: 0644]
src/main/java/com/supwisdom/dlpay/system/controller/OperatorController.java
src/main/java/com/supwisdom/dlpay/system/service/FunctionService.java
src/main/java/com/supwisdom/dlpay/system/service/RoleService.java
src/main/java/com/supwisdom/dlpay/system/service/impl/FunctionServiceImpl.java
src/main/java/com/supwisdom/dlpay/system/service/impl/RoleServiceImpl.java
src/main/kotlin/com/supwisdom/dlpay/security.kt
src/main/resources/static/custom/css/admin.css
src/main/resources/static/custom/module/admin.js
src/main/resources/templates/error/403.html [new file with mode: 0755]
src/main/resources/templates/error/404.html [new file with mode: 0755]
src/main/resources/templates/error/500.html [new file with mode: 0755]
src/main/resources/templates/index.html
src/main/resources/templates/system/function/form.html [new file with mode: 0755]
src/main/resources/templates/system/function/index.html [new file with mode: 0755]
src/main/resources/templates/system/operator/index.html

index e881f2c..619a530 100644 (file)
@@ -1,6 +1,8 @@
 package com.supwisdom.dlpay.framework.dao;
 
 import com.supwisdom.dlpay.framework.domain.TFunction;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.Pageable;
 import org.springframework.data.jpa.repository.JpaRepository;
 import org.springframework.data.jpa.repository.Query;
 import org.springframework.stereotype.Repository;
@@ -11,4 +13,6 @@ import java.util.List;
 public interface FunctionDao extends JpaRepository<TFunction, String> {
   @Query("select distinct t from TFunction t,TRoleFunction a, TOperRole b where t.id=a.functionId and a.roleId=b.roleId and b.operid=?1 order by t.orderNum ")
   List<TFunction> getTFunctionsByOperid(String operid);
+
+  Page<TFunction> findAllByNameContaining(String name,Pageable pageable);
 }
index b1a04a7..22f5c1c 100644 (file)
@@ -6,4 +6,5 @@ import org.springframework.stereotype.Repository;
 
 @Repository
 public interface ResourceDao extends JpaRepository<TResource, String> {
+    TResource findByUri(String uri);
 }
index bd2e5d7..af771de 100644 (file)
@@ -11,4 +11,7 @@ import java.util.List;
 public interface RoleDao extends JpaRepository<TRole, String> {
   @Query("from TRole order by createtime asc ")
   List<TRole> getAllRoles();
+
+  TRole findByRoleCode(String rolecode);
+
 }
index f6aea4e..de69392 100644 (file)
@@ -6,4 +6,6 @@ import org.springframework.stereotype.Repository;
 
 @Repository
 public interface RoleFunctionDao extends JpaRepository<TRoleFunction, String> {
+
+    TRoleFunction findByRoleIdAndFunctionId(String roleId,String functionId);
 }
index 91f4307..a621460 100644 (file)
@@ -19,6 +19,9 @@ public class TRoleFunction {
   @Column(name="FUNCTIONID", nullable = false, length = 32)
   private String functionId;
 
+  @Column(name="PERMISSIONS", length = 200)
+  private String permissions;
+
   public String getId() {
     return id;
   }
@@ -42,4 +45,12 @@ public class TRoleFunction {
   public void setFunctionId(String functionId) {
     this.functionId = functionId;
   }
+
+  public String getPermissions() {
+    return permissions;
+  }
+
+  public void setPermissions(String permissions) {
+    this.permissions = permissions;
+  }
 }
diff --git a/src/main/java/com/supwisdom/dlpay/framework/security/MyPermissionEvaluator.java b/src/main/java/com/supwisdom/dlpay/framework/security/MyPermissionEvaluator.java
new file mode 100644 (file)
index 0000000..dfa30c6
--- /dev/null
@@ -0,0 +1,52 @@
+package com.supwisdom.dlpay.framework.security;
+
+import com.supwisdom.dlpay.framework.domain.TResource;
+import com.supwisdom.dlpay.framework.domain.TRole;
+import com.supwisdom.dlpay.framework.domain.TRoleFunction;
+import com.supwisdom.dlpay.framework.util.StringUtil;
+import com.supwisdom.dlpay.system.service.RoleService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.PermissionEvaluator;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.stereotype.Component;
+
+import java.io.Serializable;
+import java.util.Collection;
+
+@Component
+public class MyPermissionEvaluator implements PermissionEvaluator {
+    @Autowired
+    private RoleService roleService;
+
+    @Override
+    public boolean hasPermission(Authentication authentication, Object targetUri, Object permission) {
+        if (targetUri != null && permission != null) {
+            UserDetails userDetails = (UserDetails) authentication.getPrincipal();
+            if (userDetails != null) {
+                Collection<GrantedAuthority> authorities = (Collection<GrantedAuthority>) userDetails.getAuthorities();
+                for (GrantedAuthority authority : authorities) {
+                    String roleName = authority.getAuthority();
+                    TRole role = roleService.findRoleByRolecode(roleName);
+                    if (role != null) {
+                        TResource resource = roleService.findResourceByURI(String.valueOf(targetUri));
+                        if (resource != null) {
+                            TRoleFunction roleFunction = roleService.findRoleFunctionByRoleIdAndFunctionId(role.getRoleId(), resource.getFunctionId());
+                            if (roleFunction != null && !StringUtil.isEmpty(roleFunction.getPermissions())
+                                    && roleFunction.getPermissions().contains(String.valueOf(permission))) {
+                                return true;
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        return false;
+    }
+
+    @Override
+    public boolean hasPermission(Authentication authentication, Serializable targetId, String targetType, Object permission) {
+        return false;
+    }
+}
diff --git a/src/main/java/com/supwisdom/dlpay/framework/util/PermissionConstants.java b/src/main/java/com/supwisdom/dlpay/framework/util/PermissionConstants.java
new file mode 100644 (file)
index 0000000..6ffa106
--- /dev/null
@@ -0,0 +1,26 @@
+package com.supwisdom.dlpay.framework.util;
+
+/**
+ * 增加权限常量维护表
+ * 增、删、改、查、更新密码、更新状态、打印、导出、导入
+ */
+public class PermissionConstants {
+
+    public static final String PERMISSION_QUERY = "query";
+
+    public static final String PERMISSION_ADD = "add";
+
+    public static final String PERMISSION_DELETE = "delete";
+
+    public static final String PERMISSION_UPDATE = "update";
+
+    public static final String PERMISSION_UPDATE_PWD = "upassword";
+
+    public static final String PERMISSION_UPDATE_STATUS = "ustatus";
+
+    public static final String PERMISSION_PRINT = "print";
+
+    public static final String PERMISSION_IMPORT = "import";
+
+    public static final String PERMISSION_EXPORT = "export";
+}
diff --git a/src/main/java/com/supwisdom/dlpay/system/bean/FunctionSearchBean.java b/src/main/java/com/supwisdom/dlpay/system/bean/FunctionSearchBean.java
new file mode 100644 (file)
index 0000000..67df35b
--- /dev/null
@@ -0,0 +1,13 @@
+package com.supwisdom.dlpay.system.bean;
+
+public class FunctionSearchBean extends PageBean{
+    private String functioname;
+
+    public String getFunctioname() {
+        return functioname;
+    }
+
+    public void setFunctioname(String functioname) {
+        this.functioname = functioname;
+    }
+}
diff --git a/src/main/java/com/supwisdom/dlpay/system/bean/PageBean.java b/src/main/java/com/supwisdom/dlpay/system/bean/PageBean.java
new file mode 100644 (file)
index 0000000..e615a3a
--- /dev/null
@@ -0,0 +1,22 @@
+package com.supwisdom.dlpay.system.bean;
+
+public class PageBean {
+    private int pageNo;
+    private int pageSize;
+
+    public int getPageNo() {
+        return pageNo;
+    }
+
+    public void setPageNo(int pageNo) {
+        this.pageNo = pageNo;
+    }
+
+    public int getPageSize() {
+        return pageSize;
+    }
+
+    public void setPageSize(int pageSize) {
+        this.pageSize = pageSize;
+    }
+}
diff --git a/src/main/java/com/supwisdom/dlpay/system/controller/FunctionController.java b/src/main/java/com/supwisdom/dlpay/system/controller/FunctionController.java
new file mode 100644 (file)
index 0000000..16c598a
--- /dev/null
@@ -0,0 +1,48 @@
+package com.supwisdom.dlpay.system.controller;
+
+
+import com.supwisdom.dlpay.framework.domain.TFunction;
+import com.supwisdom.dlpay.framework.domain.TOperator;
+import com.supwisdom.dlpay.framework.util.PageResult;
+import com.supwisdom.dlpay.framework.util.StringUtil;
+import com.supwisdom.dlpay.framework.util.WebConstant;
+import com.supwisdom.dlpay.system.bean.FunctionSearchBean;
+import com.supwisdom.dlpay.system.bean.OperatorSearchBean;
+import com.supwisdom.dlpay.system.service.FunctionService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+import org.springframework.ui.Model;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.ResponseBody;
+
+@Controller
+public class FunctionController {
+
+    @Autowired
+    private FunctionService functionService;
+
+    @GetMapping("/function/index")
+    public String indexView() {
+        return "system/function/index";
+    }
+
+    @GetMapping("/function/list")
+    @ResponseBody
+    public PageResult<TFunction> getDataList(@RequestParam("page") Integer pageNo,
+                                             @RequestParam("limit") Integer pageSize,
+                                             @RequestParam(value = "searchkey", required = false) String searchKey) {
+        try {
+            if (null == pageNo || pageNo < 1) pageNo = WebConstant.PAGENO_DEFAULT;
+            if (null == pageSize || pageSize < 1) pageSize = WebConstant.PAGESIZE_DEFAULT;
+            FunctionSearchBean searchBean = new FunctionSearchBean();
+            searchBean.setPageNo(pageNo);
+            searchBean.setFunctioname(searchKey);
+            searchBean.setPageSize(pageSize);
+            return functionService.getFunctionsByKey(searchBean);
+        } catch (Exception e) {
+            e.printStackTrace();
+            return new PageResult<>(99, "系统查询错误");
+        }
+    }
+}
index 58b7bf6..25e6ec5 100644 (file)
@@ -9,6 +9,7 @@ import com.supwisdom.dlpay.system.bean.OperatorSearchBean;
 import com.supwisdom.dlpay.system.service.OperatorService;
 import com.supwisdom.dlpay.system.service.RoleService;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.stereotype.Controller;
 import org.springframework.ui.Model;
 import org.springframework.web.bind.annotation.*;
@@ -23,6 +24,7 @@ public class OperatorController {
   private RoleService roleService;
 
   @GetMapping("/index")
+  @PreAuthorize("hasPermission('/operator/index','query')")
   public String indexView(Model model) {
     return "system/operator/index";
   }
@@ -55,6 +57,7 @@ public class OperatorController {
   }
 
   @GetMapping("/load4add")
+  @PreAuthorize("hasPermission('/operator/load4add','query')")
   public String load4addOperator(Model model) {
     model.addAttribute("roles", roleService.findAllRoles());
     return "system/operator/operator";
index b2e464f..55cc2aa 100644 (file)
@@ -1,6 +1,8 @@
 package com.supwisdom.dlpay.system.service;
 
 import com.supwisdom.dlpay.framework.domain.TFunction;
+import com.supwisdom.dlpay.framework.util.PageResult;
+import com.supwisdom.dlpay.system.bean.FunctionSearchBean;
 
 import java.util.List;
 import java.util.Map;
@@ -9,4 +11,6 @@ public interface FunctionService {
   List<TFunction> getFunctionsByOperid(String operid);
 
   List<Map<String, Object>> getMenuTree(List<TFunction> funcList, String parentId);
+
+  PageResult<TFunction> getFunctionsByKey(FunctionSearchBean param);
 }
index c9ca96e..e4b8082 100644 (file)
@@ -1,9 +1,17 @@
 package com.supwisdom.dlpay.system.service;
 
+import com.supwisdom.dlpay.framework.domain.TResource;
 import com.supwisdom.dlpay.framework.domain.TRole;
+import com.supwisdom.dlpay.framework.domain.TRoleFunction;
 
 import java.util.List;
 
 public interface RoleService {
-  List<TRole> findAllRoles();
+    List<TRole> findAllRoles();
+
+    TRole findRoleByRolecode(String rolecode);
+
+    TResource findResourceByURI(String uri);
+
+    TRoleFunction findRoleFunctionByRoleIdAndFunctionId(String roleid, String functionid);
 }
index 30e7a77..41b1460 100644 (file)
@@ -2,9 +2,14 @@ package com.supwisdom.dlpay.system.service.impl;
 
 import com.supwisdom.dlpay.framework.dao.FunctionDao;
 import com.supwisdom.dlpay.framework.domain.TFunction;
+import com.supwisdom.dlpay.framework.util.PageResult;
 import com.supwisdom.dlpay.framework.util.StringUtil;
+import com.supwisdom.dlpay.system.bean.FunctionSearchBean;
 import com.supwisdom.dlpay.system.service.FunctionService;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.domain.PageRequest;
+import org.springframework.data.domain.Pageable;
+import org.springframework.data.domain.Sort;
 import org.springframework.stereotype.Service;
 
 import java.util.ArrayList;
@@ -14,33 +19,43 @@ import java.util.Map;
 
 @Service
 public class FunctionServiceImpl implements FunctionService {
-  @Autowired
-  private FunctionDao functionDao;
+    @Autowired
+    private FunctionDao functionDao;
 
-  @Override
-  public List<TFunction> getFunctionsByOperid(String operid) {
-    List<TFunction> list = functionDao.getTFunctionsByOperid(StringUtil.isEmpty(operid) ? "" : operid.trim());
-    if (!StringUtil.isEmpty(list)) return list;
-    return new ArrayList(0);
-  }
+    @Override
+    public List<TFunction> getFunctionsByOperid(String operid) {
+        List<TFunction> list = functionDao.getTFunctionsByOperid(StringUtil.isEmpty(operid) ? "" : operid.trim());
+        if (!StringUtil.isEmpty(list)) return list;
+        return new ArrayList(0);
+    }
+
+    @Override
+    public List<Map<String, Object>> getMenuTree(List<TFunction> funcList, String parentId) {
+        List<Map<String, Object>> list = new ArrayList<>(0);
+        for (TFunction func : funcList) {
+            if (parentId.equals(func.getParentId())) {
+                Map<String, Object> map = new HashMap<>(0);
+                map.put("menuName", func.getName());
+                map.put("menuIcon", func.getMenuIcon());
+                if ("#".equals(func.getMenuUrl())) {
+                    map.put("menuUrl", "javascript:;");
+                } else {
+                    map.put("menuUrl", func.getMenuUrl());
+                }
+                map.put("subMenus", getMenuTree(funcList, func.getId()));
+                list.add(map);
+            }
+        }
+        return list;
+    }
 
-  @Override
-  public List<Map<String, Object>> getMenuTree(List<TFunction> funcList, String parentId) {
-    List<Map<String, Object>> list = new ArrayList<>(0);
-    for (TFunction func : funcList) {
-      if (parentId.equals(func.getParentId())) {
-        Map<String, Object> map = new HashMap<>(0);
-        map.put("menuName", func.getName());
-        map.put("menuIcon", func.getMenuIcon());
-        if ("#".equals(func.getMenuUrl())) {
-          map.put("menuUrl", "javascript:;");
-        } else {
-          map.put("menuUrl", func.getMenuUrl());
+    @Override
+    public PageResult<TFunction> getFunctionsByKey(FunctionSearchBean param) {
+        Pageable pageable = PageRequest.of(param.getPageNo() - 1, param.getPageSize()
+                , Sort.by("id"));
+        if (!StringUtil.isEmpty(param.getFunctioname())) {
+            return new PageResult<>(functionDao.findAllByNameContaining(param.getFunctioname(), pageable));
         }
-        map.put("subMenus", getMenuTree(funcList, func.getId()));
-        list.add(map);
-      }
+        return new PageResult<>(functionDao.findAll(pageable));
     }
-    return list;
-  }
 }
index 08fed96..f78b052 100644 (file)
@@ -1,7 +1,11 @@
 package com.supwisdom.dlpay.system.service.impl;
 
+import com.supwisdom.dlpay.framework.dao.ResourceDao;
 import com.supwisdom.dlpay.framework.dao.RoleDao;
+import com.supwisdom.dlpay.framework.dao.RoleFunctionDao;
+import com.supwisdom.dlpay.framework.domain.TResource;
 import com.supwisdom.dlpay.framework.domain.TRole;
+import com.supwisdom.dlpay.framework.domain.TRoleFunction;
 import com.supwisdom.dlpay.framework.util.StringUtil;
 import com.supwisdom.dlpay.system.service.RoleService;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -15,10 +19,31 @@ public class RoleServiceImpl implements RoleService {
   @Autowired
   private RoleDao roleDao;
 
+  @Autowired
+  private ResourceDao resourceDao;
+
+  @Autowired
+  private RoleFunctionDao roleFunctionDao;
+
   @Override
   public List<TRole> findAllRoles() {
     List<TRole> list = roleDao.getAllRoles();
     if(!StringUtil.isEmpty(list)) return list;
     return new ArrayList<>(0);
   }
+
+  @Override
+  public TRole findRoleByRolecode(String rolecode) {
+    return roleDao.findByRoleCode(rolecode);
+  }
+
+  @Override
+  public TResource findResourceByURI(String uri) {
+    return resourceDao.findByUri(uri);
+  }
+
+  @Override
+  public TRoleFunction findRoleFunctionByRoleIdAndFunctionId(String roleid, String functionid) {
+    return roleFunctionDao.findByRoleIdAndFunctionId(roleid,functionid);
+  }
 }
index 6274983..4392fa6 100644 (file)
@@ -4,6 +4,7 @@ import com.supwisdom.dlpay.framework.core.JwtConfig
 import com.supwisdom.dlpay.framework.core.JwtTokenUtil
 import com.supwisdom.dlpay.framework.core.PasswordBCryptConfig
 import com.supwisdom.dlpay.framework.redisrepo.ApiJwtRepository
+import com.supwisdom.dlpay.framework.security.MyPermissionEvaluator
 import com.supwisdom.dlpay.framework.security.ValidateCodeSecurityConfig
 import com.supwisdom.dlpay.framework.service.OperatorDetailService
 import com.supwisdom.dlpay.framework.util.TradeDict
@@ -17,6 +18,7 @@ import org.springframework.http.HttpStatus
 import org.springframework.security.authentication.UsernamePasswordAuthenticationToken
 import org.springframework.security.authentication.dao.DaoAuthenticationProvider
 import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder
+import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity
 import org.springframework.security.config.annotation.web.builders.HttpSecurity
 import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity
 import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter
@@ -24,6 +26,7 @@ import org.springframework.security.config.http.SessionCreationPolicy
 import org.springframework.security.core.authority.SimpleGrantedAuthority
 import org.springframework.security.core.context.SecurityContextHolder
 import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder
+import org.springframework.security.web.access.expression.DefaultWebSecurityExpressionHandler
 import org.springframework.security.web.authentication.AuthenticationFailureHandler
 import org.springframework.security.web.authentication.AuthenticationSuccessHandler
 import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter
@@ -98,6 +101,7 @@ class ApiJwtAuthenticationFilter : OncePerRequestFilter() {
 }
 
 @EnableWebSecurity
+@EnableGlobalMethodSecurity(prePostEnabled = true)
 class WebSecurityConfig {
 
     companion object {
index 608c847..29547ad 100755 (executable)
@@ -702,3 +702,100 @@ body.layui-fluid {
     padding: 0;
     overflow: hidden;
 }
+
+@-webkit-keyframes layui-rl {
+    from {
+        -webkit-transform: translate3d(100%,0,0)
+    }
+
+    to {
+        -webkit-transform: translate3d(0,0,0)
+    }
+}
+
+@keyframes layui-rl {
+    from {
+        transform: translate3d(100%,0,0)
+    }
+
+    to {
+        transform: translate3d(0,0,0)
+    }
+}
+
+.layui-anim-rl {
+    -webkit-animation-name: layui-rl;
+    animation-name: layui-rl
+}
+
+@-webkit-keyframes layui-lr {
+    from {
+        -webkit-transform: translate3d(0 0,0);
+        opacity: 1
+    }
+
+    to {
+        -webkit-transform: translate3d(100%,0,0);
+        opacity: 1
+    }
+}
+
+@keyframes layui-lr {
+    from {
+        transform: translate3d(0,0,0)
+    }
+
+    to {
+        transform: translate3d(100%,0,0)
+    }
+}
+
+.layui-anim-lr,.layui-anim-rl.layer-anim-close {
+    -webkit-animation-name: layui-lr;
+    animation-name: layui-lr
+}
+
+.layadmin-tips {
+    margin-top: 30px;
+    text-align: center
+}
+
+.layadmin-tips .layui-icon[face] {
+    display: inline-block;
+    font-size: 300px;
+    color: #393D49
+}
+
+.layadmin-tips .layui-text {
+    width: 500px;
+    margin: 30px auto;
+    padding-top: 20px;
+    border-top: 5px solid #009688;
+    font-size: 16px
+}
+
+.layadmin-tips h1 {
+    font-size: 100px;
+    line-height: 100px;
+    color: #009688
+}
+
+.layadmin-tips .layui-text .layui-anim {
+    display: inline-block
+}
+
+@media screen and (max-width: 768px) {
+    .layadmin-panel-selection {
+        margin:0;
+        width: auto
+    }
+
+    .layui-body .layui-nav .layui-nav-item {
+        display: block
+    }
+
+    .layui-layout-admin .layui-body .layadmin-tabsbody-item {
+        -webkit-overflow-scrolling: touch;
+        overflow: auto
+    }
+}
\ No newline at end of file
index 898ce05..344c44d 100755 (executable)
@@ -145,7 +145,8 @@ layui.define(['layer'], function (exports) {
                 successCallback(result, status, xhr);\r
             };\r
             param.error = function (xhr) {\r
-                param.success({code: xhr.status, msg: xhr.statusText});\r
+                //{code: xhr.status, msg: xhr.statusText}\r
+                param.success(xhr.responseText,xhr.status,xhr);\r
             };\r
             $.ajax(param);\r
         },\r
diff --git a/src/main/resources/templates/error/403.html b/src/main/resources/templates/error/403.html
new file mode 100755 (executable)
index 0000000..155f35a
--- /dev/null
@@ -0,0 +1,27 @@
+<!DOCTYPE html>\r
+<html xmlns:th="http://www.thymeleaf.org" >\r
+<head>\r
+  <meta charset="utf-8">\r
+  <title>403 无权限</title>\r
+  <meta name="renderer" content="webkit">\r
+  <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">\r
+  <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=0">\r
+  <link rel="stylesheet" th:href="@{/static/libs/layui/css/layui.css}" media="all"/>\r
+  <link rel="stylesheet" th:href="@{/static/custom/css/admin.css}" media="all"/>\r
+</head>\r
+<body>\r
+<div class="layui-fluid">\r
+  <div class="layadmin-tips">\r
+    <i class="layui-icon" face>&#xe664;</i>\r
+    <div class="layui-text">\r
+      <p>没有权限</p>\r
+      <h1>\r
+        <span class="layui-anim layui-anim-loop layui-anim-">4</span> \r
+        <span class="layui-anim layui-anim-loop layui-anim-rotate">0</span> \r
+        <span class="layui-anim layui-anim-loop layui-anim-">3</span>\r
+      </h1>\r
+    </div>\r
+  </div>\r
+</div>\r
+</body>\r
+</html>
\ No newline at end of file
diff --git a/src/main/resources/templates/error/404.html b/src/main/resources/templates/error/404.html
new file mode 100755 (executable)
index 0000000..89144f5
--- /dev/null
@@ -0,0 +1,28 @@
+<!DOCTYPE html>\r
+<html xmlns:th="http://www.thymeleaf.org" >\r
+<head>\r
+  <meta charset="utf-8">\r
+  <title>404 页面不存在</title>\r
+  <meta name="renderer" content="webkit">\r
+  <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">\r
+  <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=0">\r
+  <link rel="stylesheet" th:href="@{/static/libs/layui/css/layui.css}" media="all"/>\r
+  <link rel="stylesheet" th:href="@{/static/custom/css/admin.css}" media="all"/>\r
+</head>\r
+<body>\r
+\r
+<div class="layui-fluid">\r
+  <div class="layadmin-tips">\r
+    <i class="layui-icon" face>&#xe664;</i>\r
+    <div class="layui-text">\r
+      <p>页面不存在</p>\r
+      <h1>\r
+        <span class="layui-anim layui-anim-loop layui-anim-">4</span> \r
+        <span class="layui-anim layui-anim-loop layui-anim-rotate">0</span> \r
+        <span class="layui-anim layui-anim-loop layui-anim-">4</span>\r
+      </h1>\r
+    </div>\r
+  </div>\r
+</div>\r
+</body>\r
+</html>
\ No newline at end of file
diff --git a/src/main/resources/templates/error/500.html b/src/main/resources/templates/error/500.html
new file mode 100755 (executable)
index 0000000..c46acd2
--- /dev/null
@@ -0,0 +1,28 @@
+<!DOCTYPE html>\r
+<html xmlns:th="http://www.thymeleaf.org" >\r
+<head>\r
+  <meta charset="utf-8">\r
+  <title>500 服务出错</title>\r
+  <meta name="renderer" content="webkit">\r
+  <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">\r
+  <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=0">\r
+  <link rel="stylesheet" th:href="@{/static/libs/layui/css/layui.css}" media="all"/>\r
+  <link rel="stylesheet" th:href="@{/static/custom/css/admin.css}" media="all"/>\r
+</head>\r
+<body>\r
+\r
+<div class="layui-fluid">\r
+  <div class="layadmin-tips">\r
+    <i class="layui-icon" face>&#xe664;</i>\r
+    <div class="layui-text">\r
+      <p>服务器出错了</p>\r
+      <h1>\r
+        <span class="layui-anim layui-anim-loop layui-anim-">5</span>\r
+        <span class="layui-anim layui-anim-loop layui-anim-rotate">0</span> \r
+        <span class="layui-anim layui-anim-loop layui-anim-">0</span>\r
+      </h1>\r
+    </div>\r
+  </div>\r
+</div>\r
+</body>\r
+</html>
\ No newline at end of file
index a66007c..7dec8c5 100755 (executable)
@@ -1,5 +1,5 @@
 <!DOCTYPE html>\r
-<html xmlns:th="http://www.thymeleaf.org">\r
+<html xmlns:th="http://www.thymeleaf.org" xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity4">\r
 \r
 <head>\r
     <title>首页</title>\r
                         <dd th:each="subMenu : ${menu.subMenus}">\r
                             <a th:lay-href="${subMenu.menuUrl}">[[${subMenu.menuName}]]</a>\r
                             <dl class="layui-nav-child" th:if="${subMenu.subMenus.size()} > 0">\r
-                                <dd th:each="temp : ${subMenu.subMenus}"><a th:lay-href="${temp.menuUrl}">[[${temp.menuName}]]</a>\r
+                                <dd th:each="temp : ${subMenu.subMenus}"><a th:lay-href="${temp.menuUrl}">\r
+                                    <i th:class="'layui-icon '+${temp.menuIcon}"></i>\r
+                                    [[${temp.menuName}]]\r
+                                  </a>\r
                                 </dd>\r
                             </dl>\r
                         </dd>\r
     });\r
 </script>\r
 \r
-\r
 <script>\r
     layui.use(['index'], function () {\r
         var index = layui.index;\r
diff --git a/src/main/resources/templates/system/function/form.html b/src/main/resources/templates/system/function/form.html
new file mode 100755 (executable)
index 0000000..cd67f9f
--- /dev/null
@@ -0,0 +1,43 @@
+<div class="layui-form" lay-filter="layuiadmin-form-role" id="function-form" style="padding: 20px 30px 0 0;">\r
+    <div class="layui-form-item">\r
+        <label class="layui-form-label">角色</label>\r
+        <div class="layui-input-block">\r
+            <select name="rolename">\r
+                <option value="0">管理员</option>\r
+                <option value="1">超级管理员</option>\r
+                <option value="2">纠错员</option>\r
+                <option value="3">采购员</option>\r
+                <option value="4">推销员</option>\r
+                <option value="5">运营人员</option>\r
+                <option value="6">编辑</option>\r
+            </select>\r
+        </div>\r
+    </div>\r
+    <div class="layui-form-item">\r
+        <label class="layui-form-label">权限范围</label>\r
+        <div class="layui-input-block">\r
+            <input type="checkbox" name="limits[]" lay-skin="primary" title="内容系统">\r
+            <input type="checkbox" name="limits[]" lay-skin="primary" title="社区系统">\r
+            <input type="checkbox" name="limits[]" lay-skin="primary" title="用户">\r
+            <input type="checkbox" name="limits[]" lay-skin="primary" title="角色">\r
+            <input type="checkbox" name="limits[]" lay-skin="primary" title="评论审核">\r
+            <input type="checkbox" name="limits[]" lay-skin="primary" title="发货">\r
+            <input type="checkbox" name="limits[]" lay-skin="primary" title="采购">\r
+            <input type="checkbox" name="limits[]" lay-skin="primary" title="系统设置">\r
+            <input type="checkbox" name="limits[]" lay-skin="primary" title="发邮件">\r
+            <input type="checkbox" name="limits[]" lay-skin="primary" title="发短信">\r
+            <input type="checkbox" name="limits[]" lay-skin="primary" title="审核">\r
+            <input type="checkbox" name="limits[]" lay-skin="primary" title="删库跑路">\r
+        </div>\r
+    </div>\r
+    <div class="layui-form-item">\r
+        <label class="layui-form-label">具体描述</label>\r
+        <div class="layui-input-block">\r
+            <textarea type="text" name="descr" lay-verify="required" autocomplete="off"\r
+                      class="layui-textarea"></textarea>\r
+        </div>\r
+    </div>\r
+    <div class="layui-form-item layui-hide">\r
+        <button class="layui-btn" lay-submit lay-filter="LAY-user-role-submit" id="LAY-user-role-submit">提交</button>\r
+    </div>\r
+</div>\r
diff --git a/src/main/resources/templates/system/function/index.html b/src/main/resources/templates/system/function/index.html
new file mode 100755 (executable)
index 0000000..afcda4c
--- /dev/null
@@ -0,0 +1,170 @@
+<div class="layui-card">\r
+    <div class="layui-card-header">\r
+        <h2 class="header-title">功能维护</h2>\r
+        <span class="layui-breadcrumb pull-right">\r
+          <a href="#!_operator_index">系统中心</a>\r
+          <a><cite>功能维护</cite></a>\r
+        </span>\r
+    </div>\r
+    <div class="layui-card-body">\r
+        <div class="layui-form toolbar">\r
+            搜索:\r
+            <input id="search-value" class="layui-input search-input" type="text" placeholder="输入功能名称"/>&emsp;\r
+            <button id="btn-search" class="layui-btn icon-btn" data-type="search"><i class="layui-icon">&#xe615;</i>搜索</button>\r
+            <button id="btn-add" class="layui-btn icon-btn" data-type="add" ><i class="layui-icon"></i>添加\r
+            </button>\r
+        </div>\r
+        <table class="layui-table" id="table"></table>\r
+    </div>\r
+</div>\r
+\r
+<!-- 表格操作列 -->\r
+<script type="text/html" id="table-bar">\r
+    <a class="layui-btn layui-btn-normal layui-btn-xs" lay-event="edit"><i class="layui-icon layui-icon-edit"></i>编辑</a>\r
+    <a class="layui-btn layui-btn-normal layui-btn-xs" lay-event="edit"><i class="layui-icon layui-icon-set-sm"></i>维护资源</a>\r
+    <a class="layui-btn layui-btn-danger layui-btn-xs" lay-event="del"><i class="layui-icon layui-icon-delete"></i>删除</a>\r
+</script>\r
+\r
+<script>\r
+    layui.use(['form', 'table', 'layer', 'admin', 'element'], function () {\r
+        var form = layui.form;\r
+        var table = layui.table;\r
+        var layer = layui.layer;\r
+        var admin = layui.admin;\r
+        var element = layui.element;\r
+\r
+        form.render('select');\r
+\r
+        // 渲染表格\r
+        table.render({\r
+            elem: '#table',\r
+            url: '/function/list',\r
+            page: true,\r
+            cols: [\r
+                [\r
+                    {field: 'id', title: '功能ID', fixed: 'left', sort: true},\r
+                    {field: 'name', title: '功能名称', sort: true},\r
+                    {\r
+                        field: 'isLeaf', title: '节点', sort: true, width: 80, align: 'center', templet: function (item) {\r
+                            if (item.isLeaf == 0) {\r
+                                return '<span class="layui-badge ">父</span>'\r
+                            } else if (item.isLeaf == 1) {\r
+                                return '<span class="layui-badge layui-bg-green">子</span>'\r
+                            } else {\r
+                                return ''\r
+                            }\r
+                        }\r
+                    },\r
+                    {field: 'menuUrl', title: '路径'},\r
+                    {field: 'orderNum', sort: true, title: '序号'},\r
+                    {field: 'menuIcon', title: '图标',align: 'center', templet: function (item) {\r
+                            return '<i class="layui-icon '+item.menuIcon+'"></i> '\r
+                        }\r
+                    },\r
+                    {field:'id',align: 'center', toolbar: '#table-bar', title: '操作', fixed: 'right'}\r
+                ]\r
+            ]\r
+        });\r
+        // 搜索按钮点击事件\r
+        $('#btn-search').click(function () {\r
+            var key = $('#search-value').val();\r
+            table.reload('table', {where: {searchkey: key}, page: {curr: 1}});\r
+        });\r
+        $('#btn-add').click(function () {\r
+            layer.open({\r
+                type: 1\r
+                ,title: '添加功能'\r
+                ,content: 'form.html'\r
+                ,maxmin: true\r
+                ,area: ['500px', '450px']\r
+                ,btn: ['确定', '取消']\r
+                ,yes: function(index, layero){\r
+                    var iframeWindow = window['layui-layer-iframe'+ index]\r
+                        ,submitID = 'LAY-user-front-submit'\r
+                        ,submit = layero.find('iframe').contents().find('#'+ submitID);\r
+\r
+                    //监听提交\r
+                    iframeWindow.layui.form.on('submit('+ submitID +')', function(data){\r
+                        var field = data.field; //获取提交的字段\r
+                        //提交 Ajax 成功后,静态更新表格中的数据\r
+                        //$.ajax({});\r
+                        table.reload('table');\r
+                        layer.close(index); //关闭弹层\r
+                    });\r
+\r
+                    submit.trigger('click');\r
+                }\r
+            });\r
+        });\r
+        // 显示表单弹窗\r
+        var showEditModel = function (data) {\r
+            var title = data ? '修改用户' : '添加用户';\r
+            admin.putTempData('t_user', data);\r
+            admin.popupCenter({\r
+                title: title,\r
+                path: '/operator/load4add',\r
+                finish: function () {\r
+                    table.reload('oper-table', {});\r
+                }\r
+            });\r
+        };\r
+\r
+        // 工具条点击事件\r
+        table.on('tool(user-table)', function (obj) {\r
+            console.log(obj);\r
+            var data = obj.data;\r
+            var layEvent = obj.event;\r
+\r
+            if (layEvent === 'edit') { // 修改\r
+                showEditModel(data);\r
+            } else if (layEvent === 'reset') { // 重置密码\r
+                layer.confirm('确定重置此用户的密码吗?', function (i) {\r
+                    layer.close(i);\r
+                    layer.load(2);\r
+                    admin.go('/system/user/restPsw', {\r
+                        userId: obj.data.userId\r
+                    }, function (data) {\r
+                        console.log(data.code);\r
+                        layer.closeAll('loading');\r
+                        if (data.code == 200) {\r
+                            layer.msg(data.msg, {icon: 1});\r
+                        } else if (data.code == 401) {\r
+                            layer.msg(data.msg, {icon: 2, time: 1500}, function () {\r
+                                location.replace('/login');\r
+                            }, 1000);\r
+                            return;\r
+                        }\r
+                        else {\r
+                            layer.msg(data.msg, {icon: 2});\r
+                        }\r
+                    });\r
+                });\r
+            }\r
+        });\r
+\r
+        // 修改user状态\r
+        form.on('switch(user-tpl-state)', function (obj) {\r
+            layer.load(2);\r
+            admin.go('/system/user/updateState', {\r
+                userId: obj.elem.value,\r
+                state: obj.elem.checked ? 0 : 1\r
+            }, function (data) {\r
+                layer.closeAll('loading');\r
+                if (data.code == 200) {\r
+                    layer.msg(data.msg, {icon: 1});\r
+                    //table.reload('table-user', {});\r
+                } else if (data.code == 401) {\r
+                    layer.msg(data.msg, {icon: 2, time: 1500}, function () {\r
+                        location.replace('/login');\r
+                    }, 1000);\r
+                    return;\r
+                } else {\r
+                    layer.msg(data.msg, {icon: 2});\r
+                    $(obj.elem).prop('checked', !obj.elem.checked);\r
+                    form.render('checkbox');\r
+                }\r
+            });\r
+        });\r
+\r
+    });\r
+</script>\r
index 279a2ed..1f6dad4 100644 (file)
@@ -17,7 +17,8 @@
             </select>&emsp;
             <input id="oper-search-value" class="layui-input search-input" type="text" placeholder="输入关键字"/>&emsp;
             <button id="oper-btn-search" class="layui-btn icon-btn"><i class="layui-icon">&#xe615;</i>搜索</button>
-            <button id="oper-btn-add" class="layui-btn icon-btn" lay-tips="新用户密码为123456"><i
+            <button id="oper-btn-add" class="layui-btn icon-btn" lay-tips="新用户密码为123456"
+                    sec:authorize="hasPermission('/operator/load4add','query')" ><i
                     class="layui-icon">&#xe654;</i>添加
             </button>
         </div>