更新框架基础文件

pull/1/head
759675757@qq.com 2019-05-23 17:45:41 +08:00
parent e711199666
commit 01a88e72d7
37 changed files with 12641 additions and 177 deletions

View File

@ -48,6 +48,17 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-springsecurity5</artifactId>
</dependency>
<!--Lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
@ -107,6 +118,11 @@
<version>3.9</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
<build>

View File

@ -17,10 +17,8 @@ public class BlogController {
@Autowired
private BlogService blogService;
@GetMapping("/hello")
@GetMapping
String blog() {
String hello = blogService.hello();
System.out.println(hello);
return "client/blog/index";
}

View File

@ -5,5 +5,4 @@ package com.songpeng.blog.service;
*/
public interface BlogService {
String hello();
}

View File

@ -5,13 +5,10 @@ import org.springframework.stereotype.Service;
/**
* Controller
* Created by songpeng on 2019/5/21.
* @author songpeng
* @date 2019/5/21
*/
@Service
public class BlogServiceImpl implements BlogService {
@Override
public String hello() {
return "hello";
}
}

View File

@ -20,7 +20,7 @@ import javax.servlet.http.HttpServletRequest;
@ControllerAdvice
public class ApiAdvice {
public static final Logger logger = LoggerFactory.getLogger(ApiAdvice.class);
public static final Logger LOGGER = LoggerFactory.getLogger(ApiAdvice.class);
/**
* @RequestMapping
@ -65,7 +65,7 @@ public class ApiAdvice {
@ExceptionHandler(Exception.class)
@ResponseBody
public ApiResponse handle(HttpServletRequest request, Exception e) throws Exception {
logger.error("API接口调用异常: {}", request.getRequestURI(), e);
LOGGER.error("API接口调用异常: {}", request.getRequestURI(), e);
return ApiResponse.error(ApiResponse.ERROR_CODE, ApiResponse.ERROR_MSG);
}

View File

@ -0,0 +1,46 @@
package com.songpeng.common.config;
import com.songpeng.system.service.impl.SysUserServiceImpl;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
/**
* Controller
*
* @author songpeng
* @date 2019/5/23
*/
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Bean
UserDetailsService customUserService() { //注册UserDetailsService 的bean
return new SysUserServiceImpl();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
// user Details Service验证
auth.userDetailsService(customUserService());
}
@Override
protected void configure(HttpSecurity http) throws Exception {
// TODO 1. csrf 暂时关闭
http.authorizeRequests().anyRequest().permitAll().and().csrf().disable();
// .anyRequest().authenticated() //任何请求,登录后可以访问
// .and()
// .formLogin()
// .loginPage("/login")
// .failureUrl("/login?error")
// .permitAll() //登录页面用户任意访问
// .and()
// .logout().permitAll(); //注销行为任意访问
}
}

View File

@ -0,0 +1,123 @@
package com.songpeng.common.utils;
import java.util.regex.Pattern;
/**
* ByteUtil
*
* @author songpeng
* @date 2019/5/23
*/
public class ByteUtil {
/**
* Join two byte arrays to a new byte array.
*/
public static byte[] concat(byte[] buf1, byte[] buf2) {
byte[] buffer = new byte[buf1.length + buf2.length];
int offset = 0;
System.arraycopy(buf1, 0, buffer, offset, buf1.length);
offset += buf1.length;
System.arraycopy(buf2, 0, buffer, offset, buf2.length);
return buffer;
}
/**
* Join three byte arrays to a new byte array.
*/
public static byte[] concat(byte[] buf1, byte[] buf2, byte[] buf3) {
byte[] buffer = new byte[buf1.length + buf2.length + buf3.length];
int offset = 0;
System.arraycopy(buf1, 0, buffer, offset, buf1.length);
offset += buf1.length;
System.arraycopy(buf2, 0, buffer, offset, buf2.length);
offset += buf2.length;
System.arraycopy(buf3, 0, buffer, offset, buf3.length);
return buffer;
}
/**
* Convert bytes to hex string (all lower-case).
*
* @param b Input bytes.
* @return Hex string.
*/
public static String toHexString(byte[] b) {
StringBuilder sb = new StringBuilder(b.length * 2);
for (byte x : b) {
int hi = (x & 0xf0) >> 4;
int lo = x & 0x0f;
sb.append(HEX_CHARS[hi]);
sb.append(HEX_CHARS[lo]);
}
return sb.toString().trim();
}
/**
* Convert byte to hex string (all lower-case).
*
* @param b Input bytes.
* @return Hex string.
*/
public static String toHex(byte b) {
int hi = (b & 0xf0) >> 4;
int lo = b & 0x0f;
char[] cs = { HEX_CHARS[hi], HEX_CHARS[lo] };
return new String(cs);
}
public static byte fromHex(String s) {
if (s.length() != 2) {
throw new IllegalArgumentException("Invalid length of string.");
}
char c1 = s.charAt(0);
char c2 = s.charAt(1);
int n1 = HEX_STRING.indexOf(c1);
int n2 = HEX_STRING.indexOf(c2);
if (n1 == (-1)) {
throw new IllegalArgumentException("Invalid char in string: " + c1);
}
if (n2 == (-1)) {
throw new IllegalArgumentException("Invalid char in string: " + c2);
}
int n = (n1 << 4) + n2;
return (byte) n;
}
public static byte[] fromHexString(String s) {
if (s.length() % 2 == 1) {
throw new IllegalArgumentException("Invalid length of string.");
}
byte[] data = new byte[s.length() / 2];
for (int i = 0; i < data.length; i++) {
char c1 = s.charAt(i * 2);
char c2 = s.charAt(i * 2 + 1);
int n1 = HEX_STRING.indexOf(c1);
int n2 = HEX_STRING.indexOf(c2);
if (n1 == (-1)) {
throw new IllegalArgumentException("Invalid char in string: " + c1);
}
if (n2 == (-1)) {
throw new IllegalArgumentException("Invalid char in string: " + c2);
}
int n = (n1 << 4) + n2;
data[i] = (byte) n;
}
return data;
}
public static boolean isSha1(String s) {
return PATTERN_SHA1.matcher(s).matches();
}
public static boolean isSha256(String s) {
return PATTERN_SHA256.matcher(s).matches();
}
private static final String HEX_STRING = "0123456789abcdef";
private static final char[] HEX_CHARS = HEX_STRING.toCharArray();
private static final Pattern PATTERN_SHA1 = Pattern.compile("^[a-f0-9]{40}$");
private static final Pattern PATTERN_SHA256 = Pattern.compile("^[a-f0-9]{64}$");
}

View File

@ -0,0 +1,212 @@
package com.songpeng.common.utils;
import java.nio.charset.StandardCharsets;
import java.security.GeneralSecurityException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import javax.crypto.Mac;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
/**
* Utility class for hashing.
*
* @author songpeng
* @date 2019/5/23
*/
public class HashUtil {
/**
* Generate SHA-1 as hex string (all lower-case).
*
* @param input Input as string.
* @return Hex string.
*/
public static String sha1(String input) {
return sha1(input.getBytes(StandardCharsets.UTF_8));
}
/**
* Generate SHA-1 as hex string (all lower-case).
*
* @param input Input as bytes.
* @return Hex string.
*/
public static String sha1(byte[] input) {
MessageDigest md = null;
try {
md = MessageDigest.getInstance("SHA1");
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e);
}
md.update(input);
byte[] digest = md.digest();
return ByteUtil.toHexString(digest);
}
public static byte[] sha1AsBytes(String input) {
return sha1AsBytes(input.getBytes(StandardCharsets.UTF_8));
}
/**
* Generate SHA-1 as bytes.
*
* @param input Input as bytes.
* @return Bytes.
*/
public static byte[] sha1AsBytes(byte[] input) {
MessageDigest md = null;
try {
md = MessageDigest.getInstance("SHA1");
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e);
}
md.update(input);
return md.digest();
}
/**
* Generate SHA-256 as hex string (all lower-case).
*
* @param input Input as String.
* @return Hex string.
*/
public static String sha256(String input) {
return sha256(input.getBytes(StandardCharsets.UTF_8));
}
/**
* Generate SHA-256 as hex string (all lower-case).
*
* @param input Input as String.
* @return Hex string.
*/
public static byte[] sha256AsBytes(String input) {
return sha256AsBytes(input.getBytes(StandardCharsets.UTF_8));
}
/**
* Generate SHA-256 as hex string (all lower-case).
*
* @param input Input as bytes.
* @return Hex string.
*/
public static String sha256(byte[] input) {
MessageDigest md = null;
try {
md = MessageDigest.getInstance("SHA-256");
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e);
}
md.update(input);
byte[] digest = md.digest();
return ByteUtil.toHexString(digest);
}
/**
* Generate SHA-256 as bytes.
*
* @param input Input as bytes.
* @return SHA bytes.
*/
public static byte[] sha256AsBytes(byte[] input) {
MessageDigest md = null;
try {
md = MessageDigest.getInstance("SHA-256");
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e);
}
md.update(input);
return md.digest();
}
/**
* Generate SHA-512 as bytes.
*
* @param input Input as bytes.
* @return SHA bytes.
*/
public static byte[] sha512AsBytes(byte[] input) {
MessageDigest md = null;
try {
md = MessageDigest.getInstance("SHA-512");
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e);
}
md.update(input);
return md.digest();
}
/**
* Do HMAC-SHA256.
*
* @return Hex string.
*/
public static byte[] hmacSha256AsBytes(byte[] data, byte[] key) {
SecretKey skey = new SecretKeySpec(key, "HmacSHA256");
Mac mac;
try {
mac = Mac.getInstance("HmacSHA256");
mac.init(skey);
} catch (GeneralSecurityException e) {
throw new RuntimeException(e);
}
mac.update(data);
return mac.doFinal();
}
/**
* Do HMAC-SHA256.
*
* @return Hex string.
*/
public static String hmacSha256(byte[] data, byte[] key) {
return ByteUtil.toHexString(hmacSha256AsBytes(data, key));
}
/**
* Do HMAC-SHA1.
*
* @return byte[] as result.
*/
public static byte[] hmacSha1(byte[] data, byte[] key) {
SecretKey skey = new SecretKeySpec(key, "HmacSHA1");
Mac mac;
try {
mac = Mac.getInstance("HmacSHA1");
mac.init(skey);
} catch (GeneralSecurityException e) {
throw new RuntimeException(e);
}
mac.update(data);
return mac.doFinal();
}
/**
* Do HMAC-SHA256.
*
* @return byte[] as result.
*/
public static String hmacSha256(String data, String key) {
return hmacSha256(data.getBytes(StandardCharsets.UTF_8), key.getBytes(StandardCharsets.UTF_8));
}
/**
* Do HMAC-SHA256.
*
* @return byte[] as result.
*/
public static byte[] hmacSha256AsBytes(String data, String key) {
return hmacSha256AsBytes(data.getBytes(StandardCharsets.UTF_8), key.getBytes(StandardCharsets.UTF_8));
}
/**
* Do HMAC-SHA256.
*
* @return byte[] as result.
*/
public static String hmacSha256(byte[] data, String key) {
return hmacSha256(data, key.getBytes(StandardCharsets.UTF_8));
}
}

View File

@ -0,0 +1,130 @@
package com.songpeng.common.utils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.time.LocalDate;
import java.time.ZoneId;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* 53 bits unique id:
*
* |--------|--------|--------|--------|--------|--------|--------|--------|
* |00000000|00011111|11111111|11111111|11111111|11111111|11111111|11111111|
* |--------|---xxxxx|xxxxxxxx|xxxxxxxx|xxxxxxxx|xxx-----|--------|--------|
* |--------|--------|--------|--------|--------|---xxxxx|xxxxxxxx|xxx-----|
* |--------|--------|--------|--------|--------|--------|--------|---xxxxx|
*
* Maximum ID = 11111_11111111_11111111_11111111_11111111_11111111_11111111
*
* Maximum TS = 11111_11111111_11111111_11111111_111
*
* Maximum NT = ----- -------- -------- -------- ---11111_11111111_111 = 65535
*
* Maximum SH = ----- -------- -------- -------- -------- -------- ---11111 = 31
*
* It can generate 64k unique id per IP and up to 2106-02-07T06:28:15Z.
*
* 2106
*
* 6565
*
*
*
* host-1host-2
*
* 5364Web
* JavaScriptJavaScript53JavaScript
* 使53JavaScript53JavaScript
* APIAPIididstr
*
* https://mp.weixin.qq.com/s/C6QkzzUMPiYov8GO8zJTLA
*
* @author songpeng
* @date 2019/05/23
*/
public final class IdUtil {
private static final Logger LOGGER = LoggerFactory.getLogger(IdUtil.class);
private static final Pattern PATTERN_LONG_ID = Pattern.compile("^([0-9]{15})([0-9a-f]{32})([0-9a-f]{3})$");
private static final Pattern PATTERN_HOSTNAME = Pattern.compile("^.*\\D+([0-9]+)$");
private static final long OFFSET = LocalDate.of(2000, 1, 1).atStartOfDay(ZoneId.of("Z")).toEpochSecond();
private static final long MAX_NEXT = 0b11111_11111111_111L;
private static final long SHARD_ID = getServerIdAsLong();
private static long offset = 0;
private static long lastEpoch = 0;
public static long nextId() {
return nextId(System.currentTimeMillis() / 1000);
}
private static synchronized long nextId(long epochSecond) {
if (epochSecond < lastEpoch) {
// warning: clock is turn back:
LOGGER.warn("clock is back: " + epochSecond + " from previous:" + lastEpoch);
epochSecond = lastEpoch;
}
if (lastEpoch != epochSecond) {
lastEpoch = epochSecond;
reset();
}
offset++;
long next = offset & MAX_NEXT;
if (next == 0) {
LOGGER.warn("maximum id reached in 1 second in epoch: " + epochSecond);
return nextId(epochSecond + 1);
}
return generateId(epochSecond, next, SHARD_ID);
}
private static void reset() {
offset = 0;
}
private static long generateId(long epochSecond, long next, long shardId) {
return ((epochSecond - OFFSET) << 21) | (next << 5) | shardId;
}
private static long getServerIdAsLong() {
try {
String hostname = InetAddress.getLocalHost().getHostName();
Matcher matcher = PATTERN_HOSTNAME.matcher(hostname);
if (matcher.matches()) {
long n = Long.parseLong(matcher.group(1));
if (n >= 0 && n < 8) {
LOGGER.info("detect server id from host name {}: {}.", hostname, n);
return n;
}
}
} catch (UnknownHostException e) {
LOGGER.warn("unable to get host name. set server id = 0.");
}
return 0;
}
public static long stringIdToLongId(String stringId) {
// a stringId id is composed as timestamp (15) + uuid (32) + serverId (000~fff).
Matcher matcher = PATTERN_LONG_ID.matcher(stringId);
if (matcher.matches()) {
long epoch = Long.parseLong(matcher.group(1)) / 1000;
String uuid = matcher.group(2);
byte[] sha1 = HashUtil.sha1AsBytes(uuid);
long next = ((sha1[0] << 24) | (sha1[1] << 16) | (sha1[2] << 8) | sha1[3]) & MAX_NEXT;
long serverId = Long.parseLong(matcher.group(3), 16);
return generateId(epoch, next, serverId);
}
throw new IllegalArgumentException("Invalid id: " + stringId);
}
}

View File

@ -0,0 +1,54 @@
/**
IDID
IDUUIDID
ID32int使64long
IDID
ID1OracleSEQUENCEMySQLAUTO_INCREMENT
IDIDIDID
IDRedisZooKeeperID
TwitterSnowflake++IDIDID
Snowflake41bit10bitID12bit10244096000Twitter
400ID1024使ID
53bitID32bit+16bit+5bit3265
private static synchronized long nextId(long epochSecond) {
if (epochSecond < lastEpoch) {
// warning: clock is turn back:
logger.warn("clock is back: " + epochSecond + " from previous:" + lastEpoch);
epochSecond = lastEpoch;
}
if (lastEpoch != epochSecond) {
lastEpoch = epochSecond;
reset();
}
offset++;
long next = offset & MAX_NEXT;
if (next == 0) {
logger.warn("maximum id reached in 1 second in epoch: " + epochSecond);
return nextId(epochSecond + 1);
}
return generateId(epochSecond, next, SHARD_ID);
}
2106
6565
host-1host-2
5364WebJavaScriptJavaScript53JavaScript使53JavaScript53JavaScriptAPIAPIididstr
*/
package com.songpeng.common.utils;

View File

@ -0,0 +1,52 @@
package com.songpeng.system.controller.admin;
import com.github.pagehelper.PageInfo;
import com.songpeng.common.utils.ApiResponse;
import com.songpeng.common.utils.PageRequest;
import com.songpeng.system.domain.SysUser;
import com.songpeng.system.dto.SysUserDto;
import com.songpeng.system.service.SysUserService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import java.util.HashMap;
import java.util.Map;
/**
* Controller
*
* @author songpeng
* @date 2019-04-19
*/
@RequestMapping("/admin/sys/user")
@Controller("adminUserController")
public class SysUserController {
/**
*
*/
private static final Logger LOGGER = LoggerFactory.getLogger(SysUserController.class);
@Autowired
private SysUserService sysUserService;
@RequestMapping("/page")
@ResponseBody
public ApiResponse getPage(PageRequest pageRequest) {
LOGGER.info("获取用户列表");
PageInfo<SysUserDto> pageInfo = sysUserService.getPage(pageRequest);
Map<String, Object> result = new HashMap<>(1);
result.put("result", pageInfo);
return ApiResponse.ok(result);
}
@PostMapping("/add")
@ResponseBody
public ApiResponse add(SysUser sysUser, String[] roles) {
sysUserService.add(sysUser, roles);
return ApiResponse.ok();
}
}

View File

@ -1,46 +0,0 @@
package com.songpeng.system.controller.admin;
import com.github.pagehelper.PageInfo;
import com.songpeng.common.utils.ApiResponse;
import com.songpeng.common.utils.PageRequest;
import com.songpeng.system.domain.User;
import com.songpeng.system.service.UserService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import java.util.HashMap;
import java.util.Map;
/**
* Controller
*
* @author songpeng
* @date 2019-04-19
*/
@RequestMapping("/admin/sys/user")
@Controller("adminUserController")
public class UserController {
@Autowired
private UserService userService;
/**
*
*/
private static final Logger logger = LoggerFactory.getLogger(UserController.class);
@RequestMapping("/page")
@ResponseBody
public ApiResponse getPage(PageRequest pageRequest) {
logger.info("获取用户列表");
PageInfo<User> pageInfo = userService.getPage(pageRequest);
Map<String, Object> res = new HashMap<>(2);
res.put("result", pageInfo);
return ApiResponse.ok(res);
}
}

View File

@ -31,4 +31,34 @@ public class LoginController {
return "redirect:/blog";
}
/**
* 访
*
* @param model
* @return
*/
@GetMapping({"/index"})
String index(Model model) {
// List<Tree<MenuDO>> menus = menuService.listMenuTree(getUserId());
// model.addAttribute("menus", menus);
// model.addAttribute("name", getUser().getName());
// FileDO fileDO = fileService.get(getUser().getPicId());
// if (fileDO != null && fileDO.getUrl() != null) {
// if (fileService.isExist(fileDO.getUrl())) {
// model.addAttribute("picUrl", fileDO.getUrl());
// } else {
// model.addAttribute("picUrl", "/img/photo_s.jpg");
// }
// } else {
// model.addAttribute("picUrl", "/img/photo_s.jpg");
// }
// model.addAttribute("username", getUser().getUsername());
return "admin/index";
}
@GetMapping("/main")
String main() {
return "admin/main";
}
}

View File

@ -0,0 +1,38 @@
package com.songpeng.system.domain;
/**
*
*
* @author songpeng
* @date 2019/5/23
*/
public class SysRole {
private Long id;
private String name;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
final StringBuffer sb = new StringBuffer("SysRole{");
sb.append("id=").append(id);
sb.append(", name='").append(name).append('\'');
sb.append('}');
return sb.toString();
}
}

View File

@ -0,0 +1,71 @@
package com.songpeng.system.domain;
import javax.persistence.Column;
import javax.persistence.Id;
import javax.persistence.Table;
import java.io.Serializable;
/**
*
*
* @author songpeng
* @date 2019/05/21
*/
@Table(name = "SYS_USER")
public class SysUser implements Serializable {
private static final long serialVersionUID = -583330206794726157L;
@Id
@Column(name = "ID")
private Long id;
@Column(name = "NAME")
private String name;
@Column(name = "USERNAME")
private String username;
@Column(name = "PASSWORD")
private String password;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public String toString() {
final StringBuffer sb = new StringBuffer("SysUser{");
sb.append("id=").append(id);
sb.append(", name='").append(name).append('\'');
sb.append(", username='").append(username).append('\'');
sb.append(", password='").append(password).append('\'');
sb.append('}');
return sb.toString();
}
}

View File

@ -1,45 +0,0 @@
package com.songpeng.system.domain;
/**
* Controller
* Created by songpeng on 2019/5/21.
*/
public class User {
private String id;
private String name;
private String username;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
@Override
public String toString() {
final StringBuffer sb = new StringBuffer("User{");
sb.append("id='").append(id).append('\'');
sb.append(", name='").append(name).append('\'');
sb.append(", username='").append(username).append('\'');
sb.append('}');
return sb.toString();
}
}

View File

@ -0,0 +1,72 @@
package com.songpeng.system.dto;
import com.songpeng.system.domain.SysRole;
import com.songpeng.system.domain.SysUser;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
/**
* dto
*
* @author songpeng
* @date 2019/5/23
*/
public class SysUserDto extends SysUser implements UserDetails {
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
// List<RoleGrantedAuthority> authorityList = new ArrayList<>();
// authorityList.add(new RoleGrantedAuthority("ROLE_USER"));
//
// // 加入角色权限
// if (roleList != null && !roleList.isEmpty()) {
// for (SysRole role : roleList) {
// if (StringUtils.isNotBlank(role.getCode())) {
// authorityList.add(new RoleGrantedAuthority("ROLE_" + role.getCode().toUpperCase()));
// }
// }
// }
// return authorityList;
return null;
}
/**
*
* @return
*/
@Override
public boolean isAccountNonExpired() {
return true;
}
/**
*
* @return
*/
@Override
public boolean isAccountNonLocked() {
return false;
}
/**
* ()
* @return
*/
@Override
public boolean isCredentialsNonExpired() {
return false;
}
/**
*
* @return
*/
@Override
public boolean isEnabled() {
return false;
}
}

View File

@ -0,0 +1,17 @@
package com.songpeng.system.mapper;
import com.songpeng.common.utils.SpMapper;
import com.songpeng.system.domain.SysUser;
import com.songpeng.system.dto.SysUserDto;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
import java.util.Map;
@Mapper
public interface SysUserMapper extends SpMapper<SysUser> {
List<SysUserDto> getPage(Map<String, Object> params);
List<SysUserDto> getSysUserDtosRoles(Map<String, Object> paramMap);
}

View File

@ -1,13 +0,0 @@
package com.songpeng.system.mapper;
import com.songpeng.system.domain.User;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
import java.util.Map;
@Mapper
public interface UserMapper {
List<User> getPage(Map<String, Object> params);
}

View File

@ -0,0 +1,33 @@
package com.songpeng.system.service;
import com.github.pagehelper.PageInfo;
import com.songpeng.common.utils.PageRequest;
import com.songpeng.system.domain.SysUser;
import com.songpeng.system.dto.SysUserDto;
import java.util.Map;
/**
* UserService
* @author songpeng
* @date 2019/4/20.
*/
public interface SysUserService {
/**
*
* @param pageRequest
* @return
*/
PageInfo<SysUserDto> getPage(PageRequest pageRequest);
/**
*
* @param paramMap
* @return
*/
SysUserDto getUserDtoRoles(Map<String, Object> paramMap);
void add(SysUser sysUser, String[] roles);
}

View File

@ -1,21 +0,0 @@
package com.songpeng.system.service;
import com.github.pagehelper.PageInfo;
import com.songpeng.common.utils.PageRequest;
import com.songpeng.system.domain.User;
/**
* UserService
* @author songpeng
* @date 2019/4/20.
*/
public interface UserService {
/**
*
* @param pageRequest
* @return
*/
PageInfo<User> getPage(PageRequest pageRequest);
}

View File

@ -0,0 +1,79 @@
package com.songpeng.system.service.impl;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.songpeng.common.utils.IdUtil;
import com.songpeng.common.utils.PageRequest;
import com.songpeng.common.utils.StringUtils;
import com.songpeng.system.domain.SysUser;
import com.songpeng.system.dto.SysUserDto;
import com.songpeng.system.mapper.SysUserMapper;
import com.songpeng.system.service.SysUserService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* UserServiceImpl
*
* @author songpeng
* @date 2019/4/20
*/
@Service
public class SysUserServiceImpl implements SysUserService, UserDetailsService {
private static final Logger LOGGER = LoggerFactory.getLogger(SysUserServiceImpl.class);
@Autowired
private SysUserMapper sysUserMapper;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
if (StringUtils.isBlank(username)) {
throw new BadCredentialsException("用户名不能为空!");
}
// 根据用户名和正常状态获取用户信息
Map<String, Object> paraMap = new HashMap(1) {{
put("userName", username);
}};
SysUserDto userDto = getUserDtoRoles(paraMap);
if (userDto == null) {
throw new BadCredentialsException("未找到用户名为 " + username + " 的用户信息");
}
return userDto;
}
@Override
public PageInfo<SysUserDto> getPage(PageRequest pageRequest) {
// 将参数传给这个方法就可以实现物理分页了
PageHelper.startPage(pageRequest.getPageNum(), pageRequest.getPageSize());
List<SysUserDto> users = sysUserMapper.getPage(pageRequest.getParams());
PageInfo result = new PageInfo(users);
return result;
}
@Override
public SysUserDto getUserDtoRoles(Map<String, Object> paramMap) {
List<SysUserDto> userDtos = sysUserMapper.getSysUserDtosRoles(paramMap);
return userDtos.isEmpty() ? null : userDtos.get(0);
}
@Override
public void add(SysUser sysUser, String[] roles) {
sysUser.setId(IdUtil.nextId());
LOGGER.info("user insert id: {}", sysUser.getId());
sysUserMapper.insertSelective(sysUser);
}
}

View File

@ -1,35 +0,0 @@
package com.songpeng.system.service.impl;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.songpeng.common.utils.PageRequest;
import com.songpeng.system.domain.User;
import com.songpeng.system.mapper.UserMapper;
import com.songpeng.system.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* UserServiceImpl
*
* @author songpeng
* @date 2019/4/20
*/
@Service
public class UserServiceImpl implements UserService {
@Autowired
private UserMapper userMapper;
@Override
public PageInfo<User> getPage(PageRequest pageRequest) {
//将参数传给这个方法就可以实现物理分页了,非常简单。
PageHelper.startPage(pageRequest.getPageNum(), pageRequest.getPageSize());
List<User> users = userMapper.getPage(pageRequest.getParams());
PageInfo result = new PageInfo(users);
return result;
}
}

View File

@ -1,10 +1,36 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.songpeng.system.mapper.UserMapper" >
<select id="getPage" resultType="com.songpeng.system.domain.User">
<mapper namespace="com.songpeng.system.mapper.SysUserMapper" >
<resultMap id="BaseResultMap" type="com.songpeng.system.domain.SysUser" >
<result column="ID" jdbcType="VARCHAR" property="id" />
<result column="NAME" jdbcType="VARCHAR" property="name" />
<result column="USERNAME" jdbcType="VARCHAR" property="username" />
<result column="PASSWORD" jdbcType="VARCHAR" property="password" />
</resultMap>
<!-- SysUserRolesDto 返回 -->
<resultMap id="SysUserDtoRolesMap" type="com.songpeng.system.dto.SysUserDto" extends="BaseResultMap">
<collection property="roleList"
ofType="com.tn.iip.zu.system.model.SysRole"
column="id"
select="com.tn.iip.zu.system.mapper.SysRoleMapper.selectRolesByUserId"/>
</resultMap>
<!--分页查询用户-->
<select id="getPage" resultType="com.songpeng.system.dto.SysUserDto">
SELECT
*
t.*
FROM
sys_user
sys_user t
</select>
<!--查询用户列表(包含角色列表)-->
<select id="getSysUserDtosRoles" parameterType="java.lang.String" resultMap="SysUserDtoRolesMap">
SELECT
t.*
FROM
sys_user t
WHERE t.username = #{username}
</select>
</mapper>

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,222 @@
.toast-title {
font-weight: 700
}
.toast-message {
-ms-word-wrap: break-word;
word-wrap: break-word
}
.toast-message a, .toast-message label {
color: #fff
}
.toast-message a:hover {
color: #ccc;
text-decoration: none
}
.toast-close-button {
position: relative;
right: -.3em;
top: -.3em;
float: right;
font-size: 20px;
font-weight: 700;
color: #fff;
-webkit-text-shadow: 0 1px 0 #fff;
text-shadow: 0 1px 0 #fff;
opacity: .8;
-ms-filter: alpha(Opacity=80);
filter: alpha(opacity=80)
}
.toast-close-button:focus, .toast-close-button:hover {
color: #000;
text-decoration: none;
cursor: pointer;
opacity: .4;
-ms-filter: alpha(Opacity=40);
filter: alpha(opacity=40)
}
button.toast-close-button {
padding: 0;
cursor: pointer;
background: 0 0;
border: 0;
-webkit-appearance: none
}
.toast-top-center {
top: 0;
right: 0;
width: 100%
}
.toast-bottom-center {
bottom: 0;
right: 0;
width: 100%
}
.toast-top-full-width {
top: 0;
right: 0;
width: 100%
}
.toast-bottom-full-width {
bottom: 0;
right: 0;
width: 100%
}
.toast-top-left {
top: 12px;
left: 12px
}
.toast-top-right {
top: 12px;
right: 12px
}
.toast-bottom-right {
right: 12px;
bottom: 12px
}
.toast-bottom-left {
bottom: 12px;
left: 12px
}
#toast-container {
position: fixed;
z-index: 999999
}
#toast-container * {
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box
}
#toast-container > div {
position: relative;
overflow: hidden;
margin: 0 0 6px;
padding: 15px 15px 15px 50px;
width: 300px;
-moz-border-radius: 3px;
-webkit-border-radius: 3px;
border-radius: 3px;
background-position: 15px center;
background-repeat: no-repeat;
-moz-box-shadow: 0 0 12px #999;
-webkit-box-shadow: 0 0 12px #999;
box-shadow: 0 0 12px #999;
color: #fff;
opacity: .8;
-ms-filter: alpha(Opacity=80);
filter: alpha(opacity=80)
}
#toast-container > :hover {
-moz-box-shadow: 0 0 12px #000;
-webkit-box-shadow: 0 0 12px #000;
box-shadow: 0 0 12px #000;
opacity: 1;
-ms-filter: alpha(Opacity=100);
filter: alpha(opacity=100);
cursor: pointer
}
#toast-container > .toast-info {
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAGwSURBVEhLtZa9SgNBEMc9sUxxRcoUKSzSWIhXpFMhhYWFhaBg4yPYiWCXZxBLERsLRS3EQkEfwCKdjWJAwSKCgoKCcudv4O5YLrt7EzgXhiU3/4+b2ckmwVjJSpKkQ6wAi4gwhT+z3wRBcEz0yjSseUTrcRyfsHsXmD0AmbHOC9Ii8VImnuXBPglHpQ5wwSVM7sNnTG7Za4JwDdCjxyAiH3nyA2mtaTJufiDZ5dCaqlItILh1NHatfN5skvjx9Z38m69CgzuXmZgVrPIGE763Jx9qKsRozWYw6xOHdER+nn2KkO+Bb+UV5CBN6WC6QtBgbRVozrahAbmm6HtUsgtPC19tFdxXZYBOfkbmFJ1VaHA1VAHjd0pp70oTZzvR+EVrx2Ygfdsq6eu55BHYR8hlcki+n+kERUFG8BrA0BwjeAv2M8WLQBtcy+SD6fNsmnB3AlBLrgTtVW1c2QN4bVWLATaIS60J2Du5y1TiJgjSBvFVZgTmwCU+dAZFoPxGEEs8nyHC9Bwe2GvEJv2WXZb0vjdyFT4Cxk3e/kIqlOGoVLwwPevpYHT+00T+hWwXDf4AJAOUqWcDhbwAAAAASUVORK5CYII=) !important
}
#toast-container > .toast-error {
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAHOSURBVEhLrZa/SgNBEMZzh0WKCClSCKaIYOED+AAKeQQLG8HWztLCImBrYadgIdY+gIKNYkBFSwu7CAoqCgkkoGBI/E28PdbLZmeDLgzZzcx83/zZ2SSXC1j9fr+I1Hq93g2yxH4iwM1vkoBWAdxCmpzTxfkN2RcyZNaHFIkSo10+8kgxkXIURV5HGxTmFuc75B2RfQkpxHG8aAgaAFa0tAHqYFfQ7Iwe2yhODk8+J4C7yAoRTWI3w/4klGRgR4lO7Rpn9+gvMyWp+uxFh8+H+ARlgN1nJuJuQAYvNkEnwGFck18Er4q3egEc/oO+mhLdKgRyhdNFiacC0rlOCbhNVz4H9FnAYgDBvU3QIioZlJFLJtsoHYRDfiZoUyIxqCtRpVlANq0EU4dApjrtgezPFad5S19Wgjkc0hNVnuF4HjVA6C7QrSIbylB+oZe3aHgBsqlNqKYH48jXyJKMuAbiyVJ8KzaB3eRc0pg9VwQ4niFryI68qiOi3AbjwdsfnAtk0bCjTLJKr6mrD9g8iq/S/B81hguOMlQTnVyG40wAcjnmgsCNESDrjme7wfftP4P7SP4N3CJZdvzoNyGq2c/HWOXJGsvVg+RA/k2MC/wN6I2YA2Pt8GkAAAAASUVORK5CYII=) !important
}
#toast-container > .toast-success {
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAADsSURBVEhLY2AYBfQMgf///3P8+/evAIgvA/FsIF+BavYDDWMBGroaSMMBiE8VC7AZDrIFaMFnii3AZTjUgsUUWUDA8OdAH6iQbQEhw4HyGsPEcKBXBIC4ARhex4G4BsjmweU1soIFaGg/WtoFZRIZdEvIMhxkCCjXIVsATV6gFGACs4Rsw0EGgIIH3QJYJgHSARQZDrWAB+jawzgs+Q2UO49D7jnRSRGoEFRILcdmEMWGI0cm0JJ2QpYA1RDvcmzJEWhABhD/pqrL0S0CWuABKgnRki9lLseS7g2AlqwHWQSKH4oKLrILpRGhEQCw2LiRUIa4lwAAAABJRU5ErkJggg==) !important
}
#toast-container > .toast-warning {
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAGYSURBVEhL5ZSvTsNQFMbXZGICMYGYmJhAQIJAICYQPAACiSDB8AiICQQJT4CqQEwgJvYASAQCiZiYmJhAIBATCARJy+9rTsldd8sKu1M0+dLb057v6/lbq/2rK0mS/TRNj9cWNAKPYIJII7gIxCcQ51cvqID+GIEX8ASG4B1bK5gIZFeQfoJdEXOfgX4QAQg7kH2A65yQ87lyxb27sggkAzAuFhbbg1K2kgCkB1bVwyIR9m2L7PRPIhDUIXgGtyKw575yz3lTNs6X4JXnjV+LKM/m3MydnTbtOKIjtz6VhCBq4vSm3ncdrD2lk0VgUXSVKjVDJXJzijW1RQdsU7F77He8u68koNZTz8Oz5yGa6J3H3lZ0xYgXBK2QymlWWA+RWnYhskLBv2vmE+hBMCtbA7KX5drWyRT/2JsqZ2IvfB9Y4bWDNMFbJRFmC9E74SoS0CqulwjkC0+5bpcV1CZ8NMej4pjy0U+doDQsGyo1hzVJttIjhQ7GnBtRFN1UarUlH8F3xict+HY07rEzoUGPlWcjRFRr4/gChZgc3ZL2d8oAAAAASUVORK5CYII=) !important
}
#toast-container.toast-bottom-center > div, #toast-container.toast-top-center > div {
width: 300px;
margin: auto
}
#toast-container.toast-bottom-full-width > div, #toast-container.toast-top-full-width > div {
width: 96%;
margin: auto
}
.toast {
background-color: #030303
}
.toast-success {
background-color: #51a351
}
.toast-error {
background-color: #bd362f
}
.toast-info {
background-color: #2f96b4
}
.toast-warning {
background-color: #f89406
}
.toast-progress {
position: absolute;
left: 0;
bottom: 0;
height: 4px;
background-color: #000;
opacity: .4;
-ms-filter: alpha(Opacity=40);
filter: alpha(opacity=40)
}
@media all and (max-width: 240px) {
#toast-container > div {
padding: 8px 8px 8px 50px;
width: 11em
}
#toast-container .toast-close-button {
right: -.2em;
top: -.2em
}
}
@media all and (min-width: 241px) and (max-width: 480px) {
#toast-container > div {
padding: 8px 8px 8px 50px;
width: 18em
}
#toast-container .toast-close-button {
right: -.2em;
top: -.2em
}
}
@media all and (min-width: 481px) and (max-width: 768px) {
#toast-container > div {
padding: 15px 15px 15px 50px;
width: 25em
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,278 @@
//自定义js
//公共配置
$(document).ready(function () {
// MetsiMenu
$('#side-menu').metisMenu();
// 打开右侧边栏
$('.right-sidebar-toggle').click(function () {
$('#right-sidebar').toggleClass('sidebar-open');
});
// 右侧边栏使用slimscroll
$('.sidebar-container').slimScroll({
height: '100%',
railOpacity: 0.4,
wheelStep: 10
});
// 打开聊天窗口
$('.open-small-chat').click(function () {
$(this).children().toggleClass('fa-comments').toggleClass('fa-remove');
$('.small-chat-box').toggleClass('active');
});
// 聊天窗口使用slimscroll
$('.small-chat-box .content').slimScroll({
height: '234px',
railOpacity: 0.4
});
// Small todo handler
$('.check-link').click(function () {
var button = $(this).find('i');
var label = $(this).next('span');
button.toggleClass('fa-check-square').toggleClass('fa-square-o');
label.toggleClass('todo-completed');
return false;
});
//固定菜单栏
$(function () {
$('.sidebar-collapse').slimScroll({
height: '100%',
railOpacity: 0.9,
alwaysVisible: false
});
});
// 菜单切换
$('.navbar-minimalize').click(function () {
$("body").toggleClass("mini-navbar");
SmoothlyMenu();
});
// 侧边栏高度
function fix_height() {
var heightWithoutNavbar = $("body > #wrapper").height() - 61;
$(".sidebard-panel").css("min-height", heightWithoutNavbar + "px");
}
fix_height();
$(window).bind("load resize click scroll", function () {
if (!$("body").hasClass('body-small')) {
fix_height();
}
});
//侧边栏滚动
$(window).scroll(function () {
if ($(window).scrollTop() > 0 && !$('body').hasClass('fixed-nav')) {
$('#right-sidebar').addClass('sidebar-top');
} else {
$('#right-sidebar').removeClass('sidebar-top');
}
});
$('.full-height-scroll').slimScroll({
height: '100%'
});
$('#side-menu>li').click(function () {
if ($('body').hasClass('mini-navbar')) {
NavToggle();
}
});
$('#side-menu>li li a').click(function () {
if ($(window).width() < 769) {
NavToggle();
}
});
$('.nav-close').click(NavToggle);
//ios浏览器兼容性处理
if (/(iPhone|iPad|iPod|iOS)/i.test(navigator.userAgent)) {
$('#content-main').css('overflow-y', 'auto');
}
});
$(window).bind("load resize", function () {
if ($(this).width() < 769) {
$('body').addClass('mini-navbar');
$('.navbar-static-side').fadeIn();
}
});
function NavToggle() {
$('.navbar-minimalize').trigger('click');
}
function SmoothlyMenu() {
if (!$('body').hasClass('mini-navbar')) {
$('#side-menu').hide();
setTimeout(
function () {
$('#side-menu').fadeIn(500);
}, 100);
} else if ($('body').hasClass('fixed-sidebar')) {
$('#side-menu').hide();
setTimeout(
function () {
$('#side-menu').fadeIn(500);
}, 300);
} else {
$('#side-menu').removeAttr('style');
}
}
//主题设置
$(function () {
// 顶部菜单固定
$('#fixednavbar').click(function () {
if ($('#fixednavbar').is(':checked')) {
$(".navbar-static-top").removeClass('navbar-static-top').addClass('navbar-fixed-top');
$("body").removeClass('boxed-layout');
$("body").addClass('fixed-nav');
$('#boxedlayout').prop('checked', false);
if (localStorageSupport) {
localStorage.setItem("boxedlayout", 'off');
}
if (localStorageSupport) {
localStorage.setItem("fixednavbar", 'on');
}
} else {
$(".navbar-fixed-top").removeClass('navbar-fixed-top').addClass('navbar-static-top');
$("body").removeClass('fixed-nav');
if (localStorageSupport) {
localStorage.setItem("fixednavbar", 'off');
}
}
});
// 收起左侧菜单
$('#collapsemenu').click(function () {
if ($('#collapsemenu').is(':checked')) {
$("body").addClass('mini-navbar');
SmoothlyMenu();
if (localStorageSupport) {
localStorage.setItem("collapse_menu", 'on');
}
} else {
$("body").removeClass('mini-navbar');
SmoothlyMenu();
if (localStorageSupport) {
localStorage.setItem("collapse_menu", 'off');
}
}
});
// 固定宽度
$('#boxedlayout').click(function () {
if ($('#boxedlayout').is(':checked')) {
$("body").addClass('boxed-layout');
$('#fixednavbar').prop('checked', false);
$(".navbar-fixed-top").removeClass('navbar-fixed-top').addClass('navbar-static-top');
$("body").removeClass('fixed-nav');
if (localStorageSupport) {
localStorage.setItem("fixednavbar", 'off');
}
if (localStorageSupport) {
localStorage.setItem("boxedlayout", 'on');
}
} else {
$("body").removeClass('boxed-layout');
if (localStorageSupport) {
localStorage.setItem("boxedlayout", 'off');
}
}
});
// 默认主题
$('.s-skin-0').click(function () {
$("body").removeClass("skin-1");
$("body").removeClass("skin-2");
$("body").removeClass("skin-3");
return false;
});
// 蓝色主题
$('.s-skin-1').click(function () {
$("body").removeClass("skin-2");
$("body").removeClass("skin-3");
$("body").addClass("skin-1");
return false;
});
// 黄色主题
$('.s-skin-3').click(function () {
$("body").removeClass("skin-1");
$("body").removeClass("skin-2");
$("body").addClass("skin-3");
return false;
});
if (localStorageSupport) {
var collapse = localStorage.getItem("collapse_menu");
var fixednavbar = localStorage.getItem("fixednavbar");
var boxedlayout = localStorage.getItem("boxedlayout");
if (collapse == 'on') {
$('#collapsemenu').prop('checked', 'checked')
}
if (fixednavbar == 'on') {
$('#fixednavbar').prop('checked', 'checked')
}
if (boxedlayout == 'on') {
$('#boxedlayout').prop('checked', 'checked')
}
}
if (localStorageSupport) {
var collapse = localStorage.getItem("collapse_menu");
var fixednavbar = localStorage.getItem("fixednavbar");
var boxedlayout = localStorage.getItem("boxedlayout");
var body = $('body');
if (collapse == 'on') {
if (!body.hasClass('body-small')) {
body.addClass('mini-navbar');
}
}
if (fixednavbar == 'on') {
$(".navbar-static-top").removeClass('navbar-static-top').addClass('navbar-fixed-top');
body.addClass('fixed-nav');
}
if (boxedlayout == 'on') {
body.addClass('boxed-layout');
}
}
});
//判断浏览器是否支持html5本地存储
function localStorageSupport() {
return (('localStorage' in window) && window['localStorage'] !== null)
}

View File

@ -0,0 +1,310 @@
$(function () {
//计算元素集合的总宽度
function calSumWidth(elements) {
var width = 0;
$(elements).each(function () {
width += $(this).outerWidth(true);
});
return width;
}
//滚动到指定选项卡
function scrollToTab(element) {
var marginLeftVal = calSumWidth($(element).prevAll()), marginRightVal = calSumWidth($(element).nextAll());
// 可视区域非tab宽度
var tabOuterWidth = calSumWidth($(".content-tabs").children().not(".J_menuTabs"));
//可视区域tab宽度
var visibleWidth = $(".content-tabs").outerWidth(true) - tabOuterWidth;
//实际滚动宽度
var scrollVal = 0;
if ($(".page-tabs-content").outerWidth() < visibleWidth) {
scrollVal = 0;
} else if (marginRightVal <= (visibleWidth - $(element).outerWidth(true) - $(element).next().outerWidth(true))) {
if ((visibleWidth - $(element).next().outerWidth(true)) > marginRightVal) {
scrollVal = marginLeftVal;
var tabElement = element;
while ((scrollVal - $(tabElement).outerWidth()) > ($(".page-tabs-content").outerWidth() - visibleWidth)) {
scrollVal -= $(tabElement).prev().outerWidth();
tabElement = $(tabElement).prev();
}
}
} else if (marginLeftVal > (visibleWidth - $(element).outerWidth(true) - $(element).prev().outerWidth(true))) {
scrollVal = marginLeftVal - $(element).prev().outerWidth(true);
}
$('.page-tabs-content').animate({
marginLeft: 0 - scrollVal + 'px'
}, "fast");
}
//查看左侧隐藏的选项卡
function scrollTabLeft() {
var marginLeftVal = Math.abs(parseInt($('.page-tabs-content').css('margin-left')));
// 可视区域非tab宽度
var tabOuterWidth = calSumWidth($(".content-tabs").children().not(".J_menuTabs"));
//可视区域tab宽度
var visibleWidth = $(".content-tabs").outerWidth(true) - tabOuterWidth;
//实际滚动宽度
var scrollVal = 0;
if ($(".page-tabs-content").width() < visibleWidth) {
return false;
} else {
var tabElement = $(".J_menuTab:first");
var offsetVal = 0;
while ((offsetVal + $(tabElement).outerWidth(true)) <= marginLeftVal) {//找到离当前tab最近的元素
offsetVal += $(tabElement).outerWidth(true);
tabElement = $(tabElement).next();
}
offsetVal = 0;
if (calSumWidth($(tabElement).prevAll()) > visibleWidth) {
while ((offsetVal + $(tabElement).outerWidth(true)) < (visibleWidth) && tabElement.length > 0) {
offsetVal += $(tabElement).outerWidth(true);
tabElement = $(tabElement).prev();
}
scrollVal = calSumWidth($(tabElement).prevAll());
}
}
$('.page-tabs-content').animate({
marginLeft: 0 - scrollVal + 'px'
}, "fast");
}
//查看右侧隐藏的选项卡
function scrollTabRight() {
var marginLeftVal = Math.abs(parseInt($('.page-tabs-content').css('margin-left')));
// 可视区域非tab宽度
var tabOuterWidth = calSumWidth($(".content-tabs").children().not(".J_menuTabs"));
//可视区域tab宽度
var visibleWidth = $(".content-tabs").outerWidth(true) - tabOuterWidth;
//实际滚动宽度
var scrollVal = 0;
if ($(".page-tabs-content").width() < visibleWidth) {
return false;
} else {
var tabElement = $(".J_menuTab:first");
var offsetVal = 0;
while ((offsetVal + $(tabElement).outerWidth(true)) <= marginLeftVal) {//找到离当前tab最近的元素
offsetVal += $(tabElement).outerWidth(true);
tabElement = $(tabElement).next();
}
offsetVal = 0;
while ((offsetVal + $(tabElement).outerWidth(true)) < (visibleWidth) && tabElement.length > 0) {
offsetVal += $(tabElement).outerWidth(true);
tabElement = $(tabElement).next();
}
scrollVal = calSumWidth($(tabElement).prevAll());
if (scrollVal > 0) {
$('.page-tabs-content').animate({
marginLeft: 0 - scrollVal + 'px'
}, "fast");
}
}
}
//通过遍历给菜单项加上data-index属性
$(".J_menuItem").each(function (index) {
if (!$(this).attr('data-index')) {
$(this).attr('data-index', index);
}
});
function menuItem() {
// 获取标识数据
var dataUrl = $(this).attr('href'),
dataIndex = $(this).data('index'),
menuName = $.trim($(this).text()),
flag = true;
if (dataUrl == undefined || $.trim(dataUrl).length == 0)return false;
// 选项卡菜单已存在
$('.J_menuTab').each(function () {
if ($(this).data('id') == dataUrl) {
if (!$(this).hasClass('active')) {
$(this).addClass('active').siblings('.J_menuTab').removeClass('active');
scrollToTab(this);
// 显示tab对应的内容区
$('.J_mainContent .J_iframe').each(function () {
if ($(this).data('id') == dataUrl) {
$(this).show().siblings('.J_iframe').hide();
return false;
}
});
}
flag = false;
return false;
}
});
// 选项卡菜单不存在
if (flag) {
var str = '<a href="javascript:;" class="active J_menuTab" data-id="' + dataUrl + '">' + menuName + ' <i class="fa fa-times-circle"></i></a>';
$('.J_menuTab').removeClass('active');
// 添加选项卡对应的iframe
var str1 = '<iframe class="J_iframe" name="iframe' + dataIndex + '" width="100%" height="100%" src="' + dataUrl + '" frameborder="0" data-id="' + dataUrl + '" seamless></iframe>';
$('.J_mainContent').find('iframe.J_iframe').hide().parents('.J_mainContent').append(str1);
//显示loading提示
// var loading = layer.load();
//
// $('.J_mainContent iframe:visible').load(function () {
// //iframe加载完成后隐藏loading提示
// layer.close(loading);
// });
// 添加选项卡
$('.J_menuTabs .page-tabs-content').append(str);
scrollToTab($('.J_menuTab.active'));
}
return false;
}
$('.J_menuItem').on('click', menuItem);
// 关闭选项卡菜单
function closeTab() {
var closeTabId = $(this).parents('.J_menuTab').data('id');
var currentWidth = $(this).parents('.J_menuTab').width();
// 当前元素处于活动状态
if ($(this).parents('.J_menuTab').hasClass('active')) {
// 当前元素后面有同辈元素,使后面的一个元素处于活动状态
if ($(this).parents('.J_menuTab').next('.J_menuTab').size()) {
var activeId = $(this).parents('.J_menuTab').next('.J_menuTab:eq(0)').data('id');
$(this).parents('.J_menuTab').next('.J_menuTab:eq(0)').addClass('active');
$('.J_mainContent .J_iframe').each(function () {
if ($(this).data('id') == activeId) {
$(this).show().siblings('.J_iframe').hide();
return false;
}
});
var marginLeftVal = parseInt($('.page-tabs-content').css('margin-left'));
if (marginLeftVal < 0) {
$('.page-tabs-content').animate({
marginLeft: (marginLeftVal + currentWidth) + 'px'
}, "fast");
}
// 移除当前选项卡
$(this).parents('.J_menuTab').remove();
// 移除tab对应的内容区
$('.J_mainContent .J_iframe').each(function () {
if ($(this).data('id') == closeTabId) {
$(this).remove();
return false;
}
});
}
// 当前元素后面没有同辈元素,使当前元素的上一个元素处于活动状态
if ($(this).parents('.J_menuTab').prev('.J_menuTab').size()) {
var activeId = $(this).parents('.J_menuTab').prev('.J_menuTab:last').data('id');
$(this).parents('.J_menuTab').prev('.J_menuTab:last').addClass('active');
$('.J_mainContent .J_iframe').each(function () {
if ($(this).data('id') == activeId) {
$(this).show().siblings('.J_iframe').hide();
return false;
}
});
// 移除当前选项卡
$(this).parents('.J_menuTab').remove();
// 移除tab对应的内容区
$('.J_mainContent .J_iframe').each(function () {
if ($(this).data('id') == closeTabId) {
$(this).remove();
return false;
}
});
}
}
// 当前元素不处于活动状态
else {
// 移除当前选项卡
$(this).parents('.J_menuTab').remove();
// 移除相应tab对应的内容区
$('.J_mainContent .J_iframe').each(function () {
if ($(this).data('id') == closeTabId) {
$(this).remove();
return false;
}
});
scrollToTab($('.J_menuTab.active'));
}
return false;
}
$('.J_menuTabs').on('click', '.J_menuTab i', closeTab);
//关闭其他选项卡
function closeOtherTabs(){
$('.page-tabs-content').children("[data-id]").not(":first").not(".active").each(function () {
$('.J_iframe[data-id="' + $(this).data('id') + '"]').remove();
$(this).remove();
});
$('.page-tabs-content').css("margin-left", "0");
}
$('.J_tabCloseOther').on('click', closeOtherTabs);
//滚动到已激活的选项卡
function showActiveTab(){
scrollToTab($('.J_menuTab.active'));
}
$('.J_tabShowActive').on('click', showActiveTab);
// 点击选项卡菜单
function activeTab() {
if (!$(this).hasClass('active')) {
var currentId = $(this).data('id');
// 显示tab对应的内容区
$('.J_mainContent .J_iframe').each(function () {
if ($(this).data('id') == currentId) {
$(this).show().siblings('.J_iframe').hide();
return false;
}
});
$(this).addClass('active').siblings('.J_menuTab').removeClass('active');
scrollToTab(this);
}
}
$('.J_menuTabs').on('click', '.J_menuTab', activeTab);
//刷新iframe
function refreshTab() {
var target = $('.J_iframe[data-id="' + $(this).data('id') + '"]');
var url = target.attr('src');
// //显示loading提示
// var loading = layer.load();
// target.attr('src', url).load(function () {
// //关闭loading提示
// layer.close(loading);
// });
}
$('.J_menuTabs').on('dblclick', '.J_menuTab', refreshTab);
// 左移按扭
$('.J_tabLeft').on('click', scrollTabLeft);
// 右移按扭
$('.J_tabRight').on('click', scrollTabRight);
// 关闭全部
$('.J_tabCloseAll').on('click', function () {
$('.page-tabs-content').children("[data-id]").not(":first").each(function () {
$('.J_iframe[data-id="' + $(this).data('id') + '"]').remove();
$(this).remove();
});
$('.page-tabs-content').children("[data-id]:first").each(function () {
$('.J_iframe[data-id="' + $(this).data('id') + '"]').show();
$(this).addClass("active");
});
$('.page-tabs-content').css("margin-left", "0");
});
});

View File

@ -0,0 +1,120 @@
/*
* metismenu - v1.1.3
* Easy menu jQuery plugin for Twitter Bootstrap 3
* https://github.com/onokumus/metisMenu
*
* Made by Osman Nuri Okumus
* Under MIT License
*/
;(function($, window, document, undefined) {
var pluginName = "metisMenu",
defaults = {
toggle: true,
doubleTapToGo: false
};
function Plugin(element, options) {
this.element = $(element);
this.settings = $.extend({}, defaults, options);
this._defaults = defaults;
this._name = pluginName;
this.init();
}
Plugin.prototype = {
init: function() {
var $this = this.element,
$toggle = this.settings.toggle,
obj = this;
if (this.isIE() <= 9) {
$this.find("li.active").has("ul").children("ul").collapse("show");
$this.find("li").not(".active").has("ul").children("ul").collapse("hide");
} else {
$this.find("li.active").has("ul").children("ul").addClass("collapse in");
$this.find("li").not(".active").has("ul").children("ul").addClass("collapse");
}
//add the "doubleTapToGo" class to active items if needed
if (obj.settings.doubleTapToGo) {
$this.find("li.active").has("ul").children("a").addClass("doubleTapToGo");
}
$this.find("li").has("ul").children("a").on("click" + "." + pluginName, function(e) {
e.preventDefault();
//Do we need to enable the double tap
if (obj.settings.doubleTapToGo) {
//if we hit a second time on the link and the href is valid, navigate to that url
if (obj.doubleTapToGo($(this)) && $(this).attr("href") !== "#" && $(this).attr("href") !== "") {
e.stopPropagation();
document.location = $(this).attr("href");
return;
}
}
$(this).parent("li").toggleClass("active").children("ul").collapse("toggle");
if ($toggle) {
$(this).parent("li").siblings().removeClass("active").children("ul.in").collapse("hide");
}
});
},
isIE: function() { //https://gist.github.com/padolsey/527683
var undef,
v = 3,
div = document.createElement("div"),
all = div.getElementsByTagName("i");
while (
div.innerHTML = "<!--[if gt IE " + (++v) + "]><i></i><![endif]-->",
all[0]
) {
return v > 4 ? v : undef;
}
},
//Enable the link on the second click.
doubleTapToGo: function(elem) {
var $this = this.element;
//if the class "doubleTapToGo" exists, remove it and return
if (elem.hasClass("doubleTapToGo")) {
elem.removeClass("doubleTapToGo");
return true;
}
//does not exists, add a new class and return false
if (elem.parent().children("ul").length) {
//first remove all other class
$this.find(".doubleTapToGo").removeClass("doubleTapToGo");
//add the class on the current element
elem.addClass("doubleTapToGo");
return false;
}
},
remove: function() {
this.element.off("." + pluginName);
this.element.removeData(pluginName);
}
};
$.fn[pluginName] = function(options) {
this.each(function () {
var el = $(this);
if (el.data(pluginName)) {
el.data(pluginName).remove();
}
el.data(pluginName, new Plugin(this, options));
});
return this;
};
})(jQuery, window, document);

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,15 @@
/*! Copyright (c) 2011 Piotr Rochala (http://rocha.la)
* Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php)
* and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses.
*
* Version: 1.3.0
*
*/
(function(f){jQuery.fn.extend({slimScroll:function(h){var a=f.extend({width:"auto",height:"250px",size:"4px",color:"#000",position:"right",distance:"1px",start:"top",opacity:0.4,alwaysVisible:!1,disableFadeOut:!1,railVisible:!1,railColor:"#333",railOpacity:0.2,railDraggable:!0,railClass:"slimScrollRail",barClass:"slimScrollBar",wrapperClass:"slimScrollDiv",allowPageScroll:!1,wheelStep:20,touchScrollStep:200,borderRadius:"7px",railBorderRadius:"7px"},h);this.each(function(){function r(d){if(s){d=d||
window.event;var c=0;d.wheelDelta&&(c=-d.wheelDelta/120);d.detail&&(c=d.detail/3);f(d.target||d.srcTarget||d.srcElement).closest("."+a.wrapperClass).is(b.parent())&&m(c,!0);d.preventDefault&&!k&&d.preventDefault();k||(d.returnValue=!1)}}function m(d,f,h){k=!1;var e=d,g=b.outerHeight()-c.outerHeight();f&&(e=parseInt(c.css("top"))+d*parseInt(a.wheelStep)/100*c.outerHeight(),e=Math.min(Math.max(e,0),g),e=0<d?Math.ceil(e):Math.floor(e),c.css({top:e+"px"}));l=parseInt(c.css("top"))/(b.outerHeight()-c.outerHeight());
e=l*(b[0].scrollHeight-b.outerHeight());h&&(e=d,d=e/b[0].scrollHeight*b.outerHeight(),d=Math.min(Math.max(d,0),g),c.css({top:d+"px"}));b.scrollTop(e);b.trigger("slimscrolling",~~e);v();p()}function C(){window.addEventListener?(this.addEventListener("DOMMouseScroll",r,!1),this.addEventListener("mousewheel",r,!1),this.addEventListener("MozMousePixelScroll",r,!1)):document.attachEvent("onmousewheel",r)}function w(){u=Math.max(b.outerHeight()/b[0].scrollHeight*b.outerHeight(),D);c.css({height:u+"px"});
var a=u==b.outerHeight()?"none":"block";c.css({display:a})}function v(){w();clearTimeout(A);l==~~l?(k=a.allowPageScroll,B!=l&&b.trigger("slimscroll",0==~~l?"top":"bottom")):k=!1;B=l;u>=b.outerHeight()?k=!0:(c.stop(!0,!0).fadeIn("fast"),a.railVisible&&g.stop(!0,!0).fadeIn("fast"))}function p(){a.alwaysVisible||(A=setTimeout(function(){a.disableFadeOut&&s||(x||y)||(c.fadeOut("slow"),g.fadeOut("slow"))},1E3))}var s,x,y,A,z,u,l,B,D=30,k=!1,b=f(this);if(b.parent().hasClass(a.wrapperClass)){var n=b.scrollTop(),
c=b.parent().find("."+a.barClass),g=b.parent().find("."+a.railClass);w();if(f.isPlainObject(h)){if("height"in h&&"auto"==h.height){b.parent().css("height","auto");b.css("height","auto");var q=b.parent().parent().height();b.parent().css("height",q);b.css("height",q)}if("scrollTo"in h)n=parseInt(a.scrollTo);else if("scrollBy"in h)n+=parseInt(a.scrollBy);else if("destroy"in h){c.remove();g.remove();b.unwrap();return}m(n,!1,!0)}}else{a.height="auto"==a.height?b.parent().height():a.height;n=f("<div></div>").addClass(a.wrapperClass).css({position:"relative",width:a.width,height:a.height});b.css({width:a.width,height:a.height});var g=f("<div></div>").addClass(a.railClass).css({width:a.size,height:"100%",position:"absolute",top:0,display:a.alwaysVisible&&a.railVisible?"block":"none","border-radius":a.railBorderRadius,background:a.railColor,opacity:a.railOpacity,zIndex:90}),c=f("<div></div>").addClass(a.barClass).css({background:a.color,width:a.size,position:"absolute",top:0,opacity:a.opacity,display:a.alwaysVisible?
"block":"none","border-radius":a.borderRadius,BorderRadius:a.borderRadius,MozBorderRadius:a.borderRadius,WebkitBorderRadius:a.borderRadius,zIndex:99}),q="right"==a.position?{right:a.distance}:{left:a.distance};g.css(q);c.css(q);b.wrap(n);b.parent().append(c);b.parent().append(g);a.railDraggable&&c.bind("mousedown",function(a){var b=f(document);y=!0;t=parseFloat(c.css("top"));pageY=a.pageY;b.bind("mousemove.slimscroll",function(a){currTop=t+a.pageY-pageY;c.css("top",currTop);m(0,c.position().top,!1)});
b.bind("mouseup.slimscroll",function(a){y=!1;p();b.unbind(".slimscroll")});return!1}).bind("selectstart.slimscroll",function(a){a.stopPropagation();a.preventDefault();return!1});g.hover(function(){v()},function(){p()});c.hover(function(){x=!0},function(){x=!1});b.hover(function(){s=!0;v();p()},function(){s=!1;p()});b.bind("touchstart",function(a,b){a.originalEvent.touches.length&&(z=a.originalEvent.touches[0].pageY)});b.bind("touchmove",function(b){k||b.originalEvent.preventDefault();b.originalEvent.touches.length&&
(m((z-b.originalEvent.touches[0].pageY)/a.touchScrollStep,!0),z=b.originalEvent.touches[0].pageY)});w();"bottom"===a.start?(c.css({top:b.outerHeight()-c.outerHeight()}),m(0,!0)):"top"!==a.start&&(m(f(a.start).position().top,null,!0),a.alwaysVisible||c.hide());C()}});return this}});jQuery.fn.extend({slimscroll:jQuery.fn.slimScroll})})(jQuery);

View File

@ -0,0 +1,2 @@
!function(e){e(["jquery"],function(e){return function(){function t(e,t,n){return f({type:O.error,iconClass:g().iconClasses.error,message:e,optionsOverride:n,title:t})}function n(t,n){return t||(t=g()),v=e("#"+t.containerId),v.length?v:(n&&(v=c(t)),v)}function i(e,t,n){return f({type:O.info,iconClass:g().iconClasses.info,message:e,optionsOverride:n,title:t})}function o(e){w=e}function s(e,t,n){return f({type:O.success,iconClass:g().iconClasses.success,message:e,optionsOverride:n,title:t})}function a(e,t,n){return f({type:O.warning,iconClass:g().iconClasses.warning,message:e,optionsOverride:n,title:t})}function r(e){var t=g();v||n(t),l(e,t)||u(t)}function d(t){var i=g();return v||n(i),t&&0===e(":focus",t).length?void h(t):void(v.children().length&&v.remove())}function u(t){for(var n=v.children(),i=n.length-1;i>=0;i--)l(e(n[i]),t)}function l(t,n){return t&&0===e(":focus",t).length?(t[n.hideMethod]({duration:n.hideDuration,easing:n.hideEasing,complete:function(){h(t)}}),!0):!1}function c(t){return v=e("<div/>").attr("id",t.containerId).addClass(t.positionClass).attr("aria-live","polite").attr("role","alert"),v.appendTo(e(t.target)),v}function p(){return{tapToDismiss:!0,toastClass:"toast",containerId:"toast-container",debug:!1,showMethod:"fadeIn",showDuration:300,showEasing:"swing",onShown:void 0,hideMethod:"fadeOut",hideDuration:1e3,hideEasing:"swing",onHidden:void 0,extendedTimeOut:1e3,iconClasses:{error:"toast-error",info:"toast-info",success:"toast-success",warning:"toast-warning"},iconClass:"toast-info",positionClass:"toast-top-right",timeOut:5e3,titleClass:"toast-title",messageClass:"toast-message",target:"body",closeHtml:'<button type="button">&times;</button>',newestOnTop:!0,preventDuplicates:!1,progressBar:!1}}function m(e){w&&w(e)}function f(t){function i(t){return!e(":focus",l).length||t?(clearTimeout(O.intervalId),l[r.hideMethod]({duration:r.hideDuration,easing:r.hideEasing,complete:function(){h(l),r.onHidden&&"hidden"!==b.state&&r.onHidden(),b.state="hidden",b.endTime=new Date,m(b)}})):void 0}function o(){(r.timeOut>0||r.extendedTimeOut>0)&&(u=setTimeout(i,r.extendedTimeOut),O.maxHideTime=parseFloat(r.extendedTimeOut),O.hideEta=(new Date).getTime()+O.maxHideTime)}function s(){clearTimeout(u),O.hideEta=0,l.stop(!0,!0)[r.showMethod]({duration:r.showDuration,easing:r.showEasing})}function a(){var e=(O.hideEta-(new Date).getTime())/O.maxHideTime*100;f.width(e+"%")}var r=g(),d=t.iconClass||r.iconClass;if("undefined"!=typeof t.optionsOverride&&(r=e.extend(r,t.optionsOverride),d=t.optionsOverride.iconClass||d),r.preventDuplicates){if(t.message===C)return;C=t.message}T++,v=n(r,!0);var u=null,l=e("<div/>"),c=e("<div/>"),p=e("<div/>"),f=e("<div/>"),w=e(r.closeHtml),O={intervalId:null,hideEta:null,maxHideTime:null},b={toastId:T,state:"visible",startTime:new Date,options:r,map:t};return t.iconClass&&l.addClass(r.toastClass).addClass(d),t.title&&(c.append(t.title).addClass(r.titleClass),l.append(c)),t.message&&(p.append(t.message).addClass(r.messageClass),l.append(p)),r.closeButton&&(w.addClass("toast-close-button").attr("role","button"),l.prepend(w)),r.progressBar&&(f.addClass("toast-progress"),l.prepend(f)),l.hide(),r.newestOnTop?v.prepend(l):v.append(l),l[r.showMethod]({duration:r.showDuration,easing:r.showEasing,complete:r.onShown}),r.timeOut>0&&(u=setTimeout(i,r.timeOut),O.maxHideTime=parseFloat(r.timeOut),O.hideEta=(new Date).getTime()+O.maxHideTime,r.progressBar&&(O.intervalId=setInterval(a,10))),l.hover(s,o),!r.onclick&&r.tapToDismiss&&l.click(i),r.closeButton&&w&&w.click(function(e){e.stopPropagation?e.stopPropagation():void 0!==e.cancelBubble&&e.cancelBubble!==!0&&(e.cancelBubble=!0),i(!0)}),r.onclick&&l.click(function(){r.onclick(),i()}),m(b),r.debug&&console&&console.log(b),l}function g(){return e.extend({},p(),b.options)}function h(e){v||(v=n()),e.is(":visible")||(e.remove(),e=null,0===v.children().length&&(v.remove(),C=void 0))}var v,w,C,T=0,O={error:"error",info:"info",success:"success",warning:"warning"},b={clear:r,remove:d,error:t,getContainer:n,info:i,options:{},subscribe:o,success:s,version:"2.1.0",warning:a};return b}()})}("function"==typeof define&&define.amd?define:function(e,t){"undefined"!=typeof module&&module.exports?module.exports=t(require("jquery")):window.toastr=t(window.jQuery)});
//# sourceMappingURL=/toastr.js.map

File diff suppressed because one or more lines are too long

View File

@ -1,6 +1,47 @@
<head th:fragment="header">
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title></title>
<meta name="keywords" content="">
<meta name="description" content="">
<link rel="shortcut icon" href="favicon.ico">
<link href="css/bootstrap.min.css?v=3.3.6"
th:href="@{/css/bootstrap.min.css?v=3.3.6}" rel="stylesheet">
<link href="/css/font-awesome.css?v=4.4.0"
th:href="@{/css/font-awesome.css?v=4.4.0}" rel="stylesheet">
<link href="/css/plugins/bootstrap-table/bootstrap-table.min.css"
th:href="@{/css/plugins/bootstrap-table/bootstrap-table.min.css}"
rel="stylesheet">
<link href="/css/plugins/jsTree/style.min.css" rel="stylesheet">
<link href="/css/plugins/jqTreeGrid/jquery.treegrid.css"
rel="stylesheet">
<!--summernote css -->
<link href="/css/plugins/summernote/summernote-0.8.8.css"
rel="stylesheet">
<link href="css/animate.css" th:href="@{/css/animate.css}"
rel="stylesheet">
<link href="/css/plugins/chosen/chosen.css" rel="stylesheet">
<link href="/css/style.css?v=4.1.0" th:href="@{/css/style.css?v=4.1.0}"
rel="stylesheet">
</head>
<div th:fragment="footer">
<script src="/js/jquery.min.js?v=2.1.4"></script>
<script src="/js/bootstrap.min.js?v=3.3.6"></script>
<script src="/js/plugins/bootstrap-table/bootstrap-table.min.js"></script>
<script src="/js/plugins/bootstrap-table/bootstrap-table-mobile.min.js"></script>
<script
src="/js/plugins/bootstrap-table/locale/bootstrap-table-zh-CN.min.js"></script>
<script src="/js/plugins/validate/jquery.validate.min.js"></script>
<script src="/js/plugins/validate/messages_zh.min.js"></script>
<script src="/js/plugins/jsTree/jstree.min.js"></script>
<script src="/js/plugins/jqTreeGrid/jquery.treegrid.min.js"></script>
<script src="/js/plugins/jqTreeGrid/jquery.treegrid.extension.js"></script>
<script src="/js/plugins/jqTreeGrid/jquery.treegrid.bootstrap3.js"></script>
<script src="/js/plugins/chosen/chosen.jquery.js"></script>
<script src="/js/plugins/layer/layer.js"></script>
<script src="/js/content.js?v=1.0.0"></script>
<!--summernote-->
<script src="/js/plugins/summernote/summernote.js"></script>
<script src="/js/plugins/summernote/summernote-zh-CN.min.js"></script>
<script src="/js/ajax-util.js"></script>
</div>

View File

@ -0,0 +1,373 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="renderer" content="webkit">
<title>面向学习型的开源框架,简洁高效,减少过渡封装,展现技术本质</title>
<meta name="keywords" content="面向学习型的开源框架,简洁高效,杜绝过渡封装,展现技术本质本质">
<meta name="description" content="面向学习型的开源框架,简洁高效,杜绝过渡封装,展现技术本质本质">
<!--[if lt IE 9]>
<meta http-equiv="refresh" content="0;ie.html"/>
<![endif]-->
<link rel="shortcut icon" href="favicon.ico">
<link href="/css/bootstrap.min.css?v=3.3.6" rel="stylesheet">
<link href="/css/font-awesome.min.css?v=4.4.0" rel="stylesheet">
<link href="/css/plugins/toastr/toastr.min.css" rel="stylesheet">
<link href="/css/animate.css" rel="stylesheet">
<link href="/css/style.css?v=4.1.0" rel="stylesheet">
</head>
<body class="fixed-sidebar full-height-layout gray-bg"
style="overflow: hidden">
<div id="wrapper">
<!--左侧导航开始-->
<nav class="navbar-default navbar-static-side" role="navigation">
<div class="nav-close">
<i class="fa fa-times-circle"></i>
</div>
<div class="sidebar-collapse">
<ul class="nav" id="side-menu">
<li class="nav-header">
<div>
<span><img alt="image" class="img-circle" height="60" width="60" th:src="${picUrl}"/></span>
<h3 class="" style="color: #ffffff">
</i>BootDo后台管理系统
</h3>
</div>
<div class="dropdown profile-element hidden">
<a data-toggle="dropdown" class="dropdown-toggle" href="#">
<span class="clear">
<span class="block m-t-xs"><strong class="font-bold"
th:text="${username}">admin</strong></span>
<span class="text-muted text-xs block">超级管理员<b class="caret"></b></span>
</span>
</a>
<ul class="dropdown-menu animated fadeInRight m-t-xs">
<li><a @click="personal" href="#">修改头像</a>
</li>
<li><a @click="personal" href="#">个人资料</a>
</li>
<li><a @click="personal" href="#">密码修改</a>
</li>
<li><a @click="personal" href="#">信箱</a>
</li>
<li class="divider"></li>
<li><a href="/logout">安全退出</a>
</li>
</ul>
<div class="logo-element">BootDo</div>
</div>
</li>
<li>
<a href="#"> <i class="fa fa-home"></i> <span
class="nav-label">主页</span> <span class="fa arrow"></span>
</a>
<ul class="nav nav-second-level">
<li><a id="index001" class="J_menuItem" href="index_v1.html"
data-index="0" th:href="@{/main}">了解BootDo</a></li>
</ul>
</li>
<li th:each="menu : ${menus}"><a href="#"> <i
class="fa fa fa-bar-chart-o" th:class="${menu.attributes.icon}"></i>
<span class="nav-label" th:text="${menu.text}">基础信息</span> <span
class="fa arrow"></span>
</a>
<ul class="nav nav-second-level">
<li th:each="cmenu : ${menu.children}"><a class="J_menuItem" href="graph_echarts.html"
th:text="${cmenu.text}"
th:href="${cmenu.attributes.url}">系统管理</a></li>
</ul>
</li>
</ul>
</div>
</nav>
<!--左侧导航结束-->
<!--右侧部分开始-->
<div id="page-wrapper" class="gray-bg dashbard-1">
<div class="row border-bottom">
<nav class="navbar navbar-static-top" role="navigation"
style="margin-bottom: 0">
<div class="navbar-header">
<a class="navbar-minimalize minimalize-styl-2 btn btn-default "
href="#" title="收起菜单"><i class="fa fa-bars"></i> </a>
<form role="search" class="navbar-form-custom"
method="post" action="">
<div class="form-group">
<input type="text" placeholder="请输入您需要查找的内容 …"
class="form-control" name="top-search" id="top-search">
</div>
</form>
</div>
<ul class="nav navbar-top-links navbar-right">
<li class="hidden-xs"><a href="/blog" target="_Blank"
class=""><i class="fa fa-rss-square"></i>博客</a></li>
<li class="dropdown"><a class="dropdown-toggle count-info"
data-toggle="dropdown" href="#"> <i class="fa fa-envelope"></i>
<span class="label label-warning">{{total}}</span>通知
</a>
<ul class="dropdown-menu dropdown-messages">
<li v-for="row in rows" class="m-t-xs">
<div class="dropdown-messages-box">
<a class="pull-left"> <i
class="fa fa-server"></i>
</a>
<div class="media-body">
<small class="pull-right">{{row.before}}</small>
<strong>{{row.sender}}</strong>
{{row.title}} <br>
<small class="text-muted">{{row.updateDate}}</small>
</div>
</div>
<div class="divider"></div>
</li>
<li>
<div class="text-center link-block">
<a class="J_menuItem" href="/oa/notify/selfNotify"> <i
class="fa fa-envelope"></i> <strong> 查看所有消息</strong>
</a>
</div>
</li>
</ul>
</li>
<li class="hidden-xs"><a @click="personal" href="#"><i class="fa fa-id-card"></i> 个人</a></li>
<li class="dropdown hidden-xs"><a
class="right-sidebar-toggle" aria-expanded="false"> <i
class="fa fa-tasks"></i> 主题
</a></li>
</ul>
</nav>
</div>
<div class="row content-tabs">
<button class="roll-nav roll-left J_tabLeft">
<i class="fa fa-backward"></i>
</button>
<nav class="page-tabs J_menuTabs">
<div class="page-tabs-content">
<a href="javascript:;" class="active J_menuTab"
data-id="index_v1.html">首页</a>
</div>
</nav>
<button class="roll-nav roll-right J_tabRight">
<i class="fa fa-forward"></i>
</button>
<div class="btn-group roll-nav roll-right">
<button class="dropdown J_tabClose" data-toggle="dropdown">
关闭操作<span class="caret"></span>
</button>
<ul role="menu" class="dropdown-menu dropdown-menu-right">
<li class="J_tabShowActive"><a>定位当前选项卡</a></li>
<li class="divider"></li>
<li class="J_tabCloseAll"><a>关闭全部选项卡</a></li>
<li class="J_tabCloseOther"><a>关闭其他选项卡</a></li>
</ul>
</div>
<a href="/logout" class="roll-nav roll-right J_tabExit"><i
class="fa fa fa-sign-out"></i> 退出</a>
</div>
<div class="row J_mainContent" id="content-main">
<iframe class="J_iframe" name="iframe0" width="100%" height="100%"
src="" th:src="@{/main}" frameborder="0" data-id="index.html" seamless></iframe>
</div>
<div class="footer">
<div class="pull-right">BootDo面向学习型的开源框架</div>
</div>
</div>
<!--右侧部分结束-->
<!--右侧边栏开始-->
<div id="right-sidebar">
<div class="sidebar-container">
<ul class="nav nav-tabs navs-3">
<li class="active"><a data-toggle="tab" href="#tab-1"> <i
class="fa fa-gear"></i> 主题
</a></li>
<li class=""><a data-toggle="tab" href="#tab-2"> 通知 </a></li>
<li><a data-toggle="tab" href="#tab-3"> 项目进度 </a></li>
</ul>
<div class="tab-content">
<div id="tab-1" class="tab-pane active">
<div class="sidebar-title">
<h3>
<i class="fa fa-comments-o"></i> 主题设置
</h3>
<small><i class="fa fa-tim"></i>
你可以从这里选择和预览主题的布局和样式,这些设置会被保存在本地,下次打开的时候会直接应用这些设置。
</small>
</div>
<div class="skin-setttings">
<div class="title">主题设置</div>
<div class="setings-item">
<span>收起左侧菜单</span>
<div class="switch">
<div class="onoffswitch">
<input type="checkbox" name="collapsemenu"
class="onoffswitch-checkbox" id="collapsemenu"> <label
class="onoffswitch-label" for="collapsemenu"> <span
class="onoffswitch-inner"></span> <span
class="onoffswitch-switch"></span>
</label>
</div>
</div>
</div>
<div class="setings-item">
<span>固定顶部</span>
<div class="switch">
<div class="onoffswitch">
<input type="checkbox" name="fixednavbar"
class="onoffswitch-checkbox" id="fixednavbar"> <label
class="onoffswitch-label" for="fixednavbar"> <span
class="onoffswitch-inner"></span> <span
class="onoffswitch-switch"></span>
</label>
</div>
</div>
</div>
<div class="setings-item">
<span> 固定宽度 </span>
<div class="switch">
<div class="onoffswitch">
<input type="checkbox" name="boxedlayout"
class="onoffswitch-checkbox" id="boxedlayout"> <label
class="onoffswitch-label" for="boxedlayout"> <span
class="onoffswitch-inner"></span> <span
class="onoffswitch-switch"></span>
</label>
</div>
</div>
</div>
<div class="title">皮肤选择</div>
<div class="setings-item default-skin nb">
<span class="skin-name "> <a href="#" class="s-skin-0">
默认皮肤 </a>
</span>
</div>
<div class="setings-item blue-skin nb">
<span class="skin-name "> <a href="#" class="s-skin-1">
蓝色主题 </a>
</span>
</div>
<div class="setings-item yellow-skin nb">
<span class="skin-name "> <a href="#" class="s-skin-3">
黄色/紫色主题 </a>
</span>
</div>
</div>
</div>
<div id="tab-2" class="tab-pane">
<div class="sidebar-title">
<h3>
<i class="fa fa-comments-o"></i> 最新通知
</h3>
<small><i class="fa fa-tim"></i> 您当前有10条未读信息</small>
</div>
</div>
<div id="tab-3" class="tab-pane">
<div class="sidebar-title">
<h3>
<i class="fa fa-cube"></i> 最新任务
</h3>
<small><i class="fa fa-tim"></i> 您当前有14个任务10个已完成</small>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- 全局js -->
<script src="/js/jquery.min.js?v=2.1.4"></script>
<script src="/js/bootstrap.min.js?v=3.3.6"></script>
<script src="/js/plugins/metisMenu/jquery.metisMenu.js"></script>
<script src="/js/plugins/slimscroll/jquery.slimscroll.min.js"></script>
<script src="/js/plugins/layer/layer.min.js"></script>
<!-- 自定义js -->
<script src="/js/app.js?v=4.1.0"></script>
<script type="text/javascript" src="/js/contabs.js"></script>
<!-- 第三方插件 -->
<script src="/js/plugins/pace/pace.min.js"></script>
<!-- vue -->
<script type="text/javascript"
src="/js/vue.min.js">
</script>
<script src="/js/appjs/oa/webSocket/sockjs.min.js"></script>
<script src="/js/appjs/oa/webSocket/stomp.min.js"></script>
<!-- Toastr script -->
<script src="/js/plugins/toastr/toastr.min.js"></script>
<script type="text/javascript">
var stompClient = null;
$(function () {
connect();
});
function connect() {
var sock = new SockJS("/endpointChat");
var stomp = Stomp.over(sock);
stomp.connect('guest', 'guest', function (frame) {
/** 订阅了/user/queue/notifications 发送的消息,这里雨在控制器的 convertAndSendToUser 定义的地址保持一致,
* 这里多用了一个/user,并且这个user 是必须的,使用user 才会发送消息到指定的用户。

* */
stomp.subscribe("/user/queue/notifications", handleNotification);
stomp.subscribe('/topic/getResponse', function (response) { //订阅/topic/getResponse 目标发送的消息。这个是在控制器的@SendTo中定义的。
toastr.options = {
"closeButton": true,
"debug": false,
"progressBar": true,
"positionClass": "toast-bottom-right",
"onclick": null,
"showDuration": "400",
"hideDuration": "1000",
"timeOut": "7000",
"extendedTimeOut": "1000",
"showEasing": "swing",
"hideEasing": "linear",
"showMethod": "fadeIn",
"hideMethod": "fadeOut"
}
toastr.info(JSON.parse(response.body).responseMessage);
});
});
function handleNotification(message) {
wrapper.notify();
toastr.info(message.body);
}
}
var wrapper = new Vue({
el: '#wrapper',
data: {
total: '',
rows: '',
},
methods: {
notify: function () {
$.getJSON('/oa/notify/message', function (r) {
wrapper.total = r.total;
wrapper.rows = r.rows;
});
},
personal: function () {
layer.open({
type: 2,
title: '个人设置',
maxmin: true,
shadeClose: false,
area: ['800px', '600px'],
content: '/sys/user/personal'
});
}
},
created: function () {
this.notify()
}
})
</script>
</body>
</html>

View File

@ -0,0 +1,45 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>欢迎页</title>
<meta content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" name="viewport">
<link rel="stylesheet" href="css/bootstrap.min.css">
</head>
<body>
<div class="panel panel-default">
<div class="panel-heading">了解BootDo</div>
<div style="padding: 10px 0 20px 10px;">
<h3>&nbsp;&nbsp;&nbsp;项目介绍</h3>
<ul>
<li>面向学习型的开源框架,简洁高效,减少过渡封装,展现技术本质</li>
<li>Springboot作为基础框架使用mybatis作为持久层框架</li>
<li>使用官方推荐的thymeleaf做为模板引擎shiro作为安全框架,主流技术,“一网打尽”</li>
<li>极简配置,一键前后台代码生成</li>
</ul>
<h3>&nbsp;&nbsp;&nbsp;获取源码</h3>
<ul>
<li>Github地址<a href="https://github.com/lcg0124/bootdo.git"
th:href="@{https://github.com/lcg0124/bootdo.git}" target="_blank">https://github.com/lcg0124/bootdo.git</a>
</li>
<li>Oschina地址<a href="https://gitee.com/lcg0124/bootdo.git" target="_blank">https://gitee.com/lcg0124/bootdo.git</a>
</li>
</ul>
<h3>&nbsp;&nbsp;&nbsp;官方QQ群</h3>
<ul>
<li>点击链接加入群聊【BootDo交流群】<a href="https://jq.qq.com/?_wv=1027&k=5EYXfiZ">669039323</a></li>
<li>点击链接加入群聊【BootDo交流二群】<a href="https://jq.qq.com/?_wv=1027&k=5M659N4">614726589</a></li>
<li>点击链接加入群聊【BootDo交流三群】<a href="https://jq.qq.com/?_wv=1027&k=5tE3A9O">600801035</a></li>
<li>点击链接加入群聊【CloudDo交流群】<a href="https://jq.qq.com/?_wv=1027&k=5Zk12Xl">719741533</a></li>
</ul>
<button class="btn" onclick="openPage('http://bootdo.com','bootdo.com')">访问bootdo官网(新打开tab页事例)</button>
</div>
</div>
</body>
<script src="js/jquery.min.js"></script>
<script src="js/openTab.js"></script>
</html>