Commit cb6a0a7f6d679cbe962bb2e323e810df324894af

Authored by 潘钊
0 parents

init

Showing 79 changed files with 4471 additions and 0 deletions

Too many changes to show.

To preserve performance only 79 of 573 files are displayed.

.gitignore 0 → 100644
  1 +++ a/.gitignore
  1 +.classpath
  2 +.project
  3 +.springBeans
  4 +.settings/*
  5 +/target/*
0 6 \ No newline at end of file
... ...
pom.xml 0 → 100644
  1 +++ a/pom.xml
  1 +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  2 + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  3 +
  4 + <modelVersion>4.0.0</modelVersion>
  5 + <groupId>com.bsth</groupId>
  6 + <artifactId>bsth_control</artifactId>
  7 + <version>0.0.1-SNAPSHOT</version>
  8 + <packaging>jar</packaging>
  9 +
  10 + <parent>
  11 + <groupId>org.springframework.boot</groupId>
  12 + <artifactId>spring-boot-starter-parent</artifactId>
  13 + <version>1.3.3.RELEASE</version>
  14 + </parent>
  15 +
  16 + <dependencies>
  17 + <dependency>
  18 + <groupId>org.springframework.boot</groupId>
  19 + <artifactId>spring-boot-starter-web</artifactId>
  20 + </dependency>
  21 + <dependency>
  22 + <groupId>org.springframework.boot</groupId>
  23 + <artifactId>spring-boot-starter-security</artifactId>
  24 + </dependency>
  25 +<!-- <dependency>
  26 + <groupId>org.springframework.security</groupId>
  27 + <artifactId>spring-security-config</artifactId>
  28 + </dependency> -->
  29 + <dependency>
  30 + <groupId>org.springframework.boot</groupId>
  31 + <artifactId>spring-boot-starter-data-jpa</artifactId>
  32 + </dependency>
  33 + <dependency>
  34 + <groupId>org.springframework.boot</groupId>
  35 + <artifactId>spring-boot-starter-aop</artifactId>
  36 + </dependency>
  37 +
  38 + <dependency>
  39 + <groupId>org.springframework</groupId>
  40 + <artifactId>spring-context-support</artifactId>
  41 + </dependency>
  42 + <dependency>
  43 + <groupId>org.springframework.boot</groupId>
  44 + <artifactId>spring-boot-starter-redis</artifactId>
  45 + </dependency>
  46 + <dependency>
  47 + <groupId>org.springframework.boot</groupId>
  48 + <artifactId>spring-boot-starter-websocket</artifactId>
  49 + </dependency>
  50 + <dependency>
  51 + <groupId>mysql</groupId>
  52 + <artifactId>mysql-connector-java</artifactId>
  53 + </dependency>
  54 +
  55 + <dependency>
  56 + <groupId>joda-time</groupId>
  57 + <artifactId>joda-time</artifactId>
  58 + </dependency>
  59 + <dependency>
  60 + <groupId>com.alibaba</groupId>
  61 + <artifactId>fastjson</artifactId>
  62 + <version>1.2.4</version>
  63 + </dependency>
  64 + <dependency>
  65 + <groupId>commons-httpclient</groupId>
  66 + <artifactId>commons-httpclient</artifactId>
  67 + <version>3.1</version>
  68 + </dependency>
  69 +
  70 + <dependency>
  71 + <groupId>commons-dbcp</groupId>
  72 + <artifactId>commons-dbcp</artifactId>
  73 + </dependency>
  74 +
  75 + <dependency>
  76 + <groupId>org.apache.commons</groupId>
  77 + <artifactId>commons-lang3</artifactId>
  78 + <version>3.4</version>
  79 + </dependency>
  80 + <dependency>
  81 + <groupId>commons-io</groupId>
  82 + <artifactId>commons-io</artifactId>
  83 + <version>2.4</version>
  84 + </dependency>
  85 + <dependency>
  86 + <groupId>org.codehaus.janino</groupId>
  87 + <artifactId>janino</artifactId>
  88 + </dependency>
  89 +
  90 + <dependency>
  91 + <groupId>org.apache.poi</groupId>
  92 + <artifactId>poi</artifactId>
  93 + <version>3.13</version>
  94 + </dependency>
  95 +
  96 + <dependency>
  97 + <groupId>com.google.guava</groupId>
  98 + <artifactId>guava</artifactId>
  99 + <version>19.0</version>
  100 + </dependency>
  101 + </dependencies>
  102 + <build>
  103 + <plugins>
  104 + <plugin>
  105 + <artifactId>maven-compiler-plugin</artifactId>
  106 + <version>2.3.2</version><!--$NO-MVN-MAN-VER$ -->
  107 + <configuration>
  108 + <source>1.7</source>
  109 + <target>1.7</target>
  110 + </configuration>
  111 + </plugin>
  112 + <plugin>
  113 + <artifactId>maven-war-plugin</artifactId>
  114 + <version>2.2</version><!--$NO-MVN-MAN-VER$ -->
  115 + <configuration>
  116 + <version>3.1</version>
  117 + <failOnMissingWebXml>false</failOnMissingWebXml>
  118 + </configuration>
  119 + </plugin>
  120 + <plugin>
  121 + <groupId>org.springframework.boot</groupId>
  122 + <artifactId>spring-boot-maven-plugin</artifactId>
  123 + </plugin>
  124 + </plugins>
  125 + </build>
  126 + <repositories>
  127 + <repository>
  128 + <id>spring-snapshots</id>
  129 + <url>http://repo.spring.io/snapshot</url>
  130 + <snapshots>
  131 + <enabled>true</enabled>
  132 + </snapshots>
  133 + </repository>
  134 + <repository>
  135 + <id>spring-milestones</id>
  136 + <url>http://repo.spring.io/milestone</url>
  137 + </repository>
  138 + </repositories>
  139 + <pluginRepositories>
  140 + <pluginRepository>
  141 + <id>spring-snapshots</id>
  142 + <url>http://repo.spring.io/snapshot</url>
  143 + </pluginRepository>
  144 + <pluginRepository>
  145 + <id>spring-milestones</id>
  146 + <url>http://repo.spring.io/milestone</url>
  147 + </pluginRepository>
  148 + </pluginRepositories>
  149 +</project>
0 150 \ No newline at end of file
... ...
src/main/java/com/bsth/Application.java 0 → 100644
  1 +++ a/src/main/java/com/bsth/Application.java
  1 +package com.bsth;
  2 +
  3 +import org.springframework.boot.SpringApplication;
  4 +import org.springframework.boot.autoconfigure.*;
  5 +
  6 +@SpringBootApplication
  7 +public class Application{
  8 +
  9 + public static void main(String[] args) throws Exception {
  10 + SpringApplication.run(Application.class, args);
  11 + }
  12 +}
0 13 \ No newline at end of file
... ...
src/main/java/com/bsth/StartCommand.java 0 → 100644
  1 +++ a/src/main/java/com/bsth/StartCommand.java
  1 +package com.bsth;
  2 +
  3 +
  4 +import org.slf4j.Logger;
  5 +import org.slf4j.LoggerFactory;
  6 +import org.springframework.beans.factory.annotation.Autowired;
  7 +import org.springframework.boot.CommandLineRunner;
  8 +import org.springframework.stereotype.Component;
  9 +
  10 +import com.bsth.security.SecurityMetadataSourceService;
  11 +
  12 +/**
  13 + * 随应用启动运行
  14 + * @author PanZhao
  15 + *
  16 + */
  17 +@Component
  18 +public class StartCommand implements CommandLineRunner{
  19 +
  20 + Logger logger = LoggerFactory.getLogger(this.getClass());
  21 +
  22 + @Autowired
  23 + SecurityMetadataSourceService invocationSecurityMetadataSourceService;
  24 +
  25 + @Override
  26 + public void run(String... arg0){
  27 +
  28 + try {
  29 + //启动时加载所有资源
  30 + invocationSecurityMetadataSourceService.loadResourceDefine();
  31 + } catch (Exception e) {
  32 + e.printStackTrace();
  33 + }
  34 + }
  35 +}
... ...
src/main/java/com/bsth/WebAppConfiguration.java 0 → 100644
  1 +++ a/src/main/java/com/bsth/WebAppConfiguration.java
  1 +package com.bsth;
  2 +
  3 +import javax.servlet.Filter;
  4 +
  5 +import org.springframework.boot.context.embedded.FilterRegistrationBean;
  6 +import org.springframework.context.annotation.Bean;
  7 +import org.springframework.context.annotation.ComponentScan;
  8 +import org.springframework.context.annotation.Configuration;
  9 +import org.springframework.web.filter.CharacterEncodingFilter;
  10 +import org.springframework.web.filter.HttpPutFormContentFilter;
  11 +import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
  12 +import org.springframework.web.socket.config.annotation.EnableWebSocket;
  13 +import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
  14 +import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;
  15 +
  16 +import com.bsth.filter.ResourceFilter;
  17 +
  18 +@Configuration
  19 +@EnableWebSocket
  20 +@ComponentScan
  21 +public class WebAppConfiguration extends WebMvcConfigurerAdapter implements WebSocketConfigurer{
  22 +
  23 + /**
  24 + *
  25 + * @Title: httpPutFormContentFilter
  26 + * @Description: TODO(弥补浏览器不支持PUT/DELETE,对携带 _method 参数的请求进行转换)
  27 + * @return Filter 返回类型
  28 + * @throws
  29 + */
  30 + @Bean
  31 + public Filter httpPutFormContentFilter() {
  32 + return new HttpPutFormContentFilter();
  33 + }
  34 +
  35 + /**
  36 + *
  37 + * @Title: characterEncodingFilter
  38 + * @Description: TODO(编码过滤器)
  39 + * @return Filter 返回类型
  40 + * @throws
  41 + */
  42 + @Bean
  43 + public Filter characterEncodingFilter(){
  44 + return new CharacterEncodingFilter("UTF-8");
  45 + }
  46 +
  47 + /**
  48 + *
  49 + * @Title: resourceFilterRegistration
  50 + * @Description: TODO(静态资源过滤器, 只处理 /pages 目录下的片段请求 )
  51 + * @return FilterRegistrationBean 返回类型
  52 + * @throws
  53 + */
  54 + @Bean
  55 + public FilterRegistrationBean resourceFilterRegistration(){
  56 + FilterRegistrationBean registration = new FilterRegistrationBean();
  57 + registration.setFilter(new ResourceFilter());
  58 + registration.addUrlPatterns("/pages/*");
  59 + return registration;
  60 + }
  61 +
  62 + @Override
  63 + public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
  64 +
  65 + }
  66 +}
... ...
src/main/java/com/bsth/common/Constants.java 0 → 100644
  1 +++ a/src/main/java/com/bsth/common/Constants.java
  1 +package com.bsth.common;
  2 +
  3 +/**
  4 + *
  5 + * @ClassName: Constants
  6 + * @Description: TODO(常量类)
  7 + * @author PanZhao
  8 + * @date 2016年3月18日 下午11:06:53
  9 + *
  10 + */
  11 +public class Constants {
  12 +
  13 +
  14 + /**
  15 + * 不需要拦截的资源
  16 + */
  17 + public static final String LOGIN = "/login";
  18 + public static final String LOGIN_PAGE = "/login.html";
  19 + public static final String ASSETS_URL = "/assets/**";
  20 + public static final String FAVICON_URL = "/favicon.ico";
  21 + public static final String METRONIC_URL = "/metronic_v4.5.4/**";
  22 + public static final String LOGIN_FAILURE = "/user/loginFailure";
  23 +}
... ...
src/main/java/com/bsth/common/ResponseCode.java 0 → 100644
  1 +++ a/src/main/java/com/bsth/common/ResponseCode.java
  1 +package com.bsth.common;
  2 +
  3 +/**
  4 + *
  5 + * @ClassName: ResponseCode
  6 + * @Description: TODO(响应状态码)
  7 + * @author PanZhao
  8 + * @date 2016年3月18日 下午11:12:08
  9 + *
  10 + */
  11 +public enum ResponseCode {
  12 +
  13 + SUCCESS("操作成功", 200),
  14 + NO_PERMISSION("无资源访问权限", 403),
  15 + NO_AUTHENTICATION("客户端未授权", 407),
  16 + ERROR("服务器异常", 500);
  17 +
  18 + private String text;
  19 + private int code;
  20 +
  21 + ResponseCode(String text, int code) {
  22 + this.text = text;
  23 + this.code = code;
  24 + }
  25 +
  26 + @Override
  27 + public String toString() {
  28 + return this.code + "";
  29 + }
  30 +
  31 + public String getText() {
  32 + return this.text;
  33 + }
  34 +}
... ...
src/main/java/com/bsth/controller/BaseController.java 0 → 100644
  1 +++ a/src/main/java/com/bsth/controller/BaseController.java
  1 +package com.bsth.controller;
  2 +
  3 +import java.io.Serializable;
  4 +import java.util.Map;
  5 +
  6 +import org.springframework.beans.factory.annotation.Autowired;
  7 +import org.springframework.data.domain.Page;
  8 +import org.springframework.data.domain.PageRequest;
  9 +import org.springframework.data.domain.Sort;
  10 +import org.springframework.data.domain.Sort.Direction;
  11 +import org.springframework.web.bind.annotation.PathVariable;
  12 +import org.springframework.web.bind.annotation.RequestMapping;
  13 +import org.springframework.web.bind.annotation.RequestMethod;
  14 +import org.springframework.web.bind.annotation.RequestParam;
  15 +
  16 +import com.bsth.service.BaseService;
  17 +
  18 +/**
  19 + *
  20 + * @ClassName: BaseController
  21 + * @Description: TODO(基础的Controller实现)
  22 + * @author PanZhao
  23 + * @date 2016年3月17日 下午12:44:06
  24 + *
  25 + * @param <T>
  26 + * @param <ID> 主键类型
  27 + */
  28 +public class BaseController<T, ID extends Serializable> {
  29 +
  30 + @Autowired
  31 + BaseService<T, ID> baseService;
  32 +
  33 + /**
  34 + *
  35 + * @Title: list
  36 + * @Description: TODO(多条件分页查询)
  37 + * @param @param map 查询条件
  38 + * @param @param page 页码
  39 + * @param @param size 每页显示数量
  40 + * @throws
  41 + */
  42 + @RequestMapping(method = RequestMethod.GET)
  43 + public Page<T> list(@RequestParam Map<String, Object> map,
  44 + @RequestParam(defaultValue = "0") int page,
  45 + @RequestParam(defaultValue = "10") int size,
  46 + @RequestParam(defaultValue = "id") String order,
  47 + @RequestParam(defaultValue = "DESC") String direction){
  48 +
  49 + Direction d;
  50 +
  51 + if(null != direction && direction.equals("ASC"))
  52 + d = Direction.ASC;
  53 + else
  54 + d = Direction.DESC;
  55 +
  56 + return baseService.list(map, new PageRequest(page, size, new Sort(d, order)));
  57 + }
  58 +
  59 + /**
  60 + *
  61 + * @Title: list
  62 + * @Description: TODO(多条件查询)
  63 + * @param @param map
  64 + * @throws
  65 + */
  66 + @RequestMapping(value = "/all", method = RequestMethod.GET)
  67 + public Iterable<T> list(@RequestParam Map<String, Object> map){
  68 + return baseService.list(map);
  69 + }
  70 +
  71 + /**
  72 + *
  73 + * @Title: save
  74 + * @Description: TODO(持久化对象)
  75 + * @param @param t
  76 + * @param @return 设定文件
  77 + * @return Map<String,Object> {status: 1(成功),-1(失败)}
  78 + * @throws
  79 + */
  80 + @RequestMapping(method = RequestMethod.POST)
  81 + public Map<String, Object> save(T t){
  82 + return baseService.save(t);
  83 + }
  84 +
  85 + /**
  86 + *
  87 + * @Title: findById
  88 + * @Description: TODO(根据主键获取单个对象)
  89 + * @param @param id
  90 + * @throws
  91 + */
  92 + @RequestMapping(value="/{id}",method = RequestMethod.GET)
  93 + public T findById(@PathVariable("id") ID id){
  94 + return baseService.findById(id);
  95 + }
  96 +
  97 + /**
  98 + *
  99 + * @Title: delete
  100 + * @Description: TODO(根据主键删除对象)
  101 + * @param @param id
  102 + * @throws
  103 + */
  104 + @RequestMapping(value="/{id}",method = RequestMethod.DELETE)
  105 + public Map<String, Object> delete(@PathVariable("id") ID id){
  106 + return baseService.delete(id);
  107 + }
  108 +
  109 +}
... ...
src/main/java/com/bsth/controller/DictionaryController.java 0 → 100644
  1 +++ a/src/main/java/com/bsth/controller/DictionaryController.java
  1 +package com.bsth.controller;
  2 +
  3 +import org.springframework.web.bind.annotation.RequestMapping;
  4 +import org.springframework.web.bind.annotation.RestController;
  5 +
  6 +import com.bsth.entity.sys.Dictionary;
  7 +
  8 +@RestController
  9 +@RequestMapping("dictionary")
  10 +public class DictionaryController extends BaseController<Dictionary, Integer>{
  11 +
  12 +}
... ...
src/main/java/com/bsth/controller/ModuleController.java 0 → 100644
  1 +++ a/src/main/java/com/bsth/controller/ModuleController.java
  1 +package com.bsth.controller;
  2 +
  3 +import java.util.List;
  4 +
  5 +import org.springframework.beans.factory.annotation.Autowired;
  6 +import org.springframework.web.bind.annotation.RequestMapping;
  7 +import org.springframework.web.bind.annotation.RequestParam;
  8 +import org.springframework.web.bind.annotation.RestController;
  9 +
  10 +import com.bsth.entity.sys.Module;
  11 +import com.bsth.service.ModuleService;
  12 +
  13 +@RestController
  14 +@RequestMapping("module")
  15 +public class ModuleController extends BaseController<Module, Integer>{
  16 +
  17 + @Autowired
  18 + ModuleService moduleService;
  19 +
  20 + @RequestMapping(value = "/findByGroupType")
  21 + public List<Module> findByGroupType(@RequestParam String group){
  22 + return moduleService.findByGroupType(group);
  23 + }
  24 +
  25 + /**
  26 + *
  27 + * @Title: findByRoleId
  28 + * @Description: TODO(根据角色获取功能模块)
  29 + * @param @param roleId
  30 + * @throws
  31 + */
  32 + @RequestMapping(value = "/findByCurrentUser")
  33 + public List<Module> findByCurrentUser(){
  34 + return moduleService.findByCurrentUser();
  35 + }
  36 +}
... ...
src/main/java/com/bsth/controller/ResourceController.java 0 → 100644
  1 +++ a/src/main/java/com/bsth/controller/ResourceController.java
  1 +package com.bsth.controller;
  2 +
  3 +import java.util.Map;
  4 +
  5 +import org.springframework.beans.factory.annotation.Autowired;
  6 +import org.springframework.web.bind.annotation.RequestMapping;
  7 +import org.springframework.web.bind.annotation.RequestMethod;
  8 +import org.springframework.web.bind.annotation.RequestParam;
  9 +import org.springframework.web.bind.annotation.RestController;
  10 +
  11 +import com.alibaba.fastjson.JSON;
  12 +import com.bsth.entity.sys.Resource;
  13 +import com.bsth.service.ResourceService;
  14 +
  15 +@RestController
  16 +@RequestMapping("resource")
  17 +public class ResourceController extends BaseController<Resource, Integer>{
  18 +
  19 + @Autowired
  20 + ResourceService resourceService;
  21 +
  22 + @RequestMapping(value = "/batch", method = RequestMethod.POST)
  23 + public Map<String, Object> save(@RequestParam String array){
  24 + return resourceService.saveList(JSON.parseArray(array, Resource.class));
  25 + }
  26 +}
... ...
src/main/java/com/bsth/controller/RoleController.java 0 → 100644
  1 +++ a/src/main/java/com/bsth/controller/RoleController.java
  1 +package com.bsth.controller;
  2 +
  3 +import java.util.Map;
  4 +
  5 +import org.springframework.beans.factory.annotation.Autowired;
  6 +import org.springframework.web.bind.annotation.RequestMapping;
  7 +import org.springframework.web.bind.annotation.RequestMethod;
  8 +import org.springframework.web.bind.annotation.RequestParam;
  9 +import org.springframework.web.bind.annotation.RestController;
  10 +
  11 +import com.bsth.entity.sys.Role;
  12 +import com.bsth.service.RoleService;
  13 +
  14 +@RestController
  15 +@RequestMapping("role")
  16 +public class RoleController extends BaseController<Role, Integer>{
  17 +
  18 +
  19 + @Autowired
  20 + RoleService roleService;
  21 +
  22 + /**
  23 + *
  24 + * @Title: settRoleModules
  25 + * @Description: TODO(为角色设置模块,全量覆盖)
  26 + * @param @param roleId 角色ID
  27 + * @param @param mIds 模块ID字符串(1,2,3,4)
  28 + * @throws
  29 + */
  30 + @RequestMapping(value = "/settModules", method = RequestMethod.POST)
  31 + public Map<String, Object> settRoleModules(@RequestParam Integer roleId,@RequestParam String mIds){
  32 + return roleService.settRoleModules(roleId, mIds);
  33 + }
  34 +}
... ...
src/main/java/com/bsth/controller/UserController.java 0 → 100644
  1 +++ a/src/main/java/com/bsth/controller/UserController.java
  1 +package com.bsth.controller;
  2 +
  3 +import javax.servlet.http.HttpServletRequest;
  4 +import javax.servlet.http.HttpServletResponse;
  5 +import javax.servlet.http.HttpSession;
  6 +
  7 +import org.springframework.security.authentication.BadCredentialsException;
  8 +import org.springframework.security.core.Authentication;
  9 +import org.springframework.security.core.context.SecurityContextHolder;
  10 +import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler;
  11 +import org.springframework.security.web.authentication.session.SessionAuthenticationException;
  12 +import org.springframework.web.bind.annotation.RequestMapping;
  13 +import org.springframework.web.bind.annotation.RestController;
  14 +import org.springframework.web.servlet.ModelAndView;
  15 +
  16 +import com.bsth.entity.sys.SysUser;
  17 +
  18 +@RestController
  19 +@RequestMapping("user")
  20 +public class UserController extends BaseController<SysUser, Integer>{
  21 +
  22 + /**
  23 + *
  24 + * @Title: loginFailure
  25 + * @Description: TODO(查询登录失败的详细信息)
  26 + * @param @param request
  27 + * @return String 返回类型
  28 + * @throws
  29 + */
  30 + @RequestMapping("/loginFailure")
  31 + public String loginFailure(HttpServletRequest request){
  32 + String msg = "";
  33 + HttpSession session = request.getSession();
  34 +
  35 + Object obj = session.getAttribute("SPRING_SECURITY_LAST_EXCEPTION");
  36 +
  37 + if(obj instanceof BadCredentialsException)
  38 + msg = "登录失败,用户名或密码错误.";
  39 + else if(obj instanceof SessionAuthenticationException)
  40 + msg = "登录失败,当前策略不允许重复登录.";
  41 + session.removeAttribute("SPRING_SECURITY_LAST_EXCEPTION");
  42 + return msg;
  43 + }
  44 +
  45 + /**
  46 + *
  47 + * @Title: logout
  48 + * @Description: TODO(注销吧皮卡丘)
  49 + * @param @param request
  50 + * @return ModelAndView 返回类型
  51 + * @throws
  52 + */
  53 + @RequestMapping("/logout")
  54 + public ModelAndView logout(HttpServletRequest request, HttpServletResponse response){
  55 + Authentication auth = SecurityContextHolder.getContext().getAuthentication();
  56 + if (auth != null){
  57 + new SecurityContextLogoutHandler().logout(request, response, auth);
  58 + }
  59 + return new ModelAndView("/");
  60 + }
  61 +}
... ...
src/main/java/com/bsth/entity/search/CustomerSpecs.java 0 → 100644
  1 +++ a/src/main/java/com/bsth/entity/search/CustomerSpecs.java
  1 +package com.bsth.entity.search;
  2 +
  3 +import java.lang.reflect.Method;
  4 +import java.util.ArrayList;
  5 +import java.util.List;
  6 +import java.util.Map;
  7 +import java.util.Set;
  8 +import java.util.TreeSet;
  9 +
  10 +import javax.persistence.criteria.CriteriaBuilder;
  11 +import javax.persistence.criteria.CriteriaQuery;
  12 +import javax.persistence.criteria.Path;
  13 +import javax.persistence.criteria.Predicate;
  14 +import javax.persistence.criteria.Root;
  15 +
  16 +import org.apache.commons.lang3.StringUtils;
  17 +import org.slf4j.Logger;
  18 +import org.slf4j.LoggerFactory;
  19 +import org.springframework.data.jpa.domain.Specification;
  20 +
  21 +import com.bsth.entity.search.exception.UnrecognizableSearchSymbolException;
  22 +
  23 +/**
  24 + *
  25 + * @ClassName: CustomerSpecs
  26 + * @Description: 用于动态条件查询的Specification
  27 + * @author PanZhao
  28 + * @date 2016年3月16日 下午4:05:22
  29 + *
  30 + * @param <T>
  31 + */
  32 +public class CustomerSpecs<T> implements Specification<T> {
  33 +
  34 + Logger logger = LoggerFactory.getLogger(this.getClass());
  35 +
  36 + private Map<String, Object> map;
  37 +
  38 + // 查询操作符
  39 + private static Set<String> eSet;
  40 +
  41 + static {
  42 + eSet = new TreeSet<String>();
  43 + for (SearchOperator s : SearchOperator.values()) {
  44 + eSet.add(s.toString());
  45 + }
  46 + }
  47 +
  48 + private static Class<PredicatesBuilder> preBuilderClazz = PredicatesBuilder.class;
  49 + private static Class<CriteriaBuilder> cBuilderClazz = CriteriaBuilder.class;
  50 + private static Class<Object> objClazz = Object.class;
  51 +
  52 + // 查询参数分隔符
  53 + public static final String separator = "_";
  54 +
  55 + /**
  56 + * 构造函数
  57 + *
  58 + * @param map
  59 + */
  60 + public CustomerSpecs(Map<String, Object> map) {
  61 + this.map = map;
  62 + }
  63 +
  64 + @Override
  65 + public Predicate toPredicate(Root<T> root, CriteriaQuery<?> query,
  66 + CriteriaBuilder cb) {
  67 + List<Predicate> predicates = new ArrayList<>();
  68 +
  69 + for (Map.Entry<String, Object> entry : map.entrySet()) {
  70 + Object value = entry.getValue();
  71 + String[] searchs = StringUtils.split(entry.getKey(), separator);
  72 + if (null == searchs || searchs.length < 2)
  73 + continue;
  74 + // 值为空的不参与查询
  75 + if (value == null || (value instanceof String && value.equals("")))
  76 + continue;
  77 +
  78 + try {
  79 + if(!eSet.contains(searchs[1]))
  80 + throw new UnrecognizableSearchSymbolException(searchs[1]);
  81 +
  82 + // 根据操作符调用对应静态函数
  83 + Method method = preBuilderClazz.getMethod(searchs[1],
  84 + cBuilderClazz, Path.class, objClazz);
  85 +
  86 + Predicate predicate = (Predicate) method.invoke(null, cb,
  87 + createPath(root, searchs[0]), value);
  88 +
  89 + predicates.add(predicate);
  90 + } catch (Exception e) {
  91 + logger.error("Specification search error.", e);
  92 + }
  93 + }
  94 + Predicate[] pre = new Predicate[predicates.size()];
  95 + return query.where(predicates.toArray(pre)).getRestriction();
  96 + }
  97 +
  98 + /**
  99 + * 生成Path
  100 + * @param root
  101 + * @param field
  102 + * @return
  103 + */
  104 + public Path<T> createPath(Root<T> root, String field){
  105 + Path<T> p = null;
  106 +
  107 + if(field.indexOf(".") == -1)
  108 + p = root.get(field);
  109 + else{
  110 + String[] fs = field.split("\\.");
  111 +
  112 + p = root.get(fs[0]);
  113 + for(int i = 1; i < fs.length; i ++){
  114 + p = p.get(fs[i]);
  115 + }
  116 + }
  117 + return p;
  118 + }
  119 +}
... ...
src/main/java/com/bsth/entity/search/PredicatesBuilder.java 0 → 100644
  1 +++ a/src/main/java/com/bsth/entity/search/PredicatesBuilder.java
  1 +package com.bsth.entity.search;
  2 +
  3 +import java.text.NumberFormat;
  4 +import java.text.ParseException;
  5 +import javax.persistence.criteria.CriteriaBuilder;
  6 +import javax.persistence.criteria.Path;
  7 +import javax.persistence.criteria.Predicate;
  8 +
  9 +/**
  10 + *
  11 + * @ClassName: PredicatesBuilder
  12 + * @author PanZhao
  13 + * @date 2016年3月16日 下午4:05:07
  14 + *
  15 + */
  16 +public class PredicatesBuilder {
  17 +
  18 + /**
  19 + * Number转换器
  20 + */
  21 + private static NumberFormat nf;
  22 +
  23 + static{
  24 + nf = NumberFormat.getInstance();
  25 + }
  26 +
  27 + public static Predicate eq(CriteriaBuilder cb,Path<?> expression, Object object){
  28 + return cb.equal(expression, object);
  29 + }
  30 +
  31 + public static Predicate ne(CriteriaBuilder cb,Path<?> expression, Object object){
  32 + return cb.notEqual(expression, object);
  33 + }
  34 +
  35 + public static Predicate gt(CriteriaBuilder cb,Path<Number> expression, Object object){
  36 + try {
  37 + return cb.gt(expression, nf.parse(object.toString()));
  38 + } catch (ParseException e) {
  39 + e.printStackTrace();
  40 + return null;
  41 + }
  42 + }
  43 +
  44 + public static Predicate ge(CriteriaBuilder cb,Path<Number> expression, Object object){
  45 + try {
  46 + return cb.ge(expression, nf.parse(object.toString()));
  47 + } catch (ParseException e) {
  48 + e.printStackTrace();
  49 + return null;
  50 + }
  51 + }
  52 +
  53 + public static Predicate lt(CriteriaBuilder cb,Path<Number> expression, Object object){
  54 + try {
  55 + return cb.lt(expression, nf.parse(object.toString()));
  56 + } catch (ParseException e) {
  57 + e.printStackTrace();
  58 + return null;
  59 + }
  60 + }
  61 +
  62 + public static Predicate le(CriteriaBuilder cb,Path<Number> expression, Object object){
  63 + try {
  64 + return cb.le(expression, nf.parse(object.toString()));
  65 + } catch (ParseException e) {
  66 + e.printStackTrace();
  67 + return null;
  68 + }
  69 + }
  70 +
  71 + public static Predicate prefixLike(CriteriaBuilder cb,Path<String> expression, Object object){
  72 + return cb.like(expression, object.toString() + "%");
  73 + }
  74 +
  75 + public static Predicate prefixNotLike(CriteriaBuilder cb,Path<String> expression, Object object){
  76 + return cb.notLike(expression, object.toString() + "%");
  77 + }
  78 +
  79 + public static Predicate suffixLike(CriteriaBuilder cb,Path<String> expression, Object object){
  80 + return cb.like(expression, "%" + object.toString());
  81 + }
  82 +
  83 + public static Predicate suffixNotLike(CriteriaBuilder cb,Path<String> expression, Object object){
  84 + return cb.notLike(expression, "%" + object.toString());
  85 + }
  86 +
  87 + public static Predicate like(CriteriaBuilder cb,Path<String> expression, Object object){
  88 + return cb.like(expression, "%" + object.toString() + "%");
  89 + }
  90 +
  91 + public static Predicate notLike(CriteriaBuilder cb,Path<String> expression, Object object){
  92 + return cb.notLike(expression, "%" + object.toString() + "%");
  93 + }
  94 +
  95 + public static Predicate isNull(CriteriaBuilder cb,Path<String> expression, Object object){
  96 + return cb.isNull(expression);
  97 + }
  98 +
  99 + public static Predicate isNotNull(CriteriaBuilder cb,Path<String> expression, Object object){
  100 + return cb.isNotNull(expression);
  101 + }
  102 +}
... ...
src/main/java/com/bsth/entity/search/SearchOperator.java 0 → 100644
  1 +++ a/src/main/java/com/bsth/entity/search/SearchOperator.java
  1 +package com.bsth.entity.search;
  2 +
  3 +/**
  4 + *
  5 + * @ClassName: SearchOperator
  6 + * @Description: 查询操作符
  7 + * @author PanZhao
  8 + * @date 2016年3月16日 下午4:08:22
  9 + *
  10 + */
  11 +public enum SearchOperator {
  12 +
  13 + eq, // 等于
  14 + ne, // 不等于
  15 + gt, // 大于
  16 + ge, // 大于等于
  17 + lt, // 小于
  18 + le, // 小于等于
  19 + prefixLike, // 前缀模糊匹配
  20 + prefixNotLike, // 前缀模糊不匹配
  21 + suffixLike, // 后缀模糊匹配
  22 + suffixNotLike, // 后缀模糊不匹配
  23 + like, // 模糊匹配
  24 + notLike, // 不匹配
  25 + isNull, // 空
  26 + isNotNull, // 非空
  27 +}
... ...
src/main/java/com/bsth/entity/search/exception/UnrecognizableSearchSymbolException.java 0 → 100644
  1 +++ a/src/main/java/com/bsth/entity/search/exception/UnrecognizableSearchSymbolException.java
  1 +package com.bsth.entity.search.exception;
  2 +
  3 +/**
  4 + *
  5 + * @ClassName: UnrecognizableSearchSymbolException
  6 + * @Description: TODO(查询操作符无法识别时抛出此异常)
  7 + * @author PanZhao
  8 + * @date 2016年3月17日 下午3:11:02
  9 + *
  10 + */
  11 +public class UnrecognizableSearchSymbolException extends Exception{
  12 +
  13 + private static final long serialVersionUID = 1L;
  14 +
  15 + public UnrecognizableSearchSymbolException(String symbol) {
  16 + super("无法识别的查询操作符:" + symbol + " 请参考 com.bsth.entity.search.SearchOperator.java");
  17 + }
  18 +}
... ...
src/main/java/com/bsth/entity/sys/Dictionary.java 0 → 100644
  1 +++ a/src/main/java/com/bsth/entity/sys/Dictionary.java
  1 +package com.bsth.entity.sys;
  2 +
  3 +import java.util.Date;
  4 +
  5 +import javax.persistence.Column;
  6 +import javax.persistence.Entity;
  7 +import javax.persistence.GeneratedValue;
  8 +import javax.persistence.GenerationType;
  9 +import javax.persistence.Id;
  10 +import javax.persistence.Table;
  11 +import javax.persistence.UniqueConstraint;
  12 +
  13 +@Entity
  14 +@Table(name = "t_sys_dictionary",
  15 +uniqueConstraints = { @UniqueConstraint(columnNames = {"dCode"}) })
  16 +public class Dictionary {
  17 +
  18 + @Id
  19 + @GeneratedValue(strategy = GenerationType.IDENTITY)
  20 + private Integer id;
  21 +
  22 + private String dCode;
  23 +
  24 + private String dName;
  25 +
  26 + private String descriptions;
  27 +
  28 + private String dGroup;
  29 +
  30 + /**
  31 + * 固化的字典不能修改
  32 + */
  33 + private boolean fixed;
  34 +
  35 + @Column(name = "update_date", columnDefinition = "timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP")
  36 + private Date updateDate;
  37 +
  38 +
  39 + public Integer getId() {
  40 + return id;
  41 + }
  42 +
  43 + public void setId(Integer id) {
  44 + this.id = id;
  45 + }
  46 +
  47 + public boolean isFixed() {
  48 + return fixed;
  49 + }
  50 +
  51 + public void setFixed(boolean fixed) {
  52 + this.fixed = fixed;
  53 + }
  54 +
  55 + public String getdCode() {
  56 + return dCode;
  57 + }
  58 +
  59 + public void setdCode(String dCode) {
  60 + this.dCode = dCode;
  61 + }
  62 +
  63 + public String getdName() {
  64 + return dName;
  65 + }
  66 +
  67 + public void setdName(String dName) {
  68 + this.dName = dName;
  69 + }
  70 +
  71 + public String getDescriptions() {
  72 + return descriptions;
  73 + }
  74 +
  75 + public void setDescriptions(String descriptions) {
  76 + this.descriptions = descriptions;
  77 + }
  78 +
  79 + public String getdGroup() {
  80 + return dGroup;
  81 + }
  82 +
  83 + public void setdGroup(String dGroup) {
  84 + this.dGroup = dGroup;
  85 + }
  86 +
  87 + public Date getUpdateDate() {
  88 + return updateDate;
  89 + }
  90 +
  91 + public void setUpdateDate(Date updateDate) {
  92 + this.updateDate = updateDate;
  93 + }
  94 +}
... ...
src/main/java/com/bsth/entity/sys/Module.java 0 → 100644
  1 +++ a/src/main/java/com/bsth/entity/sys/Module.java
  1 +package com.bsth.entity.sys;
  2 +
  3 +import java.util.Date;
  4 +import java.util.LinkedHashSet;
  5 +import java.util.Set;
  6 +
  7 +import javax.persistence.Column;
  8 +import javax.persistence.Entity;
  9 +import javax.persistence.FetchType;
  10 +import javax.persistence.GeneratedValue;
  11 +import javax.persistence.GenerationType;
  12 +import javax.persistence.Id;
  13 +import javax.persistence.ManyToMany;
  14 +import javax.persistence.Table;
  15 +
  16 +@Entity
  17 +@Table(name = "t_sys_module")
  18 +public class Module {
  19 +
  20 + @Id
  21 + @GeneratedValue(strategy = GenerationType.IDENTITY)
  22 + private Integer id;
  23 +
  24 + private Integer pId;
  25 +
  26 + private String name;
  27 +
  28 + private String descriptions;
  29 +
  30 + private String path;
  31 +
  32 + private String mappSymbol;
  33 +
  34 + private boolean enable;
  35 +
  36 + private String icon;
  37 +
  38 + /**
  39 + * 1:组
  40 + * 2:目录
  41 + * 3:功能模块
  42 + */
  43 + private String groupType;
  44 +
  45 + @ManyToMany(fetch = FetchType.EAGER, mappedBy = "modules")
  46 + private Set<Role> roles = new LinkedHashSet<>();
  47 +
  48 + @Column(updatable = false,name = "create_date", columnDefinition = "TIMESTAMP DEFAULT CURRENT_TIMESTAMP")
  49 + private Date createDate;
  50 +
  51 + @Column(name = "update_date", columnDefinition = "timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP")
  52 + private Date updateDate;
  53 +
  54 + public Integer getId() {
  55 + return id;
  56 + }
  57 +
  58 + public void setId(Integer id) {
  59 + this.id = id;
  60 + }
  61 +
  62 + public String getName() {
  63 + return name;
  64 + }
  65 +
  66 + public void setName(String name) {
  67 + this.name = name;
  68 + }
  69 +
  70 + public String getDescriptions() {
  71 + return descriptions;
  72 + }
  73 +
  74 + public void setDescriptions(String descriptions) {
  75 + this.descriptions = descriptions;
  76 + }
  77 +
  78 + public Set<Role> getRoles() {
  79 + return roles;
  80 + }
  81 +
  82 + public void setRoles(Set<Role> roles) {
  83 + this.roles = roles;
  84 + }
  85 +
  86 + public String getPath() {
  87 + return path;
  88 + }
  89 +
  90 + public void setPath(String path) {
  91 + this.path = path;
  92 + }
  93 +
  94 + public String getMappSymbol() {
  95 + return mappSymbol;
  96 + }
  97 +
  98 + public void setMappSymbol(String mappSymbol) {
  99 + this.mappSymbol = mappSymbol;
  100 + }
  101 +
  102 + public boolean isEnable() {
  103 + return enable;
  104 + }
  105 +
  106 + public void setEnable(boolean enable) {
  107 + this.enable = enable;
  108 + }
  109 +
  110 + public String getIcon() {
  111 + return icon;
  112 + }
  113 +
  114 + public void setIcon(String icon) {
  115 + this.icon = icon;
  116 + }
  117 +
  118 + public Integer getpId() {
  119 + return pId;
  120 + }
  121 +
  122 + public void setpId(Integer pId) {
  123 + this.pId = pId;
  124 + }
  125 +
  126 + public String getGroupType() {
  127 + return groupType;
  128 + }
  129 +
  130 + public void setGroupType(String groupType) {
  131 + this.groupType = groupType;
  132 + }
  133 +
  134 + public Date getCreateDate() {
  135 + return createDate;
  136 + }
  137 +
  138 + public void setCreateDate(Date createDate) {
  139 + this.createDate = createDate;
  140 + }
  141 +
  142 + public Date getUpdateDate() {
  143 + return updateDate;
  144 + }
  145 +
  146 + public void setUpdateDate(Date updateDate) {
  147 + this.updateDate = updateDate;
  148 + }
  149 +
  150 + @Override
  151 + public boolean equals(Object obj) {
  152 + // TODO Auto-generated method stub
  153 + return this.id.equals(((Module)obj).getId());
  154 + }
  155 +}
... ...
src/main/java/com/bsth/entity/sys/Resource.java 0 → 100644
  1 +++ a/src/main/java/com/bsth/entity/sys/Resource.java
  1 +package com.bsth.entity.sys;
  2 +
  3 +import java.util.Date;
  4 +import java.util.LinkedHashSet;
  5 +import java.util.Set;
  6 +
  7 +import javax.persistence.Column;
  8 +import javax.persistence.Entity;
  9 +import javax.persistence.FetchType;
  10 +import javax.persistence.GeneratedValue;
  11 +import javax.persistence.GenerationType;
  12 +import javax.persistence.Id;
  13 +import javax.persistence.ManyToMany;
  14 +import javax.persistence.ManyToOne;
  15 +import javax.persistence.Table;
  16 +
  17 +import com.fasterxml.jackson.annotation.JsonIgnore;
  18 +
  19 +@Entity
  20 +@Table(name = "t_sys_resource")
  21 +public class Resource {
  22 +
  23 + @Id
  24 + @GeneratedValue(strategy = GenerationType.IDENTITY)
  25 + private Integer id;
  26 +
  27 + private String name;
  28 +
  29 + private String url;
  30 +
  31 + private String method;
  32 +
  33 + private String descriptions;
  34 +
  35 + @ManyToOne
  36 + private Module module;
  37 +
  38 + private boolean enable;
  39 +
  40 + @JsonIgnore
  41 + @ManyToMany(fetch = FetchType.EAGER)
  42 + private Set<Role> roles = new LinkedHashSet<>();
  43 +
  44 + @Column(updatable = false, name = "create_date", columnDefinition = "TIMESTAMP DEFAULT CURRENT_TIMESTAMP")
  45 + private Date createDate;
  46 +
  47 + @Column(name = "update_date", columnDefinition = "timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP")
  48 + private Date updateDate;
  49 +
  50 + public Integer getId() {
  51 + return id;
  52 + }
  53 +
  54 + public void setId(Integer id) {
  55 + this.id = id;
  56 + }
  57 +
  58 + public String getName() {
  59 + return name;
  60 + }
  61 +
  62 + public void setName(String name) {
  63 + this.name = name;
  64 + }
  65 +
  66 + public String getDescriptions() {
  67 + return descriptions;
  68 + }
  69 +
  70 + public void setDescriptions(String descriptions) {
  71 + this.descriptions = descriptions;
  72 + }
  73 +
  74 + public Set<Role> getRoles() {
  75 + return roles;
  76 + }
  77 +
  78 + public void setRoles(Set<Role> roles) {
  79 + this.roles = roles;
  80 + }
  81 +
  82 + public Module getModule() {
  83 + return module;
  84 + }
  85 +
  86 + public void setModule(Module module) {
  87 + this.module = module;
  88 + }
  89 +
  90 + public boolean isEnable() {
  91 + return enable;
  92 + }
  93 +
  94 + public void setEnable(boolean enable) {
  95 + this.enable = enable;
  96 + }
  97 +
  98 + public String getUrl() {
  99 + return url;
  100 + }
  101 +
  102 + public void setUrl(String url) {
  103 + this.url = url;
  104 + }
  105 +
  106 + public String getMethod() {
  107 + return method;
  108 + }
  109 +
  110 + public void setMethod(String method) {
  111 + this.method = method;
  112 + }
  113 +
  114 + public Date getCreateDate() {
  115 + return createDate;
  116 + }
  117 +
  118 + public void setCreateDate(Date createDate) {
  119 + this.createDate = createDate;
  120 + }
  121 +
  122 + public Date getUpdateDate() {
  123 + return updateDate;
  124 + }
  125 +
  126 + public void setUpdateDate(Date updateDate) {
  127 + this.updateDate = updateDate;
  128 + }
  129 +}
... ...
src/main/java/com/bsth/entity/sys/Role.java 0 → 100644
  1 +++ a/src/main/java/com/bsth/entity/sys/Role.java
  1 +package com.bsth.entity.sys;
  2 +
  3 +import java.util.Date;
  4 +import java.util.LinkedHashSet;
  5 +import java.util.Set;
  6 +
  7 +import javax.persistence.Column;
  8 +import javax.persistence.Entity;
  9 +import javax.persistence.FetchType;
  10 +import javax.persistence.GeneratedValue;
  11 +import javax.persistence.GenerationType;
  12 +import javax.persistence.Id;
  13 +import javax.persistence.ManyToMany;
  14 +import javax.persistence.Table;
  15 +
  16 +import com.fasterxml.jackson.annotation.JsonIgnore;
  17 +
  18 +@Entity
  19 +@Table(name = "t_sys_role")
  20 +public class Role {
  21 +
  22 + @Id
  23 + @GeneratedValue(strategy = GenerationType.IDENTITY)
  24 + private Integer id;
  25 +
  26 + private String codeName;
  27 +
  28 + private String roleName;
  29 +
  30 + private String descriptions;
  31 +
  32 + private boolean isSuperAdmin;
  33 +
  34 + private boolean enable;
  35 +
  36 + @JsonIgnore
  37 + @ManyToMany(fetch = FetchType.LAZY, mappedBy = "roles")
  38 + private Set<SysUser> users = new LinkedHashSet<>();
  39 +
  40 + @JsonIgnore
  41 + @ManyToMany
  42 + private Set<Module> modules = new LinkedHashSet<>();
  43 +
  44 + @JsonIgnore
  45 + @ManyToMany(mappedBy = "roles")
  46 + private Set<Resource> resources = new LinkedHashSet<>();
  47 +
  48 + @Column(updatable = false, name = "create_date", columnDefinition = "TIMESTAMP DEFAULT CURRENT_TIMESTAMP")
  49 + private Date createDate;
  50 +
  51 + @Column(name = "update_date", columnDefinition = "timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP")
  52 + private Date updateDate;
  53 +
  54 + private int pic;
  55 +
  56 + public Integer getId() {
  57 + return id;
  58 + }
  59 +
  60 + public void setId(Integer id) {
  61 + this.id = id;
  62 + }
  63 +
  64 + public String getRoleName() {
  65 + return roleName;
  66 + }
  67 +
  68 + public String getDescriptions() {
  69 + return descriptions;
  70 + }
  71 +
  72 + public void setDescriptions(String descriptions) {
  73 + this.descriptions = descriptions;
  74 + }
  75 +
  76 + public void setRoleName(String roleName) {
  77 + this.roleName = roleName;
  78 + }
  79 +
  80 + public boolean isEnable() {
  81 + return enable;
  82 + }
  83 +
  84 + public void setEnable(boolean enable) {
  85 + this.enable = enable;
  86 + }
  87 +
  88 + public Set<SysUser> getUsers() {
  89 + return users;
  90 + }
  91 +
  92 + public void setUsers(Set<SysUser> users) {
  93 + this.users = users;
  94 + }
  95 +
  96 + public boolean isSuperAdmin() {
  97 + return isSuperAdmin;
  98 + }
  99 +
  100 + public void setSuperAdmin(boolean isSuperAdmin) {
  101 + this.isSuperAdmin = isSuperAdmin;
  102 + }
  103 +
  104 + public Set<Module> getModules() {
  105 + return modules;
  106 + }
  107 +
  108 + public void setModules(Set<Module> modules) {
  109 + this.modules = modules;
  110 + }
  111 +
  112 + public Set<Resource> getResources() {
  113 + return resources;
  114 + }
  115 +
  116 + public void setResources(Set<Resource> resources) {
  117 + this.resources = resources;
  118 + }
  119 +
  120 + public Date getCreateDate() {
  121 + return createDate;
  122 + }
  123 +
  124 + public void setCreateDate(Date createDate) {
  125 + this.createDate = createDate;
  126 + }
  127 +
  128 + public Date getUpdateDate() {
  129 + return updateDate;
  130 + }
  131 +
  132 + public void setUpdateDate(Date updateDate) {
  133 + this.updateDate = updateDate;
  134 + }
  135 +
  136 + public String getCodeName() {
  137 + return codeName;
  138 + }
  139 +
  140 + public void setCodeName(String codeName) {
  141 + this.codeName = codeName;
  142 + }
  143 +
  144 + public int getPic() {
  145 + return pic;
  146 + }
  147 +
  148 + public void setPic(int pic) {
  149 + this.pic = pic;
  150 + }
  151 +
  152 + @Override
  153 + public boolean equals(Object obj) {
  154 + return this.id.equals(((Role)obj).getId());
  155 + }
  156 +
  157 + @Override
  158 + public int hashCode() {
  159 + return this.toString().hashCode();
  160 + }
  161 +
  162 + @Override
  163 + public String toString() {
  164 + return this.id + "" + this.getCodeName();
  165 + }
  166 +}
... ...
src/main/java/com/bsth/entity/sys/SecurityUser.java 0 → 100644
  1 +++ a/src/main/java/com/bsth/entity/sys/SecurityUser.java
  1 +package com.bsth.entity.sys;
  2 +
  3 +import java.util.ArrayList;
  4 +import java.util.Collection;
  5 +import java.util.Set;
  6 +
  7 +import org.springframework.security.core.GrantedAuthority;
  8 +import org.springframework.security.core.authority.SimpleGrantedAuthority;
  9 +import org.springframework.security.core.userdetails.UserDetails;
  10 +
  11 +public class SecurityUser extends SysUser implements UserDetails {
  12 +
  13 + private static final long serialVersionUID = 1L;
  14 +
  15 + public SecurityUser(SysUser user) {
  16 + if (null != user) {
  17 + this.setId(user.getId());
  18 + this.setUserName(user.getUserName());
  19 + this.setName(user.getName());
  20 + this.setPassword(user.getPassword());
  21 + this.setAgencies(user.getAgencies());
  22 + this.setRoles(user.getRoles());
  23 + this.setEnabled(user.isEnabled());
  24 + }
  25 + }
  26 +
  27 + @Override
  28 + public Collection<? extends GrantedAuthority> getAuthorities() {
  29 + Collection<GrantedAuthority> authorities = new ArrayList<>();
  30 + Set<Role> userRoles = this.getRoles();
  31 +
  32 + if (userRoles != null) {
  33 + for (Role role : userRoles) {
  34 + SimpleGrantedAuthority authority = new SimpleGrantedAuthority(
  35 + role.getCodeName());
  36 + authorities.add(authority);
  37 + }
  38 + }
  39 + return authorities;
  40 + }
  41 +
  42 + @Override
  43 + public String getPassword() {
  44 + return super.getPassword();
  45 + }
  46 +
  47 + @Override
  48 + public boolean isAccountNonExpired() {
  49 + return true;
  50 + }
  51 +
  52 + @Override
  53 + public boolean isAccountNonLocked() {
  54 + return true;
  55 + }
  56 +
  57 + @Override
  58 + public boolean isCredentialsNonExpired() {
  59 + return true;
  60 + }
  61 +
  62 + @Override
  63 + public String getUsername() {
  64 + return super.getUserName();
  65 + }
  66 +
  67 + @Override
  68 + public boolean equals(Object obj) {
  69 + return this.getUserName().equals(((SysUser)obj).getUserName());
  70 + }
  71 +
  72 + @Override
  73 + public int hashCode() {
  74 + return this.getId() + this.getUserName().hashCode();
  75 + }
  76 +}
... ...
src/main/java/com/bsth/entity/sys/SysUser.java 0 → 100644
  1 +++ a/src/main/java/com/bsth/entity/sys/SysUser.java
  1 +package com.bsth.entity.sys;
  2 +
  3 +import java.util.Date;
  4 +import java.util.LinkedHashSet;
  5 +import java.util.Set;
  6 +
  7 +import javax.persistence.Column;
  8 +import javax.persistence.Entity;
  9 +import javax.persistence.FetchType;
  10 +import javax.persistence.GeneratedValue;
  11 +import javax.persistence.GenerationType;
  12 +import javax.persistence.Id;
  13 +import javax.persistence.ManyToMany;
  14 +import javax.persistence.Table;
  15 +
  16 +@Entity
  17 +@Table(name = "t_sys_user")
  18 +public class SysUser {
  19 +
  20 + @Id
  21 + @GeneratedValue(strategy = GenerationType.IDENTITY)
  22 + private Integer id;
  23 +
  24 + private String userName;
  25 +
  26 + private String name;
  27 +
  28 + private String password;
  29 +
  30 + @Column(updatable = false, name = "create_date", columnDefinition = "TIMESTAMP DEFAULT CURRENT_TIMESTAMP")
  31 + private Date createDate;
  32 +
  33 + @Column(name = "last_loginDate", columnDefinition = "timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP")
  34 + private Date lastLoginDate;
  35 +
  36 + private String agencies;
  37 +
  38 + private boolean enabled;
  39 +
  40 + @ManyToMany(fetch = FetchType.EAGER)
  41 + private Set<Role> roles = new LinkedHashSet<>();
  42 +
  43 +
  44 + public Integer getId() {
  45 + return id;
  46 + }
  47 +
  48 + public void setId(Integer id) {
  49 + this.id = id;
  50 + }
  51 +
  52 + public String getUserName() {
  53 + return userName;
  54 + }
  55 +
  56 + public void setUserName(String userName) {
  57 + this.userName = userName;
  58 + }
  59 +
  60 + public String getName() {
  61 + return name;
  62 + }
  63 +
  64 + public void setName(String name) {
  65 + this.name = name;
  66 + }
  67 +
  68 + public Date getCreateDate() {
  69 + return createDate;
  70 + }
  71 +
  72 + public void setCreateDate(Date createDate) {
  73 + this.createDate = createDate;
  74 + }
  75 +
  76 + public Date getLastLoginDate() {
  77 + return lastLoginDate;
  78 + }
  79 +
  80 + public void setLastLoginDate(Date lastLoginDate) {
  81 + this.lastLoginDate = lastLoginDate;
  82 + }
  83 +
  84 + public String getAgencies() {
  85 + return agencies;
  86 + }
  87 +
  88 + public void setAgencies(String agencies) {
  89 + this.agencies = agencies;
  90 + }
  91 +
  92 + public boolean isEnabled() {
  93 + return enabled;
  94 + }
  95 +
  96 + public void setEnabled(boolean enabled) {
  97 + this.enabled = enabled;
  98 + }
  99 +
  100 + public String getPassword() {
  101 + return password;
  102 + }
  103 +
  104 + public void setPassword(String password) {
  105 + this.password = password;
  106 + }
  107 +
  108 + public Set<Role> getRoles() {
  109 + return roles;
  110 + }
  111 +
  112 + public void setRoles(Set<Role> roles) {
  113 + this.roles = roles;
  114 + }
  115 +}
... ...
src/main/java/com/bsth/filter/AccessLogFilter.java 0 → 100644
  1 +++ a/src/main/java/com/bsth/filter/AccessLogFilter.java
  1 +package com.bsth.filter;
  2 +
  3 +import javax.servlet.FilterChain;
  4 +import javax.servlet.ServletException;
  5 +import javax.servlet.http.HttpServletRequest;
  6 +import javax.servlet.http.HttpServletResponse;
  7 +
  8 +import org.slf4j.Logger;
  9 +import org.slf4j.LoggerFactory;
  10 +import org.springframework.stereotype.Component;
  11 +
  12 +import com.alibaba.fastjson.JSON;
  13 +import com.bsth.security.util.SecurityUtils;
  14 +import com.bsth.util.IpUtils;
  15 +import com.google.common.collect.Lists;
  16 +import com.google.common.collect.Maps;
  17 +
  18 +import java.io.IOException;
  19 +import java.util.Enumeration;
  20 +import java.util.List;
  21 +import java.util.Map;
  22 +
  23 +/**
  24 + *
  25 + * @ClassName: AccessLogFilter
  26 + * @Description: TODO(记录访问日志)
  27 + * @author PanZhao
  28 + * @date 2016年3月17日 下午4:28:31
  29 + *
  30 + */
  31 +@Component
  32 +public class AccessLogFilter extends BaseFilter {
  33 +
  34 + Logger logger = LoggerFactory.getLogger(this.getClass());
  35 +
  36 + @Override
  37 + public void doFilter(HttpServletRequest request,
  38 + HttpServletResponse response, FilterChain chain)
  39 + throws IOException, ServletException {
  40 +
  41 + String username = SecurityUtils.getCurrentUser().getName(); //等集成shiro之后再取
  42 + String jsessionId = request.getRequestedSessionId();
  43 + String ip = IpUtils.getIpAddr(request);
  44 + String userAgent = request.getHeader("User-Agent");
  45 + String url = request.getRequestURI();
  46 + String params = getParams(request);
  47 + String headers = getHeaders(request);
  48 +
  49 + StringBuilder s = new StringBuilder();
  50 + s.append(getBlock(username));
  51 + s.append(getBlock(jsessionId));
  52 + s.append(getBlock(ip));
  53 + s.append(getBlock(userAgent));
  54 + s.append(getBlock(url));
  55 + s.append(getBlock(params));
  56 + s.append(getBlock(headers));
  57 + s.append(getBlock(request.getHeader("Referer")));
  58 +
  59 + logger.info(s.toString());
  60 + chain.doFilter(request, response);
  61 + }
  62 +
  63 + private static String getParams(HttpServletRequest request) {
  64 + Map<String, String[]> params = request.getParameterMap();
  65 + return JSON.toJSONString(params);
  66 + }
  67 +
  68 + private static String getHeaders(HttpServletRequest request) {
  69 + Map<String, List<String>> headers = Maps.newHashMap();
  70 + Enumeration<String> namesEnumeration = request.getHeaderNames();
  71 + while (namesEnumeration.hasMoreElements()) {
  72 + String name = namesEnumeration.nextElement();
  73 + Enumeration<String> valueEnumeration = request.getHeaders(name);
  74 + List<String> values = Lists.newArrayList();
  75 + while (valueEnumeration.hasMoreElements()) {
  76 + values.add(valueEnumeration.nextElement());
  77 + }
  78 + headers.put(name, values);
  79 + }
  80 + return JSON.toJSONString(headers);
  81 + }
  82 +
  83 + public static String getBlock(Object msg) {
  84 + if (msg == null) {
  85 + msg = "";
  86 + }
  87 + return "[" + msg.toString() + "]";
  88 + }
  89 +}
... ...
src/main/java/com/bsth/filter/BaseFilter.java 0 → 100644
  1 +++ a/src/main/java/com/bsth/filter/BaseFilter.java
  1 +package com.bsth.filter;
  2 +
  3 +import java.io.IOException;
  4 +
  5 +import javax.servlet.Filter;
  6 +import javax.servlet.FilterChain;
  7 +import javax.servlet.FilterConfig;
  8 +import javax.servlet.ServletException;
  9 +import javax.servlet.ServletRequest;
  10 +import javax.servlet.ServletResponse;
  11 +import javax.servlet.http.HttpServletRequest;
  12 +import javax.servlet.http.HttpServletResponse;
  13 +
  14 +import org.springframework.util.AntPathMatcher;
  15 +import org.springframework.util.PathMatcher;
  16 +
  17 +import com.bsth.common.Constants;
  18 +
  19 +public abstract class BaseFilter implements Filter {
  20 +
  21 + private final PathMatcher pathMatcher = new AntPathMatcher();
  22 +
  23 + /**
  24 + * 白名单
  25 + */
  26 + private String[] whiteListURLs = { Constants.LOGIN_PAGE,
  27 + Constants.ASSETS_URL, Constants.FAVICON_URL, Constants.METRONIC_URL, Constants.LOGIN, Constants.LOGIN_FAILURE };
  28 +
  29 + @Override
  30 + public void destroy() {
  31 +
  32 + }
  33 +
  34 + @Override
  35 + public void doFilter(ServletRequest request, ServletResponse response,
  36 + FilterChain chain) throws IOException, ServletException {
  37 +
  38 + HttpServletRequest httpRequest = (HttpServletRequest) request;
  39 + HttpServletResponse httpResponse = (HttpServletResponse) response;
  40 +
  41 + String currentURL = httpRequest.getServletPath();
  42 +
  43 + if (isWhiteURL(currentURL)) {
  44 + chain.doFilter(request, response);
  45 + return;
  46 + }
  47 +
  48 + doFilter(httpRequest, httpResponse, chain);
  49 + return;
  50 + }
  51 +
  52 + public void doFilter(HttpServletRequest request,
  53 + HttpServletResponse response, FilterChain chain)
  54 + throws IOException, ServletException {
  55 + chain.doFilter(request, response);
  56 + }
  57 +
  58 + @Override
  59 + public void init(FilterConfig arg0) throws ServletException {
  60 +
  61 + }
  62 +
  63 + private boolean isWhiteURL(String currentURL) {
  64 + for (String whiteURL : whiteListURLs) {
  65 + if (pathMatcher.match(whiteURL, currentURL)) {
  66 + return true;
  67 + }
  68 + }
  69 + return false;
  70 + }
  71 +}
... ...
src/main/java/com/bsth/filter/CORSFilter.java 0 → 100644
  1 +++ a/src/main/java/com/bsth/filter/CORSFilter.java
  1 +package com.bsth.filter;
  2 +
  3 +import java.io.IOException;
  4 +
  5 +import javax.servlet.FilterChain;
  6 +import javax.servlet.FilterConfig;
  7 +import javax.servlet.ServletException;
  8 +import javax.servlet.http.HttpServletRequest;
  9 +import javax.servlet.http.HttpServletResponse;
  10 +
  11 +import org.springframework.stereotype.Component;
  12 +
  13 +@Component
  14 +public class CORSFilter extends BaseFilter {
  15 +
  16 + public void init(FilterConfig filterConfig) {
  17 + }
  18 +
  19 + @Override
  20 + public void doFilter(HttpServletRequest request,
  21 + HttpServletResponse response, FilterChain chain)
  22 + throws IOException, ServletException {
  23 +
  24 + response.setHeader("Access-Control-Allow-Origin", "*");
  25 + response.setHeader("Access-Control-Allow-Methods",
  26 + "POST, GET, OPTIONS, DELETE");
  27 + response.setHeader("Access-Control-Max-Age", "3600");
  28 + response.setHeader("Access-Control-Allow-Headers", "x-requested-with");
  29 + chain.doFilter(request, response);
  30 + }
  31 +
  32 + public void destroy() {
  33 + }
  34 +
  35 +}
... ...
src/main/java/com/bsth/filter/ResourceFilter.java 0 → 100644
  1 +++ a/src/main/java/com/bsth/filter/ResourceFilter.java
  1 +package com.bsth.filter;
  2 +
  3 +import java.io.File;
  4 +import java.io.IOException;
  5 +
  6 +import javax.servlet.FilterChain;
  7 +import javax.servlet.ServletException;
  8 +import javax.servlet.http.HttpServletRequest;
  9 +import javax.servlet.http.HttpServletResponse;
  10 +
  11 +import org.apache.commons.lang3.StringUtils;
  12 +
  13 +import com.bsth.util.RequestUtils;
  14 +
  15 +/**
  16 + *
  17 + * @ClassName: ResourceFilter
  18 + * @Description: TODO(HTML片段过滤器)
  19 + * @author PanZhao
  20 + * @date 2016年3月19日 下午10:10:11
  21 + *
  22 + */
  23 +public class ResourceFilter extends BaseFilter {
  24 +
  25 + String[] params = new String[]{"no"};
  26 +
  27 + @Override
  28 + public void doFilter(HttpServletRequest request,
  29 + HttpServletResponse response, FilterChain chain)
  30 + throws IOException, ServletException {
  31 +
  32 + String uri = request.getRequestURI();
  33 + int len = uri.length();
  34 + if (RequestUtils.isAjaxRequest(request) ||
  35 + !uri.substring(len - 5, len).equals(".html")) {
  36 + super.doFilter(request, response, chain);
  37 + } else {
  38 +
  39 + String fPath = this.getClass().getResource("/").getPath()
  40 + + "static/" + uri;
  41 +
  42 + File f = new File(fPath);
  43 +
  44 + if (f.exists() && f.isFile() ){
  45 + response.sendRedirect("/#" + joinParam(request));
  46 + }else
  47 + response.sendRedirect("/");
  48 + }
  49 + }
  50 +
  51 + /**
  52 + * 拼接参数
  53 + * @param request
  54 + * @return
  55 + */
  56 + public String joinParam(HttpServletRequest request){
  57 +
  58 + StringBuilder sb = new StringBuilder();
  59 +
  60 + String v
  61 + ,url = request.getRequestURI();
  62 + for(String p : params){
  63 + v = request.getParameter(p);
  64 + if(!StringUtils.isEmpty(v))
  65 + sb.append("&" + p + "=" + v);
  66 + }
  67 +
  68 + if(sb.length() > 0)
  69 + url += "?" + sb.substring(1, sb.length());
  70 + return url;
  71 + }
  72 +}
... ...
src/main/java/com/bsth/repository/BaseRepository.java 0 → 100644
  1 +++ a/src/main/java/com/bsth/repository/BaseRepository.java
  1 +package com.bsth.repository;
  2 +
  3 +import java.io.Serializable;
  4 +
  5 +import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
  6 +import org.springframework.data.repository.NoRepositoryBean;
  7 +import org.springframework.data.repository.PagingAndSortingRepository;
  8 +
  9 +@NoRepositoryBean
  10 +public interface BaseRepository<T, ID extends Serializable> extends PagingAndSortingRepository<T, ID>,JpaSpecificationExecutor<T>{
  11 +
  12 +}
... ...
src/main/java/com/bsth/repository/DictionaryRepository.java 0 → 100644
  1 +++ a/src/main/java/com/bsth/repository/DictionaryRepository.java
  1 +package com.bsth.repository;
  2 +
  3 +import org.springframework.stereotype.Repository;
  4 +
  5 +import com.bsth.entity.sys.Dictionary;
  6 +
  7 +@Repository
  8 +public interface DictionaryRepository extends BaseRepository<Dictionary, Integer>{
  9 +
  10 +}
... ...
src/main/java/com/bsth/repository/ModuleRepository.java 0 → 100644
  1 +++ a/src/main/java/com/bsth/repository/ModuleRepository.java
  1 +package com.bsth.repository;
  2 +
  3 +import java.util.List;
  4 +import java.util.Set;
  5 +
  6 +import org.springframework.data.jpa.repository.Query;
  7 +import org.springframework.stereotype.Repository;
  8 +
  9 +import com.bsth.entity.sys.Module;
  10 +
  11 +@Repository
  12 +public interface ModuleRepository extends BaseRepository<Module, Integer>{
  13 +
  14 + @Query("select m from Module m where m.groupType in ?1")
  15 + List<Module> findByGroupType(String[] groupType);
  16 +
  17 + List<Module> findByPId(Integer pId);
  18 +
  19 + @Query("select m from Module m where m.id in ?1")
  20 + Set<Module> findByIds(List<Integer> ids);
  21 +}
... ...
src/main/java/com/bsth/repository/ResourceRepository.java 0 → 100644
  1 +++ a/src/main/java/com/bsth/repository/ResourceRepository.java
  1 +package com.bsth.repository;
  2 +
  3 +import java.util.List;
  4 +
  5 +import org.springframework.stereotype.Repository;
  6 +
  7 +import com.bsth.entity.sys.Resource;
  8 +
  9 +@Repository
  10 +public interface ResourceRepository extends BaseRepository<Resource, Integer> {
  11 +
  12 + List<Resource> findByRolesId(Integer roleId);
  13 +}
... ...
src/main/java/com/bsth/repository/RoleRepository.java 0 → 100644
  1 +++ a/src/main/java/com/bsth/repository/RoleRepository.java
  1 +package com.bsth.repository;
  2 +
  3 +
  4 +import javax.transaction.Transactional;
  5 +
  6 +import org.springframework.data.jpa.repository.Modifying;
  7 +import org.springframework.data.jpa.repository.Query;
  8 +import org.springframework.stereotype.Repository;
  9 +
  10 +import com.bsth.entity.sys.Role;
  11 +
  12 +@Repository
  13 +public interface RoleRepository extends BaseRepository<Role, Integer>{
  14 +
  15 + /**
  16 + * @Title: update
  17 + * @Description: TODO(简洁版更新(不需要级联的))
  18 + */
  19 + @Modifying
  20 + @Transactional
  21 + @Query("update Role r set r.codeName=?1, r.roleName=?2, r.enable=?3, r.descriptions=?4 where r.id=?5")
  22 + void update(String codeName, String roleName, boolean enable, String descriptions, Integer id);
  23 +}
... ...
src/main/java/com/bsth/repository/SysUserRepository.java 0 → 100644
  1 +++ a/src/main/java/com/bsth/repository/SysUserRepository.java
  1 +package com.bsth.repository;
  2 +
  3 +import org.springframework.stereotype.Repository;
  4 +
  5 +import com.bsth.entity.sys.SysUser;
  6 +
  7 +@Repository
  8 +public interface SysUserRepository extends BaseRepository<SysUser, Integer>{
  9 +
  10 + SysUser findByUserName(String userName);
  11 +
  12 +}
... ...
src/main/java/com/bsth/security/CustomAccessDecisionManager.java 0 → 100644
  1 +++ a/src/main/java/com/bsth/security/CustomAccessDecisionManager.java
  1 +package com.bsth.security;
  2 +
  3 +import java.util.Collection;
  4 +import java.util.Iterator;
  5 +
  6 +import org.springframework.security.access.AccessDecisionManager;
  7 +import org.springframework.security.access.AccessDeniedException;
  8 +import org.springframework.security.access.ConfigAttribute;
  9 +import org.springframework.security.access.SecurityConfig;
  10 +import org.springframework.security.authentication.InsufficientAuthenticationException;
  11 +import org.springframework.security.core.Authentication;
  12 +import org.springframework.security.core.GrantedAuthority;
  13 +import org.springframework.stereotype.Component;
  14 +
  15 +@Component
  16 +public class CustomAccessDecisionManager implements AccessDecisionManager{
  17 +
  18 + @Override
  19 + public void decide(Authentication authentication, Object object, Collection<ConfigAttribute> configAttributes)
  20 + throws AccessDeniedException, InsufficientAuthenticationException {
  21 +
  22 + Iterator<ConfigAttribute> iter = configAttributes.iterator();
  23 + Object obj;
  24 + while (iter.hasNext())
  25 + {
  26 + obj = iter.next();
  27 + if(null == obj)
  28 + continue;
  29 +
  30 + String accessResourceNeedRole = ((SecurityConfig) obj)
  31 + .getAttribute();
  32 + for (GrantedAuthority grantedAuthority : authentication.getAuthorities())
  33 + {
  34 + String userOwnRole = grantedAuthority.getAuthority();
  35 + if (accessResourceNeedRole.equals(userOwnRole))
  36 + {
  37 + return;
  38 + }
  39 + }
  40 + }
  41 + throw new AccessDeniedException("访问被拒绝!");
  42 + }
  43 +
  44 + @Override
  45 + public boolean supports(ConfigAttribute arg0) {
  46 + return false;
  47 + }
  48 +
  49 + @Override
  50 + public boolean supports(Class<?> arg0) {
  51 + return false;
  52 + }
  53 +
  54 +}
... ...
src/main/java/com/bsth/security/LoginSuccessHandler.java 0 → 100644
  1 +++ a/src/main/java/com/bsth/security/LoginSuccessHandler.java
  1 +package com.bsth.security;
  2 +
  3 +import java.io.IOException;
  4 +import javax.servlet.ServletException;
  5 +import javax.servlet.http.HttpServletRequest;
  6 +import javax.servlet.http.HttpServletResponse;
  7 +
  8 +import org.springframework.security.core.Authentication;
  9 +import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler;
  10 +
  11 +import com.bsth.entity.sys.SysUser;
  12 +import com.bsth.util.IpUtils;
  13 +
  14 +public class LoginSuccessHandler extends SavedRequestAwareAuthenticationSuccessHandler{
  15 +
  16 + @Override
  17 + public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
  18 + Authentication authentication) throws ServletException, IOException {
  19 +
  20 + SysUser user = (SysUser) authentication.getPrincipal();
  21 +
  22 + System.out.println("管理员 " + user.getUserName() + " 登录");
  23 + System.out.println("IP :"+IpUtils.getIpAddr(request));
  24 +
  25 + super.onAuthenticationSuccess(request, response, authentication);
  26 + }
  27 +
  28 +}
... ...
src/main/java/com/bsth/security/SecurityMetadataSourceService.java 0 → 100644
  1 +++ a/src/main/java/com/bsth/security/SecurityMetadataSourceService.java
  1 +package com.bsth.security;
  2 +
  3 +import java.util.Collection;
  4 +import java.util.Iterator;
  5 +import java.util.List;
  6 +import java.util.Set;
  7 +
  8 +import org.springframework.beans.factory.annotation.Autowired;
  9 +import org.springframework.security.access.ConfigAttribute;
  10 +import org.springframework.security.access.SecurityConfig;
  11 +import org.springframework.security.web.FilterInvocation;
  12 +import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;
  13 +import org.springframework.stereotype.Component;
  14 +import org.springframework.util.AntPathMatcher;
  15 +import org.springframework.util.PathMatcher;
  16 +
  17 +import com.bsth.entity.sys.Resource;
  18 +import com.bsth.entity.sys.Role;
  19 +import com.bsth.service.ResourceService;
  20 +import com.bsth.service.RoleService;
  21 +import com.google.common.collect.ArrayListMultimap;
  22 +import com.google.common.collect.Multimap;
  23 +
  24 +@Component
  25 +public class SecurityMetadataSourceService implements
  26 + FilterInvocationSecurityMetadataSource {
  27 +
  28 + @Autowired
  29 + RoleService roleService;
  30 +
  31 + @Autowired
  32 + ResourceService resourceService;
  33 +
  34 + private PathMatcher matcher = new AntPathMatcher();
  35 +
  36 + private Multimap<String, ConfigAttribute> multimap;
  37 +
  38 +
  39 + public void loadResourceDefine() throws Exception {
  40 +
  41 +
  42 + multimap = ArrayListMultimap.create();
  43 + //获取所有资源
  44 + List<Resource> resList = (List<Resource>) resourceService.findAll();
  45 +
  46 + Set<Role> roles;
  47 + String url;
  48 + for(Resource res : resList){
  49 + url = res.getMethod() + "#" + replacePlaceholders(res.getUrl());
  50 + roles = res.getRoles();
  51 +
  52 + if(null == roles || roles.size() == 0)
  53 + multimap.put(url, null);
  54 + else{
  55 + for(Role role : roles)
  56 + multimap.put(url , new SecurityConfig(role.getCodeName()));
  57 + }
  58 + }
  59 + System.out.println(multimap);
  60 + }
  61 +
  62 + public Collection<ConfigAttribute> getAttributes(Object object)
  63 + throws IllegalArgumentException {
  64 +
  65 + FilterInvocation invocation = ((FilterInvocation) object);
  66 + String method = invocation.getRequest().getMethod();
  67 + String url = method.toLowerCase() + "#" + invocation.getRequestUrl();
  68 +
  69 + System.out.println(url);
  70 +
  71 + int symIndex = url.indexOf("?");
  72 + if(symIndex != -1){
  73 + url = url.substring(0, symIndex);
  74 + }
  75 +
  76 + Iterator<String> iter = multimap.keySet().iterator();
  77 +
  78 + while(iter.hasNext()){
  79 + String temp = iter.next();
  80 +
  81 + if(matcher.match(temp, url)){
  82 + return multimap.get(url);
  83 + }
  84 + }
  85 +
  86 + return null;
  87 + }
  88 +
  89 + /**
  90 + *
  91 + * @Title: replacePlaceholders
  92 + * @Description: TODO(把/{xx}占位符替换成*)
  93 + * @param @param url
  94 + * @throws
  95 + */
  96 + public String replacePlaceholders(String url){
  97 + int s = url.indexOf("/{");
  98 + int e = url.indexOf("}");
  99 + if(s != -1 && e != -1){
  100 + String newUrl = url.substring(0, s) + "/*" + url.substring(e + 1, url.length());
  101 + return replacePlaceholders(newUrl);
  102 + }
  103 + else
  104 + return url;
  105 + }
  106 +
  107 + public boolean supports(Class<?> clazz) {
  108 + return true;
  109 + }
  110 +
  111 + public Collection<ConfigAttribute> getAllConfigAttributes() {
  112 + return null;
  113 + }
  114 +}
... ...
src/main/java/com/bsth/security/UserDetailServiceImpl.java 0 → 100644
  1 +++ a/src/main/java/com/bsth/security/UserDetailServiceImpl.java
  1 +package com.bsth.security;
  2 +
  3 +import org.springframework.beans.factory.annotation.Autowired;
  4 +import org.springframework.dao.DataAccessException;
  5 +import org.springframework.security.core.userdetails.UserDetails;
  6 +import org.springframework.security.core.userdetails.UserDetailsService;
  7 +import org.springframework.security.core.userdetails.UsernameNotFoundException;
  8 +import org.springframework.stereotype.Component;
  9 +
  10 +import com.bsth.entity.sys.SecurityUser;
  11 +import com.bsth.entity.sys.SysUser;
  12 +import com.bsth.service.SysUserService;
  13 +
  14 +@Component
  15 +public class UserDetailServiceImpl implements UserDetailsService{
  16 +
  17 + @Autowired
  18 + SysUserService sysUserService;
  19 +
  20 + public UserDetails loadUserByUsername(String username)throws UsernameNotFoundException, DataAccessException {
  21 +
  22 + SysUser user = sysUserService.findByUserName(username);
  23 + if(null == user){
  24 + throw new UsernameNotFoundException("UserName " + username + " not found");
  25 + }
  26 + return new SecurityUser(user);
  27 + }
  28 +}
... ...
src/main/java/com/bsth/security/WebSecurityConfig.java 0 → 100644
  1 +++ a/src/main/java/com/bsth/security/WebSecurityConfig.java
  1 +package com.bsth.security;
  2 +
  3 +import org.springframework.beans.factory.annotation.Autowired;
  4 +import org.springframework.boot.context.embedded.ServletListenerRegistrationBean;
  5 +import org.springframework.context.annotation.Bean;
  6 +import org.springframework.context.annotation.Configuration;
  7 +import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
  8 +import org.springframework.security.config.annotation.web.builders.HttpSecurity;
  9 +import org.springframework.security.config.annotation.web.builders.WebSecurity;
  10 +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
  11 +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
  12 +import org.springframework.security.core.session.SessionRegistry;
  13 +import org.springframework.security.core.session.SessionRegistryImpl;
  14 +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
  15 +import org.springframework.security.web.access.intercept.FilterSecurityInterceptor;
  16 +import org.springframework.security.web.session.HttpSessionEventPublisher;
  17 +
  18 +import com.bsth.common.Constants;
  19 +import com.bsth.security.filter.LoginInterceptor;
  20 +
  21 +@Configuration
  22 +@EnableWebSecurity
  23 +public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
  24 +
  25 + @Autowired
  26 + UserDetailServiceImpl customUserDetailService;
  27 +
  28 + @Autowired
  29 + CustomAccessDecisionManager customAccessDecisionManager;
  30 +
  31 + @Autowired
  32 + SecurityMetadataSourceService securityMetadataSourceService;
  33 +
  34 + @Override
  35 + public void configure(WebSecurity web) throws Exception {
  36 + // 白名单
  37 + web.ignoring().antMatchers(Constants.ASSETS_URL, Constants.FAVICON_URL,
  38 + Constants.METRONIC_URL, Constants.LOGIN_PAGE,
  39 + Constants.LOGIN_FAILURE);
  40 + }
  41 +
  42 + @Override
  43 + protected void configure(AuthenticationManagerBuilder auth)
  44 + throws Exception {
  45 + auth.userDetailsService(customUserDetailService).passwordEncoder(
  46 + new BCryptPasswordEncoder(4));
  47 + }
  48 +
  49 + @Override
  50 + protected void configure(HttpSecurity http) throws Exception {
  51 + http.authorizeRequests().antMatchers("/").permitAll().anyRequest()
  52 + .authenticated().and()
  53 + .formLogin()
  54 + //指定登录页
  55 + .loginPage(Constants.LOGIN_PAGE)
  56 + .loginProcessingUrl(Constants.LOGIN).permitAll()
  57 + //登录失败跳转的链接
  58 + .failureUrl(Constants.LOGIN_PAGE + "?error=true")
  59 + //登录成功后处理
  60 + .successHandler(loginSuccessHandler())
  61 + //禁用CXRF
  62 + .and().csrf().disable()
  63 + //禁用匿名用户功能
  64 + .anonymous().disable();
  65 +
  66 + // 同时只保持一个回话
  67 + http.sessionManagement().maximumSessions(1)
  68 + .expiredUrl(Constants.LOGIN_PAGE + "?error=true")
  69 + .maxSessionsPreventsLogin(false)//让之前的登录过期
  70 + .sessionRegistry(sessionRegistry());
  71 +
  72 + http.addFilterBefore(new LoginInterceptor(), FilterSecurityInterceptor.class);
  73 + http.addFilter(filterSecurityInterceptor());
  74 + }
  75 +
  76 + private FilterSecurityInterceptor filterSecurityInterceptor()
  77 + throws Exception {
  78 + FilterSecurityInterceptor filterSecurityInterceptor = new FilterSecurityInterceptor();
  79 + filterSecurityInterceptor
  80 + .setAccessDecisionManager(customAccessDecisionManager);
  81 + filterSecurityInterceptor
  82 + .setSecurityMetadataSource(securityMetadataSourceService);
  83 + filterSecurityInterceptor
  84 + .setAuthenticationManager(authenticationManager());
  85 + return filterSecurityInterceptor;
  86 + }
  87 +
  88 + @Bean
  89 + public LoginSuccessHandler loginSuccessHandler(){
  90 + return new LoginSuccessHandler();
  91 + }
  92 +
  93 + @Bean
  94 + public SessionRegistry sessionRegistry() {
  95 + SessionRegistry sessionRegistry = new SessionRegistryImpl();
  96 + return sessionRegistry;
  97 + }
  98 +
  99 + @Bean
  100 + public static ServletListenerRegistrationBean<HttpSessionEventPublisher> httpSessionEventPublisher() {
  101 + return new ServletListenerRegistrationBean<HttpSessionEventPublisher>(
  102 + new HttpSessionEventPublisher());
  103 + }
  104 +}
... ...
src/main/java/com/bsth/security/filter/LoginInterceptor.java 0 → 100644
  1 +++ a/src/main/java/com/bsth/security/filter/LoginInterceptor.java
  1 +package com.bsth.security.filter;
  2 +
  3 +import java.io.IOException;
  4 +import java.util.HashMap;
  5 +import java.util.Map;
  6 +
  7 +import javax.servlet.Filter;
  8 +import javax.servlet.FilterChain;
  9 +import javax.servlet.FilterConfig;
  10 +import javax.servlet.ServletException;
  11 +import javax.servlet.ServletRequest;
  12 +import javax.servlet.ServletResponse;
  13 +import javax.servlet.http.HttpServletRequest;
  14 +import javax.servlet.http.HttpServletResponse;
  15 +
  16 +import org.springframework.security.access.SecurityMetadataSource;
  17 +import org.springframework.security.access.intercept.AbstractSecurityInterceptor;
  18 +import org.springframework.security.core.Authentication;
  19 +import org.springframework.security.core.context.SecurityContextHolder;
  20 +
  21 +import com.bsth.common.Constants;
  22 +import com.bsth.common.ResponseCode;
  23 +import com.bsth.util.RequestUtils;
  24 +
  25 +/**
  26 + *
  27 + * @ClassName: LoginInterceptor
  28 + * @Description: TODO(登录校验)
  29 + * @author PanZhao
  30 + * @date 2016年3月24日 上午11:49:20
  31 + *
  32 + */
  33 +public class LoginInterceptor extends AbstractSecurityInterceptor implements Filter{
  34 +
  35 + @Override
  36 + public void destroy() {
  37 +
  38 + }
  39 +
  40 + @Override
  41 + public void doFilter(ServletRequest arg0, ServletResponse arg1,
  42 + FilterChain arg2) throws IOException, ServletException {
  43 +
  44 + Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
  45 +
  46 + if(null == authentication){
  47 + //没有登录
  48 + HttpServletRequest request = (HttpServletRequest)arg0;
  49 + HttpServletResponse response = ((HttpServletResponse)arg1);
  50 +
  51 + if(RequestUtils.isAjaxRequest(request)){
  52 + Map<String, Object> map = new HashMap<>();
  53 + map.put("status",
  54 + ResponseCode.NO_AUTHENTICATION);
  55 + response.getWriter().print(map);
  56 + }
  57 + else
  58 + response.sendRedirect(Constants.LOGIN_PAGE);
  59 +
  60 + return;
  61 + }
  62 +
  63 + arg2.doFilter(arg0, arg1);
  64 + }
  65 +
  66 + @Override
  67 + public void init(FilterConfig arg0) throws ServletException {
  68 +
  69 + }
  70 +
  71 + @Override
  72 + public Class<?> getSecureObjectClass() {
  73 + // TODO Auto-generated method stub
  74 + return null;
  75 + }
  76 +
  77 + @Override
  78 + public SecurityMetadataSource obtainSecurityMetadataSource() {
  79 + // TODO Auto-generated method stub
  80 + return null;
  81 + }
  82 +
  83 +}
... ...
src/main/java/com/bsth/security/util/SecurityUtils.java 0 → 100644
  1 +++ a/src/main/java/com/bsth/security/util/SecurityUtils.java
  1 +package com.bsth.security.util;
  2 +
  3 +import org.slf4j.Logger;
  4 +import org.slf4j.LoggerFactory;
  5 +import org.springframework.security.core.context.SecurityContextHolder;
  6 +
  7 +import com.bsth.entity.sys.SysUser;
  8 +
  9 +/**
  10 + *
  11 + * @ClassName: SecurityUtils
  12 + * @author PanZhao
  13 + * @date 2016年3月30日 上午11:28:24
  14 + *
  15 + */
  16 +public class SecurityUtils {
  17 +
  18 + static Logger logger = LoggerFactory.getLogger(SecurityUtils.class);
  19 +
  20 + /**
  21 + *
  22 + * @Title: getCurrentUser
  23 + * @Description: TODO(获取当前用户)
  24 + * @return SysUser 返回类型
  25 + * @throws
  26 + */
  27 + public static SysUser getCurrentUser(){
  28 + SysUser user = null;
  29 + try{
  30 + user = (SysUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
  31 + }catch(Exception e){
  32 + logger.error("", e);
  33 + }
  34 + return user;
  35 + }
  36 +}
... ...
src/main/java/com/bsth/service/BaseService.java 0 → 100644
  1 +++ a/src/main/java/com/bsth/service/BaseService.java
  1 +package com.bsth.service;
  2 +
  3 +import java.io.Serializable;
  4 +import java.util.Map;
  5 +
  6 +import org.springframework.data.domain.Page;
  7 +import org.springframework.data.domain.Pageable;
  8 +
  9 +/**
  10 + *
  11 + * @ClassName: BaseService
  12 + * @Description: TODO(基础的Service接口)
  13 + * @author PanZhao
  14 + * @date 2016年3月17日 下午12:48:43
  15 + *
  16 + * @param <T>
  17 + * @param <ID>
  18 + */
  19 +public interface BaseService<T, ID extends Serializable> {
  20 + /**
  21 + * 根据主键获取单个对象
  22 + * @param id
  23 + * @return
  24 + */
  25 + T findById(ID id);
  26 +
  27 + /**
  28 + * 保存
  29 + * @param t
  30 + * @return
  31 + */
  32 + Map<String, Object> save(T t);
  33 +
  34 + /**
  35 + *
  36 + * @Title: list
  37 + * @Description: TODO(多条件分页查询)
  38 + * @param @param map 查询条件
  39 + * @param @param pageable 分页对象
  40 + * @throws
  41 + */
  42 + Page<T> list(Map<String, Object> map, Pageable pageable);
  43 +
  44 + /**
  45 + *
  46 + * @Title: list
  47 + * @Description: TODO(多条件查询)
  48 + * @throws
  49 + */
  50 + Iterable<T> list(Map<String, Object> map);
  51 +
  52 + /**
  53 + * 获取所有
  54 + * @return
  55 + */
  56 + Iterable<T> findAll();
  57 +
  58 + /**
  59 + *
  60 + * @Title: deleteById
  61 + * @Description: TODO(根据主键删除对象)
  62 + * @param @param id
  63 + * @throws
  64 + */
  65 + Map<String, Object> delete(ID id);
  66 +}
... ...
src/main/java/com/bsth/service/DictionaryService.java 0 → 100644
  1 +++ a/src/main/java/com/bsth/service/DictionaryService.java
  1 +package com.bsth.service;
  2 +
  3 +import com.bsth.entity.sys.Dictionary;
  4 +
  5 +public interface DictionaryService extends BaseService<Dictionary, Integer>{
  6 +
  7 +}
... ...
src/main/java/com/bsth/service/ModuleService.java 0 → 100644
  1 +++ a/src/main/java/com/bsth/service/ModuleService.java
  1 +package com.bsth.service;
  2 +
  3 +import java.util.List;
  4 +
  5 +import com.bsth.entity.sys.Module;
  6 +
  7 +public interface ModuleService extends BaseService<Module, Integer>{
  8 +
  9 + public List<Module> findByGroupType(String group);
  10 +
  11 + public List<Module> findByCurrentUser();
  12 +
  13 +}
... ...
src/main/java/com/bsth/service/ResourceService.java 0 → 100644
  1 +++ a/src/main/java/com/bsth/service/ResourceService.java
  1 +package com.bsth.service;
  2 +
  3 +import java.util.List;
  4 +import java.util.Map;
  5 +
  6 +import com.bsth.entity.sys.Resource;
  7 +
  8 +public interface ResourceService extends BaseService<Resource, Integer> {
  9 +
  10 + Map<String, Object> saveList(List<Resource> parseArray);
  11 +
  12 + List<Resource> findByRolesId(Integer id);
  13 +
  14 +}
... ...
src/main/java/com/bsth/service/RoleService.java 0 → 100644
  1 +++ a/src/main/java/com/bsth/service/RoleService.java
  1 +package com.bsth.service;
  2 +
  3 +import java.util.Map;
  4 +
  5 +import com.bsth.entity.sys.Role;
  6 +
  7 +public interface RoleService extends BaseService<Role, Integer>{
  8 +
  9 + Map<String, Object> settRoleModules(Integer roleId, String mIds);
  10 +
  11 +}
... ...
src/main/java/com/bsth/service/SysUserService.java 0 → 100644
  1 +++ a/src/main/java/com/bsth/service/SysUserService.java
  1 +package com.bsth.service;
  2 +
  3 +import com.bsth.entity.sys.SysUser;
  4 +
  5 +public interface SysUserService extends BaseService<SysUser, Integer>{
  6 +
  7 + SysUser findByUserName(String name);
  8 +}
... ...
src/main/java/com/bsth/service/impl/BaseServiceImpl.java 0 → 100644
  1 +++ a/src/main/java/com/bsth/service/impl/BaseServiceImpl.java
  1 +package com.bsth.service.impl;
  2 +
  3 +import java.io.Serializable;
  4 +import java.util.HashMap;
  5 +import java.util.Map;
  6 +
  7 +import org.slf4j.Logger;
  8 +import org.slf4j.LoggerFactory;
  9 +import org.springframework.beans.factory.annotation.Autowired;
  10 +import org.springframework.dao.DataIntegrityViolationException;
  11 +import org.springframework.data.domain.Page;
  12 +import org.springframework.data.domain.Pageable;
  13 +
  14 +import com.bsth.common.ResponseCode;
  15 +import com.bsth.entity.search.CustomerSpecs;
  16 +import com.bsth.repository.BaseRepository;
  17 +import com.bsth.service.BaseService;
  18 +
  19 +public class BaseServiceImpl<T, ID extends Serializable> implements BaseService<T, ID>{
  20 +
  21 + @Autowired
  22 + private BaseRepository<T, ID> baseRepository;
  23 +
  24 + Logger logger = LoggerFactory.getLogger(this.getClass());
  25 +
  26 + @Override
  27 + public Page<T> list(Map<String, Object> map, Pageable pageable) {
  28 + return this.baseRepository.findAll(new CustomerSpecs<T>(map), pageable);
  29 + }
  30 +
  31 + @Override
  32 + public Iterable<T> list(Map<String, Object> map) {
  33 + return this.baseRepository.findAll(new CustomerSpecs<T>(map));
  34 + }
  35 +
  36 + @Override
  37 + public T findById(ID id) {
  38 + return baseRepository.findOne(id);
  39 + }
  40 +
  41 + @Override
  42 + public Map<String, Object> save(T t) {
  43 + Map<String, Object> map = new HashMap<>();
  44 + try{
  45 + baseRepository.save(t);
  46 + map.put("status", ResponseCode.SUCCESS);
  47 + map.put("t", t);
  48 + }catch(Exception e){
  49 + map.put("status", ResponseCode.ERROR);
  50 + logger.error("save erro.", e);
  51 + }
  52 + return map;
  53 + }
  54 +
  55 +
  56 + @Override
  57 + public Iterable<T> findAll() {
  58 + return baseRepository.findAll();
  59 + }
  60 +
  61 + @Override
  62 + public Map<String, Object> delete(ID id) {
  63 + Map<String, Object> map = new HashMap<>();
  64 + try{
  65 + baseRepository.delete(id);
  66 + map.put("status", ResponseCode.SUCCESS);
  67 + }catch(DataIntegrityViolationException de){
  68 + map.put("status", ResponseCode.ERROR);
  69 + map.put("msg", "“完整性约束”校验失败,请检查要删除的对象是否存在外键约束");
  70 + }
  71 + return map;
  72 + }
  73 +}
... ...
src/main/java/com/bsth/service/impl/DictionaryServiceImpl.java 0 → 100644
  1 +++ a/src/main/java/com/bsth/service/impl/DictionaryServiceImpl.java
  1 +package com.bsth.service.impl;
  2 +
  3 +import org.springframework.stereotype.Service;
  4 +
  5 +import com.bsth.entity.sys.Dictionary;
  6 +import com.bsth.service.DictionaryService;
  7 +
  8 +@Service
  9 +public class DictionaryServiceImpl extends BaseServiceImpl<Dictionary, Integer> implements DictionaryService{
  10 +
  11 +}
... ...
src/main/java/com/bsth/service/impl/ModuleServiceImpl.java 0 → 100644
  1 +++ a/src/main/java/com/bsth/service/impl/ModuleServiceImpl.java
  1 +package com.bsth.service.impl;
  2 +
  3 +import java.util.ArrayList;
  4 +import java.util.HashMap;
  5 +import java.util.HashSet;
  6 +import java.util.List;
  7 +import java.util.Map;
  8 +import java.util.Set;
  9 +
  10 +import org.springframework.beans.factory.annotation.Autowired;
  11 +import org.springframework.stereotype.Service;
  12 +
  13 +import com.bsth.common.ResponseCode;
  14 +import com.bsth.entity.sys.Module;
  15 +import com.bsth.entity.sys.Role;
  16 +import com.bsth.entity.sys.SysUser;
  17 +import com.bsth.repository.ModuleRepository;
  18 +import com.bsth.security.util.SecurityUtils;
  19 +import com.bsth.service.ModuleService;
  20 +
  21 +@Service
  22 +public class ModuleServiceImpl extends BaseServiceImpl<Module, Integer> implements ModuleService{
  23 +
  24 + @Autowired
  25 + ModuleRepository moduleRepository;
  26 +
  27 + @Override
  28 + public List<Module> findByGroupType(String group) {
  29 + String[] array;
  30 + if(group.indexOf(",") != -1){
  31 + array = group.split(",");
  32 + }
  33 + else
  34 + array = new String[]{group};
  35 + return moduleRepository.findByGroupType(array);
  36 + }
  37 +
  38 + @Override
  39 + public Map<String, Object> delete(Integer id) {
  40 +
  41 + Map<String, Object> map = new HashMap<>();
  42 +
  43 + //判断删除的节点是否有子节点
  44 + List<Module> list = moduleRepository.findByPId(id);
  45 +
  46 + if(null != list && list.size() > 0){
  47 + map.put("status", ResponseCode.ERROR);
  48 + map.put("msg", "失败,要删除的项还存在子节点");
  49 + }
  50 + else{
  51 + map = super.delete(id);
  52 + }
  53 + return map;
  54 + }
  55 +
  56 + @Override
  57 + public List<Module> findByCurrentUser() {
  58 +
  59 + SysUser user = SecurityUtils.getCurrentUser();
  60 + Set<Role> roles = user.getRoles();
  61 +
  62 + List<Module> all = (List<Module>) moduleRepository.findAll()
  63 + ,results = new ArrayList<>();
  64 +
  65 + Map<Integer, Module> map = new HashMap<>();
  66 + for(Module m : all){
  67 + map.put(m.getId(), m);
  68 + for(Role r : roles){
  69 + if(m.getRoles().contains(r))
  70 + results.add(m);
  71 + }
  72 + }
  73 +
  74 + //上层目录和组节点
  75 + Set<Module> pSet = new HashSet<>();
  76 + for(Module m : results){
  77 + searchParentNode(m, map, pSet);
  78 + }
  79 + results.addAll(pSet);
  80 + return results;
  81 + }
  82 +
  83 + /**
  84 + *
  85 + * @Title: searchParentNode
  86 + * @Description: TODO(搜索上层节点)
  87 + * @param @param m 当前节点
  88 + * @param @param idMap 全量的ID和节点对照
  89 + * @param @param pSet 上层节点容器
  90 + * @throws
  91 + */
  92 + public void searchParentNode(Module m, Map<Integer, Module> idMap, Set<Module> pSet){
  93 + int pId = m.getpId();
  94 + if(pId > 0){
  95 + Module pModule = idMap.get(pId);
  96 + pSet.add(pModule);
  97 +
  98 + if(null != pModule &&
  99 + null != pModule.getpId()
  100 + && pModule.getpId() > 0)
  101 + searchParentNode(pModule, idMap, pSet);
  102 + }
  103 + }
  104 +}
... ...
src/main/java/com/bsth/service/impl/ResourceServiceImpl.java 0 → 100644
  1 +++ a/src/main/java/com/bsth/service/impl/ResourceServiceImpl.java
  1 +package com.bsth.service.impl;
  2 +
  3 +import java.util.HashMap;
  4 +import java.util.List;
  5 +import java.util.Map;
  6 +
  7 +import org.springframework.beans.factory.annotation.Autowired;
  8 +import org.springframework.stereotype.Service;
  9 +
  10 +import com.bsth.common.ResponseCode;
  11 +import com.bsth.entity.sys.Resource;
  12 +import com.bsth.repository.ResourceRepository;
  13 +import com.bsth.service.ResourceService;
  14 +
  15 +@Service
  16 +public class ResourceServiceImpl extends BaseServiceImpl<Resource, Integer> implements ResourceService{
  17 +
  18 + @Autowired
  19 + ResourceRepository resourceRepository;
  20 +
  21 + @Override
  22 + public Map<String, Object> saveList(List<Resource> array) {
  23 + Map<String, Object> map = new HashMap<>();
  24 + try{
  25 + resourceRepository.save(array);
  26 + map.put("status", ResponseCode.SUCCESS);
  27 + }catch(Exception e){
  28 + map.put("status", ResponseCode.ERROR);
  29 + logger.error("", e);
  30 + }
  31 + return map;
  32 + }
  33 +
  34 + @Override
  35 + public List<Resource> findByRolesId(Integer id) {
  36 + return resourceRepository.findByRolesId(id);
  37 + }
  38 +}
... ...
src/main/java/com/bsth/service/impl/RoleServiceImpl.java 0 → 100644
  1 +++ a/src/main/java/com/bsth/service/impl/RoleServiceImpl.java
  1 +package com.bsth.service.impl;
  2 +
  3 +import java.util.ArrayList;
  4 +import java.util.HashMap;
  5 +import java.util.List;
  6 +import java.util.Map;
  7 +import java.util.Set;
  8 +
  9 +import org.slf4j.Logger;
  10 +import org.slf4j.LoggerFactory;
  11 +import org.springframework.beans.factory.annotation.Autowired;
  12 +import org.springframework.stereotype.Service;
  13 +
  14 +import com.bsth.common.ResponseCode;
  15 +import com.bsth.entity.sys.Module;
  16 +import com.bsth.entity.sys.Role;
  17 +import com.bsth.repository.ModuleRepository;
  18 +import com.bsth.repository.RoleRepository;
  19 +import com.bsth.service.RoleService;
  20 +
  21 +@Service
  22 +public class RoleServiceImpl extends BaseServiceImpl<Role, Integer> implements
  23 + RoleService {
  24 +
  25 + Logger logger = LoggerFactory.getLogger(this.getClass());
  26 +
  27 + @Autowired
  28 + RoleRepository roleRepository;
  29 +
  30 + @Autowired
  31 + ModuleRepository moduleRepository;
  32 +
  33 + @Override
  34 + public Map<String, Object> save(Role t) {
  35 + if (t.getId() != null) {
  36 + // 更新
  37 + Map<String, Object> map = new HashMap<>();
  38 + try {
  39 + roleRepository.update(t.getCodeName(), t.getRoleName(),
  40 + t.isEnable(), t.getDescriptions(), t.getId());
  41 + map.put("status", ResponseCode.SUCCESS);
  42 + } catch (Exception e) {
  43 + map.put("status", ResponseCode.ERROR);
  44 + }
  45 + return map;
  46 + }
  47 + return super.save(t);
  48 + }
  49 +
  50 + @Override
  51 + public Map<String, Object> settRoleModules(Integer roleId, String mIds) {
  52 +
  53 + Map<String, Object> map = new HashMap<>();
  54 + try {
  55 + Role role = roleRepository.findOne(roleId);
  56 +
  57 + List<Integer> idList = new ArrayList<>();
  58 + String[] array = mIds.split(",");
  59 + for (String id : array) {
  60 + if (null == id || id.trim().equals(""))
  61 + continue;
  62 + idList.add(Integer.parseInt(id));
  63 + }
  64 +
  65 + Set<Module> mList = moduleRepository.findByIds(idList);
  66 + role.setModules(mList);
  67 + roleRepository.save(role);
  68 + map.put("status", ResponseCode.SUCCESS);
  69 + } catch (Exception e) {
  70 + logger.error("", e);
  71 + map.put("status", ResponseCode.ERROR);
  72 + }
  73 + return map;
  74 + }
  75 +}
... ...
src/main/java/com/bsth/service/impl/SysUserServiceImpl.java 0 → 100644
  1 +++ a/src/main/java/com/bsth/service/impl/SysUserServiceImpl.java
  1 +package com.bsth.service.impl;
  2 +
  3 +import org.springframework.beans.factory.annotation.Autowired;
  4 +import org.springframework.stereotype.Service;
  5 +
  6 +import com.bsth.entity.sys.SysUser;
  7 +import com.bsth.repository.SysUserRepository;
  8 +import com.bsth.service.SysUserService;
  9 +
  10 +@Service
  11 +public class SysUserServiceImpl extends BaseServiceImpl<SysUser, Integer> implements SysUserService{
  12 +
  13 + @Autowired
  14 + SysUserRepository sysUserRepository;
  15 +
  16 + @Override
  17 + public SysUser findByUserName(String name) {
  18 + return sysUserRepository.findByUserName(name);
  19 + }
  20 +}
... ...
src/main/java/com/bsth/util/IpUtils.java 0 → 100644
  1 +++ a/src/main/java/com/bsth/util/IpUtils.java
  1 +package com.bsth.util;
  2 +
  3 +import javax.servlet.http.HttpServletRequest;
  4 +
  5 +public class IpUtils {
  6 +
  7 + public static String getIpAddr(HttpServletRequest request) {
  8 + if (request == null) {
  9 + return "unknown";
  10 + }
  11 + String ip = request.getHeader("x-forwarded-for");
  12 + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
  13 + ip = request.getHeader("Proxy-Client-IP");
  14 + }
  15 + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
  16 + ip = request.getHeader("X-Forwarded-For");
  17 + }
  18 + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
  19 + ip = request.getHeader("WL-Proxy-Client-IP");
  20 + }
  21 + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
  22 + ip = request.getHeader("X-Real-IP");
  23 + }
  24 + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
  25 + ip = request.getRemoteAddr();
  26 + }
  27 + return ip;
  28 + }
  29 +}
... ...
src/main/java/com/bsth/util/RequestUtils.java 0 → 100644
  1 +++ a/src/main/java/com/bsth/util/RequestUtils.java
  1 +package com.bsth.util;
  2 +
  3 +import javax.servlet.http.HttpServletRequest;
  4 +
  5 +public class RequestUtils {
  6 +
  7 + /**
  8 + *
  9 + * @Title: isAjaxRequest
  10 + * @Description: TODO(判断Request是否是Ajax请求)
  11 + * @param @param request
  12 + * @param @return 设定文件
  13 + * @return boolean 返回类型
  14 + * @throws
  15 + */
  16 + public static boolean isAjaxRequest(HttpServletRequest request){
  17 + String requestType = request.getHeader("X-Requested-With");
  18 + return null != requestType
  19 + && requestType.equals("XMLHttpRequest");
  20 + }
  21 +}
... ...
src/main/resources/application.properties 0 → 100644
  1 +++ a/src/main/resources/application.properties
  1 +server.port=9088
  2 +management.port= 9001
  3 +management.address= 127.0.0.1
  4 +
  5 +spring.jpa.hibernate.ddl-auto= update
  6 +spring.jpa.hibernate.naming_strategy= org.hibernate.cfg.ImprovedNamingStrategy
  7 +
  8 +#DATABASE
  9 +spring.jpa.database= MYSQL
  10 +spring.jpa.show-sql= true
  11 +spring.datasource.driver-class-name= com.mysql.jdbc.Driver
  12 +spring.datasource.url= jdbc:mysql://192.168.168.201:3306/control
  13 +spring.datasource.username= root
  14 +spring.datasource.password= 123456
  15 +
  16 +#DATASOURCE
  17 +spring.datasource.max-active=100
  18 +spring.datasource.max-idle=8
  19 +spring.datasource.min-idle=8
  20 +spring.datasource.initial-size=5
  21 +
  22 +spring.view.suffix=.html
  23 +
  24 +server.session-timeout=-1
  25 +
  26 +security.basic.enabled=false
... ...
src/main/resources/banner.txt 0 → 100644
  1 +++ a/src/main/resources/banner.txt
  1 + ____ _____ _______ _ _
  2 + | _ \ / ____| |__ __| | | | |
  3 + | |_) | | (___ | | | |__| |
  4 + | _ < \___ \ | | | __ |
  5 + | |_) | ____) | | | | | | |
  6 + |____/ |_____/ |_| |_| |_|
  7 +
  8 +Running Spring Boot ${spring-boot.version}
0 9 \ No newline at end of file
... ...
src/main/resources/init.sql 0 → 100644
  1 +++ a/src/main/resources/init.sql
  1 +##初始的角色
  2 +insert into t_sys_role(id, code_name, role_name, pic, enable, create_date, update_date, is_super_admin,descriptions)
  3 +values(1, 'ROLE_ADMIN', '管理员', 1, 1, now(), now(), 0, '');
  4 +
  5 +##默认的模块
  6 +insert into t_sys_module(id,p_id, name, group_type, enable, path, create_date, update_date, mapp_symbol)
  7 +values (1,null , '系统管理', 1, 1, null, now(), now(), null)
  8 +,(2, 1, '权限管理', 2, 1, null, now(), now(), null)
  9 +,(3, 2, '资源管理', 3, 1, 'permission/resource/list.html', now(), now(), '/resource')
  10 +,(4, 2, '模块管理', 3, 1, 'permission/module/list.html', now(), now(), '/module')
  11 +,(5, 2, '角色管理', 3, 1, 'permission/role/list.html', now(), now(), '/role')
  12 +,(6, 2, '用户管理', 3, 1, 'permission/user/list.html', now(), now(), '/user')
  13 +,(7, 2, '字典管理', 3, 1, 'permission/dictionary/list.html', now(), now(), '/dictionary');
  14 +
  15 +##管理员角色和模块关联
  16 +insert into t_sys_role_modules(roles, modules)
  17 +values (1, 3)
  18 +,(1, 4)
  19 +,(1, 5)
  20 +,(1, 6)
  21 +,(1, 7);
  22 +
  23 +##管理员用户 admin/admin
  24 +insert into t_sys_user(id, name, user_name, password, create_date, enabled)
  25 +values(1, '系统管理员', 'admin', '$2a$04$4C6Xdjbfsqrbn3oFvmUl3eOm4.31FmzV3gEhzMIJuM7Gni4DQ8xQe', now(), 1);
  26 +insert into t_sys_user_roles(users, roles)
  27 +values(1, 1);
... ...
src/main/resources/logback.xml 0 → 100644
  1 +++ a/src/main/resources/logback.xml
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<!-- <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/2002/xmlspec/dtd/2.10/xmlspec.dtd"> -->
  3 +<configuration>
  4 +
  5 + <!-- <property resource="application.properties" /> -->
  6 + <property name="LOG_BASE" value="E:/bsth_control_logs" />
  7 + <!-- 控制台输出 -->
  8 + <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
  9 +
  10 + <layout class="ch.qos.logback.classic.PatternLayout">
  11 + <!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符 -->
  12 + <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] [%file:%line] %-5level -%msg%n
  13 + </pattern>
  14 + </layout>
  15 + </appender>
  16 +
  17 + <!-- 主日志文件 -->
  18 + <appender name="FILE"
  19 + class="ch.qos.logback.core.rolling.RollingFileAppender">
  20 + <file>${LOG_BASE}/main.log</file>
  21 + <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
  22 + <fileNamePattern>${LOG_BASE}/main-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
  23 + <timeBasedFileNamingAndTriggeringPolicy
  24 + class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
  25 + <maxFileSize>100MB</maxFileSize>
  26 + </timeBasedFileNamingAndTriggeringPolicy>
  27 + </rollingPolicy>
  28 + <encoder>
  29 + <pattern>%msg%n</pattern>
  30 + </encoder>
  31 +
  32 + <layout class="ch.qos.logback.classic.PatternLayout">
  33 + <!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符 -->
  34 + <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] [%file:%line] %-5level -%msg%n
  35 + </pattern>
  36 + </layout>
  37 + </appender>
  38 +
  39 + <!-- 访问日志 -->
  40 + <appender name="ACCESS"
  41 + class="ch.qos.logback.core.rolling.RollingFileAppender">
  42 + <file>${LOG_BASE}/access.log</file>
  43 + <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
  44 + <fileNamePattern>${LOG_BASE}/access-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
  45 + <timeBasedFileNamingAndTriggeringPolicy
  46 + class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
  47 + <maxFileSize>100MB</maxFileSize>
  48 + </timeBasedFileNamingAndTriggeringPolicy>
  49 + </rollingPolicy>
  50 + <encoder>
  51 + <pattern>%msg%n</pattern>
  52 + </encoder>
  53 +
  54 + <layout class="ch.qos.logback.classic.PatternLayout">
  55 + <!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符 -->
  56 + <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] [%file:%line] %-5level -%msg%n
  57 + </pattern>
  58 + </layout>
  59 + </appender>
  60 +
  61 + <logger name="com.bsth.filter.AccessLogFilter" level="INFO" additivity="false">
  62 + <appender-ref ref="ACCESS" />
  63 + </logger>
  64 +
  65 + <!-- 日志输出级别 -->
  66 + <root level="info">
  67 + <appender-ref ref="STDOUT" />
  68 + <appender-ref ref="FILE" />
  69 + </root>
  70 +</configuration>
0 71 \ No newline at end of file
... ...
src/main/resources/static/assets/img/roleHead/ROLE_ADMIN.png 0 → 100644

43.5 KB

src/main/resources/static/assets/img/roleHead/ROLE_MAINTAIN.png 0 → 100644

57 KB

src/main/resources/static/assets/img/roleHead/normal.png 0 → 100644

26.5 KB

src/main/resources/static/assets/js/common.js 0 → 100644
  1 +++ a/src/main/resources/static/assets/js/common.js
  1 +/**
  2 + * 删除提示框
  3 + * text 文本
  4 + * url 删除接口
  5 + * success 删除成功之后的回调
  6 + */
  7 +function removeConfirm(text, url, success) {
  8 + layer.confirm(text, {
  9 + btn : [ '确定删除', '取消' ],
  10 + icon : 3,
  11 + skin : 'layui-layer-cfm-delete'
  12 + }, function(){
  13 + layer.msg('正在删除...', {icon: 16});
  14 +
  15 + $post(url, {'_method': 'delete'},function(res){
  16 + layer.msg('删除成功!');
  17 + success && success();
  18 + });
  19 + });
  20 +}
  21 +
  22 +
  23 +function successHandle(json, handle){
  24 + if(!json.status){
  25 + handle && handle(json);
  26 + return ;
  27 + }
  28 +
  29 + if(json.status == 'ERROR')
  30 + layer.alert(json.msg, {icon: 2, title: '操作失败'});
  31 + else
  32 + handle && handle(json);
  33 +}
  34 +
  35 +function ajaxComplete(xhr, ts, succ){
  36 + if(ts == 'success'){
  37 + successHandle(xhr.responseJSON, succ);
  38 + }
  39 + else if(ts == 'error'){
  40 + layer.alert(xhr.responseText, {icon: 2, title: '操作失败'});
  41 + }
  42 +}
  43 +
  44 +function $get(url,data, successFun) {
  45 + $.ajax({
  46 + url: url,
  47 + data: data,
  48 + complete: function(xhr, ts){
  49 + ajaxComplete(xhr, ts, successFun);
  50 + }
  51 + });
  52 +}
  53 +
  54 +function $post(url,data, successFun) {
  55 + $.ajax({
  56 + url: url,
  57 + method: 'POST',
  58 + data: data,
  59 + complete: function(xhr, ts){
  60 + ajaxComplete(xhr, ts, successFun);
  61 + }
  62 + });
  63 +}
  64 +
  65 +//将数据写入表单
  66 +function putFormData(json, fId){
  67 + json.enable = json.enable==true? 1 : 0;
  68 + for(var att in json){
  69 + var f = 'name=' +att
  70 + ,elem = $('input['+f+'],select['+f+'],textarea['+f+']', fId);
  71 + if(elem.length > 0){
  72 + if(elem.attr('type') == 'checkbox')
  73 + elem[0].checked = json[att];
  74 + else
  75 + elem.val(json[att]).change();
  76 + }
  77 + }
  78 +}
  79 +
  80 +/**
  81 + * 将模块List 转换为树结构
  82 + * @param arr
  83 + * @returns {Array}
  84 + */
  85 +function createTreeData(arr){
  86 + var treeData = [];
  87 + var len = arr.length;
  88 + for(var i = 0; i < len; i ++){
  89 + var pId = arr[i].pId;
  90 + arr[i].text = arr[i].name;
  91 + if(!pId){
  92 + treeData.push(arr[i]);
  93 + }
  94 +
  95 + for(var j = 0; j < len; j ++){
  96 + if(pId == arr[j].id){
  97 + if(!arr[j].children)
  98 + arr[j].children = [];
  99 + arr[j].children.push(arr[i]);
  100 + break;
  101 + }
  102 + }
  103 + }
  104 + return treeData;
  105 +}
0 106 \ No newline at end of file
... ...
src/main/resources/static/assets/plugins/excanvas.min.js 0 → 100644
  1 +++ a/src/main/resources/static/assets/plugins/excanvas.min.js
  1 +if(!document.createElement("canvas").getContext){(function(){var ab=Math;var n=ab.round;var l=ab.sin;var A=ab.cos;var H=ab.abs;var N=ab.sqrt;var d=10;var f=d/2;var z=+navigator.userAgent.match(/MSIE ([\d.]+)?/)[1];function y(){return this.context_||(this.context_=new D(this))}var t=Array.prototype.slice;function g(j,m,p){var i=t.call(arguments,2);return function(){return j.apply(m,i.concat(t.call(arguments)))}}function af(i){return String(i).replace(/&/g,"&amp;").replace(/"/g,"&quot;")}function Y(m,j,i){if(!m.namespaces[j]){m.namespaces.add(j,i,"#default#VML")}}function R(j){Y(j,"g_vml_","urn:schemas-microsoft-com:vml");Y(j,"g_o_","urn:schemas-microsoft-com:office:office");if(!j.styleSheets.ex_canvas_){var i=j.createStyleSheet();i.owningElement.id="ex_canvas_";i.cssText="canvas{display:inline-block;overflow:hidden;text-align:left;width:300px;height:150px}"}}R(document);var e={init:function(i){var j=i||document;j.createElement("canvas");j.attachEvent("onreadystatechange",g(this.init_,this,j))},init_:function(p){var m=p.getElementsByTagName("canvas");for(var j=0;j<m.length;j++){this.initElement(m[j])}},initElement:function(j){if(!j.getContext){j.getContext=y;R(j.ownerDocument);j.innerHTML="";j.attachEvent("onpropertychange",x);j.attachEvent("onresize",W);var i=j.attributes;if(i.width&&i.width.specified){j.style.width=i.width.nodeValue+"px"}else{j.width=j.clientWidth}if(i.height&&i.height.specified){j.style.height=i.height.nodeValue+"px"}else{j.height=j.clientHeight}}return j}};function x(j){var i=j.srcElement;switch(j.propertyName){case"width":i.getContext().clearRect();i.style.width=i.attributes.width.nodeValue+"px";i.firstChild.style.width=i.clientWidth+"px";break;case"height":i.getContext().clearRect();i.style.height=i.attributes.height.nodeValue+"px";i.firstChild.style.height=i.clientHeight+"px";break}}function W(j){var i=j.srcElement;if(i.firstChild){i.firstChild.style.width=i.clientWidth+"px";i.firstChild.style.height=i.clientHeight+"px"}}e.init();var k=[];for(var ae=0;ae<16;ae++){for(var ad=0;ad<16;ad++){k[ae*16+ad]=ae.toString(16)+ad.toString(16)}}function B(){return[[1,0,0],[0,1,0],[0,0,1]]}function J(p,m){var j=B();for(var i=0;i<3;i++){for(var ah=0;ah<3;ah++){var Z=0;for(var ag=0;ag<3;ag++){Z+=p[i][ag]*m[ag][ah]}j[i][ah]=Z}}return j}function v(j,i){i.fillStyle=j.fillStyle;i.lineCap=j.lineCap;i.lineJoin=j.lineJoin;i.lineWidth=j.lineWidth;i.miterLimit=j.miterLimit;i.shadowBlur=j.shadowBlur;i.shadowColor=j.shadowColor;i.shadowOffsetX=j.shadowOffsetX;i.shadowOffsetY=j.shadowOffsetY;i.strokeStyle=j.strokeStyle;i.globalAlpha=j.globalAlpha;i.font=j.font;i.textAlign=j.textAlign;i.textBaseline=j.textBaseline;i.arcScaleX_=j.arcScaleX_;i.arcScaleY_=j.arcScaleY_;i.lineScale_=j.lineScale_}var b={aliceblue:"#F0F8FF",antiquewhite:"#FAEBD7",aquamarine:"#7FFFD4",azure:"#F0FFFF",beige:"#F5F5DC",bisque:"#FFE4C4",black:"#000000",blanchedalmond:"#FFEBCD",blueviolet:"#8A2BE2",brown:"#A52A2A",burlywood:"#DEB887",cadetblue:"#5F9EA0",chartreuse:"#7FFF00",chocolate:"#D2691E",coral:"#FF7F50",cornflowerblue:"#6495ED",cornsilk:"#FFF8DC",crimson:"#DC143C",cyan:"#00FFFF",darkblue:"#00008B",darkcyan:"#008B8B",darkgoldenrod:"#B8860B",darkgray:"#A9A9A9",darkgreen:"#006400",darkgrey:"#A9A9A9",darkkhaki:"#BDB76B",darkmagenta:"#8B008B",darkolivegreen:"#556B2F",darkorange:"#FF8C00",darkorchid:"#9932CC",darkred:"#8B0000",darksalmon:"#E9967A",darkseagreen:"#8FBC8F",darkslateblue:"#483D8B",darkslategray:"#2F4F4F",darkslategrey:"#2F4F4F",darkturquoise:"#00CED1",darkviolet:"#9400D3",deeppink:"#FF1493",deepskyblue:"#00BFFF",dimgray:"#696969",dimgrey:"#696969",dodgerblue:"#1E90FF",firebrick:"#B22222",floralwhite:"#FFFAF0",forestgreen:"#228B22",gainsboro:"#DCDCDC",ghostwhite:"#F8F8FF",gold:"#FFD700",goldenrod:"#DAA520",grey:"#808080",greenyellow:"#ADFF2F",honeydew:"#F0FFF0",hotpink:"#FF69B4",indianred:"#CD5C5C",indigo:"#4B0082",ivory:"#FFFFF0",khaki:"#F0E68C",lavender:"#E6E6FA",lavenderblush:"#FFF0F5",lawngreen:"#7CFC00",lemonchiffon:"#FFFACD",lightblue:"#ADD8E6",lightcoral:"#F08080",lightcyan:"#E0FFFF",lightgoldenrodyellow:"#FAFAD2",lightgreen:"#90EE90",lightgrey:"#D3D3D3",lightpink:"#FFB6C1",lightsalmon:"#FFA07A",lightseagreen:"#20B2AA",lightskyblue:"#87CEFA",lightslategray:"#778899",lightslategrey:"#778899",lightsteelblue:"#B0C4DE",lightyellow:"#FFFFE0",limegreen:"#32CD32",linen:"#FAF0E6",magenta:"#FF00FF",mediumaquamarine:"#66CDAA",mediumblue:"#0000CD",mediumorchid:"#BA55D3",mediumpurple:"#9370DB",mediumseagreen:"#3CB371",mediumslateblue:"#7B68EE",mediumspringgreen:"#00FA9A",mediumturquoise:"#48D1CC",mediumvioletred:"#C71585",midnightblue:"#191970",mintcream:"#F5FFFA",mistyrose:"#FFE4E1",moccasin:"#FFE4B5",navajowhite:"#FFDEAD",oldlace:"#FDF5E6",olivedrab:"#6B8E23",orange:"#FFA500",orangered:"#FF4500",orchid:"#DA70D6",palegoldenrod:"#EEE8AA",palegreen:"#98FB98",paleturquoise:"#AFEEEE",palevioletred:"#DB7093",papayawhip:"#FFEFD5",peachpuff:"#FFDAB9",peru:"#CD853F",pink:"#FFC0CB",plum:"#DDA0DD",powderblue:"#B0E0E6",rosybrown:"#BC8F8F",royalblue:"#4169E1",saddlebrown:"#8B4513",salmon:"#FA8072",sandybrown:"#F4A460",seagreen:"#2E8B57",seashell:"#FFF5EE",sienna:"#A0522D",skyblue:"#87CEEB",slateblue:"#6A5ACD",slategray:"#708090",slategrey:"#708090",snow:"#FFFAFA",springgreen:"#00FF7F",steelblue:"#4682B4",tan:"#D2B48C",thistle:"#D8BFD8",tomato:"#FF6347",turquoise:"#40E0D0",violet:"#EE82EE",wheat:"#F5DEB3",whitesmoke:"#F5F5F5",yellowgreen:"#9ACD32"};function M(j){var p=j.indexOf("(",3);var i=j.indexOf(")",p+1);var m=j.substring(p+1,i).split(",");if(m.length!=4||j.charAt(3)!="a"){m[3]=1}return m}function c(i){return parseFloat(i)/100}function r(j,m,i){return Math.min(i,Math.max(m,j))}function I(ag){var i,ai,aj,ah,ak,Z;ah=parseFloat(ag[0])/360%360;if(ah<0){ah++}ak=r(c(ag[1]),0,1);Z=r(c(ag[2]),0,1);if(ak==0){i=ai=aj=Z}else{var j=Z<0.5?Z*(1+ak):Z+ak-Z*ak;var m=2*Z-j;i=a(m,j,ah+1/3);ai=a(m,j,ah);aj=a(m,j,ah-1/3)}return"#"+k[Math.floor(i*255)]+k[Math.floor(ai*255)]+k[Math.floor(aj*255)]}function a(j,i,m){if(m<0){m++}if(m>1){m--}if(6*m<1){return j+(i-j)*6*m}else{if(2*m<1){return i}else{if(3*m<2){return j+(i-j)*(2/3-m)*6}else{return j}}}}var C={};function F(j){if(j in C){return C[j]}var ag,Z=1;j=String(j);if(j.charAt(0)=="#"){ag=j}else{if(/^rgb/.test(j)){var p=M(j);var ag="#",ah;for(var m=0;m<3;m++){if(p[m].indexOf("%")!=-1){ah=Math.floor(c(p[m])*255)}else{ah=+p[m]}ag+=k[r(ah,0,255)]}Z=+p[3]}else{if(/^hsl/.test(j)){var p=M(j);ag=I(p);Z=p[3]}else{ag=b[j]||j}}}return C[j]={color:ag,alpha:Z}}var o={style:"normal",variant:"normal",weight:"normal",size:10,family:"sans-serif"};var L={};function E(i){if(L[i]){return L[i]}var p=document.createElement("div");var m=p.style;try{m.font=i}catch(j){}return L[i]={style:m.fontStyle||o.style,variant:m.fontVariant||o.variant,weight:m.fontWeight||o.weight,size:m.fontSize||o.size,family:m.fontFamily||o.family}}function u(m,j){var i={};for(var ah in m){i[ah]=m[ah]}var ag=parseFloat(j.currentStyle.fontSize),Z=parseFloat(m.size);if(typeof m.size=="number"){i.size=m.size}else{if(m.size.indexOf("px")!=-1){i.size=Z}else{if(m.size.indexOf("em")!=-1){i.size=ag*Z}else{if(m.size.indexOf("%")!=-1){i.size=(ag/100)*Z}else{if(m.size.indexOf("pt")!=-1){i.size=Z/0.75}else{i.size=ag}}}}}i.size*=0.981;return i}function ac(i){return i.style+" "+i.variant+" "+i.weight+" "+i.size+"px "+i.family}var s={butt:"flat",round:"round"};function S(i){return s[i]||"square"}function D(i){this.m_=B();this.mStack_=[];this.aStack_=[];this.currentPath_=[];this.strokeStyle="#000";this.fillStyle="#000";this.lineWidth=1;this.lineJoin="miter";this.lineCap="butt";this.miterLimit=d*1;this.globalAlpha=1;this.font="10px sans-serif";this.textAlign="left";this.textBaseline="alphabetic";this.canvas=i;var m="width:"+i.clientWidth+"px;height:"+i.clientHeight+"px;overflow:hidden;position:absolute";var j=i.ownerDocument.createElement("div");j.style.cssText=m;i.appendChild(j);var p=j.cloneNode(false);p.style.backgroundColor="red";p.style.filter="alpha(opacity=0)";i.appendChild(p);this.element_=j;this.arcScaleX_=1;this.arcScaleY_=1;this.lineScale_=1}var q=D.prototype;q.clearRect=function(){if(this.textMeasureEl_){this.textMeasureEl_.removeNode(true);this.textMeasureEl_=null}this.element_.innerHTML=""};q.beginPath=function(){this.currentPath_=[]};q.moveTo=function(j,i){var m=V(this,j,i);this.currentPath_.push({type:"moveTo",x:m.x,y:m.y});this.currentX_=m.x;this.currentY_=m.y};q.lineTo=function(j,i){var m=V(this,j,i);this.currentPath_.push({type:"lineTo",x:m.x,y:m.y});this.currentX_=m.x;this.currentY_=m.y};q.bezierCurveTo=function(m,j,ak,aj,ai,ag){var i=V(this,ai,ag);var ah=V(this,m,j);var Z=V(this,ak,aj);K(this,ah,Z,i)};function K(i,Z,m,j){i.currentPath_.push({type:"bezierCurveTo",cp1x:Z.x,cp1y:Z.y,cp2x:m.x,cp2y:m.y,x:j.x,y:j.y});i.currentX_=j.x;i.currentY_=j.y}q.quadraticCurveTo=function(ai,m,j,i){var ah=V(this,ai,m);var ag=V(this,j,i);var aj={x:this.currentX_+2/3*(ah.x-this.currentX_),y:this.currentY_+2/3*(ah.y-this.currentY_)};var Z={x:aj.x+(ag.x-this.currentX_)/3,y:aj.y+(ag.y-this.currentY_)/3};K(this,aj,Z,ag)};q.arc=function(al,aj,ak,ag,j,m){ak*=d;var ap=m?"at":"wa";var am=al+A(ag)*ak-f;var ao=aj+l(ag)*ak-f;var i=al+A(j)*ak-f;var an=aj+l(j)*ak-f;if(am==i&&!m){am+=0.125}var Z=V(this,al,aj);var ai=V(this,am,ao);var ah=V(this,i,an);this.currentPath_.push({type:ap,x:Z.x,y:Z.y,radius:ak,xStart:ai.x,yStart:ai.y,xEnd:ah.x,yEnd:ah.y})};q.rect=function(m,j,i,p){this.moveTo(m,j);this.lineTo(m+i,j);this.lineTo(m+i,j+p);this.lineTo(m,j+p);this.closePath()};q.strokeRect=function(m,j,i,p){var Z=this.currentPath_;this.beginPath();this.moveTo(m,j);this.lineTo(m+i,j);this.lineTo(m+i,j+p);this.lineTo(m,j+p);this.closePath();this.stroke();this.currentPath_=Z};q.fillRect=function(m,j,i,p){var Z=this.currentPath_;this.beginPath();this.moveTo(m,j);this.lineTo(m+i,j);this.lineTo(m+i,j+p);this.lineTo(m,j+p);this.closePath();this.fill();this.currentPath_=Z};q.createLinearGradient=function(j,p,i,m){var Z=new U("gradient");Z.x0_=j;Z.y0_=p;Z.x1_=i;Z.y1_=m;return Z};q.createRadialGradient=function(p,ag,m,j,Z,i){var ah=new U("gradientradial");ah.x0_=p;ah.y0_=ag;ah.r0_=m;ah.x1_=j;ah.y1_=Z;ah.r1_=i;return ah};q.drawImage=function(aq,m){var aj,ah,al,ay,ao,am,at,aA;var ak=aq.runtimeStyle.width;var ap=aq.runtimeStyle.height;aq.runtimeStyle.width="auto";aq.runtimeStyle.height="auto";var ai=aq.width;var aw=aq.height;aq.runtimeStyle.width=ak;aq.runtimeStyle.height=ap;if(arguments.length==3){aj=arguments[1];ah=arguments[2];ao=am=0;at=al=ai;aA=ay=aw}else{if(arguments.length==5){aj=arguments[1];ah=arguments[2];al=arguments[3];ay=arguments[4];ao=am=0;at=ai;aA=aw}else{if(arguments.length==9){ao=arguments[1];am=arguments[2];at=arguments[3];aA=arguments[4];aj=arguments[5];ah=arguments[6];al=arguments[7];ay=arguments[8]}else{throw Error("Invalid number of arguments")}}}var az=V(this,aj,ah);var p=at/2;var j=aA/2;var ax=[];var i=10;var ag=10;ax.push(" <g_vml_:group",' coordsize="',d*i,",",d*ag,'"',' coordorigin="0,0"',' style="width:',i,"px;height:",ag,"px;position:absolute;");if(this.m_[0][0]!=1||this.m_[0][1]||this.m_[1][1]!=1||this.m_[1][0]){var Z=[];Z.push("M11=",this.m_[0][0],",","M12=",this.m_[1][0],",","M21=",this.m_[0][1],",","M22=",this.m_[1][1],",","Dx=",n(az.x/d),",","Dy=",n(az.y/d),"");var av=az;var au=V(this,aj+al,ah);var ar=V(this,aj,ah+ay);var an=V(this,aj+al,ah+ay);av.x=ab.max(av.x,au.x,ar.x,an.x);av.y=ab.max(av.y,au.y,ar.y,an.y);ax.push("padding:0 ",n(av.x/d),"px ",n(av.y/d),"px 0;filter:progid:DXImageTransform.Microsoft.Matrix(",Z.join(""),", sizingmethod='clip');")}else{ax.push("top:",n(az.y/d),"px;left:",n(az.x/d),"px;")}ax.push(' ">','<g_vml_:image src="',aq.src,'"',' style="width:',d*al,"px;"," height:",d*ay,'px"',' cropleft="',ao/ai,'"',' croptop="',am/aw,'"',' cropright="',(ai-ao-at)/ai,'"',' cropbottom="',(aw-am-aA)/aw,'"'," />","</g_vml_:group>");this.element_.insertAdjacentHTML("BeforeEnd",ax.join(""))};q.stroke=function(ao){var Z=10;var ap=10;var ag=5000;var ai={x:null,y:null};var an={x:null,y:null};for(var aj=0;aj<this.currentPath_.length;aj+=ag){var am=[];var ah=false;am.push("<g_vml_:shape",' filled="',!!ao,'"',' style="position:absolute;width:',Z,"px;height:",ap,'px;"',' coordorigin="0,0"',' coordsize="',d*Z,",",d*ap,'"',' stroked="',!ao,'"',' path="');var aq=false;for(var ak=aj;ak<Math.min(aj+ag,this.currentPath_.length);ak++){if(ak%ag==0&&ak>0){am.push(" m ",n(this.currentPath_[ak-1].x),",",n(this.currentPath_[ak-1].y))}var m=this.currentPath_[ak];var al;switch(m.type){case"moveTo":al=m;am.push(" m ",n(m.x),",",n(m.y));break;case"lineTo":am.push(" l ",n(m.x),",",n(m.y));break;case"close":am.push(" x ");m=null;break;case"bezierCurveTo":am.push(" c ",n(m.cp1x),",",n(m.cp1y),",",n(m.cp2x),",",n(m.cp2y),",",n(m.x),",",n(m.y));break;case"at":case"wa":am.push(" ",m.type," ",n(m.x-this.arcScaleX_*m.radius),",",n(m.y-this.arcScaleY_*m.radius)," ",n(m.x+this.arcScaleX_*m.radius),",",n(m.y+this.arcScaleY_*m.radius)," ",n(m.xStart),",",n(m.yStart)," ",n(m.xEnd),",",n(m.yEnd));break}if(m){if(ai.x==null||m.x<ai.x){ai.x=m.x}if(an.x==null||m.x>an.x){an.x=m.x}if(ai.y==null||m.y<ai.y){ai.y=m.y}if(an.y==null||m.y>an.y){an.y=m.y}}}am.push(' ">');if(!ao){w(this,am)}else{G(this,am,ai,an)}am.push("</g_vml_:shape>");this.element_.insertAdjacentHTML("beforeEnd",am.join(""))}};function w(m,ag){var j=F(m.strokeStyle);var p=j.color;var Z=j.alpha*m.globalAlpha;var i=m.lineScale_*m.lineWidth;if(i<1){Z*=i}ag.push("<g_vml_:stroke",' opacity="',Z,'"',' joinstyle="',m.lineJoin,'"',' miterlimit="',m.miterLimit,'"',' endcap="',S(m.lineCap),'"',' weight="',i,'px"',' color="',p,'" />')}function G(aq,ai,aK,ar){var aj=aq.fillStyle;var aB=aq.arcScaleX_;var aA=aq.arcScaleY_;var j=ar.x-aK.x;var p=ar.y-aK.y;if(aj instanceof U){var an=0;var aF={x:0,y:0};var ax=0;var am=1;if(aj.type_=="gradient"){var al=aj.x0_/aB;var m=aj.y0_/aA;var ak=aj.x1_/aB;var aM=aj.y1_/aA;var aJ=V(aq,al,m);var aI=V(aq,ak,aM);var ag=aI.x-aJ.x;var Z=aI.y-aJ.y;an=Math.atan2(ag,Z)*180/Math.PI;if(an<0){an+=360}if(an<0.000001){an=0}}else{var aJ=V(aq,aj.x0_,aj.y0_);aF={x:(aJ.x-aK.x)/j,y:(aJ.y-aK.y)/p};j/=aB*d;p/=aA*d;var aD=ab.max(j,p);ax=2*aj.r0_/aD;am=2*aj.r1_/aD-ax}var av=aj.colors_;av.sort(function(aN,i){return aN.offset-i.offset});var ap=av.length;var au=av[0].color;var at=av[ap-1].color;var az=av[0].alpha*aq.globalAlpha;var ay=av[ap-1].alpha*aq.globalAlpha;var aE=[];for(var aH=0;aH<ap;aH++){var ao=av[aH];aE.push(ao.offset*am+ax+" "+ao.color)}ai.push('<g_vml_:fill type="',aj.type_,'"',' method="none" focus="100%"',' color="',au,'"',' color2="',at,'"',' colors="',aE.join(","),'"',' opacity="',ay,'"',' g_o_:opacity2="',az,'"',' angle="',an,'"',' focusposition="',aF.x,",",aF.y,'" />')}else{if(aj instanceof T){if(j&&p){var ah=-aK.x;var aC=-aK.y;ai.push("<g_vml_:fill",' position="',ah/j*aB*aB,",",aC/p*aA*aA,'"',' type="tile"',' src="',aj.src_,'" />')}}else{var aL=F(aq.fillStyle);var aw=aL.color;var aG=aL.alpha*aq.globalAlpha;ai.push('<g_vml_:fill color="',aw,'" opacity="',aG,'" />')}}}q.fill=function(){this.stroke(true)};q.closePath=function(){this.currentPath_.push({type:"close"})};function V(j,Z,p){var i=j.m_;return{x:d*(Z*i[0][0]+p*i[1][0]+i[2][0])-f,y:d*(Z*i[0][1]+p*i[1][1]+i[2][1])-f}}q.save=function(){var i={};v(this,i);this.aStack_.push(i);this.mStack_.push(this.m_);this.m_=J(B(),this.m_)};q.restore=function(){if(this.aStack_.length){v(this.aStack_.pop(),this);this.m_=this.mStack_.pop()}};function h(i){return isFinite(i[0][0])&&isFinite(i[0][1])&&isFinite(i[1][0])&&isFinite(i[1][1])&&isFinite(i[2][0])&&isFinite(i[2][1])}function aa(j,i,p){if(!h(i)){return}j.m_=i;if(p){var Z=i[0][0]*i[1][1]-i[0][1]*i[1][0];j.lineScale_=N(H(Z))}}q.translate=function(m,j){var i=[[1,0,0],[0,1,0],[m,j,1]];aa(this,J(i,this.m_),false)};q.rotate=function(j){var p=A(j);var m=l(j);var i=[[p,m,0],[-m,p,0],[0,0,1]];aa(this,J(i,this.m_),false)};q.scale=function(m,j){this.arcScaleX_*=m;this.arcScaleY_*=j;var i=[[m,0,0],[0,j,0],[0,0,1]];aa(this,J(i,this.m_),true)};q.transform=function(Z,p,ah,ag,j,i){var m=[[Z,p,0],[ah,ag,0],[j,i,1]];aa(this,J(m,this.m_),true)};q.setTransform=function(ag,Z,ai,ah,p,j){var i=[[ag,Z,0],[ai,ah,0],[p,j,1]];aa(this,i,true)};q.drawText_=function(am,ak,aj,ap,ai){var ao=this.m_,at=1000,j=0,ar=at,ah={x:0,y:0},ag=[];var i=u(E(this.font),this.element_);var p=ac(i);var au=this.element_.currentStyle;var Z=this.textAlign.toLowerCase();switch(Z){case"left":case"center":case"right":break;case"end":Z=au.direction=="ltr"?"right":"left";break;case"start":Z=au.direction=="rtl"?"right":"left";break;default:Z="left"}switch(this.textBaseline){case"hanging":case"top":ah.y=i.size/1.75;break;case"middle":break;default:case null:case"alphabetic":case"ideographic":case"bottom":ah.y=-i.size/2.25;break}switch(Z){case"right":j=at;ar=0.05;break;case"center":j=ar=at/2;break}var aq=V(this,ak+ah.x,aj+ah.y);ag.push('<g_vml_:line from="',-j,' 0" to="',ar,' 0.05" ',' coordsize="100 100" coordorigin="0 0"',' filled="',!ai,'" stroked="',!!ai,'" style="position:absolute;width:1px;height:1px;">');if(ai){w(this,ag)}else{G(this,ag,{x:-j,y:0},{x:ar,y:i.size})}var an=ao[0][0].toFixed(3)+","+ao[1][0].toFixed(3)+","+ao[0][1].toFixed(3)+","+ao[1][1].toFixed(3)+",0,0";var al=n(aq.x/d)+","+n(aq.y/d);ag.push('<g_vml_:skew on="t" matrix="',an,'" ',' offset="',al,'" origin="',j,' 0" />','<g_vml_:path textpathok="true" />','<g_vml_:textpath on="true" string="',af(am),'" style="v-text-align:',Z,";font:",af(p),'" /></g_vml_:line>');this.element_.insertAdjacentHTML("beforeEnd",ag.join(""))};q.fillText=function(m,i,p,j){this.drawText_(m,i,p,j,false)};q.strokeText=function(m,i,p,j){this.drawText_(m,i,p,j,true)};q.measureText=function(m){if(!this.textMeasureEl_){var i='<span style="position:absolute;top:-20000px;left:0;padding:0;margin:0;border:none;white-space:pre;"></span>';this.element_.insertAdjacentHTML("beforeEnd",i);this.textMeasureEl_=this.element_.lastChild}var j=this.element_.ownerDocument;this.textMeasureEl_.innerHTML="";this.textMeasureEl_.style.font=this.font;this.textMeasureEl_.appendChild(j.createTextNode(m));return{width:this.textMeasureEl_.offsetWidth}};q.clip=function(){};q.arcTo=function(){};q.createPattern=function(j,i){return new T(j,i)};function U(i){this.type_=i;this.x0_=0;this.y0_=0;this.r0_=0;this.x1_=0;this.y1_=0;this.r1_=0;this.colors_=[]}U.prototype.addColorStop=function(j,i){i=F(i);this.colors_.push({offset:j,color:i.color,alpha:i.alpha})};function T(j,i){Q(j);switch(i){case"repeat":case null:case"":this.repetition_="repeat";break;case"repeat-x":case"repeat-y":case"no-repeat":this.repetition_=i;break;default:O("SYNTAX_ERR")}this.src_=j.src;this.width_=j.width;this.height_=j.height}function O(i){throw new P(i)}function Q(i){if(!i||i.nodeType!=1||i.tagName!="IMG"){O("TYPE_MISMATCH_ERR")}if(i.readyState!="complete"){O("INVALID_STATE_ERR")}}function P(i){this.code=this[i];this.message=i+": DOM Exception "+this.code}var X=P.prototype=new Error;X.INDEX_SIZE_ERR=1;X.DOMSTRING_SIZE_ERR=2;X.HIERARCHY_REQUEST_ERR=3;X.WRONG_DOCUMENT_ERR=4;X.INVALID_CHARACTER_ERR=5;X.NO_DATA_ALLOWED_ERR=6;X.NO_MODIFICATION_ALLOWED_ERR=7;X.NOT_FOUND_ERR=8;X.NOT_SUPPORTED_ERR=9;X.INUSE_ATTRIBUTE_ERR=10;X.INVALID_STATE_ERR=11;X.SYNTAX_ERR=12;X.INVALID_MODIFICATION_ERR=13;X.NAMESPACE_ERR=14;X.INVALID_ACCESS_ERR=15;X.VALIDATION_ERR=16;X.TYPE_MISMATCH_ERR=17;G_vmlCanvasManager=e;CanvasRenderingContext2D=D;CanvasGradient=U;CanvasPattern=T;DOMException=P})()};
0 2 \ No newline at end of file
... ...
src/main/resources/static/assets/plugins/jqPaginator.min.js 0 → 100644
  1 +++ a/src/main/resources/static/assets/plugins/jqPaginator.min.js
  1 +/*! jqPaginator-1.2.0
  2 + * http://jqPaginator.keenwon.com
  3 + */
  4 +!function(a){"use strict";a.jqPaginator=function(b,c){if(!(this instanceof a.jqPaginator))return new a.jqPaginator(b,c);var d=this;return d.$container=a(b),d.$container.data("jqPaginator",d),d.init=function(){(c.first||c.prev||c.next||c.last||c.page)&&(c=a.extend({},{first:"",prev:"",next:"",last:"",page:""},c)),d.options=a.extend({},a.jqPaginator.defaultOptions,c),d.verify(),d.extendJquery(),d.render(),d.fireEvent(this.options.currentPage,"init")},d.verify=function(){var a=d.options;if(!d.isNumber(a.totalPages))throw new Error("[jqPaginator] type error: totalPages");if(!d.isNumber(a.totalCounts))throw new Error("[jqPaginator] type error: totalCounts");if(!d.isNumber(a.pageSize))throw new Error("[jqPaginator] type error: pageSize");if(!d.isNumber(a.currentPage))throw new Error("[jqPaginator] type error: currentPage");if(!d.isNumber(a.visiblePages))throw new Error("[jqPaginator] type error: visiblePages");if(!a.totalPages&&!a.totalCounts)throw new Error("[jqPaginator] totalCounts or totalPages is required");if(!a.totalPages&&!a.totalCounts)throw new Error("[jqPaginator] totalCounts or totalPages is required");if(!a.totalPages&&a.totalCounts&&!a.pageSize)throw new Error("[jqPaginator] pageSize is required");if(a.totalCounts&&a.pageSize&&(a.totalPages=Math.ceil(a.totalCounts/a.pageSize)),a.currentPage<1||a.currentPage>a.totalPages)throw new Error("[jqPaginator] currentPage is incorrect");if(a.totalPages<1)throw new Error("[jqPaginator] totalPages cannot be less currentPage")},d.extendJquery=function(){a.fn.jqPaginatorHTML=function(b){return b?this.before(b).remove():a("<p>").append(this.eq(0).clone()).html()}},d.render=function(){d.renderHtml(),d.setStatus(),d.bindEvents()},d.renderHtml=function(){for(var b=[],c=d.getPages(),e=0,f=c.length;f>e;e++)b.push(d.buildItem("page",c[e]));d.isEnable("prev")&&b.unshift(d.buildItem("prev",d.options.currentPage-1)),d.isEnable("first")&&b.unshift(d.buildItem("first",1)),d.isEnable("statistics")&&b.unshift(d.buildItem("statistics")),d.isEnable("next")&&b.push(d.buildItem("next",d.options.currentPage+1)),d.isEnable("last")&&b.push(d.buildItem("last",d.options.totalPages)),d.$container.html(d.options.wrapper?a(d.options.wrapper).html(b.join("")).jqPaginatorHTML():b.join(""))},d.buildItem=function(b,c){var e=d.options[b].replace(/{{page}}/g,c).replace(/{{totalPages}}/g,d.options.totalPages).replace(/{{totalCounts}}/g,d.options.totalCounts);return a(e).attr({"jp-role":b,"jp-data":c}).jqPaginatorHTML()},d.setStatus=function(){var b=d.options;d.isEnable("first")&&1!==b.currentPage||a("[jp-role=first]",d.$container).addClass(b.disableClass),d.isEnable("prev")&&1!==b.currentPage||a("[jp-role=prev]",d.$container).addClass(b.disableClass),(!d.isEnable("next")||b.currentPage>=b.totalPages)&&a("[jp-role=next]",d.$container).addClass(b.disableClass),(!d.isEnable("last")||b.currentPage>=b.totalPages)&&a("[jp-role=last]",d.$container).addClass(b.disableClass),a("[jp-role=page]",d.$container).removeClass(b.activeClass),a("[jp-role=page][jp-data="+b.currentPage+"]",d.$container).addClass(b.activeClass)},d.getPages=function(){var a=[],b=d.options.visiblePages,c=d.options.currentPage,e=d.options.totalPages;b>e&&(b=e);var f=Math.floor(b/2),g=c-f+1-b%2,h=c+f;1>g&&(g=1,h=b),h>e&&(h=e,g=1+e-b);for(var i=g;h>=i;)a.push(i),i++;return a},d.isNumber=function(a){var b=typeof a;return"number"===b||"undefined"===b},d.isEnable=function(a){return d.options[a]&&"string"==typeof d.options[a]},d.switchPage=function(a){d.options.currentPage=a,d.render()},d.fireEvent=function(a,b){return"function"!=typeof d.options.onPageChange||d.options.onPageChange(a,b)!==!1},d.callMethod=function(b,c){switch(b){case"option":d.options=a.extend({},d.options,c),d.verify(),d.render();break;case"destroy":d.$container.empty(),d.$container.removeData("jqPaginator");break;default:throw new Error('[jqPaginator] method "'+b+'" does not exist')}return d.$container},d.bindEvents=function(){var b=d.options;d.$container.off(),d.$container.on("click","[jp-role]",function(){var c=a(this);if(!c.hasClass(b.disableClass)&&!c.hasClass(b.activeClass)){var e=+c.attr("jp-data");d.fireEvent(e,"change")&&d.switchPage(e)}})},d.init(),d.$container},a.jqPaginator.defaultOptions={wrapper:"",first:'<li class="first"><a href="javascript:;">First</a></li>',prev:'<li class="prev"><a href="javascript:;">Previous</a></li>',next:'<li class="next"><a href="javascript:;">Next</a></li>',last:'<li class="last"><a href="javascript:;">Last</a></li>',page:'<li class="page"><a href="javascript:;">{{page}}</a></li>',totalPages:0,totalCounts:0,pageSize:0,currentPage:1,visiblePages:7,disableClass:"disabled",activeClass:"active",onPageChange:null},a.fn.jqPaginator=function(){var b=this,c=Array.prototype.slice.call(arguments);if("string"==typeof c[0]){var d=a(b).data("jqPaginator");if(d)return d.callMethod(c[0],c[1]);throw new Error("[jqPaginator] the element is not instantiated")}return new a.jqPaginator(this,c[0])}}(jQuery);
0 5 \ No newline at end of file
... ...
src/main/resources/static/assets/plugins/jquery.pjax.js 0 → 100644
  1 +++ a/src/main/resources/static/assets/plugins/jquery.pjax.js
  1 +/*!
  2 + * Copyright 2012, Chris Wanstrath
  3 + * Released under the MIT License
  4 + * https://github.com/defunkt/jquery-pjax
  5 + */
  6 +
  7 +(function($){
  8 +
  9 +// When called on a container with a selector, fetches the href with
  10 +// ajax into the container or with the data-pjax attribute on the link
  11 +// itself.
  12 +//
  13 +// Tries to make sure the back button and ctrl+click work the way
  14 +// you'd expect.
  15 +//
  16 +// Exported as $.fn.pjax
  17 +//
  18 +// Accepts a jQuery ajax options object that may include these
  19 +// pjax specific options:
  20 +//
  21 +//
  22 +// container - Where to stick the response body. Usually a String selector.
  23 +// $(container).html(xhr.responseBody)
  24 +// (default: current jquery context)
  25 +// push - Whether to pushState the URL. Defaults to true (of course).
  26 +// replace - Want to use replaceState instead? That's cool.
  27 +//
  28 +// For convenience the second parameter can be either the container or
  29 +// the options object.
  30 +//
  31 +// Returns the jQuery object
  32 +function fnPjax(selector, container, options) {
  33 + var context = this
  34 + return this.on('click.pjax', selector, function(event) {
  35 + var opts = $.extend({}, optionsFor(container, options))
  36 + if (!opts.container)
  37 + opts.container = $(this).attr('data-pjax') || context
  38 + handleClick(event, opts)
  39 + })
  40 +}
  41 +
  42 +// Public: pjax on click handler
  43 +//
  44 +// Exported as $.pjax.click.
  45 +//
  46 +// event - "click" jQuery.Event
  47 +// options - pjax options
  48 +//
  49 +// Examples
  50 +//
  51 +// $(document).on('click', 'a', $.pjax.click)
  52 +// // is the same as
  53 +// $(document).pjax('a')
  54 +//
  55 +// $(document).on('click', 'a', function(event) {
  56 +// var container = $(this).closest('[data-pjax-container]')
  57 +// $.pjax.click(event, container)
  58 +// })
  59 +//
  60 +// Returns nothing.
  61 +function handleClick(event, container, options) {
  62 + options = optionsFor(container, options)
  63 +
  64 + var link = event.currentTarget
  65 +
  66 + if (link.tagName.toUpperCase() !== 'A')
  67 + throw "$.fn.pjax or $.pjax.click requires an anchor element"
  68 +
  69 + // Middle click, cmd click, and ctrl click should open
  70 + // links in a new tab as normal.
  71 + if ( event.which > 1 || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey )
  72 + return
  73 +
  74 + // Ignore cross origin links
  75 + if ( location.protocol !== link.protocol || location.hostname !== link.hostname )
  76 + return
  77 +
  78 + // Ignore case when a hash is being tacked on the current URL
  79 + if ( link.href.indexOf('#') > -1 && stripHash(link) == stripHash(location) )
  80 + return
  81 +
  82 + // Ignore event with default prevented
  83 + if (event.isDefaultPrevented())
  84 + return
  85 +
  86 + var defaults = {
  87 + url: link.href,
  88 + container: $(link).attr('data-pjax'),
  89 + target: link
  90 + }
  91 +
  92 + var opts = $.extend({}, defaults, options)
  93 + var clickEvent = $.Event('pjax:click')
  94 + $(link).trigger(clickEvent, [opts])
  95 +
  96 + if (!clickEvent.isDefaultPrevented()) {
  97 + pjax(opts)
  98 + event.preventDefault()
  99 + $(link).trigger('pjax:clicked', [opts])
  100 + }
  101 +}
  102 +
  103 +// Public: pjax on form submit handler
  104 +//
  105 +// Exported as $.pjax.submit
  106 +//
  107 +// event - "click" jQuery.Event
  108 +// options - pjax options
  109 +//
  110 +// Examples
  111 +//
  112 +// $(document).on('submit', 'form', function(event) {
  113 +// var container = $(this).closest('[data-pjax-container]')
  114 +// $.pjax.submit(event, container)
  115 +// })
  116 +//
  117 +// Returns nothing.
  118 +function handleSubmit(event, container, options) {
  119 + options = optionsFor(container, options)
  120 +
  121 + var form = event.currentTarget
  122 +
  123 + if (form.tagName.toUpperCase() !== 'FORM')
  124 + throw "$.pjax.submit requires a form element"
  125 +
  126 + var defaults = {
  127 + type: form.method.toUpperCase(),
  128 + url: form.action,
  129 + container: $(form).attr('data-pjax'),
  130 + target: form
  131 + }
  132 +
  133 + if (defaults.type !== 'GET' && window.FormData !== undefined) {
  134 + defaults.data = new FormData(form);
  135 + defaults.processData = false;
  136 + defaults.contentType = false;
  137 + } else {
  138 + // Can't handle file uploads, exit
  139 + if ($(form).find(':file').length) {
  140 + return;
  141 + }
  142 +
  143 + // Fallback to manually serializing the fields
  144 + defaults.data = $(form).serializeArray();
  145 + }
  146 +
  147 + pjax($.extend({}, defaults, options))
  148 +
  149 + event.preventDefault()
  150 +}
  151 +
  152 +// Loads a URL with ajax, puts the response body inside a container,
  153 +// then pushState()'s the loaded URL.
  154 +//
  155 +// Works just like $.ajax in that it accepts a jQuery ajax
  156 +// settings object (with keys like url, type, data, etc).
  157 +//
  158 +// Accepts these extra keys:
  159 +//
  160 +// container - Where to stick the response body.
  161 +// $(container).html(xhr.responseBody)
  162 +// push - Whether to pushState the URL. Defaults to true (of course).
  163 +// replace - Want to use replaceState instead? That's cool.
  164 +//
  165 +// Use it just like $.ajax:
  166 +//
  167 +// var xhr = $.pjax({ url: this.href, container: '#main' })
  168 +// console.log( xhr.readyState )
  169 +//
  170 +// Returns whatever $.ajax returns.
  171 +function pjax(options) {
  172 + options = $.extend(true, {}, $.ajaxSettings, pjax.defaults, options)
  173 +
  174 + if ($.isFunction(options.url)) {
  175 + options.url = options.url()
  176 + }
  177 +
  178 + var target = options.target
  179 +
  180 + var hash = parseURL(options.url).hash
  181 +
  182 + var context = options.context = findContainerFor(options.container)
  183 +
  184 + // We want the browser to maintain two separate internal caches: one
  185 + // for pjax'd partial page loads and one for normal page loads.
  186 + // Without adding this secret parameter, some browsers will often
  187 + // confuse the two.
  188 + if (!options.data) options.data = {}
  189 + if ($.isArray(options.data)) {
  190 + options.data.push({name: '_pjax', value: context.selector})
  191 + } else {
  192 + options.data._pjax = context.selector
  193 + }
  194 +
  195 + function fire(type, args, props) {
  196 + if (!props) props = {}
  197 + props.relatedTarget = target
  198 + var event = $.Event(type, props)
  199 + context.trigger(event, args)
  200 + return !event.isDefaultPrevented()
  201 + }
  202 +
  203 + var timeoutTimer
  204 +
  205 + options.beforeSend = function(xhr, settings) {
  206 + // No timeout for non-GET requests
  207 + // Its not safe to request the resource again with a fallback method.
  208 + if (settings.type !== 'GET') {
  209 + settings.timeout = 0
  210 + }
  211 +
  212 + xhr.setRequestHeader('X-PJAX', 'true')
  213 + xhr.setRequestHeader('X-PJAX-Container', context.selector)
  214 +
  215 + if (!fire('pjax:beforeSend', [xhr, settings]))
  216 + return false
  217 +
  218 + if (settings.timeout > 0) {
  219 + timeoutTimer = setTimeout(function() {
  220 + if (fire('pjax:timeout', [xhr, options]))
  221 + xhr.abort('timeout')
  222 + }, settings.timeout)
  223 +
  224 + // Clear timeout setting so jquerys internal timeout isn't invoked
  225 + settings.timeout = 0
  226 + }
  227 +
  228 + var url = parseURL(settings.url)
  229 + if (hash) url.hash = hash
  230 + options.requestUrl = stripInternalParams(url)
  231 + }
  232 +
  233 + options.complete = function(xhr, textStatus) {
  234 + if (timeoutTimer)
  235 + clearTimeout(timeoutTimer)
  236 +
  237 + fire('pjax:complete', [xhr, textStatus, options])
  238 +
  239 + fire('pjax:end', [xhr, options])
  240 + }
  241 +
  242 + options.error = function(xhr, textStatus, errorThrown) {
  243 + var container = extractContainer("", xhr, options)
  244 +
  245 + var allowed = fire('pjax:error', [xhr, textStatus, errorThrown, options])
  246 + if (options.type == 'GET' && textStatus !== 'abort' && allowed) {
  247 + locationReplace(container.url)
  248 + }
  249 + }
  250 +
  251 + options.success = function(data, status, xhr) {
  252 + var previousState = pjax.state;
  253 +
  254 + // If $.pjax.defaults.version is a function, invoke it first.
  255 + // Otherwise it can be a static string.
  256 + var currentVersion = (typeof $.pjax.defaults.version === 'function') ?
  257 + $.pjax.defaults.version() :
  258 + $.pjax.defaults.version
  259 +
  260 + var latestVersion = xhr.getResponseHeader('X-PJAX-Version')
  261 +
  262 + var container = extractContainer(data, xhr, options)
  263 +
  264 + var url = parseURL(container.url)
  265 + if (hash) {
  266 + url.hash = hash
  267 + container.url = url.href
  268 + }
  269 +
  270 + // If there is a layout version mismatch, hard load the new url
  271 + if (currentVersion && latestVersion && currentVersion !== latestVersion) {
  272 + locationReplace(container.url)
  273 + return
  274 + }
  275 +
  276 + // If the new response is missing a body, hard load the page
  277 + if (!container.contents) {
  278 + locationReplace(container.url)
  279 + return
  280 + }
  281 +
  282 + pjax.state = {
  283 + id: options.id || uniqueId(),
  284 + url: container.url,
  285 + title: container.title,
  286 + container: context.selector,
  287 + fragment: options.fragment,
  288 + timeout: options.timeout
  289 + }
  290 +
  291 + if (options.push || options.replace) {
  292 + window.history.replaceState(pjax.state, container.title, container.url)
  293 + }
  294 +
  295 + // Only blur the focus if the focused element is within the container.
  296 + var blurFocus = $.contains(options.container, document.activeElement)
  297 +
  298 + // Clear out any focused controls before inserting new page contents.
  299 + if (blurFocus) {
  300 + try {
  301 + document.activeElement.blur()
  302 + } catch (e) { }
  303 + }
  304 +
  305 + if (container.title) document.title = container.title
  306 +
  307 + fire('pjax:beforeReplace', [container.contents, options], {
  308 + state: pjax.state,
  309 + previousState: previousState
  310 + })
  311 + context.html(container.contents)
  312 +
  313 + // FF bug: Won't autofocus fields that are inserted via JS.
  314 + // This behavior is incorrect. So if theres no current focus, autofocus
  315 + // the last field.
  316 + //
  317 + // http://www.w3.org/html/wg/drafts/html/master/forms.html
  318 + var autofocusEl = context.find('input[autofocus], textarea[autofocus]').last()[0]
  319 + if (autofocusEl && document.activeElement !== autofocusEl) {
  320 + autofocusEl.focus();
  321 + }
  322 +
  323 + executeScriptTags(container.scripts)
  324 +
  325 + var scrollTo = options.scrollTo
  326 +
  327 + // Ensure browser scrolls to the element referenced by the URL anchor
  328 + if (hash) {
  329 + var name = decodeURIComponent(hash.slice(1))
  330 + var target = document.getElementById(name) || document.getElementsByName(name)[0]
  331 + if (target) scrollTo = $(target).offset().top
  332 + }
  333 +
  334 + if (typeof scrollTo == 'number') $(window).scrollTop(scrollTo)
  335 +
  336 + fire('pjax:success', [data, status, xhr, options])
  337 + }
  338 +
  339 +
  340 + // Initialize pjax.state for the initial page load. Assume we're
  341 + // using the container and options of the link we're loading for the
  342 + // back button to the initial page. This ensures good back button
  343 + // behavior.
  344 + if (!pjax.state) {
  345 + pjax.state = {
  346 + id: uniqueId(),
  347 + url: window.location.href,
  348 + title: document.title,
  349 + container: context.selector,
  350 + fragment: options.fragment,
  351 + timeout: options.timeout
  352 + }
  353 + window.history.replaceState(pjax.state, document.title)
  354 + }
  355 +
  356 + // Cancel the current request if we're already pjaxing
  357 + abortXHR(pjax.xhr)
  358 +
  359 + pjax.options = options
  360 + var xhr = pjax.xhr = $.ajax(options)
  361 +
  362 + if (xhr.readyState > 0) {
  363 + if (options.push && !options.replace) {
  364 + // Cache current container element before replacing it
  365 + cachePush(pjax.state.id, cloneContents(context))
  366 +
  367 + window.history.pushState(null, "", options.requestUrl)
  368 + }
  369 +
  370 + fire('pjax:start', [xhr, options])
  371 + fire('pjax:send', [xhr, options])
  372 + }
  373 +
  374 + return pjax.xhr
  375 +}
  376 +
  377 +// Public: Reload current page with pjax.
  378 +//
  379 +// Returns whatever $.pjax returns.
  380 +function pjaxReload(container, options) {
  381 + var defaults = {
  382 + url: window.location.href,
  383 + push: false,
  384 + replace: true,
  385 + scrollTo: false
  386 + }
  387 +
  388 + return pjax($.extend(defaults, optionsFor(container, options)))
  389 +}
  390 +
  391 +// Internal: Hard replace current state with url.
  392 +//
  393 +// Work for around WebKit
  394 +// https://bugs.webkit.org/show_bug.cgi?id=93506
  395 +//
  396 +// Returns nothing.
  397 +function locationReplace(url) {
  398 + window.history.replaceState(null, "", pjax.state.url)
  399 + window.location.replace(url)
  400 +}
  401 +
  402 +
  403 +var initialPop = true
  404 +var initialURL = window.location.href
  405 +var initialState = window.history.state
  406 +
  407 +// Initialize $.pjax.state if possible
  408 +// Happens when reloading a page and coming forward from a different
  409 +// session history.
  410 +if (initialState && initialState.container) {
  411 + pjax.state = initialState
  412 +}
  413 +
  414 +// Non-webkit browsers don't fire an initial popstate event
  415 +if ('state' in window.history) {
  416 + initialPop = false
  417 +}
  418 +
  419 +// popstate handler takes care of the back and forward buttons
  420 +//
  421 +// You probably shouldn't use pjax on pages with other pushState
  422 +// stuff yet.
  423 +function onPjaxPopstate(event) {
  424 +
  425 + // Hitting back or forward should override any pending PJAX request.
  426 + if (!initialPop) {
  427 + abortXHR(pjax.xhr)
  428 + }
  429 +
  430 + var previousState = pjax.state
  431 + var state = event.state
  432 + var direction
  433 +
  434 + if (state && state.container) {
  435 + // When coming forward from a separate history session, will get an
  436 + // initial pop with a state we are already at. Skip reloading the current
  437 + // page.
  438 + if (initialPop && initialURL == state.url) return
  439 +
  440 + if (previousState) {
  441 + // If popping back to the same state, just skip.
  442 + // Could be clicking back from hashchange rather than a pushState.
  443 + if (previousState.id === state.id) return
  444 +
  445 + // Since state IDs always increase, we can deduce the navigation direction
  446 + direction = previousState.id < state.id ? 'forward' : 'back'
  447 + }
  448 +
  449 + var cache = cacheMapping[state.id] || []
  450 + var container = $(cache[0] || state.container), contents = cache[1]
  451 +
  452 + if (container.length) {
  453 + if (previousState) {
  454 + // Cache current container before replacement and inform the
  455 + // cache which direction the history shifted.
  456 + cachePop(direction, previousState.id, cloneContents(container))
  457 + }
  458 +
  459 + var popstateEvent = $.Event('pjax:popstate', {
  460 + state: state,
  461 + direction: direction
  462 + })
  463 + container.trigger(popstateEvent)
  464 +
  465 + var options = {
  466 + id: state.id,
  467 + url: state.url,
  468 + container: container,
  469 + push: false,
  470 + fragment: state.fragment,
  471 + timeout: state.timeout,
  472 + scrollTo: false
  473 + }
  474 +
  475 + if (contents) {
  476 + container.trigger('pjax:start', [null, options])
  477 +
  478 + pjax.state = state
  479 + if (state.title) document.title = state.title
  480 + var beforeReplaceEvent = $.Event('pjax:beforeReplace', {
  481 + state: state,
  482 + previousState: previousState
  483 + })
  484 + container.trigger(beforeReplaceEvent, [contents, options])
  485 + container.html(contents)
  486 +
  487 + container.trigger('pjax:end', [null, options])
  488 + } else {
  489 + pjax(options)
  490 + }
  491 +
  492 + // Force reflow/relayout before the browser tries to restore the
  493 + // scroll position.
  494 + container[0].offsetHeight
  495 + } else {
  496 + locationReplace(location.href)
  497 + }
  498 + }
  499 + initialPop = false
  500 +}
  501 +
  502 +// Fallback version of main pjax function for browsers that don't
  503 +// support pushState.
  504 +//
  505 +// Returns nothing since it retriggers a hard form submission.
  506 +function fallbackPjax(options) {
  507 + var url = $.isFunction(options.url) ? options.url() : options.url,
  508 + method = options.type ? options.type.toUpperCase() : 'GET'
  509 +
  510 + var form = $('<form>', {
  511 + method: method === 'GET' ? 'GET' : 'POST',
  512 + action: url,
  513 + style: 'display:none'
  514 + })
  515 +
  516 + if (method !== 'GET' && method !== 'POST') {
  517 + form.append($('<input>', {
  518 + type: 'hidden',
  519 + name: '_method',
  520 + value: method.toLowerCase()
  521 + }))
  522 + }
  523 +
  524 + var data = options.data
  525 + if (typeof data === 'string') {
  526 + $.each(data.split('&'), function(index, value) {
  527 + var pair = value.split('=')
  528 + form.append($('<input>', {type: 'hidden', name: pair[0], value: pair[1]}))
  529 + })
  530 + } else if ($.isArray(data)) {
  531 + $.each(data, function(index, value) {
  532 + form.append($('<input>', {type: 'hidden', name: value.name, value: value.value}))
  533 + })
  534 + } else if (typeof data === 'object') {
  535 + var key
  536 + for (key in data)
  537 + form.append($('<input>', {type: 'hidden', name: key, value: data[key]}))
  538 + }
  539 +
  540 + $(document.body).append(form)
  541 + form.submit()
  542 +}
  543 +
  544 +// Internal: Abort an XmlHttpRequest if it hasn't been completed,
  545 +// also removing its event handlers.
  546 +function abortXHR(xhr) {
  547 + if ( xhr && xhr.readyState < 4) {
  548 + xhr.onreadystatechange = $.noop
  549 + xhr.abort()
  550 + }
  551 +}
  552 +
  553 +// Internal: Generate unique id for state object.
  554 +//
  555 +// Use a timestamp instead of a counter since ids should still be
  556 +// unique across page loads.
  557 +//
  558 +// Returns Number.
  559 +function uniqueId() {
  560 + return (new Date).getTime()
  561 +}
  562 +
  563 +function cloneContents(container) {
  564 + var cloned = container.clone()
  565 + // Unmark script tags as already being eval'd so they can get executed again
  566 + // when restored from cache. HAXX: Uses jQuery internal method.
  567 + cloned.find('script').each(function(){
  568 + if (!this.src) jQuery._data(this, 'globalEval', false)
  569 + })
  570 + return [container.selector, cloned.contents()]
  571 +}
  572 +
  573 +// Internal: Strip internal query params from parsed URL.
  574 +//
  575 +// Returns sanitized url.href String.
  576 +function stripInternalParams(url) {
  577 + url.search = url.search.replace(/([?&])(_pjax|_)=[^&]*/g, '')
  578 + return url.href.replace(/\?($|#)/, '$1')
  579 +}
  580 +
  581 +// Internal: Parse URL components and returns a Locationish object.
  582 +//
  583 +// url - String URL
  584 +//
  585 +// Returns HTMLAnchorElement that acts like Location.
  586 +function parseURL(url) {
  587 + var a = document.createElement('a')
  588 + a.href = url
  589 + return a
  590 +}
  591 +
  592 +// Internal: Return the `href` component of given URL object with the hash
  593 +// portion removed.
  594 +//
  595 +// location - Location or HTMLAnchorElement
  596 +//
  597 +// Returns String
  598 +function stripHash(location) {
  599 + return location.href.replace(/#.*/, '')
  600 +}
  601 +
  602 +// Internal: Build options Object for arguments.
  603 +//
  604 +// For convenience the first parameter can be either the container or
  605 +// the options object.
  606 +//
  607 +// Examples
  608 +//
  609 +// optionsFor('#container')
  610 +// // => {container: '#container'}
  611 +//
  612 +// optionsFor('#container', {push: true})
  613 +// // => {container: '#container', push: true}
  614 +//
  615 +// optionsFor({container: '#container', push: true})
  616 +// // => {container: '#container', push: true}
  617 +//
  618 +// Returns options Object.
  619 +function optionsFor(container, options) {
  620 + // Both container and options
  621 + if ( container && options )
  622 + options.container = container
  623 +
  624 + // First argument is options Object
  625 + else if ( $.isPlainObject(container) )
  626 + options = container
  627 +
  628 + // Only container
  629 + else
  630 + options = {container: container}
  631 +
  632 + // Find and validate container
  633 + if (options.container)
  634 + options.container = findContainerFor(options.container)
  635 +
  636 + return options
  637 +}
  638 +
  639 +// Internal: Find container element for a variety of inputs.
  640 +//
  641 +// Because we can't persist elements using the history API, we must be
  642 +// able to find a String selector that will consistently find the Element.
  643 +//
  644 +// container - A selector String, jQuery object, or DOM Element.
  645 +//
  646 +// Returns a jQuery object whose context is `document` and has a selector.
  647 +function findContainerFor(container) {
  648 + container = $(container)
  649 +
  650 + if ( !container.length ) {
  651 + throw "no pjax container for " + container.selector
  652 + } else if ( container.selector !== '' && container.context === document ) {
  653 + return container
  654 + } else if ( container.attr('id') ) {
  655 + return $('#' + container.attr('id'))
  656 + } else {
  657 + throw "cant get selector for pjax container!"
  658 + }
  659 +}
  660 +
  661 +// Internal: Filter and find all elements matching the selector.
  662 +//
  663 +// Where $.fn.find only matches descendants, findAll will test all the
  664 +// top level elements in the jQuery object as well.
  665 +//
  666 +// elems - jQuery object of Elements
  667 +// selector - String selector to match
  668 +//
  669 +// Returns a jQuery object.
  670 +function findAll(elems, selector) {
  671 + return elems.filter(selector).add(elems.find(selector));
  672 +}
  673 +
  674 +function parseHTML(html) {
  675 + return $.parseHTML(html, document, true)
  676 +}
  677 +
  678 +// Internal: Extracts container and metadata from response.
  679 +//
  680 +// 1. Extracts X-PJAX-URL header if set
  681 +// 2. Extracts inline <title> tags
  682 +// 3. Builds response Element and extracts fragment if set
  683 +//
  684 +// data - String response data
  685 +// xhr - XHR response
  686 +// options - pjax options Object
  687 +//
  688 +// Returns an Object with url, title, and contents keys.
  689 +function extractContainer(data, xhr, options) {
  690 + var obj = {}, fullDocument = /<html/i.test(data)
  691 +
  692 + // Prefer X-PJAX-URL header if it was set, otherwise fallback to
  693 + // using the original requested url.
  694 + var serverUrl = xhr.getResponseHeader('X-PJAX-URL')
  695 + obj.url = serverUrl ? stripInternalParams(parseURL(serverUrl)) : options.requestUrl
  696 +
  697 + // Attempt to parse response html into elements
  698 + if (fullDocument) {
  699 + var $head = $(parseHTML(data.match(/<head[^>]*>([\s\S.]*)<\/head>/i)[0]))
  700 + var $body = $(parseHTML(data.match(/<body[^>]*>([\s\S.]*)<\/body>/i)[0]))
  701 + } else {
  702 + var $head = $body = $(parseHTML(data))
  703 + }
  704 +
  705 + // If response data is empty, return fast
  706 + if ($body.length === 0)
  707 + return obj
  708 +
  709 + // If there's a <title> tag in the header, use it as
  710 + // the page's title.
  711 + obj.title = findAll($head, 'title').last().text()
  712 +
  713 + if (options.fragment) {
  714 + // If they specified a fragment, look for it in the response
  715 + // and pull it out.
  716 + if (options.fragment === 'body') {
  717 + var $fragment = $body
  718 + } else {
  719 + var $fragment = findAll($body, options.fragment).first()
  720 + }
  721 +
  722 + if ($fragment.length) {
  723 + obj.contents = options.fragment === 'body' ? $fragment : $fragment.contents()
  724 +
  725 + // If there's no title, look for data-title and title attributes
  726 + // on the fragment
  727 + if (!obj.title)
  728 + obj.title = $fragment.attr('title') || $fragment.data('title')
  729 + }
  730 +
  731 + } else if (!fullDocument) {
  732 + obj.contents = $body
  733 + }
  734 +
  735 + // Clean up any <title> tags
  736 + if (obj.contents) {
  737 + // Remove any parent title elements
  738 + obj.contents = obj.contents.not(function() { return $(this).is('title') })
  739 +
  740 + // Then scrub any titles from their descendants
  741 + obj.contents.find('title').remove()
  742 +
  743 + // Gather all script[src] elements
  744 + obj.scripts = findAll(obj.contents, 'script[src]').remove()
  745 + obj.contents = obj.contents.not(obj.scripts)
  746 + }
  747 +
  748 + // Trim any whitespace off the title
  749 + if (obj.title) obj.title = $.trim(obj.title)
  750 +
  751 + return obj
  752 +}
  753 +
  754 +// Load an execute scripts using standard script request.
  755 +//
  756 +// Avoids jQuery's traditional $.getScript which does a XHR request and
  757 +// globalEval.
  758 +//
  759 +// scripts - jQuery object of script Elements
  760 +//
  761 +// Returns nothing.
  762 +function executeScriptTags(scripts) {
  763 + if (!scripts) return
  764 +
  765 + var existingScripts = $('script[src]')
  766 +
  767 + scripts.each(function() {
  768 + var src = this.src
  769 + var matchedScripts = existingScripts.filter(function() {
  770 + return this.src === src
  771 + })
  772 + if (matchedScripts.length) return
  773 +
  774 + var script = document.createElement('script')
  775 + var type = $(this).attr('type')
  776 + if (type) script.type = type
  777 + script.src = $(this).attr('src')
  778 + document.head.appendChild(script)
  779 + })
  780 +}
  781 +
  782 +// Internal: History DOM caching class.
  783 +var cacheMapping = {}
  784 +var cacheForwardStack = []
  785 +var cacheBackStack = []
  786 +
  787 +// Push previous state id and container contents into the history
  788 +// cache. Should be called in conjunction with `pushState` to save the
  789 +// previous container contents.
  790 +//
  791 +// id - State ID Number
  792 +// value - DOM Element to cache
  793 +//
  794 +// Returns nothing.
  795 +function cachePush(id, value) {
  796 + cacheMapping[id] = value
  797 + cacheBackStack.push(id)
  798 +
  799 + // Remove all entries in forward history stack after pushing a new page.
  800 + trimCacheStack(cacheForwardStack, 0)
  801 +
  802 + // Trim back history stack to max cache length.
  803 + trimCacheStack(cacheBackStack, pjax.defaults.maxCacheLength)
  804 +}
  805 +
  806 +// Shifts cache from directional history cache. Should be
  807 +// called on `popstate` with the previous state id and container
  808 +// contents.
  809 +//
  810 +// direction - "forward" or "back" String
  811 +// id - State ID Number
  812 +// value - DOM Element to cache
  813 +//
  814 +// Returns nothing.
  815 +function cachePop(direction, id, value) {
  816 + var pushStack, popStack
  817 + cacheMapping[id] = value
  818 +
  819 + if (direction === 'forward') {
  820 + pushStack = cacheBackStack
  821 + popStack = cacheForwardStack
  822 + } else {
  823 + pushStack = cacheForwardStack
  824 + popStack = cacheBackStack
  825 + }
  826 +
  827 + pushStack.push(id)
  828 + if (id = popStack.pop())
  829 + delete cacheMapping[id]
  830 +
  831 + // Trim whichever stack we just pushed to to max cache length.
  832 + trimCacheStack(pushStack, pjax.defaults.maxCacheLength)
  833 +}
  834 +
  835 +// Trim a cache stack (either cacheBackStack or cacheForwardStack) to be no
  836 +// longer than the specified length, deleting cached DOM elements as necessary.
  837 +//
  838 +// stack - Array of state IDs
  839 +// length - Maximum length to trim to
  840 +//
  841 +// Returns nothing.
  842 +function trimCacheStack(stack, length) {
  843 + while (stack.length > length)
  844 + delete cacheMapping[stack.shift()]
  845 +}
  846 +
  847 +// Public: Find version identifier for the initial page load.
  848 +//
  849 +// Returns String version or undefined.
  850 +function findVersion() {
  851 + return $('meta').filter(function() {
  852 + var name = $(this).attr('http-equiv')
  853 + return name && name.toUpperCase() === 'X-PJAX-VERSION'
  854 + }).attr('content')
  855 +}
  856 +
  857 +// Install pjax functions on $.pjax to enable pushState behavior.
  858 +//
  859 +// Does nothing if already enabled.
  860 +//
  861 +// Examples
  862 +//
  863 +// $.pjax.enable()
  864 +//
  865 +// Returns nothing.
  866 +function enable() {
  867 + $.fn.pjax = fnPjax
  868 + $.pjax = pjax
  869 + $.pjax.enable = $.noop
  870 + $.pjax.disable = disable
  871 + $.pjax.click = handleClick
  872 + $.pjax.submit = handleSubmit
  873 + $.pjax.reload = pjaxReload
  874 + $.pjax.defaults = {
  875 + timeout: 650,
  876 + push: true,
  877 + replace: false,
  878 + type: 'GET',
  879 + dataType: 'html',
  880 + scrollTo: 0,
  881 + maxCacheLength: 20,
  882 + version: findVersion
  883 + }
  884 + $(window).on('popstate.pjax', onPjaxPopstate)
  885 +}
  886 +
  887 +// Disable pushState behavior.
  888 +//
  889 +// This is the case when a browser doesn't support pushState. It is
  890 +// sometimes useful to disable pushState for debugging on a modern
  891 +// browser.
  892 +//
  893 +// Examples
  894 +//
  895 +// $.pjax.disable()
  896 +//
  897 +// Returns nothing.
  898 +function disable() {
  899 + $.fn.pjax = function() { return this }
  900 + $.pjax = fallbackPjax
  901 + $.pjax.enable = enable
  902 + $.pjax.disable = $.noop
  903 + $.pjax.click = $.noop
  904 + $.pjax.submit = $.noop
  905 + $.pjax.reload = function() { window.location.reload() }
  906 +
  907 + $(window).off('popstate.pjax', onPjaxPopstate)
  908 +}
  909 +
  910 +
  911 +// Add the state property to jQuery's event object so we can use it in
  912 +// $(window).bind('popstate')
  913 +if ( $.inArray('state', $.event.props) < 0 )
  914 + $.event.props.push('state')
  915 +
  916 +// Is pjax supported by this browser?
  917 +$.support.pjax =
  918 + window.history && window.history.pushState && window.history.replaceState &&
  919 + // pushState isn't reliable on iOS until 5.
  920 + !navigator.userAgent.match(/((iPod|iPhone|iPad).+\bOS\s+[1-4]\D|WebApps\/.+CFNetwork)/)
  921 +
  922 +$.support.pjax ? enable() : disable()
  923 +
  924 +})(jQuery);
... ...
src/main/resources/static/assets/plugins/jquery.serializejson.js 0 → 100644
  1 +++ a/src/main/resources/static/assets/plugins/jquery.serializejson.js
  1 +/*!
  2 + SerializeJSON jQuery plugin.
  3 + https://github.com/marioizquierdo/jquery.serializeJSON
  4 + version 2.6.0 (Apr, 2015)
  5 +
  6 + Copyright (c) 2012, 2015 Mario Izquierdo
  7 + Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php)
  8 + and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses.
  9 +*/
  10 +(function ($) {
  11 + "use strict";
  12 +
  13 + // jQuery('form').serializeJSON()
  14 + $.fn.serializeJSON = function (options) {
  15 + var serializedObject, formAsArray, keys, type, value, _ref, f, opts;
  16 + f = $.serializeJSON;
  17 + opts = f.setupOpts(options); // calculate values for options {parseNumbers, parseBoolens, parseNulls}
  18 + formAsArray = this.serializeArray(); // array of objects {name, value}
  19 + f.readCheckboxUncheckedValues(formAsArray, this, opts); // add {name, value} of unchecked checkboxes if needed
  20 +
  21 + serializedObject = {};
  22 + $.each(formAsArray, function (i, input) {
  23 + keys = f.splitInputNameIntoKeysArray(input.name, opts);
  24 + type = keys.pop(); // the last element is always the type ("string" by default)
  25 + if (type !== 'skip') { // easy way to skip a value
  26 + value = f.parseValue(input.value, type, opts); // string, number, boolean or null
  27 + if (opts.parseWithFunction && type === '_') value = opts.parseWithFunction(value, input.name); // allow for custom parsing
  28 + f.deepSet(serializedObject, keys, value, opts);
  29 + }
  30 + });
  31 + return serializedObject;
  32 + };
  33 +
  34 + // Use $.serializeJSON as namespace for the auxiliar functions
  35 + // and to define defaults
  36 + $.serializeJSON = {
  37 +
  38 + defaultOptions: {
  39 + checkboxUncheckedValue: undefined, // to include that value for unchecked checkboxes (instead of ignoring them)
  40 +
  41 + parseNumbers: false, // convert values like "1", "-2.33" to 1, -2.33
  42 + parseBooleans: false, // convert "true", "false" to true, false
  43 + parseNulls: false, // convert "null" to null
  44 + parseAll: false, // all of the above
  45 + parseWithFunction: null, // to use custom parser, a function like: function(val){ return parsed_val; }
  46 +
  47 + customTypes: {}, // override defaultTypes
  48 + defaultTypes: {
  49 + string: function(str) { return String(str) },
  50 + number: function(str) { return Number(str) },
  51 + boolean: function(str) { return (["false", "null", "undefined", "", "0"].indexOf(str) === -1) },
  52 + null: function(str) { return (["false", "null", "undefined", "", "0"].indexOf(str) !== -1) ? null : str },
  53 + array: function(str) { return JSON.parse(str) },
  54 + object: function(str) { return JSON.parse(str) },
  55 + auto: function(str) { return $.serializeJSON.parseValue(str, null, {parseNumbers: true, parseBooleans: true, parseNulls: true}) } // try again with something like "parseAll"
  56 + },
  57 +
  58 + useIntKeysAsArrayIndex: false, // name="foo[2]" value="v" => {foo: [null, null, "v"]}, instead of {foo: ["2": "v"]}
  59 + },
  60 +
  61 + // Merge option defaults into the options
  62 + setupOpts: function(options) {
  63 + var opt, validOpts, defaultOptions, optWithDefault, parseAll, f;
  64 + f = $.serializeJSON;
  65 +
  66 + if (options == null) options = {}; // options ||= {}
  67 + defaultOptions = f.defaultOptions || {}; // defaultOptions
  68 +
  69 + // Make sure that the user didn't misspell an option
  70 + validOpts = ['checkboxUncheckedValue', 'parseNumbers', 'parseBooleans', 'parseNulls', 'parseAll', 'parseWithFunction', 'customTypes', 'defaultTypes', 'useIntKeysAsArrayIndex']; // re-define because the user may override the defaultOptions
  71 + for (opt in options) {
  72 + if (validOpts.indexOf(opt) === -1) {
  73 + throw new Error("serializeJSON ERROR: invalid option '" + opt + "'. Please use one of " + validOpts.join(', '));
  74 + }
  75 + }
  76 +
  77 + // Helper to get the default value for this option if none is specified by the user
  78 + optWithDefault = function(key) { return (options[key] !== false) && (options[key] !== '') && (options[key] || defaultOptions[key]); }
  79 +
  80 + // Return computed options (opts to be used in the rest of the script)
  81 + parseAll = optWithDefault('parseAll');
  82 + return {
  83 + checkboxUncheckedValue: optWithDefault('checkboxUncheckedValue'),
  84 +
  85 + parseNumbers: parseAll || optWithDefault('parseNumbers'),
  86 + parseBooleans: parseAll || optWithDefault('parseBooleans'),
  87 + parseNulls: parseAll || optWithDefault('parseNulls'),
  88 + parseWithFunction: optWithDefault('parseWithFunction'),
  89 +
  90 + typeFunctions: $.extend({}, optWithDefault('defaultTypes'), optWithDefault('customTypes')),
  91 +
  92 + useIntKeysAsArrayIndex: optWithDefault('useIntKeysAsArrayIndex'),
  93 + }
  94 + },
  95 +
  96 + // Given a string, apply the type or the relevant "parse" options, to return the parsed value
  97 + parseValue: function(str, type, opts) {
  98 + var typeFunction, f;
  99 + f = $.serializeJSON;
  100 +
  101 + // Parse with a type if available
  102 + typeFunction = opts.typeFunctions && opts.typeFunctions[type];
  103 + if (typeFunction) return typeFunction(str); // use specific type
  104 +
  105 + // Otherwise, check if there is any auto-parse option enabled and use it.
  106 + if (opts.parseNumbers && f.isNumeric(str)) return Number(str); // auto: number
  107 + if (opts.parseBooleans && (str === "true" || str === "false")) return str === "true"; // auto: boolean
  108 + if (opts.parseNulls && str == "null") return null; // auto: null
  109 +
  110 + // If none applies, just return the str
  111 + return str;
  112 + },
  113 +
  114 + isObject: function(obj) { return obj === Object(obj); }, // is this variable an object?
  115 + isUndefined: function(obj) { return obj === void 0; }, // safe check for undefined values
  116 + isValidArrayIndex: function(val) { return /^[0-9]+$/.test(String(val)); }, // 1,2,3,4 ... are valid array indexes
  117 + isNumeric: function(obj) { return obj - parseFloat(obj) >= 0; }, // taken from jQuery.isNumeric implementation. Not using jQuery.isNumeric to support old jQuery and Zepto versions
  118 +
  119 + optionKeys: function(obj) { if(Object.keys){ return Object.keys(obj); } else { var keys = []; for(var key in obj){ keys.push(key) }; return keys;} }, // polyfill Object.keys to get option keys in IE<9
  120 +
  121 + // Split the input name in programatically readable keys.
  122 + // The last element is always the type (default "_").
  123 + // Examples:
  124 + // "foo" => ['foo', '_']
  125 + // "foo:string" => ['foo', 'string']
  126 + // "foo:boolean" => ['foo', 'boolean']
  127 + // "[foo]" => ['foo', '_']
  128 + // "foo[inn][bar]" => ['foo', 'inn', 'bar', '_']
  129 + // "foo[inn[bar]]" => ['foo', 'inn', 'bar', '_']
  130 + // "foo[inn][arr][0]" => ['foo', 'inn', 'arr', '0', '_']
  131 + // "arr[][val]" => ['arr', '', 'val', '_']
  132 + // "arr[][val]:null" => ['arr', '', 'val', 'null']
  133 + splitInputNameIntoKeysArray: function(name, opts) {
  134 + var keys, nameWithoutType, type, _ref, f;
  135 + f = $.serializeJSON;
  136 + _ref = f.extractTypeFromInputName(name, opts), nameWithoutType = _ref[0], type = _ref[1];
  137 + keys = nameWithoutType.split('['); // split string into array
  138 + keys = $.map(keys, function (key) { return key.replace(/]/g, ''); }); // remove closing brackets
  139 + if (keys[0] === '') { keys.shift(); } // ensure no opening bracket ("[foo][inn]" should be same as "foo[inn]")
  140 + keys.push(type); // add type at the end
  141 + return keys;
  142 + },
  143 +
  144 + // Returns [name-without-type, type] from name.
  145 + // "foo" => ["foo", '_']
  146 + // "foo:boolean" => ["foo", 'boolean']
  147 + // "foo[bar]:null" => ["foo[bar]", 'null']
  148 + extractTypeFromInputName: function(name, opts) {
  149 + var match, validTypes, f;
  150 + if (match = name.match(/(.*):([^:]+)$/)){
  151 + f = $.serializeJSON;
  152 +
  153 + validTypes = f.optionKeys(opts ? opts.typeFunctions : f.defaultOptions.defaultTypes);
  154 + validTypes.push('skip'); // skip is a special type that makes it easy to remove
  155 + if (validTypes.indexOf(match[2]) !== -1) {
  156 + return [match[1], match[2]];
  157 + } else {
  158 + throw new Error("serializeJSON ERROR: Invalid type " + match[2] + " found in input name '" + name + "', please use one of " + validTypes.join(', '))
  159 + }
  160 + } else {
  161 + return [name, '_']; // no defined type, then use parse options
  162 + }
  163 + },
  164 +
  165 + // Set a value in an object or array, using multiple keys to set in a nested object or array:
  166 + //
  167 + // deepSet(obj, ['foo'], v) // obj['foo'] = v
  168 + // deepSet(obj, ['foo', 'inn'], v) // obj['foo']['inn'] = v // Create the inner obj['foo'] object, if needed
  169 + // deepSet(obj, ['foo', 'inn', '123'], v) // obj['foo']['arr']['123'] = v //
  170 + //
  171 + // deepSet(obj, ['0'], v) // obj['0'] = v
  172 + // deepSet(arr, ['0'], v, {useIntKeysAsArrayIndex: true}) // arr[0] = v
  173 + // deepSet(arr, [''], v) // arr.push(v)
  174 + // deepSet(obj, ['arr', ''], v) // obj['arr'].push(v)
  175 + //
  176 + // arr = [];
  177 + // deepSet(arr, ['', v] // arr => [v]
  178 + // deepSet(arr, ['', 'foo'], v) // arr => [v, {foo: v}]
  179 + // deepSet(arr, ['', 'bar'], v) // arr => [v, {foo: v, bar: v}]
  180 + // deepSet(arr, ['', 'bar'], v) // arr => [v, {foo: v, bar: v}, {bar: v}]
  181 + //
  182 + deepSet: function (o, keys, value, opts) {
  183 + var key, nextKey, tail, lastIdx, lastVal, f;
  184 + if (opts == null) opts = {};
  185 + f = $.serializeJSON;
  186 + if (f.isUndefined(o)) { throw new Error("ArgumentError: param 'o' expected to be an object or array, found undefined"); }
  187 + if (!keys || keys.length === 0) { throw new Error("ArgumentError: param 'keys' expected to be an array with least one element"); }
  188 +
  189 + key = keys[0];
  190 +
  191 + // Only one key, then it's not a deepSet, just assign the value.
  192 + if (keys.length === 1) {
  193 + if (key === '') {
  194 + o.push(value); // '' is used to push values into the array (assume o is an array)
  195 + } else {
  196 + o[key] = value; // other keys can be used as object keys or array indexes
  197 + }
  198 +
  199 + // With more keys is a deepSet. Apply recursively.
  200 + } else {
  201 + nextKey = keys[1];
  202 +
  203 + // '' is used to push values into the array,
  204 + // with nextKey, set the value into the same object, in object[nextKey].
  205 + // Covers the case of ['', 'foo'] and ['', 'var'] to push the object {foo, var}, and the case of nested arrays.
  206 + if (key === '') {
  207 + lastIdx = o.length - 1; // asume o is array
  208 + lastVal = o[lastIdx];
  209 + if (f.isObject(lastVal) && (f.isUndefined(lastVal[nextKey]) || keys.length > 2)) { // if nextKey is not present in the last object element, or there are more keys to deep set
  210 + key = lastIdx; // then set the new value in the same object element
  211 + } else {
  212 + key = lastIdx + 1; // otherwise, point to set the next index in the array
  213 + }
  214 + }
  215 +
  216 + // '' is used to push values into the array "array[]"
  217 + if (nextKey === '') {
  218 + if (f.isUndefined(o[key]) || !$.isArray(o[key])) {
  219 + o[key] = []; // define (or override) as array to push values
  220 + }
  221 + } else {
  222 + if (opts.useIntKeysAsArrayIndex && f.isValidArrayIndex(nextKey)) { // if 1, 2, 3 ... then use an array, where nextKey is the index
  223 + if (f.isUndefined(o[key]) || !$.isArray(o[key])) {
  224 + o[key] = []; // define (or override) as array, to insert values using int keys as array indexes
  225 + }
  226 + } else { // for anything else, use an object, where nextKey is going to be the attribute name
  227 + if (f.isUndefined(o[key]) || !f.isObject(o[key])) {
  228 + o[key] = {}; // define (or override) as object, to set nested properties
  229 + }
  230 + }
  231 + }
  232 +
  233 + // Recursively set the inner object
  234 + tail = keys.slice(1);
  235 + f.deepSet(o[key], tail, value, opts);
  236 + }
  237 + },
  238 +
  239 + // Fill the formAsArray object with values for the unchecked checkbox inputs,
  240 + // using the same format as the jquery.serializeArray function.
  241 + // The value of the unchecked values is determined from the opts.checkboxUncheckedValue
  242 + // and/or the data-unchecked-value attribute of the inputs.
  243 + readCheckboxUncheckedValues: function (formAsArray, $form, opts) {
  244 + var selector, $uncheckedCheckboxes, $el, dataUncheckedValue, f;
  245 + if (opts == null) opts = {};
  246 + f = $.serializeJSON;
  247 +
  248 + selector = 'input[type=checkbox][name]:not(:checked):not([disabled])';
  249 + $uncheckedCheckboxes = $form.find(selector).add($form.filter(selector));
  250 + $uncheckedCheckboxes.each(function (i, el) {
  251 + $el = $(el);
  252 + dataUncheckedValue = $el.attr('data-unchecked-value');
  253 + if(dataUncheckedValue) { // data-unchecked-value has precedence over option opts.checkboxUncheckedValue
  254 + formAsArray.push({name: el.name, value: dataUncheckedValue});
  255 + } else {
  256 + if (!f.isUndefined(opts.checkboxUncheckedValue)) {
  257 + formAsArray.push({name: el.name, value: opts.checkboxUncheckedValue});
  258 + }
  259 + }
  260 + });
  261 + }
  262 +
  263 + };
  264 +
  265 +}(window.jQuery || window.Zepto || window.$));
... ...
src/main/resources/static/assets/plugins/layer-v2.2/doc/jquery下载.url 0 → 100644
  1 +++ a/src/main/resources/static/assets/plugins/layer-v2.2/doc/jquery下载.url
  1 +[{000214A0-0000-0000-C000-000000000046}]
  2 +Prop3=19,2
  3 +[InternetShortcut]
  4 +URL=http://code.jquery.com/jquery-1.9.1.min.js
  5 +IDList=
  6 +HotKey=0
... ...
src/main/resources/static/assets/plugins/layer-v2.2/doc/layer交流.url 0 → 100644
  1 +++ a/src/main/resources/static/assets/plugins/layer-v2.2/doc/layer交流.url
  1 +[{000214A0-0000-0000-C000-000000000046}]
  2 +Prop3=19,2
  3 +[InternetShortcut]
  4 +URL=http://fly.layui.com/
  5 +IDList=
  6 +HotKey=0
  7 +IconFile=F:\bd_xianxin\bayuanbao\www\favicon.ico
  8 +IconIndex=0
... ...
src/main/resources/static/assets/plugins/layer-v2.2/doc/layer官网.url 0 → 100644
  1 +++ a/src/main/resources/static/assets/plugins/layer-v2.2/doc/layer官网.url
  1 +[{000214A0-0000-0000-C000-000000000046}]
  2 +Prop3=19,2
  3 +[InternetShortcut]
  4 +URL=http://sentsin.com/jquery/layer/
  5 +IDList=
  6 +HotKey=0
... ...
src/main/resources/static/assets/plugins/layer-v2.2/layer/extend/layer.ext.js 0 → 100644
  1 +++ a/src/main/resources/static/assets/plugins/layer-v2.2/layer/extend/layer.ext.js
  1 +/*! layer弹层组件拓展类 */
  2 +;!function(){layer.use("skin/layer.ext.css",function(){layer.layui_layer_extendlayerextjs=!0});var a=layer.cache||{},b=function(b){return a.skin?" "+a.skin+" "+a.skin+"-"+b:""};layer.prompt=function(a,c){a=a||{},"function"==typeof a&&(c=a);var d,e=2==a.formType?'<textarea class="layui-layer-input">'+(a.value||"")+"</textarea>":function(){return'<input type="'+(1==a.formType?"password":"text")+'" class="layui-layer-input" value="'+(a.value||"")+'">'}();return layer.open($.extend({btn:["&#x786E;&#x5B9A;","&#x53D6;&#x6D88;"],content:e,skin:"layui-layer-prompt"+b("prompt"),success:function(a){d=a.find(".layui-layer-input"),d.focus()},yes:function(b){var e=d.val();""===e?d.focus():e.length>(a.maxlength||500)?layer.tips("&#x6700;&#x591A;&#x8F93;&#x5165;"+(a.maxlength||500)+"&#x4E2A;&#x5B57;&#x6570;",d,{tips:1}):c&&c(e,b,d)}},a))},layer.tab=function(a){a=a||{};var c=a.tab||{};return layer.open($.extend({type:1,skin:"layui-layer-tab"+b("tab"),title:function(){var a=c.length,b=1,d="";if(a>0)for(d='<span class="layui-layer-tabnow">'+c[0].title+"</span>";a>b;b++)d+="<span>"+c[b].title+"</span>";return d}(),content:'<ul class="layui-layer-tabmain">'+function(){var a=c.length,b=1,d="";if(a>0)for(d='<li class="layui-layer-tabli xubox_tab_layer">'+(c[0].content||"no content")+"</li>";a>b;b++)d+='<li class="layui-layer-tabli">'+(c[b].content||"no content")+"</li>";return d}()+"</ul>",success:function(b){var c=b.find(".layui-layer-title").children(),d=b.find(".layui-layer-tabmain").children();c.on("mousedown",function(b){b.stopPropagation?b.stopPropagation():b.cancelBubble=!0;var c=$(this),e=c.index();c.addClass("layui-layer-tabnow").siblings().removeClass("layui-layer-tabnow"),d.eq(e).show().siblings().hide(),"function"==typeof a.change&&a.change(e)})}},a))},layer.photos=function(a,c,d){function e(a,b,c){var d=new Image;d.onload=function(){d.onload=null,b(d)},d.onerror=function(a){d.onerror=null,c(a)},d.src=a}var f={};if(a=a||{},a.photos){var g=a.photos.constructor===Object,h=g?a.photos:{},i=h.data||[],j=h.start||0;if(f.imgIndex=j+1,g){if(0===i.length)return layer.msg("&#x6CA1;&#x6709;&#x56FE;&#x7247;")}else{var k=$(a.photos),l=function(){return i=[],k.find(a.img||"img").each(function(a){var b=$(this);i.push({alt:b.attr("alt"),pid:b.attr("layer-pid"),src:b.attr("layer-src")||b.attr("src"),thumb:b.attr("src")})}),arguments.callee}();if(0===i.length)return;if(c||k.on("click",a.img||"img",function(){var b=$(this),c=b.index();l(),layer.photos($.extend(a,{photos:{start:c,data:i,tab:a.tab},full:a.full}),!0)}),!c)return}f.imgprev=function(a){f.imgIndex--,f.imgIndex<1&&(f.imgIndex=i.length),f.tabimg(a)},f.imgnext=function(a,b){f.imgIndex++,f.imgIndex>i.length&&(f.imgIndex=1,b)||f.tabimg(a)},f.keyup=function(a){if(!f.end){var b=a.keyCode;a.preventDefault(),37===b?f.imgprev(!0):39===b?f.imgnext(!0):27===b&&layer.close(f.index)}},f.tabimg=function(b){i.length<=1||(h.start=f.imgIndex-1,layer.close(f.index),layer.photos(a,!0,b))},f.event=function(){f.bigimg.hover(function(){f.imgsee.show()},function(){f.imgsee.hide()}),f.bigimg.find(".layui-layer-imgprev").on("click",function(a){a.preventDefault(),f.imgprev()}),f.bigimg.find(".layui-layer-imgnext").on("click",function(a){a.preventDefault(),f.imgnext()}),$(document).on("keyup",f.keyup)},f.loadi=layer.load(1,{shade:"shade"in a?!1:.9,scrollbar:!1}),e(i[j].src,function(c){layer.close(f.loadi),f.index=layer.open($.extend({type:1,area:function(){var b=[c.width,c.height],d=[$(window).width()-100,$(window).height()-100];return!a.full&&b[0]>d[0]&&(b[0]=d[0],b[1]=b[0]*d[1]/b[0]),[b[0]+"px",b[1]+"px"]}(),title:!1,shade:.9,shadeClose:!0,closeBtn:!1,move:".layui-layer-phimg img",moveType:1,scrollbar:!1,moveOut:!0,shift:5*Math.random()|0,skin:"layui-layer-photos"+b("photos"),content:'<div class="layui-layer-phimg"><img src="'+i[j].src+'" alt="'+(i[j].alt||"")+'" layer-pid="'+i[j].pid+'"><div class="layui-layer-imgsee">'+(i.length>1?'<span class="layui-layer-imguide"><a href="javascript:;" class="layui-layer-iconext layui-layer-imgprev"></a><a href="javascript:;" class="layui-layer-iconext layui-layer-imgnext"></a></span>':"")+'<div class="layui-layer-imgbar" style="display:'+(d?"block":"")+'"><span class="layui-layer-imgtit"><a href="javascript:;">'+(i[j].alt||"")+"</a><em>"+f.imgIndex+"/"+i.length+"</em></span></div></div></div>",success:function(b,c){f.bigimg=b.find(".layui-layer-phimg"),f.imgsee=b.find(".layui-layer-imguide,.layui-layer-imgbar"),f.event(b),a.tab&&a.tab(i[j],b)},end:function(){f.end=!0,$(document).off("keyup",f.keyup)}},a))},function(){layer.close(f.loadi),layer.msg("&#x5F53;&#x524D;&#x56FE;&#x7247;&#x5730;&#x5740;&#x5F02;&#x5E38;<br>&#x662F;&#x5426;&#x7EE7;&#x7EED;&#x67E5;&#x770B;&#x4E0B;&#x4E00;&#x5F20;&#xFF1F;",{time:3e4,btn:["下一张","不看了"],yes:function(){i.length>1&&f.imgnext(!0,!0)}})})}}}();
0 3 \ No newline at end of file
... ...
src/main/resources/static/assets/plugins/layer-v2.2/layer/layer.js 0 → 100644
  1 +++ a/src/main/resources/static/assets/plugins/layer-v2.2/layer/layer.js
  1 +/*! layer-v2.2 弹层组件 License LGPL http://layer.layui.com/ By 贤心 */
  2 +;!function(a,b){"use strict";var c,d,e={getPath:function(){var a=document.scripts,b=a[a.length-1],c=b.src;if(!b.getAttribute("merge"))return c.substring(0,c.lastIndexOf("/")+1)}(),enter:function(a){13===a.keyCode&&a.preventDefault()},config:{},end:{},btn:["&#x786E;&#x5B9A;","&#x53D6;&#x6D88;"],type:["dialog","page","iframe","loading","tips"]},f={v:"2.2",ie6:!!a.ActiveXObject&&!a.XMLHttpRequest,index:0,path:e.getPath,config:function(a,b){var d=0;return a=a||{},f.cache=e.config=c.extend(e.config,a),f.path=e.config.path||f.path,"string"==typeof a.extend&&(a.extend=[a.extend]),f.use("skin/layer.css",a.extend&&a.extend.length>0?function g(){var c=a.extend;f.use(c[c[d]?d:d-1],d<c.length?function(){return++d,g}():b)}():b),this},use:function(a,b,d){var e=c("head")[0],a=a.replace(/\s/g,""),g=/\.css$/.test(a),h=document.createElement(g?"link":"script"),i="layui_layer_"+a.replace(/\.|\//g,"");return f.path?(g&&(h.rel="stylesheet"),h[g?"href":"src"]=/^http:\/\//.test(a)?a:f.path+a,h.id=i,c("#"+i)[0]||e.appendChild(h),function j(){(g?1989===parseInt(c("#"+i).css("width")):f[d||i])?function(){b&&b();try{g||e.removeChild(h)}catch(a){}}():setTimeout(j,100)}(),this):void 0},ready:function(a,b){var d="function"==typeof a;return d&&(b=a),f.config(c.extend(e.config,function(){return d?{}:{path:a}}()),b),this},alert:function(a,b,d){var e="function"==typeof b;return e&&(d=b),f.open(c.extend({content:a,yes:d},e?{}:b))},confirm:function(a,b,d,g){var h="function"==typeof b;return h&&(g=d,d=b),f.open(c.extend({content:a,btn:e.btn,yes:d,cancel:g},h?{}:b))},msg:function(a,d,g){var i="function"==typeof d,j=e.config.skin,k=(j?j+" "+j+"-msg":"")||"layui-layer-msg",l=h.anim.length-1;return i&&(g=d),f.open(c.extend({content:a,time:3e3,shade:!1,skin:k,title:!1,closeBtn:!1,btn:!1,end:g},i&&!e.config.skin?{skin:k+" layui-layer-hui",shift:l}:function(){return d=d||{},(-1===d.icon||d.icon===b&&!e.config.skin)&&(d.skin=k+" "+(d.skin||"layui-layer-hui")),d}()))},load:function(a,b){return f.open(c.extend({type:3,icon:a||0,shade:.01},b))},tips:function(a,b,d){return f.open(c.extend({type:4,content:[a,b],closeBtn:!1,time:3e3,shade:!1,maxWidth:210},d))}},g=function(a){var b=this;b.index=++f.index,b.config=c.extend({},b.config,e.config,a),b.creat()};g.pt=g.prototype;var h=["layui-layer",".layui-layer-title",".layui-layer-main",".layui-layer-dialog","layui-layer-iframe","layui-layer-content","layui-layer-btn","layui-layer-close"];h.anim=["layui-anim","layui-anim-01","layui-anim-02","layui-anim-03","layui-anim-04","layui-anim-05","layui-anim-06"],g.pt.config={type:0,shade:.3,fix:!0,move:h[1],title:"&#x4FE1;&#x606F;",offset:"auto",area:"auto",closeBtn:1,time:0,zIndex:19891014,maxWidth:360,shift:0,icon:-1,scrollbar:!0,tips:2},g.pt.vessel=function(a,b){var c=this,d=c.index,f=c.config,g=f.zIndex+d,i="object"==typeof f.title,j=f.maxmin&&(1===f.type||2===f.type),k=f.title?'<div class="layui-layer-title" style="'+(i?f.title[1]:"")+'">'+(i?f.title[0]:f.title)+"</div>":"";return f.zIndex=g,b([f.shade?'<div class="layui-layer-shade" id="layui-layer-shade'+d+'" times="'+d+'" style="'+("z-index:"+(g-1)+"; background-color:"+(f.shade[1]||"#000")+"; opacity:"+(f.shade[0]||f.shade)+"; filter:alpha(opacity="+(100*f.shade[0]||100*f.shade)+");")+'"></div>':"",'<div class="'+h[0]+" "+(h.anim[f.shift]||"")+(" layui-layer-"+e.type[f.type])+(0!=f.type&&2!=f.type||f.shade?"":" layui-layer-border")+" "+(f.skin||"")+'" id="'+h[0]+d+'" type="'+e.type[f.type]+'" times="'+d+'" showtime="'+f.time+'" conType="'+(a?"object":"string")+'" style="z-index: '+g+"; width:"+f.area[0]+";height:"+f.area[1]+(f.fix?"":";position:absolute;")+'">'+(a&&2!=f.type?"":k)+'<div id="'+(f.id||"")+'" class="layui-layer-content'+(0==f.type&&-1!==f.icon?" layui-layer-padding":"")+(3==f.type?" layui-layer-loading"+f.icon:"")+'">'+(0==f.type&&-1!==f.icon?'<i class="layui-layer-ico layui-layer-ico'+f.icon+'"></i>':"")+(1==f.type&&a?"":f.content||"")+'</div><span class="layui-layer-setwin">'+function(){var a=j?'<a class="layui-layer-min" href="javascript:;"><cite></cite></a><a class="layui-layer-ico layui-layer-max" href="javascript:;"></a>':"";return f.closeBtn&&(a+='<a class="layui-layer-ico '+h[7]+" "+h[7]+(f.title?f.closeBtn:4==f.type?"1":"2")+'" href="javascript:;"></a>'),a}()+"</span>"+(f.btn?function(){var a="";"string"==typeof f.btn&&(f.btn=[f.btn]);for(var b=0,c=f.btn.length;c>b;b++)a+='<a class="'+h[6]+b+'">'+f.btn[b]+"</a>";return'<div class="'+h[6]+'">'+a+"</div>"}():"")+"</div>"],k),c},g.pt.creat=function(){var a=this,b=a.config,g=a.index,i=b.content,j="object"==typeof i;if(!c("#"+b.id)[0]){switch("string"==typeof b.area&&(b.area="auto"===b.area?["",""]:[b.area,""]),b.type){case 0:b.btn="btn"in b?b.btn:e.btn[0],f.closeAll("dialog");break;case 2:var i=b.content=j?b.content:[b.content||"http://layer.layui.com","auto"];b.content='<iframe scrolling="'+(b.content[1]||"auto")+'" allowtransparency="true" id="'+h[4]+g+'" name="'+h[4]+g+'" onload="this.className=\'\';" class="layui-layer-load" frameborder="0" src="'+b.content[0]+'"></iframe>';break;case 3:b.title=!1,b.closeBtn=!1,-1===b.icon&&0===b.icon,f.closeAll("loading");break;case 4:j||(b.content=[b.content,"body"]),b.follow=b.content[1],b.content=b.content[0]+'<i class="layui-layer-TipsG"></i>',b.title=!1,b.fix=!1,b.tips="object"==typeof b.tips?b.tips:[b.tips,!0],b.tipsMore||f.closeAll("tips")}a.vessel(j,function(d,e){c("body").append(d[0]),j?function(){2==b.type||4==b.type?function(){c("body").append(d[1])}():function(){i.parents("."+h[0])[0]||(i.show().addClass("layui-layer-wrap").wrap(d[1]),c("#"+h[0]+g).find("."+h[5]).before(e))}()}():c("body").append(d[1]),a.layero=c("#"+h[0]+g),b.scrollbar||h.html.css("overflow","hidden").attr("layer-full",g)}).auto(g),2==b.type&&f.ie6&&a.layero.find("iframe").attr("src",i[0]),c(document).off("keydown",e.enter).on("keydown",e.enter),a.layero.on("keydown",function(a){c(document).off("keydown",e.enter)}),4==b.type?a.tips():a.offset(),b.fix&&d.on("resize",function(){a.offset(),(/^\d+%$/.test(b.area[0])||/^\d+%$/.test(b.area[1]))&&a.auto(g),4==b.type&&a.tips()}),b.time<=0||setTimeout(function(){f.close(a.index)},b.time),a.move().callback()}},g.pt.auto=function(a){function b(a){a=g.find(a),a.height(i[1]-j-k-2*(0|parseFloat(a.css("padding"))))}var e=this,f=e.config,g=c("#"+h[0]+a);""===f.area[0]&&f.maxWidth>0&&(/MSIE 7/.test(navigator.userAgent)&&f.btn&&g.width(g.innerWidth()),g.outerWidth()>f.maxWidth&&g.width(f.maxWidth));var i=[g.innerWidth(),g.innerHeight()],j=g.find(h[1]).outerHeight()||0,k=g.find("."+h[6]).outerHeight()||0;switch(f.type){case 2:b("iframe");break;default:""===f.area[1]?f.fix&&i[1]>=d.height()&&(i[1]=d.height(),b("."+h[5])):b("."+h[5])}return e},g.pt.offset=function(){var a=this,b=a.config,c=a.layero,e=[c.outerWidth(),c.outerHeight()],f="object"==typeof b.offset;a.offsetTop=(d.height()-e[1])/2,a.offsetLeft=(d.width()-e[0])/2,f?(a.offsetTop=b.offset[0],a.offsetLeft=b.offset[1]||a.offsetLeft):"auto"!==b.offset&&(a.offsetTop=b.offset,"rb"===b.offset&&(a.offsetTop=d.height()-e[1],a.offsetLeft=d.width()-e[0])),b.fix||(a.offsetTop=/%$/.test(a.offsetTop)?d.height()*parseFloat(a.offsetTop)/100:parseFloat(a.offsetTop),a.offsetLeft=/%$/.test(a.offsetLeft)?d.width()*parseFloat(a.offsetLeft)/100:parseFloat(a.offsetLeft),a.offsetTop+=d.scrollTop(),a.offsetLeft+=d.scrollLeft()),c.css({top:a.offsetTop,left:a.offsetLeft})},g.pt.tips=function(){var a=this,b=a.config,e=a.layero,f=[e.outerWidth(),e.outerHeight()],g=c(b.follow);g[0]||(g=c("body"));var i={width:g.outerWidth(),height:g.outerHeight(),top:g.offset().top,left:g.offset().left},j=e.find(".layui-layer-TipsG"),k=b.tips[0];b.tips[1]||j.remove(),i.autoLeft=function(){i.left+f[0]-d.width()>0?(i.tipLeft=i.left+i.width-f[0],j.css({right:12,left:"auto"})):i.tipLeft=i.left},i.where=[function(){i.autoLeft(),i.tipTop=i.top-f[1]-10,j.removeClass("layui-layer-TipsB").addClass("layui-layer-TipsT").css("border-right-color",b.tips[1])},function(){i.tipLeft=i.left+i.width+10,i.tipTop=i.top,j.removeClass("layui-layer-TipsL").addClass("layui-layer-TipsR").css("border-bottom-color",b.tips[1])},function(){i.autoLeft(),i.tipTop=i.top+i.height+10,j.removeClass("layui-layer-TipsT").addClass("layui-layer-TipsB").css("border-right-color",b.tips[1])},function(){i.tipLeft=i.left-f[0]-10,i.tipTop=i.top,j.removeClass("layui-layer-TipsR").addClass("layui-layer-TipsL").css("border-bottom-color",b.tips[1])}],i.where[k-1](),1===k?i.top-(d.scrollTop()+f[1]+16)<0&&i.where[2]():2===k?d.width()-(i.left+i.width+f[0]+16)>0||i.where[3]():3===k?i.top-d.scrollTop()+i.height+f[1]+16-d.height()>0&&i.where[0]():4===k&&f[0]+16-i.left>0&&i.where[1](),e.find("."+h[5]).css({"background-color":b.tips[1],"padding-right":b.closeBtn?"30px":""}),e.css({left:i.tipLeft,top:i.tipTop})},g.pt.move=function(){var a=this,b=a.config,e={setY:0,moveLayer:function(){var a=e.layero,b=parseInt(a.css("margin-left")),c=parseInt(e.move.css("left"));0===b||(c-=b),"fixed"!==a.css("position")&&(c-=a.parent().offset().left,e.setY=0),a.css({left:c,top:parseInt(e.move.css("top"))-e.setY})}},f=a.layero.find(b.move);return b.move&&f.attr("move","ok"),f.css({cursor:b.move?"move":"auto"}),c(b.move).on("mousedown",function(a){if(a.preventDefault(),"ok"===c(this).attr("move")){e.ismove=!0,e.layero=c(this).parents("."+h[0]);var f=e.layero.offset().left,g=e.layero.offset().top,i=e.layero.outerWidth()-6,j=e.layero.outerHeight()-6;c("#layui-layer-moves")[0]||c("body").append('<div id="layui-layer-moves" class="layui-layer-moves" style="left:'+f+"px; top:"+g+"px; width:"+i+"px; height:"+j+'px; z-index:2147483584"></div>'),e.move=c("#layui-layer-moves"),b.moveType&&e.move.css({visibility:"hidden"}),e.moveX=a.pageX-e.move.position().left,e.moveY=a.pageY-e.move.position().top,"fixed"!==e.layero.css("position")||(e.setY=d.scrollTop())}}),c(document).mousemove(function(a){if(e.ismove){var c=a.pageX-e.moveX,f=a.pageY-e.moveY;if(a.preventDefault(),!b.moveOut){e.setY=d.scrollTop();var g=d.width()-e.move.outerWidth(),h=e.setY;0>c&&(c=0),c>g&&(c=g),h>f&&(f=h),f>d.height()-e.move.outerHeight()+e.setY&&(f=d.height()-e.move.outerHeight()+e.setY)}e.move.css({left:c,top:f}),b.moveType&&e.moveLayer(),c=f=g=h=null}}).mouseup(function(){try{e.ismove&&(e.moveLayer(),e.move.remove(),b.moveEnd&&b.moveEnd()),e.ismove=!1}catch(a){e.ismove=!1}}),a},g.pt.callback=function(){function a(){var a=g.cancel&&g.cancel(b.index);a===!1||f.close(b.index)}var b=this,d=b.layero,g=b.config;b.openLayer(),g.success&&(2==g.type?d.find("iframe").on("load",function(){g.success(d,b.index)}):g.success(d,b.index)),f.ie6&&b.IE6(d),d.find("."+h[6]).children("a").on("click",function(){var e=c(this).index();g["btn"+(e+1)]&&g["btn"+(e+1)](b.index,d),0===e?g.yes?g.yes(b.index,d):f.close(b.index):1===e?a():g["btn"+(e+1)]||f.close(b.index)}),d.find("."+h[7]).on("click",a),g.shadeClose&&c("#layui-layer-shade"+b.index).on("click",function(){f.close(b.index)}),d.find(".layui-layer-min").on("click",function(){f.min(b.index,g),g.min&&g.min(d)}),d.find(".layui-layer-max").on("click",function(){c(this).hasClass("layui-layer-maxmin")?(f.restore(b.index),g.restore&&g.restore(d)):(f.full(b.index,g),g.full&&g.full(d))}),g.end&&(e.end[b.index]=g.end)},e.reselect=function(){c.each(c("select"),function(a,b){var d=c(this);d.parents("."+h[0])[0]||1==d.attr("layer")&&c("."+h[0]).length<1&&d.removeAttr("layer").show(),d=null})},g.pt.IE6=function(a){function b(){a.css({top:f+(e.config.fix?d.scrollTop():0)})}var e=this,f=a.offset().top;b(),d.scroll(b),c("select").each(function(a,b){var d=c(this);d.parents("."+h[0])[0]||"none"===d.css("display")||d.attr({layer:"1"}).hide(),d=null})},g.pt.openLayer=function(){var a=this;f.zIndex=a.config.zIndex,f.setTop=function(a){var b=function(){f.zIndex++,a.css("z-index",f.zIndex+1)};return f.zIndex=parseInt(a[0].style.zIndex),a.on("mousedown",b),f.zIndex}},e.record=function(a){var b=[a.outerWidth(),a.outerHeight(),a.position().top,a.position().left+parseFloat(a.css("margin-left"))];a.find(".layui-layer-max").addClass("layui-layer-maxmin"),a.attr({area:b})},e.rescollbar=function(a){h.html.attr("layer-full")==a&&(h.html[0].style.removeProperty?h.html[0].style.removeProperty("overflow"):h.html[0].style.removeAttribute("overflow"),h.html.removeAttr("layer-full"))},a.layer=f,f.getChildFrame=function(a,b){return b=b||c("."+h[4]).attr("times"),c("#"+h[0]+b).find("iframe").contents().find(a)},f.getFrameIndex=function(a){return c("#"+a).parents("."+h[4]).attr("times")},f.iframeAuto=function(a){if(a){var b=f.getChildFrame("html",a).outerHeight(),d=c("#"+h[0]+a),e=d.find(h[1]).outerHeight()||0,g=d.find("."+h[6]).outerHeight()||0;d.css({height:b+e+g}),d.find("iframe").css({height:b})}},f.iframeSrc=function(a,b){c("#"+h[0]+a).find("iframe").attr("src",b)},f.style=function(a,b){var d=c("#"+h[0]+a),f=d.attr("type"),g=d.find(h[1]).outerHeight()||0,i=d.find("."+h[6]).outerHeight()||0;(f===e.type[1]||f===e.type[2])&&(d.css(b),f===e.type[2]&&d.find("iframe").css({height:parseFloat(b.height)-g-i}))},f.min=function(a,b){var d=c("#"+h[0]+a),g=d.find(h[1]).outerHeight()||0;e.record(d),f.style(a,{width:180,height:g,overflow:"hidden"}),d.find(".layui-layer-min").hide(),"page"===d.attr("type")&&d.find(h[4]).hide(),e.rescollbar(a)},f.restore=function(a){var b=c("#"+h[0]+a),d=b.attr("area").split(",");b.attr("type");f.style(a,{width:parseFloat(d[0]),height:parseFloat(d[1]),top:parseFloat(d[2]),left:parseFloat(d[3]),overflow:"visible"}),b.find(".layui-layer-max").removeClass("layui-layer-maxmin"),b.find(".layui-layer-min").show(),"page"===b.attr("type")&&b.find(h[4]).show(),e.rescollbar(a)},f.full=function(a){var b,g=c("#"+h[0]+a);e.record(g),h.html.attr("layer-full")||h.html.css("overflow","hidden").attr("layer-full",a),clearTimeout(b),b=setTimeout(function(){var b="fixed"===g.css("position");f.style(a,{top:b?0:d.scrollTop(),left:b?0:d.scrollLeft(),width:d.width(),height:d.height()}),g.find(".layui-layer-min").hide()},100)},f.title=function(a,b){var d=c("#"+h[0]+(b||f.index)).find(h[1]);d.html(a)},f.close=function(a){var b=c("#"+h[0]+a),d=b.attr("type");if(b[0]){if(d===e.type[1]&&"object"===b.attr("conType")){b.children(":not(."+h[5]+")").remove();for(var g=0;2>g;g++)b.find(".layui-layer-wrap").unwrap().hide()}else{if(d===e.type[2])try{var i=c("#"+h[4]+a)[0];i.contentWindow.document.write(""),i.contentWindow.close(),b.find("."+h[5])[0].removeChild(i)}catch(j){}b[0].innerHTML="",b.remove()}c("#layui-layer-moves, #layui-layer-shade"+a).remove(),f.ie6&&e.reselect(),e.rescollbar(a),c(document).off("keydown",e.enter),"function"==typeof e.end[a]&&e.end[a](),delete e.end[a]}},f.closeAll=function(a){c.each(c("."+h[0]),function(){var b=c(this),d=a?b.attr("type")===a:1;d&&f.close(b.attr("times")),d=null})},e.run=function(){c=jQuery,d=c(a),h.html=c("html"),f.open=function(a){var b=new g(a);return b.index}},"function"==typeof define?define(function(){return e.run(),f}):function(){e.run(),f.use("skin/layer.css")}()}(window);
0 3 \ No newline at end of file
... ...
src/main/resources/static/assets/plugins/layer-v2.2/layer/skin/default/icon-ext.png 0 → 100644

5.77 KB

src/main/resources/static/assets/plugins/layer-v2.2/layer/skin/default/icon.png 0 → 100644

11.2 KB

src/main/resources/static/assets/plugins/layer-v2.2/layer/skin/default/loading-0.gif 0 → 100644

5.66 KB

src/main/resources/static/assets/plugins/layer-v2.2/layer/skin/default/loading-1.gif 0 → 100644

701 Bytes

src/main/resources/static/assets/plugins/layer-v2.2/layer/skin/default/loading-2.gif 0 → 100644

1.75 KB

src/main/resources/static/assets/plugins/layer-v2.2/layer/skin/layer.css 0 → 100644
  1 +++ a/src/main/resources/static/assets/plugins/layer-v2.2/layer/skin/layer.css
  1 +/*!
  2 +
  3 + @Name: layer's style
  4 + @Author: 贤心
  5 + @Blog: sentsin.com
  6 +
  7 + */*html{background-image:url(about:blank);background-attachment:fixed}html #layui_layer_skinlayercss{display:none;position:absolute;width:1989px}.layui-layer,.layui-layer-shade{position:fixed;_position:absolute;pointer-events:auto}.layui-layer-shade{top:0;left:0;width:100%;height:100%;_height:expression(document.body.offsetHeight+"px")}.layui-layer{top:150px;left:50%;margin:0;padding:0;background-color:#fff;-webkit-background-clip:content;box-shadow:1px 1px 50px rgba(0,0,0,.3);border-radius:2px;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-duration:.3s;animation-duration:.3s}.layui-layer-close{position:absolute}.layui-layer-content{position:relative}.layui-layer-border{border:1px solid #B2B2B2;border:1px solid rgba(0,0,0,.3);box-shadow:1px 1px 5px rgba(0,0,0,.2)}.layui-layer-moves{position:absolute;border:3px solid #666;border:3px solid rgba(0,0,0,.5);cursor:move;background-color:#fff;background-color:rgba(255,255,255,.3);filter:alpha(opacity=50)}.layui-layer-load{background:url(default/loading-0.gif) center center no-repeat #fff}.layui-layer-ico{background:url(default/icon.png) no-repeat}.layui-layer-btn a,.layui-layer-dialog .layui-layer-ico,.layui-layer-setwin a{display:inline-block;*display:inline;*zoom:1;vertical-align:top}@-webkit-keyframes bounceIn{0%{opacity:0;-webkit-transform:scale(.5);transform:scale(.5)}100%{opacity:1;-webkit-transform:scale(1);transform:scale(1)}}@keyframes bounceIn{0%{opacity:0;-webkit-transform:scale(.5);-ms-transform:scale(.5);transform:scale(.5)}100%{opacity:1;-webkit-transform:scale(1);-ms-transform:scale(1);transform:scale(1)}}.layui-anim{-webkit-animation-name:bounceIn;animation-name:bounceIn}@-webkit-keyframes bounceOut{100%{opacity:0;-webkit-transform:scale(.7);transform:scale(.7)}30%{-webkit-transform:scale(1.03);transform:scale(1.03)}0%{-webkit-transform:scale(1);transform:scale(1)}}@keyframes bounceOut{100%{opacity:0;-webkit-transform:scale(.7);-ms-transform:scale(.7);transform:scale(.7)}30%{-webkit-transform:scale(1.03);-ms-transform:scale(1.03);transform:scale(1.03)}0%{-webkit-transform:scale(1);-ms-transform:scale(1);transform:scale(1)}}.layui-anim-close{-webkit-animation-name:bounceOut;animation-name:bounceOut;-webkit-animation-duration:.2s;animation-duration:.2s}@-webkit-keyframes zoomInDown{0%{opacity:0;-webkit-transform:scale(.1) translateY(-2000px);transform:scale(.1) translateY(-2000px);-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out}60%{opacity:1;-webkit-transform:scale(.475) translateY(60px);transform:scale(.475) translateY(60px);-webkit-animation-timing-function:ease-out;animation-timing-function:ease-out}}@keyframes zoomInDown{0%{opacity:0;-webkit-transform:scale(.1) translateY(-2000px);-ms-transform:scale(.1) translateY(-2000px);transform:scale(.1) translateY(-2000px);-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out}60%{opacity:1;-webkit-transform:scale(.475) translateY(60px);-ms-transform:scale(.475) translateY(60px);transform:scale(.475) translateY(60px);-webkit-animation-timing-function:ease-out;animation-timing-function:ease-out}}.layui-anim-01{-webkit-animation-name:zoomInDown;animation-name:zoomInDown}@-webkit-keyframes fadeInUpBig{0%{opacity:0;-webkit-transform:translateY(2000px);transform:translateY(2000px)}100%{opacity:1;-webkit-transform:translateY(0);transform:translateY(0)}}@keyframes fadeInUpBig{0%{opacity:0;-webkit-transform:translateY(2000px);-ms-transform:translateY(2000px);transform:translateY(2000px)}100%{opacity:1;-webkit-transform:translateY(0);-ms-transform:translateY(0);transform:translateY(0)}}.layui-anim-02{-webkit-animation-name:fadeInUpBig;animation-name:fadeInUpBig}@-webkit-keyframes zoomInLeft{0%{opacity:0;-webkit-transform:scale(.1) translateX(-2000px);transform:scale(.1) translateX(-2000px);-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out}60%{opacity:1;-webkit-transform:scale(.475) translateX(48px);transform:scale(.475) translateX(48px);-webkit-animation-timing-function:ease-out;animation-timing-function:ease-out}}@keyframes zoomInLeft{0%{opacity:0;-webkit-transform:scale(.1) translateX(-2000px);-ms-transform:scale(.1) translateX(-2000px);transform:scale(.1) translateX(-2000px);-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out}60%{opacity:1;-webkit-transform:scale(.475) translateX(48px);-ms-transform:scale(.475) translateX(48px);transform:scale(.475) translateX(48px);-webkit-animation-timing-function:ease-out;animation-timing-function:ease-out}}.layui-anim-03{-webkit-animation-name:zoomInLeft;animation-name:zoomInLeft}@-webkit-keyframes rollIn{0%{opacity:0;-webkit-transform:translateX(-100%) rotate(-120deg);transform:translateX(-100%) rotate(-120deg)}100%{opacity:1;-webkit-transform:translateX(0) rotate(0);transform:translateX(0) rotate(0)}}@keyframes rollIn{0%{opacity:0;-webkit-transform:translateX(-100%) rotate(-120deg);-ms-transform:translateX(-100%) rotate(-120deg);transform:translateX(-100%) rotate(-120deg)}100%{opacity:1;-webkit-transform:translateX(0) rotate(0);-ms-transform:translateX(0) rotate(0);transform:translateX(0) rotate(0)}}.layui-anim-04{-webkit-animation-name:rollIn;animation-name:rollIn}@keyframes fadeIn{0%{opacity:0}100%{opacity:1}}.layui-anim-05{-webkit-animation-name:fadeIn;animation-name:fadeIn}@-webkit-keyframes shake{0%,100%{-webkit-transform:translateX(0);transform:translateX(0)}10%,30%,50%,70%,90%{-webkit-transform:translateX(-10px);transform:translateX(-10px)}20%,40%,60%,80%{-webkit-transform:translateX(10px);transform:translateX(10px)}}@keyframes shake{0%,100%{-webkit-transform:translateX(0);-ms-transform:translateX(0);transform:translateX(0)}10%,30%,50%,70%,90%{-webkit-transform:translateX(-10px);-ms-transform:translateX(-10px);transform:translateX(-10px)}20%,40%,60%,80%{-webkit-transform:translateX(10px);-ms-transform:translateX(10px);transform:translateX(10px)}}.layui-anim-06{-webkit-animation-name:shake;animation-name:shake}@-webkit-keyframes fadeIn{0%{opacity:0}100%{opacity:1}}.layui-layer-title{padding:0 80px 0 20px;height:42px;line-height:42px;border-bottom:1px solid #eee;font-size:14px;color:#333;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;background-color:#F8F8F8;border-radius:2px 2px 0 0}.layui-layer-setwin{position:absolute;right:15px;*right:0;top:15px;font-size:0;line-height:initial}.layui-layer-setwin a{position:relative;width:16px;height:16px;margin-left:10px;font-size:12px;_overflow:hidden}.layui-layer-setwin .layui-layer-min cite{position:absolute;width:14px;height:2px;left:0;top:50%;margin-top:-1px;background-color:#2E2D3C;cursor:pointer;_overflow:hidden}.layui-layer-setwin .layui-layer-min:hover cite{background-color:#2D93CA}.layui-layer-setwin .layui-layer-max{background-position:-32px -40px}.layui-layer-setwin .layui-layer-max:hover{background-position:-16px -40px}.layui-layer-setwin .layui-layer-maxmin{background-position:-65px -40px}.layui-layer-setwin .layui-layer-maxmin:hover{background-position:-49px -40px}.layui-layer-setwin .layui-layer-close1{background-position:0 -40px;cursor:pointer}.layui-layer-setwin .layui-layer-close1:hover{opacity:.7}.layui-layer-setwin .layui-layer-close2{position:absolute;right:-28px;top:-28px;width:30px;height:30px;margin-left:0;background-position:-149px -31px;*right:-18px;_display:none}.layui-layer-setwin .layui-layer-close2:hover{background-position:-180px -31px}.layui-layer-btn{text-align:right;padding:0 10px 12px;pointer-events:auto}.layui-layer-btn a{height:28px;line-height:28px;margin:0 6px;padding:0 15px;border:1px solid #dedede;background-color:#f1f1f1;color:#333;border-radius:2px;font-weight:400;cursor:pointer;text-decoration:none}.layui-layer-btn a:hover{opacity:.9;text-decoration:none}.layui-layer-btn a:active{opacity:.7}.layui-layer-btn .layui-layer-btn0{border-color:#4898d5;background-color:#2e8ded;color:#fff}.layui-layer-dialog{min-width:260px}.layui-layer-dialog .layui-layer-content{position:relative;padding:20px;line-height:24px;word-break:break-all;font-size:14px;overflow:auto}.layui-layer-dialog .layui-layer-content .layui-layer-ico{position:absolute;top:16px;left:15px;_left:-40px;width:30px;height:30px}.layui-layer-ico1{background-position:-30px 0}.layui-layer-ico2{background-position:-60px 0}.layui-layer-ico3{background-position:-90px 0}.layui-layer-ico4{background-position:-120px 0}.layui-layer-ico5{background-position:-150px 0}.layui-layer-ico6{background-position:-180px 0}.layui-layer-rim{border:6px solid #8D8D8D;border:6px solid rgba(0,0,0,.3);border-radius:5px;box-shadow:none}.layui-layer-msg{min-width:180px;border:1px solid #D3D4D3;box-shadow:none}.layui-layer-hui{min-width:100px;background-color:#000;filter:alpha(opacity=60);background-color:rgba(0,0,0,.6);color:#fff;border:none}.layui-layer-hui .layui-layer-content{padding:12px 25px;text-align:center}.layui-layer-dialog .layui-layer-padding{padding:20px 20px 20px 55px;text-align:left}.layui-layer-page .layui-layer-content{position:relative;overflow:auto}.layui-layer-iframe .layui-layer-btn,.layui-layer-page .layui-layer-btn{padding-top:10px}.layui-layer-nobg{background:0 0}.layui-layer-iframe .layui-layer-content{overflow:hidden}.layui-layer-iframe iframe{display:block;width:100%}.layui-layer-loading{border-radius:100%;background:0 0;box-shadow:none;border:none}.layui-layer-loading .layui-layer-content{width:60px;height:24px;background:url(default/loading-0.gif) no-repeat}.layui-layer-loading .layui-layer-loading1{width:37px;height:37px;background:url(default/loading-1.gif) no-repeat}.layui-layer-ico16,.layui-layer-loading .layui-layer-loading2{width:32px;height:32px;background:url(default/loading-2.gif) no-repeat}.layui-layer-tips{background:0 0;box-shadow:none;border:none}.layui-layer-tips .layui-layer-content{position:relative;line-height:22px;min-width:12px;padding:5px 10px;font-size:12px;_float:left;border-radius:3px;box-shadow:1px 1px 3px rgba(0,0,0,.3);background-color:#F90;color:#fff}.layui-layer-tips .layui-layer-close{right:-2px;top:-1px}.layui-layer-tips i.layui-layer-TipsG{position:absolute;width:0;height:0;border-width:8px;border-color:transparent;border-style:dashed;*overflow:hidden}.layui-layer-tips i.layui-layer-TipsB,.layui-layer-tips i.layui-layer-TipsT{left:5px;border-right-style:solid;border-right-color:#F90}.layui-layer-tips i.layui-layer-TipsT{bottom:-8px}.layui-layer-tips i.layui-layer-TipsB{top:-8px}.layui-layer-tips i.layui-layer-TipsL,.layui-layer-tips i.layui-layer-TipsR{top:1px;border-bottom-style:solid;border-bottom-color:#F90}.layui-layer-tips i.layui-layer-TipsR{left:-8px}.layui-layer-tips i.layui-layer-TipsL{right:-8px}.layui-layer-lan[type=dialog]{min-width:280px}.layui-layer-lan .layui-layer-title{background:#4476A7;color:#fff;border:none}.layui-layer-lan .layui-layer-btn{padding:10px;text-align:right;border-top:1px solid #E9E7E7}.layui-layer-lan .layui-layer-btn a{background:#BBB5B5;border:none}.layui-layer-lan .layui-layer-btn .layui-layer-btn1{background:#C9C5C5}.layui-layer-molv .layui-layer-title{background:#009f95;color:#fff;border:none}.layui-layer-molv .layui-layer-btn a{background:#009f95}.layui-layer-molv .layui-layer-btn .layui-layer-btn1{background:#92B8B1}
0 8 \ No newline at end of file
... ...
src/main/resources/static/assets/plugins/layer-v2.2/layer/skin/layer.ext.css 0 → 100644
  1 +++ a/src/main/resources/static/assets/plugins/layer-v2.2/layer/skin/layer.ext.css
  1 +/*!
  2 +
  3 + @Name: layer拓展样式
  4 + @Date: 2012.12.13
  5 + @Author: 贤心
  6 + @blog: sentsin.com
  7 +
  8 + */.layui-layer-imgbar,.layui-layer-imgtit a,.layui-layer-tab .layui-layer-title span{text-overflow:ellipsis;white-space:nowrap}.layui-layer-iconext{background:url(default/icon-ext.png) no-repeat}html #layui_layer_skinlayerextcss{display:none;position:absolute;width:1989px}.layui-layer-prompt .layui-layer-input{display:block;width:220px;height:30px;margin:0 auto;line-height:30px;padding:0 5px;border:1px solid #ccc;box-shadow:1px 1px 5px rgba(0,0,0,.1) inset;color:#333}.layui-layer-prompt textarea.layui-layer-input{width:300px;height:100px;line-height:20px}.layui-layer-tab{box-shadow:1px 1px 50px rgba(0,0,0,.4)}.layui-layer-tab .layui-layer-title{padding-left:0;border-bottom:1px solid #ccc;background-color:#eee;overflow:visible}.layui-layer-tab .layui-layer-title span{position:relative;float:left;min-width:80px;max-width:260px;padding:0 20px;text-align:center;cursor:default;overflow:hidden}.layui-layer-tab .layui-layer-title span.layui-layer-tabnow{height:43px;border-left:1px solid #ccc;border-right:1px solid #ccc;background-color:#fff;z-index:10}.layui-layer-tab .layui-layer-title span:first-child{border-left:none}.layui-layer-tabmain{line-height:24px;clear:both}.layui-layer-tabmain .layui-layer-tabli{display:none}.layui-layer-tabmain .layui-layer-tabli.xubox_tab_layer{display:block}.xubox_tabclose{position:absolute;right:10px;top:5px;cursor:pointer}.layui-layer-photos{-webkit-animation-duration:1s;animation-duration:1s}.layui-layer-photos .layui-layer-content{overflow:hidden;text-align:center}.layui-layer-photos .layui-layer-phimg img{position:relative;width:100%;display:inline-block;*display:inline;*zoom:1;vertical-align:top}.layui-layer-imgbar,.layui-layer-imguide{display:none}.layui-layer-imgnext,.layui-layer-imgprev{position:absolute;top:50%;width:27px;_width:44px;height:44px;margin-top:-22px;outline:0;blr:expression(this.onFocus=this.blur())}.layui-layer-imgprev{left:10px;background-position:-5px -5px;_background-position:-70px -5px}.layui-layer-imgprev:hover{background-position:-33px -5px;_background-position:-120px -5px}.layui-layer-imgnext{right:10px;_right:8px;background-position:-5px -50px;_background-position:-70px -50px}.layui-layer-imgnext:hover{background-position:-33px -50px;_background-position:-120px -50px}.layui-layer-imgbar{position:absolute;left:0;bottom:0;width:100%;height:32px;line-height:32px;background-color:rgba(0,0,0,.8);background-color:#000\9;filter:Alpha(opacity=80);color:#fff;overflow:hidden;font-size:0}.layui-layer-imgtit *{display:inline-block;*display:inline;*zoom:1;vertical-align:top;font-size:12px}.layui-layer-imgtit a{max-width:65%;overflow:hidden;color:#fff}.layui-layer-imgtit a:hover{color:#fff;text-decoration:underline}.layui-layer-imgtit em{padding-left:10px;font-style:normal}
0 9 \ No newline at end of file
... ...
src/main/resources/static/assets/plugins/layer-v2.2/更新日志.txt 0 → 100644
  1 +++ a/src/main/resources/static/assets/plugins/layer-v2.2/鏇存柊鏃ュ織.txt
  1 +
  2 +(2.x对1.9+版本无缝兼容,可直接全文件覆盖升级。)
  3 +
  4 +【2.2】2016.03.18
  5 +> 增加参数id,用于控制弹层唯一标识。如不想重复弹出,可设置该值。
  6 +> layer.tips允许出现遮罩,即不对shade参数做限制。
  7 +> 对layer.photos方法直接弹出页面图片进行了事件委托,修复了之前由于动态插入的img而无法执行弹出的bug,并且修复了当图片信息改变时,仍然弹出了之前的图片的bug
  8 +> layer.photos方法多处代码进行了优化
  9 +> 对layer.tab方法新增回调函数change,用于监听选项卡的切换事件,返回一个选项卡索引参数。
  10 +> 样式微调
  11 +
  12 +
  13 +【2.1】2015.11.04
  14 +> 修复在使用seajs或者requirejs后,layer.ext.js报layer未定义的错误。
  15 +> 修复弹出层后,回车键无效的bug。
  16 +> 修复iframe层的success回调在ie8以下浏览器无效的bug
  17 +> 修复只有一张图片时,并且该图片地址异常,不断弹出提示的bug。
  18 +> 修复当设定moveEnd回调,即便层关闭,仍然触发该回调的bug
  19 +> 即便采用模块加载,layer对象仍然保留全局,原因是layer自有模块需要。
  20 +> 优化图标锯齿
  21 +
  22 +【2.0】2015.09.01
  23 +> 全新的默认皮肤
  24 +> 修复按住Enter键时,出现不断弹层的bug。
  25 +> 修复模块加载时,layer仍然暴露给了全局的bug。
  26 +> 修复拖拽完毕回调moveEnd,在层关闭后拖拽鼠标仍然触发该回调的bug。
  27 +> 确认和取消的回调除了yes和cancel外,还可用btn1/btn2。 btn2可解决取消遇右上角关闭共用cancel回调的问题。即如果你只需要接受取消的回调,可以使用 btn2: function(){}
  28 +
  29 +> 修复通过<script>标签引入layer.ext.js时,出现Cannot read property 'skin' of undefined的报错问题。(虽然我们更推荐用layer.config()方式加载layer.ext.js)。
  30 +> 如果相册只有一张图片,则不触发上/下一张。
  31 +
  32 +
  33 +—— http://layer.layui.com
0 34 \ No newline at end of file
... ...