Commit cb6a0a7f6d679cbe962bb2e323e810df324894af
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
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 | \ No newline at end of file | 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 | \ No newline at end of file | 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
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
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 | \ No newline at end of file | 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 | \ No newline at end of file | 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 | \ No newline at end of file | 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,"&").replace(/"/g,""")}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 | \ No newline at end of file | 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 | \ No newline at end of file | 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
src/main/resources/static/assets/plugins/layer-v2.2/doc/layer交流.url
0 → 100644
src/main/resources/static/assets/plugins/layer-v2.2/doc/layer官网.url
0 → 100644
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:["确定","取消"],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("最多输入"+(a.maxlength||500)+"个字数",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("没有图片")}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("当前图片地址异常<br>是否继续查看下一张?",{time:3e4,btn:["下一张","不看了"],yes:function(){i.length>1&&f.imgnext(!0,!0)}})})}}}(); | ||
| 0 | \ No newline at end of file | 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:["确定","取消"],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:"信息",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 | \ No newline at end of file | 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 | \ No newline at end of file | 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 | \ No newline at end of file | 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 | \ No newline at end of file | 34 | \ No newline at end of file |