feat():用户权限集合
parent
06644f87b6
commit
4a2af4c56b
8
pom.xml
8
pom.xml
|
@ -14,6 +14,7 @@
|
||||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
<mybatisplus.version>3.5.7</mybatisplus.version>
|
<mybatisplus.version>3.5.7</mybatisplus.version>
|
||||||
<forest.version>1.5.36</forest.version>
|
<forest.version>1.5.36</forest.version>
|
||||||
|
<jjwt.version>0.12.5</jjwt.version>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
<parent>
|
<parent>
|
||||||
|
@ -79,6 +80,13 @@
|
||||||
<groupId>org.apache.commons</groupId>
|
<groupId>org.apache.commons</groupId>
|
||||||
<artifactId>commons-lang3</artifactId>
|
<artifactId>commons-lang3</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<!-- JWT -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.jsonwebtoken</groupId>
|
||||||
|
<artifactId>jjwt</artifactId>
|
||||||
|
<version>${jjwt.version}</version>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
|
|
|
@ -10,6 +10,7 @@ import org.springframework.context.annotation.Configuration;
|
||||||
import java.sql.Connection;
|
import java.sql.Connection;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* 数据源配置
|
||||||
* @Author: DongZeLiang
|
* @Author: DongZeLiang
|
||||||
* @date: 2024/9/11
|
* @date: 2024/9/11
|
||||||
* @Description: 数据源配置
|
* @Description: 数据源配置
|
||||||
|
|
|
@ -5,6 +5,7 @@ import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||||
import org.springframework.web.bind.annotation.RestControllerAdvice;
|
import org.springframework.web.bind.annotation.RestControllerAdvice;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* 异常类
|
||||||
* @author DongZeLiang
|
* @author DongZeLiang
|
||||||
* @version 1.0
|
* @version 1.0
|
||||||
* @description 异常类
|
* @description 异常类
|
||||||
|
|
|
@ -5,6 +5,7 @@ import com.muyu.system.handle.SystemHandler;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Forest配置类
|
||||||
* @Author: DongZeLiang
|
* @Author: DongZeLiang
|
||||||
* @date: 2024/6/10
|
* @date: 2024/6/10
|
||||||
* @Description: Forest配置类
|
* @Description: Forest配置类
|
||||||
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
package com.muyu.config;
|
||||||
|
|
||||||
|
import com.muyu.config.interceptor.LoginInterceptor;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
|
||||||
|
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 注册处理器拦截器
|
||||||
|
* */
|
||||||
|
@Configuration
|
||||||
|
public class SystemWebConfigurer implements WebMvcConfigurer {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private LoginInterceptor loginInterceptor;
|
||||||
|
|
||||||
|
/** 拦截器配置 */
|
||||||
|
@Override
|
||||||
|
public void addInterceptors(InterceptorRegistry registry) {
|
||||||
|
// 白名单
|
||||||
|
List<String> patterns = new ArrayList<String>();
|
||||||
|
patterns.add("/system/auth/login");
|
||||||
|
patterns.add("/system/auth/logout");
|
||||||
|
patterns.add("/");
|
||||||
|
patterns.add("/static/**");
|
||||||
|
|
||||||
|
// 通过注册工具添加拦截器
|
||||||
|
registry.addInterceptor(loginInterceptor).addPathPatterns("/**").excludePathPatterns(patterns);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,52 @@
|
||||||
|
package com.muyu.config.cache;
|
||||||
|
|
||||||
|
import com.github.benmanes.caffeine.cache.Expiry;
|
||||||
|
import org.checkerframework.checker.index.qual.NonNegative;
|
||||||
|
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Author: DongZeLiang
|
||||||
|
* @date: 2024/9/12
|
||||||
|
* @Description: 缓存过期
|
||||||
|
* @Version: 1.0
|
||||||
|
*/
|
||||||
|
public class CacheExpiry implements Expiry<String, ExpiryTime> {
|
||||||
|
/**
|
||||||
|
* @param key 缓存键
|
||||||
|
* @param value 缓存值
|
||||||
|
* @param currentTime 当前时间戳
|
||||||
|
*
|
||||||
|
* @return 进入有效期前的时间长度,以纳秒为单位
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public long expireAfterCreate (String key, ExpiryTime value, long currentTime) {
|
||||||
|
return TimeUnit.SECONDS.toNanos(value.getExpiryTime());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param key 缓存键
|
||||||
|
* @param value 缓存值
|
||||||
|
* @param currentTime 当前时间戳
|
||||||
|
* @param currentDuration 剩余时间
|
||||||
|
*
|
||||||
|
* @return 进入有效期前的时间长度,以纳秒为单位
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public long expireAfterUpdate (String key, ExpiryTime value, long currentTime, @NonNegative long currentDuration) {
|
||||||
|
return TimeUnit.SECONDS.toNanos(value.getRefreshTime());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param key 缓存键
|
||||||
|
* @param value 缓存值
|
||||||
|
* @param currentTime 当前时间戳
|
||||||
|
* @param currentDuration 剩余持续时间
|
||||||
|
*
|
||||||
|
* @return 进入有效期前的时间长度,以纳秒为单位
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public long expireAfterRead (String key, ExpiryTime value, long currentTime, @NonNegative long currentDuration) {
|
||||||
|
return TimeUnit.SECONDS.toNanos(value.getRefreshTime());
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
package com.muyu.config.cache;
|
||||||
|
|
||||||
|
import com.github.benmanes.caffeine.cache.Cache;
|
||||||
|
import com.github.benmanes.caffeine.cache.Caffeine;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 缓存配置类
|
||||||
|
*/
|
||||||
|
@Configuration
|
||||||
|
public class CaffeineConfig {
|
||||||
|
@Bean("loginUserCache")
|
||||||
|
public Cache<String, ? extends ExpiryTime> caffeineCache(){
|
||||||
|
CacheExpiry cacheExpiry = new CacheExpiry();
|
||||||
|
return Caffeine.newBuilder()
|
||||||
|
.expireAfter(cacheExpiry)
|
||||||
|
//初始容量为100
|
||||||
|
.initialCapacity(128)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
package com.muyu.config.cache;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.experimental.SuperBuilder;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Author: DongZeLiang
|
||||||
|
* @date: 2024/9/12
|
||||||
|
* @Description: 过期时间
|
||||||
|
* @Version: 1.0
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@SuperBuilder
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class ExpiryTime {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 过期时间单位(秒) 默认30分钟
|
||||||
|
*/
|
||||||
|
@Builder.Default
|
||||||
|
private long expiryTime = 30*60;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 刷新时间单位(秒) 默认15分钟
|
||||||
|
*/
|
||||||
|
@Builder.Default
|
||||||
|
private long refreshTime = 15*60;
|
||||||
|
}
|
|
@ -0,0 +1,81 @@
|
||||||
|
package com.muyu.config.interceptor;
|
||||||
|
|
||||||
|
import com.github.benmanes.caffeine.cache.Cache;
|
||||||
|
import com.muyu.system.constants.TokenConstants;
|
||||||
|
import com.muyu.system.context.SystemUserContext;
|
||||||
|
import com.muyu.system.domain.LoginUserInfo;
|
||||||
|
import com.muyu.utils.JwtUtils;
|
||||||
|
import io.jsonwebtoken.Claims;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.web.servlet.HandlerInterceptor;
|
||||||
|
import org.springframework.web.servlet.ModelAndView;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户登录拦截器
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class LoginInterceptor implements HandlerInterceptor {
|
||||||
|
|
||||||
|
@Resource( name = "loginUserCache")
|
||||||
|
private Cache<String, LoginUserInfo> loginUserInfoCache;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 在请求被处理之前进行操作
|
||||||
|
*
|
||||||
|
* @param request
|
||||||
|
* @param response
|
||||||
|
* @param handler
|
||||||
|
* @return 返回true表示继续执行后续的拦截器或Controller;返回false则不再执行后续的拦截器或Controller
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean preHandle(HttpServletRequest request, @NotNull HttpServletResponse response, @NotNull Object handler) throws Exception {
|
||||||
|
// 判断当前请求是否需要被拦截
|
||||||
|
String token = request.getHeader(TokenConstants.AUTHENTICATION);
|
||||||
|
if (StringUtils.isEmpty(token)){
|
||||||
|
throw new RuntimeException("未授权请求,请重新授权");
|
||||||
|
}
|
||||||
|
Claims claims = JwtUtils.parseToken(token);
|
||||||
|
String userKey = JwtUtils.getUserKey(claims);
|
||||||
|
LoginUserInfo loginUserInfo = loginUserInfoCache.getIfPresent(userKey);
|
||||||
|
if (loginUserInfo == null){
|
||||||
|
throw new RuntimeException("用户授权过期,请重新登录");
|
||||||
|
}
|
||||||
|
SystemUserContext.set(loginUserInfo);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 在请求被处理之后但视图还未渲染时进行操作
|
||||||
|
*
|
||||||
|
* @param request
|
||||||
|
* @param response
|
||||||
|
* @param handler
|
||||||
|
* @param modelAndView
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void postHandle(@NotNull HttpServletRequest request, @NotNull HttpServletResponse response, @NotNull Object handler, ModelAndView modelAndView) throws Exception {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 在整个请求结束之后(包括视图已经渲染)进行操作
|
||||||
|
*
|
||||||
|
* @param request
|
||||||
|
* @param response
|
||||||
|
* @param handler
|
||||||
|
* @param ex
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void afterCompletion(@NotNull HttpServletRequest request, @NotNull HttpServletResponse response, @NotNull Object handler, Exception ex) throws Exception {
|
||||||
|
SystemUserContext.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,48 @@
|
||||||
|
package com.muyu.system.constants;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 权限相关通用常量
|
||||||
|
*
|
||||||
|
* @author muyu
|
||||||
|
*/
|
||||||
|
public class SecurityConstants {
|
||||||
|
/**
|
||||||
|
* 用户ID字段
|
||||||
|
*/
|
||||||
|
public static final String DETAILS_USER_ID = "user_id";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户名字段
|
||||||
|
*/
|
||||||
|
public static final String DETAILS_USERNAME = "username";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 授权信息字段
|
||||||
|
*/
|
||||||
|
public static final String AUTHORIZATION_HEADER = "authorization";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 请求来源
|
||||||
|
*/
|
||||||
|
public static final String FROM_SOURCE = "from-source";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 内部请求
|
||||||
|
*/
|
||||||
|
public static final String INNER = "inner";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户标识
|
||||||
|
*/
|
||||||
|
public static final String USER_KEY = "user_key";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 登录用户
|
||||||
|
*/
|
||||||
|
public static final String LOGIN_USER = "login_user";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 角色权限
|
||||||
|
*/
|
||||||
|
public static final String ROLE_PERMISSION = "role_permission";
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
package com.muyu.system.constants;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Token的Key常量
|
||||||
|
*
|
||||||
|
* @author muyu
|
||||||
|
*/
|
||||||
|
public class TokenConstants {
|
||||||
|
/**
|
||||||
|
* 令牌自定义标识
|
||||||
|
*/
|
||||||
|
public static final String AUTHENTICATION = "Authorization";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 令牌前缀
|
||||||
|
*/
|
||||||
|
public static final String PREFIX = "Bearer ";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 令牌秘钥
|
||||||
|
*/
|
||||||
|
public final static String SECRET = "abcdefghijklmnsalieopadfaqawefwerstuvwxyz";
|
||||||
|
|
||||||
|
}
|
|
@ -1,10 +1,12 @@
|
||||||
package com.muyu.system.domain;
|
package com.muyu.system.domain;
|
||||||
|
|
||||||
|
import com.muyu.config.cache.ExpiryTime;
|
||||||
import com.muyu.system.properties.ServerConfigProperties;
|
import com.muyu.system.properties.ServerConfigProperties;
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.Builder;
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.experimental.SuperBuilder;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Description: 登陆用户信息
|
* @Description: 登陆用户信息
|
||||||
|
@ -12,16 +14,22 @@ import lombok.NoArgsConstructor;
|
||||||
* @date: 2024/9/11-上午10:15
|
* @date: 2024/9/11-上午10:15
|
||||||
*/
|
*/
|
||||||
@Data
|
@Data
|
||||||
@Builder
|
@SuperBuilder
|
||||||
@NoArgsConstructor
|
@NoArgsConstructor
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
public class LoginUserInfo {
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
public class LoginUserInfo extends ExpiryTime {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 用户ID
|
* 用户ID
|
||||||
*/
|
*/
|
||||||
private Long id;
|
private Long id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户token
|
||||||
|
*/
|
||||||
|
private String userKey;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 用户名称
|
* 用户名称
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -19,6 +19,14 @@ public class SystemHandler {
|
||||||
return SystemUserContext.get();
|
return SystemUserContext.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取用户key
|
||||||
|
* @return 用户Key
|
||||||
|
*/
|
||||||
|
public static String getUserKey(){
|
||||||
|
return getUserInfo().getUserKey();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 登陆用户ID
|
* 登陆用户ID
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package com.muyu.system.properties;
|
package com.muyu.system.properties;
|
||||||
|
|
||||||
|
import com.muyu.web.domain.ServerConfig;
|
||||||
import com.muyu.web.domain.model.ServerConfigModel;
|
import com.muyu.web.domain.model.ServerConfigModel;
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.Builder;
|
import lombok.Builder;
|
||||||
|
@ -71,5 +72,29 @@ public class ServerConfigProperties {
|
||||||
)
|
)
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* 模型构建配置
|
||||||
|
* @param serverConfig 配置对象
|
||||||
|
* @return 配置对象
|
||||||
|
*/
|
||||||
|
public static ServerConfigProperties configToProperties(ServerConfig serverConfig ) {
|
||||||
|
|
||||||
|
return ServerConfigProperties.builder()
|
||||||
|
.host(serverConfig.getHost())
|
||||||
|
.port(serverConfig.getPort())
|
||||||
|
.uri(serverConfig.getUri())
|
||||||
|
.mqttAddr(serverConfig.getDefaultMqttAddr())
|
||||||
|
.mqttTopic(serverConfig.getDefaultMqttTopic())
|
||||||
|
.mqttQos(serverConfig.getDefaultMqttQos())
|
||||||
|
.loadReqUrl(
|
||||||
|
String.format(
|
||||||
|
"http://%s:%s%s",
|
||||||
|
serverConfig.getHost(),
|
||||||
|
serverConfig.getPort(),
|
||||||
|
serverConfig.getUri().startsWith("/") ? serverConfig.getUri() : "/" + serverConfig.getUri()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,19 +36,4 @@ public class AesUtil {
|
||||||
byte[] decryptedBytes = cipher.doFinal(Base64.getDecoder().decode(encryptedData));
|
byte[] decryptedBytes = cipher.doFinal(Base64.getDecoder().decode(encryptedData));
|
||||||
return new String(decryptedBytes, StandardCharsets.UTF_8);
|
return new String(decryptedBytes, StandardCharsets.UTF_8);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void main(String[] args) {
|
|
||||||
try {
|
|
||||||
String data = "jdbc:mysql://47.92.86.60:23658/muyu-vehicle?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8";
|
|
||||||
String encryptedData = encrypt(data);
|
|
||||||
String decryptedData = decrypt(encryptedData);
|
|
||||||
|
|
||||||
System.out.println("Original Key: " + key);
|
|
||||||
System.out.println("Original Data: " + data);
|
|
||||||
System.out.println("Encrypted Data: " + encryptedData);
|
|
||||||
System.out.println("Decrypted Data: " + decryptedData);
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,45 @@
|
||||||
|
package com.muyu.utils;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ID生成器工具类
|
||||||
|
*
|
||||||
|
* @author muyu
|
||||||
|
*/
|
||||||
|
public class IdUtils {
|
||||||
|
/**
|
||||||
|
* 获取随机UUID
|
||||||
|
*
|
||||||
|
* @return 随机UUID
|
||||||
|
*/
|
||||||
|
public static String randomUUID () {
|
||||||
|
return UUID.randomUUID().toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 简化的UUID,去掉了横线
|
||||||
|
*
|
||||||
|
* @return 简化的UUID,去掉了横线
|
||||||
|
*/
|
||||||
|
public static String simpleUUID () {
|
||||||
|
return UUID.randomUUID().toString(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取随机UUID,使用性能更好的ThreadLocalRandom生成UUID
|
||||||
|
*
|
||||||
|
* @return 随机UUID
|
||||||
|
*/
|
||||||
|
public static String fastUUID () {
|
||||||
|
return UUID.fastUUID().toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 简化的UUID,去掉了横线,使用性能更好的ThreadLocalRandom生成UUID
|
||||||
|
*
|
||||||
|
* @return 简化的UUID,去掉了横线
|
||||||
|
*/
|
||||||
|
public static String fastSimpleUUID () {
|
||||||
|
return UUID.fastUUID().toString(true);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,165 @@
|
||||||
|
package com.muyu.utils;
|
||||||
|
|
||||||
|
import com.muyu.system.constants.SecurityConstants;
|
||||||
|
import com.muyu.system.constants.TokenConstants;
|
||||||
|
import com.muyu.web.utils.Convert;
|
||||||
|
import io.jsonwebtoken.Claims;
|
||||||
|
import io.jsonwebtoken.Jwts;
|
||||||
|
import io.jsonwebtoken.security.Keys;
|
||||||
|
import io.jsonwebtoken.security.SecureDigestAlgorithm;
|
||||||
|
|
||||||
|
import javax.crypto.SecretKey;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Jwt工具类
|
||||||
|
*
|
||||||
|
* @author muyu
|
||||||
|
*/
|
||||||
|
public class JwtUtils {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 加密算法
|
||||||
|
*/
|
||||||
|
private final static SecureDigestAlgorithm<SecretKey, SecretKey> ALGORITHM = Jwts.SIG.HS256;
|
||||||
|
/**
|
||||||
|
* 私钥 / 生成签名的时候使用的秘钥secret,一般可以从本地配置文件中读取,切记这个秘钥不能外露,只在服务端使用,在任何场景都不应该流露出去。
|
||||||
|
* 一旦客户端得知这个secret, 那就意味着客户端是可以自我签发jwt了。
|
||||||
|
* 应该大于等于 256位(长度32及以上的字符串),并且是随机的字符串
|
||||||
|
*/
|
||||||
|
private final static String secret = TokenConstants.SECRET;
|
||||||
|
/**
|
||||||
|
* 秘钥实例
|
||||||
|
*/
|
||||||
|
public static final SecretKey KEY = Keys.hmacShaKeyFor(secret.getBytes());
|
||||||
|
/**
|
||||||
|
* jwt签发者
|
||||||
|
*/
|
||||||
|
private final static String JWT_ISS = "MUYU";
|
||||||
|
/**
|
||||||
|
* jwt主题
|
||||||
|
*/
|
||||||
|
private final static String SUBJECT = "Peripherals";
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 从数据声明生成令牌
|
||||||
|
*
|
||||||
|
* @param claims 数据声明
|
||||||
|
*
|
||||||
|
* @return 令牌
|
||||||
|
*/
|
||||||
|
public static String createToken (Map<String, Object> claims) {
|
||||||
|
return Jwts.builder()
|
||||||
|
// 设置头部信息header
|
||||||
|
.header().add("typ", "JWT").add("alg", "HS256").and()
|
||||||
|
// 设置自定义负载信息payload
|
||||||
|
.claims(claims)
|
||||||
|
// 签发时间
|
||||||
|
.issuedAt(new Date())
|
||||||
|
// 主题
|
||||||
|
.subject(SUBJECT)
|
||||||
|
// 签发者
|
||||||
|
.issuer(JWT_ISS)
|
||||||
|
// 签名
|
||||||
|
.signWith(KEY, ALGORITHM)
|
||||||
|
.compact();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 从令牌中获取数据声明
|
||||||
|
*
|
||||||
|
* @param token 令牌
|
||||||
|
*
|
||||||
|
* @return 数据声明
|
||||||
|
*/
|
||||||
|
public static Claims parseToken (String token) {
|
||||||
|
return Jwts.parser()
|
||||||
|
.verifyWith(KEY)
|
||||||
|
.build()
|
||||||
|
.parseSignedClaims(token)
|
||||||
|
.getPayload();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据令牌获取用户标识
|
||||||
|
*
|
||||||
|
* @param token 令牌
|
||||||
|
*
|
||||||
|
* @return 用户ID
|
||||||
|
*/
|
||||||
|
public static String getUserKey (String token) {
|
||||||
|
Claims claims = parseToken(token);
|
||||||
|
return getValue(claims, SecurityConstants.USER_KEY);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据令牌获取用户标识
|
||||||
|
*
|
||||||
|
* @param claims 身份信息
|
||||||
|
*
|
||||||
|
* @return 用户ID
|
||||||
|
*/
|
||||||
|
public static String getUserKey (Claims claims) {
|
||||||
|
return getValue(claims, SecurityConstants.USER_KEY);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据令牌获取用户ID
|
||||||
|
*
|
||||||
|
* @param token 令牌
|
||||||
|
*
|
||||||
|
* @return 用户ID
|
||||||
|
*/
|
||||||
|
public static String getUserId (String token) {
|
||||||
|
Claims claims = parseToken(token);
|
||||||
|
return getValue(claims, SecurityConstants.DETAILS_USER_ID);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据身份信息获取用户ID
|
||||||
|
*
|
||||||
|
* @param claims 身份信息
|
||||||
|
*
|
||||||
|
* @return 用户ID
|
||||||
|
*/
|
||||||
|
public static String getUserId (Claims claims) {
|
||||||
|
return getValue(claims, SecurityConstants.DETAILS_USER_ID);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据令牌获取用户名
|
||||||
|
*
|
||||||
|
* @param token 令牌
|
||||||
|
*
|
||||||
|
* @return 用户名
|
||||||
|
*/
|
||||||
|
public static String getUserName (String token) {
|
||||||
|
Claims claims = parseToken(token);
|
||||||
|
return getValue(claims, SecurityConstants.DETAILS_USERNAME);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据身份信息获取用户名
|
||||||
|
*
|
||||||
|
* @param claims 身份信息
|
||||||
|
*
|
||||||
|
* @return 用户名
|
||||||
|
*/
|
||||||
|
public static String getUserName (Claims claims) {
|
||||||
|
return getValue(claims, SecurityConstants.DETAILS_USERNAME);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据身份信息获取键值
|
||||||
|
*
|
||||||
|
* @param claims 身份信息
|
||||||
|
* @param key 键
|
||||||
|
*
|
||||||
|
* @return 值
|
||||||
|
*/
|
||||||
|
public static String getValue (Claims claims, String key) {
|
||||||
|
return Convert.toStr(claims.get(key), "");
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,449 @@
|
||||||
|
package com.muyu.utils;
|
||||||
|
|
||||||
|
|
||||||
|
import java.security.MessageDigest;
|
||||||
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
import java.security.SecureRandom;
|
||||||
|
import java.util.Random;
|
||||||
|
import java.util.concurrent.ThreadLocalRandom;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 提供通用唯一识别码(universally unique identifier)(UUID)实现
|
||||||
|
*
|
||||||
|
* @author muyu
|
||||||
|
*/
|
||||||
|
public final class UUID implements java.io.Serializable, Comparable<UUID> {
|
||||||
|
private static final long serialVersionUID = -1185015143654744140L;
|
||||||
|
/**
|
||||||
|
* 此UUID的最高64有效位
|
||||||
|
*/
|
||||||
|
private final long mostSigBits;
|
||||||
|
/**
|
||||||
|
* 此UUID的最低64有效位
|
||||||
|
*/
|
||||||
|
private final long leastSigBits;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 私有构造
|
||||||
|
*
|
||||||
|
* @param data 数据
|
||||||
|
*/
|
||||||
|
private UUID (byte[] data) {
|
||||||
|
long msb = 0;
|
||||||
|
long lsb = 0;
|
||||||
|
assert data.length == 16 : "data must be 16 bytes in length";
|
||||||
|
for (int i = 0 ; i < 8 ; i++) {
|
||||||
|
msb = (msb << 8) | (data[i] & 0xff);
|
||||||
|
}
|
||||||
|
for (int i = 8 ; i < 16 ; i++) {
|
||||||
|
lsb = (lsb << 8) | (data[i] & 0xff);
|
||||||
|
}
|
||||||
|
this.mostSigBits = msb;
|
||||||
|
this.leastSigBits = lsb;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 使用指定的数据构造新的 UUID。
|
||||||
|
*
|
||||||
|
* @param mostSigBits 用于 {@code UUID} 的最高有效 64 位
|
||||||
|
* @param leastSigBits 用于 {@code UUID} 的最低有效 64 位
|
||||||
|
*/
|
||||||
|
public UUID (long mostSigBits, long leastSigBits) {
|
||||||
|
this.mostSigBits = mostSigBits;
|
||||||
|
this.leastSigBits = leastSigBits;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取类型 4(伪随机生成的)UUID 的静态工厂。
|
||||||
|
*
|
||||||
|
* @return 随机生成的 {@code UUID}
|
||||||
|
*/
|
||||||
|
public static UUID fastUUID () {
|
||||||
|
return randomUUID(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取类型 4(伪随机生成的)UUID 的静态工厂。 使用加密的强伪随机数生成器生成该 UUID。
|
||||||
|
*
|
||||||
|
* @return 随机生成的 {@code UUID}
|
||||||
|
*/
|
||||||
|
public static UUID randomUUID () {
|
||||||
|
return randomUUID(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取类型 4(伪随机生成的)UUID 的静态工厂。 使用加密的强伪随机数生成器生成该 UUID。
|
||||||
|
*
|
||||||
|
* @param isSecure 是否使用{@link SecureRandom}如果是可以获得更安全的随机码,否则可以得到更好的性能
|
||||||
|
*
|
||||||
|
* @return 随机生成的 {@code UUID}
|
||||||
|
*/
|
||||||
|
public static UUID randomUUID (boolean isSecure) {
|
||||||
|
final Random ng = isSecure ? Holder.numberGenerator : getRandom();
|
||||||
|
|
||||||
|
byte[] randomBytes = new byte[16];
|
||||||
|
ng.nextBytes(randomBytes);
|
||||||
|
randomBytes[6] &= 0x0f; /* clear version */
|
||||||
|
randomBytes[6] |= 0x40; /* set to version 4 */
|
||||||
|
randomBytes[8] &= 0x3f; /* clear variant */
|
||||||
|
randomBytes[8] |= (byte) 0x80; /* set to IETF variant */
|
||||||
|
return new UUID(randomBytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据指定的字节数组获取类型 3(基于名称的)UUID 的静态工厂。
|
||||||
|
*
|
||||||
|
* @param name 用于构造 UUID 的字节数组。
|
||||||
|
*
|
||||||
|
* @return 根据指定数组生成的 {@code UUID}
|
||||||
|
*/
|
||||||
|
public static UUID nameUUIDFromBytes (byte[] name) {
|
||||||
|
MessageDigest md;
|
||||||
|
try {
|
||||||
|
md = MessageDigest.getInstance("MD5");
|
||||||
|
} catch (NoSuchAlgorithmException nae) {
|
||||||
|
throw new InternalError("MD5 not supported");
|
||||||
|
}
|
||||||
|
byte[] md5Bytes = md.digest(name);
|
||||||
|
md5Bytes[6] &= 0x0f; /* clear version */
|
||||||
|
md5Bytes[6] |= 0x30; /* set to version 3 */
|
||||||
|
md5Bytes[8] &= 0x3f; /* clear variant */
|
||||||
|
md5Bytes[8] |= (byte) 0x80; /* set to IETF variant */
|
||||||
|
return new UUID(md5Bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据 {@link #toString()} 方法中描述的字符串标准表示形式创建{@code UUID}。
|
||||||
|
*
|
||||||
|
* @param name 指定 {@code UUID} 字符串
|
||||||
|
*
|
||||||
|
* @return 具有指定值的 {@code UUID}
|
||||||
|
*
|
||||||
|
* @throws IllegalArgumentException 如果 name 与 {@link #toString} 中描述的字符串表示形式不符抛出此异常
|
||||||
|
*/
|
||||||
|
public static UUID fromString (String name) {
|
||||||
|
String[] components = name.split("-");
|
||||||
|
if (components.length != 5) {
|
||||||
|
throw new IllegalArgumentException("Invalid UUID string: " + name);
|
||||||
|
}
|
||||||
|
for (int i = 0 ; i < 5 ; i++) {
|
||||||
|
components[i] = "0x" + components[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
long mostSigBits = Long.decode(components[0]);
|
||||||
|
mostSigBits <<= 16;
|
||||||
|
mostSigBits |= Long.decode(components[1]);
|
||||||
|
mostSigBits <<= 16;
|
||||||
|
mostSigBits |= Long.decode(components[2]);
|
||||||
|
|
||||||
|
long leastSigBits = Long.decode(components[3]);
|
||||||
|
leastSigBits <<= 48;
|
||||||
|
leastSigBits |= Long.decode(components[4]);
|
||||||
|
|
||||||
|
return new UUID(mostSigBits, leastSigBits);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回指定数字对应的hex值
|
||||||
|
*
|
||||||
|
* @param val 值
|
||||||
|
* @param digits 位
|
||||||
|
*
|
||||||
|
* @return 值
|
||||||
|
*/
|
||||||
|
private static String digits (long val, int digits) {
|
||||||
|
long hi = 1L << (digits * 4);
|
||||||
|
return Long.toHexString(hi | (val & (hi - 1))).substring(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取{@link SecureRandom},类提供加密的强随机数生成器 (RNG)
|
||||||
|
*
|
||||||
|
* @return {@link SecureRandom}
|
||||||
|
*/
|
||||||
|
public static SecureRandom getSecureRandom () {
|
||||||
|
try {
|
||||||
|
return SecureRandom.getInstance("SHA1PRNG");
|
||||||
|
} catch (NoSuchAlgorithmException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取随机数生成器对象<br>
|
||||||
|
* ThreadLocalRandom是JDK 7之后提供并发产生随机数,能够解决多个线程发生的竞争争夺。
|
||||||
|
*
|
||||||
|
* @return {@link ThreadLocalRandom}
|
||||||
|
*/
|
||||||
|
public static ThreadLocalRandom getRandom () {
|
||||||
|
return ThreadLocalRandom.current();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回此 UUID 的 128 位值中的最低有效 64 位。
|
||||||
|
*
|
||||||
|
* @return 此 UUID 的 128 位值中的最低有效 64 位。
|
||||||
|
*/
|
||||||
|
public long getLeastSignificantBits () {
|
||||||
|
return leastSigBits;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回此 UUID 的 128 位值中的最高有效 64 位。
|
||||||
|
*
|
||||||
|
* @return 此 UUID 的 128 位值中最高有效 64 位。
|
||||||
|
*/
|
||||||
|
public long getMostSignificantBits () {
|
||||||
|
return mostSigBits;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 与此 {@code UUID} 相关联的版本号. 版本号描述此 {@code UUID} 是如何生成的。
|
||||||
|
* <p>
|
||||||
|
* 版本号具有以下含意:
|
||||||
|
* <ul>
|
||||||
|
* <li>1 基于时间的 UUID
|
||||||
|
* <li>2 DCE 安全 UUID
|
||||||
|
* <li>3 基于名称的 UUID
|
||||||
|
* <li>4 随机生成的 UUID
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* @return 此 {@code UUID} 的版本号
|
||||||
|
*/
|
||||||
|
public int version () {
|
||||||
|
// Version is bits masked by 0x000000000000F000 in MS long
|
||||||
|
return (int) ((mostSigBits >> 12) & 0x0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 与此 {@code UUID} 相关联的变体号。变体号描述 {@code UUID} 的布局。
|
||||||
|
* <p>
|
||||||
|
* 变体号具有以下含意:
|
||||||
|
* <ul>
|
||||||
|
* <li>0 为 NCS 向后兼容保留
|
||||||
|
* <li>2 <a href="http://www.ietf.org/rfc/rfc4122.txt">IETF RFC 4122</a>(Leach-Salz), 用于此类
|
||||||
|
* <li>6 保留,微软向后兼容
|
||||||
|
* <li>7 保留供以后定义使用
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* @return 此 {@code UUID} 相关联的变体号
|
||||||
|
*/
|
||||||
|
public int variant () {
|
||||||
|
// This field is composed of a varying number of bits.
|
||||||
|
// 0 - - Reserved for NCS backward compatibility
|
||||||
|
// 1 0 - The IETF aka Leach-Salz variant (used by this class)
|
||||||
|
// 1 1 0 Reserved, Microsoft backward compatibility
|
||||||
|
// 1 1 1 Reserved for future definition.
|
||||||
|
return (int) ((leastSigBits >>> (64 - (leastSigBits >>> 62))) & (leastSigBits >> 63));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 与此 UUID 相关联的时间戳值。
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* 60 位的时间戳值根据此 {@code UUID} 的 time_low、time_mid 和 time_hi 字段构造。<br>
|
||||||
|
* 所得到的时间戳以 100 毫微秒为单位,从 UTC(通用协调时间) 1582 年 10 月 15 日零时开始。
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* 时间戳值仅在在基于时间的 UUID(其 version 类型为 1)中才有意义。<br>
|
||||||
|
* 如果此 {@code UUID} 不是基于时间的 UUID,则此方法抛出 UnsupportedOperationException。
|
||||||
|
*
|
||||||
|
* @throws UnsupportedOperationException 如果此 {@code UUID} 不是 version 为 1 的 UUID。
|
||||||
|
*/
|
||||||
|
public long timestamp () throws UnsupportedOperationException {
|
||||||
|
checkTimeBase();
|
||||||
|
return (mostSigBits & 0x0FFFL) << 48//
|
||||||
|
| ((mostSigBits >> 16) & 0x0FFFFL) << 32//
|
||||||
|
| mostSigBits >>> 32;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 与此 UUID 相关联的时钟序列值。
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* 14 位的时钟序列值根据此 UUID 的 clock_seq 字段构造。clock_seq 字段用于保证在基于时间的 UUID 中的时间唯一性。
|
||||||
|
* <p>
|
||||||
|
* {@code clockSequence} 值仅在基于时间的 UUID(其 version 类型为 1)中才有意义。 如果此 UUID 不是基于时间的 UUID,则此方法抛出
|
||||||
|
* UnsupportedOperationException。
|
||||||
|
*
|
||||||
|
* @return 此 {@code UUID} 的时钟序列
|
||||||
|
*
|
||||||
|
* @throws UnsupportedOperationException 如果此 UUID 的 version 不为 1
|
||||||
|
*/
|
||||||
|
public int clockSequence () throws UnsupportedOperationException {
|
||||||
|
checkTimeBase();
|
||||||
|
return (int) ((leastSigBits & 0x3FFF000000000000L) >>> 48);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 与此 UUID 相关的节点值。
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* 48 位的节点值根据此 UUID 的 node 字段构造。此字段旨在用于保存机器的 IEEE 802 地址,该地址用于生成此 UUID 以保证空间唯一性。
|
||||||
|
* <p>
|
||||||
|
* 节点值仅在基于时间的 UUID(其 version 类型为 1)中才有意义。<br>
|
||||||
|
* 如果此 UUID 不是基于时间的 UUID,则此方法抛出 UnsupportedOperationException。
|
||||||
|
*
|
||||||
|
* @return 此 {@code UUID} 的节点值
|
||||||
|
*
|
||||||
|
* @throws UnsupportedOperationException 如果此 UUID 的 version 不为 1
|
||||||
|
*/
|
||||||
|
public long node () throws UnsupportedOperationException {
|
||||||
|
checkTimeBase();
|
||||||
|
return leastSigBits & 0x0000FFFFFFFFFFFFL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回此{@code UUID} 的字符串表现形式。
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* UUID 的字符串表示形式由此 BNF 描述:
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
* {@code
|
||||||
|
* UUID = <time_low>-<time_mid>-<time_high_and_version>-<variant_and_sequence>-<node>
|
||||||
|
* time_low = 4*<hexOctet>
|
||||||
|
* time_mid = 2*<hexOctet>
|
||||||
|
* time_high_and_version = 2*<hexOctet>
|
||||||
|
* variant_and_sequence = 2*<hexOctet>
|
||||||
|
* node = 6*<hexOctet>
|
||||||
|
* hexOctet = <hexDigit><hexDigit>
|
||||||
|
* hexDigit = [0-9a-fA-F]
|
||||||
|
* }
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* </blockquote>
|
||||||
|
*
|
||||||
|
* @return 此{@code UUID} 的字符串表现形式
|
||||||
|
*
|
||||||
|
* @see #toString(boolean)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public String toString () {
|
||||||
|
return toString(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回此{@code UUID} 的字符串表现形式。
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* UUID 的字符串表示形式由此 BNF 描述:
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
* {@code
|
||||||
|
* UUID = <time_low>-<time_mid>-<time_high_and_version>-<variant_and_sequence>-<node>
|
||||||
|
* time_low = 4*<hexOctet>
|
||||||
|
* time_mid = 2*<hexOctet>
|
||||||
|
* time_high_and_version = 2*<hexOctet>
|
||||||
|
* variant_and_sequence = 2*<hexOctet>
|
||||||
|
* node = 6*<hexOctet>
|
||||||
|
* hexOctet = <hexDigit><hexDigit>
|
||||||
|
* hexDigit = [0-9a-fA-F]
|
||||||
|
* }
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* </blockquote>
|
||||||
|
*
|
||||||
|
* @param isSimple 是否简单模式,简单模式为不带'-'的UUID字符串
|
||||||
|
*
|
||||||
|
* @return 此{@code UUID} 的字符串表现形式
|
||||||
|
*/
|
||||||
|
public String toString (boolean isSimple) {
|
||||||
|
final StringBuilder builder = new StringBuilder(isSimple ? 32 : 36);
|
||||||
|
// time_low
|
||||||
|
builder.append(digits(mostSigBits >> 32, 8));
|
||||||
|
if (false == isSimple) {
|
||||||
|
builder.append('-');
|
||||||
|
}
|
||||||
|
// time_mid
|
||||||
|
builder.append(digits(mostSigBits >> 16, 4));
|
||||||
|
if (!isSimple) {
|
||||||
|
builder.append('-');
|
||||||
|
}
|
||||||
|
// time_high_and_version
|
||||||
|
builder.append(digits(mostSigBits, 4));
|
||||||
|
if (!isSimple) {
|
||||||
|
builder.append('-');
|
||||||
|
}
|
||||||
|
// variant_and_sequence
|
||||||
|
builder.append(digits(leastSigBits >> 48, 4));
|
||||||
|
if (!isSimple) {
|
||||||
|
builder.append('-');
|
||||||
|
}
|
||||||
|
// node
|
||||||
|
builder.append(digits(leastSigBits, 12));
|
||||||
|
|
||||||
|
return builder.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Comparison Operations
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回此 UUID 的哈希码。
|
||||||
|
*
|
||||||
|
* @return UUID 的哈希码值。
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public int hashCode () {
|
||||||
|
long hilo = mostSigBits ^ leastSigBits;
|
||||||
|
return ((int) (hilo >> 32)) ^ (int) hilo;
|
||||||
|
}
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------------------------------------------------------
|
||||||
|
// Private method start
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将此对象与指定对象比较。
|
||||||
|
* <p>
|
||||||
|
* 当且仅当参数不为 {@code null}、而是一个 UUID 对象、具有与此 UUID 相同的 varriant、包含相同的值(每一位均相同)时,结果才为 {@code true}。
|
||||||
|
*
|
||||||
|
* @param obj 要与之比较的对象
|
||||||
|
*
|
||||||
|
* @return 如果对象相同,则返回 {@code true};否则返回 {@code false}
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean equals (Object obj) {
|
||||||
|
if ((null == obj) || (obj.getClass() != UUID.class)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
UUID id = (UUID) obj;
|
||||||
|
return (mostSigBits == id.mostSigBits && leastSigBits == id.leastSigBits);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将此 UUID 与指定的 UUID 比较。
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* 如果两个 UUID 不同,且第一个 UUID 的最高有效字段大于第二个 UUID 的对应字段,则第一个 UUID 大于第二个 UUID。
|
||||||
|
*
|
||||||
|
* @param val 与此 UUID 比较的 UUID
|
||||||
|
*
|
||||||
|
* @return 在此 UUID 小于、等于或大于 val 时,分别返回 -1、0 或 1。
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public int compareTo (UUID val) {
|
||||||
|
// The ordering is intentionally set up so that the UUIDs
|
||||||
|
// can simply be numerically compared as two numbers
|
||||||
|
//
|
||||||
|
//
|
||||||
|
return (this.mostSigBits < val.mostSigBits ? -1 : //
|
||||||
|
(this.mostSigBits > val.mostSigBits ? 1 : //
|
||||||
|
(Long.compare(this.leastSigBits, val.leastSigBits))));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查是否为time-based版本UUID
|
||||||
|
*/
|
||||||
|
private void checkTimeBase () {
|
||||||
|
if (version() != 1) {
|
||||||
|
throw new UnsupportedOperationException("Not a time-based UUID");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SecureRandom 的单例
|
||||||
|
*/
|
||||||
|
private static class Holder {
|
||||||
|
static final SecureRandom numberGenerator = getSecureRandom();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,52 @@
|
||||||
|
package com.muyu.web.controller;
|
||||||
|
|
||||||
|
import com.muyu.system.domain.LoginUserInfo;
|
||||||
|
import com.muyu.web.common.Result;
|
||||||
|
import com.muyu.web.domain.req.UserLoginReq;
|
||||||
|
import com.muyu.web.service.SystemAuthService;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Author: DongZeLiang
|
||||||
|
* @date: 2024/9/12
|
||||||
|
* @Description: 系统登录接口
|
||||||
|
* @Version: 1.0
|
||||||
|
*/
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/system/auth")
|
||||||
|
public class SystemAuthController {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private SystemAuthService systemAuthService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户登录
|
||||||
|
* @param userLoginReq 用户登录请求对象
|
||||||
|
* @return token
|
||||||
|
*/
|
||||||
|
@PostMapping("/login")
|
||||||
|
public Result<String> login(@RequestBody UserLoginReq userLoginReq){
|
||||||
|
String token = systemAuthService.login(userLoginReq.getUserName(), userLoginReq.getPassword());
|
||||||
|
return Result.success(token);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户退出
|
||||||
|
* @return token
|
||||||
|
*/
|
||||||
|
@GetMapping("/info")
|
||||||
|
public Result<LoginUserInfo> info(){
|
||||||
|
return Result.success(systemAuthService.info());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户退出
|
||||||
|
* @return token
|
||||||
|
*/
|
||||||
|
@PostMapping("/logout")
|
||||||
|
public Result<String> logout(){
|
||||||
|
systemAuthService.logout();
|
||||||
|
return Result.success();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,46 @@
|
||||||
|
package com.muyu.web.domain;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Author: DongZeLiang
|
||||||
|
* @date: 2024/9/12
|
||||||
|
* @Description: 用户信息
|
||||||
|
* @Version: 1.0
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Builder
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class UserInfo {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 主键
|
||||||
|
*/
|
||||||
|
private Long id;
|
||||||
|
/**
|
||||||
|
* 用户名
|
||||||
|
*/
|
||||||
|
private String userName;
|
||||||
|
/**
|
||||||
|
* 用户密码
|
||||||
|
*/
|
||||||
|
private String password;
|
||||||
|
/**
|
||||||
|
* 租户ID
|
||||||
|
*/
|
||||||
|
private String tenantId;
|
||||||
|
/**
|
||||||
|
* 创建时间
|
||||||
|
*/
|
||||||
|
private Date createTime;
|
||||||
|
/**
|
||||||
|
* 修改时间
|
||||||
|
*/
|
||||||
|
private Date updateTime;
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
package com.muyu.web.domain.req;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Author: DongZeLiang
|
||||||
|
* @date: 2024/9/12
|
||||||
|
* @Description: 用户登录请求对象
|
||||||
|
* @Version: 1.0
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Builder
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class UserLoginReq {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户名称
|
||||||
|
*/
|
||||||
|
private String userName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 密码
|
||||||
|
*/
|
||||||
|
private String password;
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
package com.muyu.web.mapper;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
|
import com.muyu.web.domain.UserInfo;
|
||||||
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Author: DongZeLiang
|
||||||
|
* @date: 2024/9/12
|
||||||
|
* @Description: 用户持久层
|
||||||
|
* @Version: 1.0
|
||||||
|
*/
|
||||||
|
@Mapper
|
||||||
|
public interface UserInfoMapper extends BaseMapper<UserInfo> {
|
||||||
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
package com.muyu.web.service;
|
||||||
|
|
||||||
|
import com.muyu.system.domain.LoginUserInfo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Author: DongZeLiang
|
||||||
|
* @date: 2024/9/12
|
||||||
|
* @Description: 授权业务层
|
||||||
|
* @Version: 1.0
|
||||||
|
*/
|
||||||
|
public interface SystemAuthService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户登录
|
||||||
|
* @param userName 用户名称
|
||||||
|
* @param password 用户密码
|
||||||
|
* @return 生成令牌
|
||||||
|
*/
|
||||||
|
String login (String userName, String password);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户登出
|
||||||
|
*/
|
||||||
|
void logout ();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取登录用户信息
|
||||||
|
* @return 登录用户信息
|
||||||
|
*/
|
||||||
|
LoginUserInfo info ();
|
||||||
|
|
||||||
|
}
|
|
@ -17,12 +17,6 @@ import org.springframework.stereotype.Service;
|
||||||
*/
|
*/
|
||||||
@Service
|
@Service
|
||||||
public class ServerConfigServiceImpl extends ServiceImpl<BaseMapper<ServerConfig>, ServerConfig> implements ServerConfigService {
|
public class ServerConfigServiceImpl extends ServiceImpl<BaseMapper<ServerConfig>, ServerConfig> implements ServerConfigService {
|
||||||
|
|
||||||
/**
|
|
||||||
* 配置Key
|
|
||||||
*/
|
|
||||||
private final Integer key = 1;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取配置模型
|
* 获取配置模型
|
||||||
*
|
*
|
||||||
|
@ -41,7 +35,7 @@ public class ServerConfigServiceImpl extends ServiceImpl<BaseMapper<ServerConfig
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void edit (ServerConfigModel serverConfigModel) {
|
public void edit (ServerConfigModel serverConfigModel) {
|
||||||
ServerConfig serverConfig = ServerConfig.modeBuild(serverConfigModel, () -> SystemHandler.getUserId());
|
ServerConfig serverConfig = ServerConfig.modeBuild(serverConfigModel, SystemHandler::getUserId);
|
||||||
updateById(serverConfig);
|
updateById(serverConfig);
|
||||||
SystemHandler.setServerConfig(
|
SystemHandler.setServerConfig(
|
||||||
ServerConfigProperties.modelToProperties(serverConfigModel)
|
ServerConfigProperties.modelToProperties(serverConfigModel)
|
||||||
|
|
|
@ -0,0 +1,101 @@
|
||||||
|
package com.muyu.web.service.impl;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
|
import com.github.benmanes.caffeine.cache.Cache;
|
||||||
|
import com.muyu.system.constants.SecurityConstants;
|
||||||
|
import com.muyu.system.domain.LoginUserInfo;
|
||||||
|
import com.muyu.system.handle.SystemHandler;
|
||||||
|
import com.muyu.system.properties.ServerConfigProperties;
|
||||||
|
import com.muyu.utils.IdUtils;
|
||||||
|
import com.muyu.utils.JwtUtils;
|
||||||
|
import com.muyu.web.domain.ServerConfig;
|
||||||
|
import com.muyu.web.domain.UserInfo;
|
||||||
|
import com.muyu.web.mapper.UserInfoMapper;
|
||||||
|
import com.muyu.web.service.ServerConfigService;
|
||||||
|
import com.muyu.web.service.SystemAuthService;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Author: DongZeLiang
|
||||||
|
* @date: 2024/9/12
|
||||||
|
* @Description: 系统认证业务层
|
||||||
|
* @Version: 1.0
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
public class SystemAuthServiceImpl implements SystemAuthService {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private UserInfoMapper userInfoMapper;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ServerConfigService serverConfigService;
|
||||||
|
|
||||||
|
@Resource( name = "loginUserCache")
|
||||||
|
private Cache<String, LoginUserInfo> loginUserInfoCache;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户登录
|
||||||
|
*
|
||||||
|
* @param userName 用户名称
|
||||||
|
* @param password 用户密码
|
||||||
|
*
|
||||||
|
* @return 生成令牌
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public String login (String userName, String password) {
|
||||||
|
LambdaQueryWrapper<UserInfo> queryWrapper = new LambdaQueryWrapper<>();
|
||||||
|
queryWrapper.eq(UserInfo::getUserName, userName);
|
||||||
|
queryWrapper.eq(UserInfo::getPassword, password);
|
||||||
|
List<UserInfo> userInfoList = userInfoMapper.selectList(queryWrapper);
|
||||||
|
if (userInfoList.isEmpty()){
|
||||||
|
throw new RuntimeException("用户用户名或者密码错误");
|
||||||
|
}
|
||||||
|
UserInfo userInfo = userInfoList.get(0);
|
||||||
|
LambdaQueryWrapper<ServerConfig> serverConfigQueryWrapper = new LambdaQueryWrapper<>();
|
||||||
|
serverConfigQueryWrapper.eq(ServerConfig::getTenantId, userInfo.getTenantId());
|
||||||
|
ServerConfig serverConfig = serverConfigService.getOne(serverConfigQueryWrapper);
|
||||||
|
LoginUserInfo loginUserInfo = LoginUserInfo.builder()
|
||||||
|
.id(userInfo.getId())
|
||||||
|
.tenantId(userInfo.getTenantId())
|
||||||
|
.userName(userInfo.getUserName())
|
||||||
|
.serverConfig(
|
||||||
|
ServerConfigProperties.configToProperties(serverConfig)
|
||||||
|
)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
String userKey = IdUtils.fastUUID();
|
||||||
|
loginUserInfo.setUserKey(userKey);
|
||||||
|
loginUserInfoCache.put(userKey, loginUserInfo);
|
||||||
|
// Jwt存储信息
|
||||||
|
Map<String, Object> claimsMap = new HashMap<String, Object>();
|
||||||
|
claimsMap.put(SecurityConstants.USER_KEY, userKey);
|
||||||
|
claimsMap.put(SecurityConstants.DETAILS_USER_ID, userInfo.getId());
|
||||||
|
claimsMap.put(SecurityConstants.DETAILS_USERNAME, userName);
|
||||||
|
|
||||||
|
return JwtUtils.createToken(claimsMap);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户登出
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void logout () {
|
||||||
|
loginUserInfoCache.invalidate(SystemHandler.getUserKey());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取登录用户信息
|
||||||
|
*
|
||||||
|
* @return 登录用户信息
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public LoginUserInfo info () {
|
||||||
|
return SystemHandler.getUserInfo();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
.app-container[data-v-26d8c57e]{padding:10px 5px 0 10px;background-color:#f4f4f5}.el-row[data-v-26d8c57e]{&:last-child{margin-bottom:0}}.bg-purple[data-v-26d8c57e]{background:#f4f4f5}.grid-content[data-v-26d8c57e]{border-radius:4px;overflow-x:hidden;overflow-y:auto}.grid-content[data-v-26d8c57e]::-webkit-scrollbar{width:4px}.grid-content[data-v-26d8c57e]::-webkit-scrollbar-thumb{border-radius:10px;background:rgba(0,0,0,.2)}.grid-content[data-v-26d8c57e]::-webkit-scrollbar-track{border-radius:0;background:rgba(0,0,0,.1)}.vehicleDiv[data-v-26d8c57e]{height:50px;margin:0 0 10px 0}.contentMain[data-v-26d8c57e]{margin-top:10px}.vehicleDataTab[data-v-26d8c57e]{width:100%;overflow-y:auto;overflow-x:hidden}.vehicleDataTab[data-v-26d8c57e]::-webkit-scrollbar{width:4px}.vehicleDataTab[data-v-26d8c57e]::-webkit-scrollbar-thumb{border-radius:10px;background:rgba(0,0,0,.2)}.vehicleDataTab[data-v-26d8c57e]::-webkit-scrollbar-track{border-radius:0;background:rgba(0,0,0,.1)}.el-form-item__label[data-v-26d8c57e]{padding:0}.el-form-item[data-v-26d8c57e]{margin-bottom:5px}
|
|
@ -1 +1 @@
|
||||||
@supports(-webkit-mask:none) and (not (cater-color:#fff)){.login-container .el-input input{color:#fff}}.login-container .el-input{display:inline-block;height:47px;width:85%}.login-container .el-input input{background:transparent;border:0;-webkit-appearance:none;border-radius:0;padding:12px 5px 12px 15px;color:#fff;height:47px;caret-color:#fff}.login-container .el-input input:-webkit-autofill{-webkit-box-shadow:0 0 0 1000px #283443 inset!important;box-shadow:inset 0 0 0 1000px #283443!important;-webkit-text-fill-color:#fff!important}.login-container .el-form-item{border:1px solid hsla(0,0%,100%,.1);background:rgba(0,0,0,.1);border-radius:5px;color:#454545}.login-container[data-v-5d9ae9a2]{min-height:100%;width:100%;background-color:#2d3a4b;overflow:hidden}.login-container .login-form[data-v-5d9ae9a2]{position:relative;width:520px;max-width:100%;padding:160px 35px 0;margin:0 auto;overflow:hidden}.login-container .tips[data-v-5d9ae9a2]{font-size:14px;color:#fff;margin-bottom:10px}.login-container .tips span[data-v-5d9ae9a2]:first-of-type{margin-right:16px}.login-container .svg-container[data-v-5d9ae9a2]{padding:6px 5px 6px 15px;color:#889aa4;vertical-align:middle;width:30px;display:inline-block}.login-container .title-container[data-v-5d9ae9a2]{position:relative}.login-container .title-container .title[data-v-5d9ae9a2]{font-size:26px;color:#eee;margin:0 auto 40px auto;text-align:center;font-weight:700}.login-container .show-pwd[data-v-5d9ae9a2]{position:absolute;right:10px;top:7px;font-size:16px;color:#889aa4;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}
|
@supports(-webkit-mask:none) and (not (cater-color:#fff)){.login-container .el-input input{color:#fff}}.login-container .el-input{display:inline-block;height:47px;width:85%}.login-container .el-input input{background:transparent;border:0;-webkit-appearance:none;border-radius:0;padding:12px 5px 12px 15px;color:#fff;height:47px;caret-color:#fff}.login-container .el-input input:-webkit-autofill{-webkit-box-shadow:0 0 0 1000px #283443 inset!important;box-shadow:inset 0 0 0 1000px #283443!important;-webkit-text-fill-color:#fff!important}.login-container .el-form-item{border:1px solid hsla(0,0%,100%,.1);background:rgba(0,0,0,.1);border-radius:5px;color:#454545}.login-container[data-v-30d4a998]{min-height:100%;width:100%;background-color:#2d3a4b;overflow:hidden}.login-container .login-form[data-v-30d4a998]{position:relative;width:520px;max-width:100%;padding:160px 35px 0;margin:0 auto;overflow:hidden}.login-container .tips[data-v-30d4a998]{font-size:14px;color:#fff;margin-bottom:10px}.login-container .tips span[data-v-30d4a998]:first-of-type{margin-right:16px}.login-container .svg-container[data-v-30d4a998]{padding:6px 5px 6px 15px;color:#889aa4;vertical-align:middle;width:30px;display:inline-block}.login-container .title-container[data-v-30d4a998]{position:relative}.login-container .title-container .title[data-v-30d4a998]{font-size:26px;color:#eee;margin:0 auto 40px auto;text-align:center;font-weight:700}.login-container .show-pwd[data-v-30d4a998]{position:absolute;right:10px;top:7px;font-size:16px;color:#889aa4;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}
|
|
@ -1 +0,0 @@
|
||||||
.app-container[data-v-5503ff78]{padding:10px 5px 0 10px;background-color:#f4f4f5}.el-row[data-v-5503ff78]{&:last-child{margin-bottom:0}}.bg-purple[data-v-5503ff78]{background:#f4f4f5}.grid-content[data-v-5503ff78]{border-radius:4px;overflow-x:hidden;overflow-y:auto}.grid-content[data-v-5503ff78]::-webkit-scrollbar{width:4px}.grid-content[data-v-5503ff78]::-webkit-scrollbar-thumb{border-radius:10px;background:rgba(0,0,0,.2)}.grid-content[data-v-5503ff78]::-webkit-scrollbar-track{border-radius:0;background:rgba(0,0,0,.1)}.vehicleDiv[data-v-5503ff78]{height:50px;margin:0 0 10px 0}.contentMain[data-v-5503ff78]{margin-top:10px}.vehicleDataTab[data-v-5503ff78]{width:100%;overflow-y:auto;overflow-x:hidden}.vehicleDataTab[data-v-5503ff78]::-webkit-scrollbar{width:4px}.vehicleDataTab[data-v-5503ff78]::-webkit-scrollbar-thumb{border-radius:10px;background:rgba(0,0,0,.2)}.vehicleDataTab[data-v-5503ff78]::-webkit-scrollbar-track{border-radius:0;background:rgba(0,0,0,.1)}.el-form-item__label[data-v-5503ff78]{padding:0}.el-form-item[data-v-5503ff78]{margin-bottom:5px}
|
|
|
@ -1 +1 @@
|
||||||
<!DOCTYPE html><html><head><meta charset=utf-8><meta http-equiv=X-UA-Compatible content="IE=edge,chrome=1"><meta name=viewport content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no"><link rel=icon href=/favicon.ico><title>车辆</title><link href=/static/css/app.63269458.css rel=preload as=style><link href=/static/css/chunk-elementUI.c1c3b808.css rel=preload as=style><link href=/static/css/chunk-libs.3dfb7769.css rel=preload as=style><link href=/static/js/app.93fb13d1.js rel=preload as=script><link href=/static/js/chunk-elementUI.2491fb2f.js rel=preload as=script><link href=/static/js/chunk-libs.2ec7c235.js rel=preload as=script><link href=/static/css/chunk-elementUI.c1c3b808.css rel=stylesheet><link href=/static/css/chunk-libs.3dfb7769.css rel=stylesheet><link href=/static/css/app.63269458.css rel=stylesheet></head><body><noscript><strong>We're sorry but 车辆 doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id=app></div><script>(function(e){function t(t){for(var r,c,u=t[0],f=t[1],i=t[2],l=0,s=[];l<u.length;l++)c=u[l],Object.prototype.hasOwnProperty.call(o,c)&&o[c]&&s.push(o[c][0]),o[c]=0;for(r in f)Object.prototype.hasOwnProperty.call(f,r)&&(e[r]=f[r]);d&&d(t);while(s.length)s.shift()();return a.push.apply(a,i||[]),n()}function n(){for(var e,t=0;t<a.length;t++){for(var n=a[t],r=!0,c=1;c<n.length;c++){var u=n[c];0!==o[u]&&(r=!1)}r&&(a.splice(t--,1),e=f(f.s=n[0]))}return e}var r={},c={runtime:0},o={runtime:0},a=[];function u(e){return f.p+"static/js/"+({}[e]||e)+"."+{"chunk-019c66da":"083a8c5c","chunk-6f60c8f1":"f16bf298","chunk-4a014042":"01579a29","chunk-cd3ab578":"f6e9746e","chunk-e4980b30":"a769f676","chunk-22cea610":"7879ff8f","chunk-2d22c18f":"51f4b062","chunk-510f32e7":"26fc8e8e"}[e]+".js"}function f(t){if(r[t])return r[t].exports;var n=r[t]={i:t,l:!1,exports:{}};return e[t].call(n.exports,n,n.exports,f),n.l=!0,n.exports}f.e=function(e){var t=[],n={"chunk-4a014042":1,"chunk-cd3ab578":1,"chunk-e4980b30":1,"chunk-22cea610":1,"chunk-510f32e7":1};c[e]?t.push(c[e]):0!==c[e]&&n[e]&&t.push(c[e]=new Promise((function(t,n){for(var r="static/css/"+({}[e]||e)+"."+{"chunk-019c66da":"31d6cfe0","chunk-6f60c8f1":"31d6cfe0","chunk-4a014042":"3328abfd","chunk-cd3ab578":"5a7a63c7","chunk-e4980b30":"22503e40","chunk-22cea610":"3c7f5ad9","chunk-2d22c18f":"31d6cfe0","chunk-510f32e7":"1510e3c5"}[e]+".css",o=f.p+r,a=document.getElementsByTagName("link"),u=0;u<a.length;u++){var i=a[u],l=i.getAttribute("data-href")||i.getAttribute("href");if("stylesheet"===i.rel&&(l===r||l===o))return t()}var s=document.getElementsByTagName("style");for(u=0;u<s.length;u++){i=s[u],l=i.getAttribute("data-href");if(l===r||l===o)return t()}var d=document.createElement("link");d.rel="stylesheet",d.type="text/css",d.onload=t,d.onerror=function(t){var r=t&&t.target&&t.target.src||o,a=new Error("Loading CSS chunk "+e+" failed.\n("+r+")");a.code="CSS_CHUNK_LOAD_FAILED",a.request=r,delete c[e],d.parentNode.removeChild(d),n(a)},d.href=o;var h=document.getElementsByTagName("head")[0];h.appendChild(d)})).then((function(){c[e]=0})));var r=o[e];if(0!==r)if(r)t.push(r[2]);else{var a=new Promise((function(t,n){r=o[e]=[t,n]}));t.push(r[2]=a);var i,l=document.createElement("script");l.charset="utf-8",l.timeout=120,f.nc&&l.setAttribute("nonce",f.nc),l.src=u(e);var s=new Error;i=function(t){l.onerror=l.onload=null,clearTimeout(d);var n=o[e];if(0!==n){if(n){var r=t&&("load"===t.type?"missing":t.type),c=t&&t.target&&t.target.src;s.message="Loading chunk "+e+" failed.\n("+r+": "+c+")",s.name="ChunkLoadError",s.type=r,s.request=c,n[1](s)}o[e]=void 0}};var d=setTimeout((function(){i({type:"timeout",target:l})}),12e4);l.onerror=l.onload=i,document.head.appendChild(l)}return Promise.all(t)},f.m=e,f.c=r,f.d=function(e,t,n){f.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:n})},f.r=function(e){"undefined"!==typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},f.t=function(e,t){if(1&t&&(e=f(e)),8&t)return e;if(4&t&&"object"===typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(f.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var r in e)f.d(n,r,function(t){return e[t]}.bind(null,r));return n},f.n=function(e){var t=e&&e.__esModule?function(){return e["default"]}:function(){return e};return f.d(t,"a",t),t},f.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},f.p="/",f.oe=function(e){throw console.error(e),e};var i=window["webpackJsonp"]=window["webpackJsonp"]||[],l=i.push.bind(i);i.push=t,i=i.slice();for(var s=0;s<i.length;s++)t(i[s]);var d=l;n()})([]);</script><script src=/static/js/chunk-elementUI.2491fb2f.js></script><script src=/static/js/chunk-libs.2ec7c235.js></script><script src=/static/js/app.93fb13d1.js></script></body></html>
|
<!DOCTYPE html><html><head><meta charset=utf-8><meta http-equiv=X-UA-Compatible content="IE=edge,chrome=1"><meta name=viewport content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no"><link rel=icon href=/favicon.ico><title>车辆</title><link href=/static/css/app.63269458.css rel=preload as=style><link href=/static/css/chunk-elementUI.c1c3b808.css rel=preload as=style><link href=/static/css/chunk-libs.3dfb7769.css rel=preload as=style><link href=/static/js/app.8eebfa14.js rel=preload as=script><link href=/static/js/chunk-elementUI.2491fb2f.js rel=preload as=script><link href=/static/js/chunk-libs.5e39c7d0.js rel=preload as=script><link href=/static/css/chunk-elementUI.c1c3b808.css rel=stylesheet><link href=/static/css/chunk-libs.3dfb7769.css rel=stylesheet><link href=/static/css/app.63269458.css rel=stylesheet></head><body><noscript><strong>We're sorry but 车辆 doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id=app></div><script>(function(e){function t(t){for(var r,o,a=t[0],f=t[1],i=t[2],l=0,s=[];l<a.length;l++)o=a[l],Object.prototype.hasOwnProperty.call(u,o)&&u[o]&&s.push(u[o][0]),u[o]=0;for(r in f)Object.prototype.hasOwnProperty.call(f,r)&&(e[r]=f[r]);d&&d(t);while(s.length)s.shift()();return c.push.apply(c,i||[]),n()}function n(){for(var e,t=0;t<c.length;t++){for(var n=c[t],r=!0,o=1;o<n.length;o++){var a=n[o];0!==u[a]&&(r=!1)}r&&(c.splice(t--,1),e=f(f.s=n[0]))}return e}var r={},o={runtime:0},u={runtime:0},c=[];function a(e){return f.p+"static/js/"+({}[e]||e)+"."+{"chunk-22cea610":"7879ff8f","chunk-27278b10":"9fae002a","chunk-3f128364":"a125ba12","chunk-5e598597":"395e8d2d","chunk-6f60c8f1":"f16bf298","chunk-0e8cf5f4":"b7552abc","chunk-7d1a163b":"4d8cc933"}[e]+".js"}function f(t){if(r[t])return r[t].exports;var n=r[t]={i:t,l:!1,exports:{}};return e[t].call(n.exports,n,n.exports,f),n.l=!0,n.exports}f.e=function(e){var t=[],n={"chunk-22cea610":1,"chunk-27278b10":1,"chunk-3f128364":1,"chunk-5e598597":1,"chunk-0e8cf5f4":1};o[e]?t.push(o[e]):0!==o[e]&&n[e]&&t.push(o[e]=new Promise((function(t,n){for(var r="static/css/"+({}[e]||e)+"."+{"chunk-22cea610":"3c7f5ad9","chunk-27278b10":"887652d5","chunk-3f128364":"22503e40","chunk-5e598597":"fd551682","chunk-6f60c8f1":"31d6cfe0","chunk-0e8cf5f4":"3328abfd","chunk-7d1a163b":"31d6cfe0"}[e]+".css",u=f.p+r,c=document.getElementsByTagName("link"),a=0;a<c.length;a++){var i=c[a],l=i.getAttribute("data-href")||i.getAttribute("href");if("stylesheet"===i.rel&&(l===r||l===u))return t()}var s=document.getElementsByTagName("style");for(a=0;a<s.length;a++){i=s[a],l=i.getAttribute("data-href");if(l===r||l===u)return t()}var d=document.createElement("link");d.rel="stylesheet",d.type="text/css",d.onload=t,d.onerror=function(t){var r=t&&t.target&&t.target.src||u,c=new Error("Loading CSS chunk "+e+" failed.\n("+r+")");c.code="CSS_CHUNK_LOAD_FAILED",c.request=r,delete o[e],d.parentNode.removeChild(d),n(c)},d.href=u;var h=document.getElementsByTagName("head")[0];h.appendChild(d)})).then((function(){o[e]=0})));var r=u[e];if(0!==r)if(r)t.push(r[2]);else{var c=new Promise((function(t,n){r=u[e]=[t,n]}));t.push(r[2]=c);var i,l=document.createElement("script");l.charset="utf-8",l.timeout=120,f.nc&&l.setAttribute("nonce",f.nc),l.src=a(e);var s=new Error;i=function(t){l.onerror=l.onload=null,clearTimeout(d);var n=u[e];if(0!==n){if(n){var r=t&&("load"===t.type?"missing":t.type),o=t&&t.target&&t.target.src;s.message="Loading chunk "+e+" failed.\n("+r+": "+o+")",s.name="ChunkLoadError",s.type=r,s.request=o,n[1](s)}u[e]=void 0}};var d=setTimeout((function(){i({type:"timeout",target:l})}),12e4);l.onerror=l.onload=i,document.head.appendChild(l)}return Promise.all(t)},f.m=e,f.c=r,f.d=function(e,t,n){f.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:n})},f.r=function(e){"undefined"!==typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},f.t=function(e,t){if(1&t&&(e=f(e)),8&t)return e;if(4&t&&"object"===typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(f.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var r in e)f.d(n,r,function(t){return e[t]}.bind(null,r));return n},f.n=function(e){var t=e&&e.__esModule?function(){return e["default"]}:function(){return e};return f.d(t,"a",t),t},f.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},f.p="/",f.oe=function(e){throw console.error(e),e};var i=window["webpackJsonp"]=window["webpackJsonp"]||[],l=i.push.bind(i);i.push=t,i=i.slice();for(var s=0;s<i.length;s++)t(i[s]);var d=l;n()})([]);</script><script src=/static/js/chunk-elementUI.2491fb2f.js></script><script src=/static/js/chunk-libs.5e39c7d0.js></script><script src=/static/js/app.8eebfa14.js></script></body></html>
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -0,0 +1 @@
|
||||||
|
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-0e8cf5f4"],{7015:function(t,e,i){},8931:function(t,e,i){"use strict";i("7015")},9406:function(t,e,i){"use strict";i.r(e);var a=function(){var t=this,e=t.$createElement,i=t._self._c||e;return i("div",{staticClass:"dashboard-container"},[i("div",{staticClass:"dashboard-text"},[t._v(t._s(t.name))]),i("el-divider"),i("div",{style:{width:t.vehicleStatusWidth+"%",height:t.vehicleStatusHeight+"px",margin:"0 auto"},attrs:{id:"vehicleStatus"}})],1)},n=[],s=i("5530"),l=i("2f62"),h=i("313e"),o=i("b775");function c(){return Object(o["a"])({url:"/vehicle/overview",method:"get"})}var r={name:"Dashboard",data:function(){return{vehicleStatusChart:null,vehicleStatusWidth:50,vehicleStatusHeight:window.innerHeight-300,dataMap:{online:0,offline:2,pause:0}}},computed:Object(s["a"])({},Object(l["b"])(["name"])),watch:{dataMap:function(){this.initVehicleStatus()}},created:function(){setInterval(this.getVehicleOverview,5e3)},mounted:function(){this.vehicleStatusChart=h["a"](document.getElementById("vehicleStatus")),this.initVehicleStatus(),window.addEventListener("resize",this.initVehicleStatus)},methods:{getVehicleOverview:function(){var t=this;c().then((function(e){t.dataMap=e.data}))},initVehicleStatus:function(){this.vehicleStatusChart.setOption({title:{text:"系统模拟车辆状态统计一览",left:"center",textStyle:{fontWeight:1e3,fontSize:26}},tooltip:{trigger:"item"},legend:{top:"5%",left:"center"},series:[{type:"pie",radius:["40%","70%"],avoidLabelOverlap:!1,itemStyle:{borderRadius:10,borderColor:"#fff",borderWidth:10},label:{show:!0},emphasis:{label:{show:!0,fontSize:40,fontWeight:"bold"}},labelLine:{show:!0},data:[{value:this.dataMap.pause,name:"暂停车辆"},{value:this.dataMap.online,name:"在线车辆"},{value:this.dataMap.offline,name:"离线车辆"}]}]})}}},u=r,d=(i("8931"),i("2877")),f=Object(d["a"])(u,a,n,!1,null,"492ff9f3",null);e["default"]=f.exports}}]);
|
File diff suppressed because one or more lines are too long
|
@ -1 +0,0 @@
|
||||||
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-2d22c18f"],{f27d:function(n,t,e){"use strict";e.r(t);var c=function(){var n=this,t=n.$createElement,e=n._self._c||t;return e("div",{staticClass:"app-container"},[n._v(" 统一调配 ")])},a=[],i={name:"Unified",data:function(){return{}},created:function(){},methods:{}},r=i,s=e("2877"),u=Object(s["a"])(r,c,a,!1,null,"143c6c4c",null);t["default"]=u.exports}}]);
|
|
|
@ -1 +1 @@
|
||||||
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-e4980b30"],{"88aa":function(e,t,r){"use strict";r.r(t);var s=function(){var e=this,t=e.$createElement,r=e._self._c||t;return r("div",{staticStyle:{margin:"10px"}},[r("el-row",{attrs:{gutter:20}},[r("el-col",{attrs:{span:24}},[r("el-switch",{staticStyle:{float:"left",margin:"10px 20px"},attrs:{"active-color":"#13ce66","inactive-color":"#ff4949","active-text":"开启修改","inactive-text":"只查看"},model:{value:e.isUpdate,callback:function(t){e.isUpdate=t},expression:"isUpdate"}}),e.isUpdate?r("el-button",{staticStyle:{float:"left"},on:{click:e.editServerConfig}},[e._v("提交并刷新配置")]):e._e()],1),r("el-col",{attrs:{xs:24,md:12}},[r("el-card",{staticClass:"box-card"},[r("div",{staticClass:"clearfix",attrs:{slot:"header"},slot:"header"},[r("span",[e._v("负载均衡服务器配置")])]),r("div",{staticClass:"text item"},[r("el-form",{ref:"form",attrs:{model:e.serverConfig,"label-width":"120px"}},[r("el-form-item",{attrs:{label:"负载服务地址"}},[r("el-input",{attrs:{disabled:!e.isUpdate},model:{value:e.serverConfig.host,callback:function(t){e.$set(e.serverConfig,"host",t)},expression:"serverConfig.host"}})],1),r("el-form-item",{attrs:{label:"负载服务端口"}},[r("el-input",{attrs:{disabled:!e.isUpdate},model:{value:e.serverConfig.port,callback:function(t){e.$set(e.serverConfig,"port",t)},expression:"serverConfig.port"}})],1),r("el-form-item",{attrs:{label:"负载服务API地址"}},[r("el-input",{attrs:{disabled:!e.isUpdate},model:{value:e.serverConfig.loadUrl,callback:function(t){e.$set(e.serverConfig,"loadUrl",t)},expression:"serverConfig.loadUrl"}})],1)],1)],1)])],1),r("el-col",{attrs:{xs:24,md:12}},[r("el-card",{staticClass:"box-card"},[r("div",{staticClass:"clearfix",attrs:{slot:"header"},slot:"header"},[r("span",[e._v("默认MQTT配置")])]),r("div",{staticClass:"text item"},[r("el-form",{ref:"form",attrs:{model:e.serverConfig,"label-width":"120px"}},[r("el-form-item",{attrs:{label:"MQTT默认地址"}},[r("el-input",{attrs:{disabled:!e.isUpdate},model:{value:e.serverConfig.defaultMqttAddr,callback:function(t){e.$set(e.serverConfig,"defaultMqttAddr",t)},expression:"serverConfig.defaultMqttAddr"}})],1),r("el-form-item",{attrs:{label:"MQTT默认主题"}},[r("el-input",{attrs:{disabled:!e.isUpdate},model:{value:e.serverConfig.defaultMqttTopic,callback:function(t){e.$set(e.serverConfig,"defaultMqttTopic",t)},expression:"serverConfig.defaultMqttTopic"}})],1),r("el-form-item",{attrs:{label:"MQTT交付级别"}},[r("el-input",{attrs:{disabled:!e.isUpdate},model:{value:e.serverConfig.defaultMqttQos,callback:function(t){e.$set(e.serverConfig,"defaultMqttQos",t)},expression:"serverConfig.defaultMqttQos"}})],1)],1)],1)])],1)],1)],1)},o=[],a=r("b775");function i(){return Object(a["a"])({url:"/vehicle/server/config",method:"get"})}function n(e){return Object(a["a"])({url:"/vehicle/server/config",method:"PUT",data:e})}var l={name:"ServerConfig",data:function(){return{isUpdate:!1,serverConfig:{host:null,port:null,loadUrl:null,defaultMqttAddr:null,defaultMqttTopic:null,defaultMqttQos:null}}},created:function(){this.getServerConfig()},methods:{getServerConfig:function(){var e=this;i().then((function(t){e.serverConfig=t.data}))},editServerConfig:function(){var e=this;n(this.serverConfig).then((function(t){e.$notify({title:"操作提示",message:t.msg,type:200===t.code?"success":"error"}),200===t.code&&(e.isUpdate=!1)}))}}},c=l,d=(r("8bce"),r("2877")),f=Object(d["a"])(c,s,o,!1,null,"1fac6224",null);t["default"]=f.exports},"8bce":function(e,t,r){"use strict";r("f557")},b775:function(e,t,r){"use strict";r("d3b7");var s=r("bc3a"),o=r.n(s),a=r("5c96"),i=r("4360"),n=r("5f87"),l=o.a.create({baseURL:"/",timeout:5e3});l.interceptors.request.use((function(e){return i["a"].getters.token&&(e.headers["X-Token"]=Object(n["a"])()),e}),(function(e){return console.log(e),Promise.reject(e)})),l.interceptors.response.use((function(e){var t=e.data;return 200!==t.code?(Object(a["Message"])({message:t.msg||"Error",type:"error",duration:5e3}),50008!==t.code&&50012!==t.code&&50014!==t.code||a["MessageBox"].confirm("You have been logged out, you can cancel to stay on this page, or log in again","Confirm logout",{confirmButtonText:"Re-Login",cancelButtonText:"Cancel",type:"warning"}).then((function(){i["a"].dispatch("user/resetToken").then((function(){location.reload()}))})),Promise.reject(new Error(t.msg||"Error"))):t}),(function(e){return console.log("err"+e),Object(a["Message"])({message:e.message,type:"error",duration:5e3}),Promise.reject(e)})),t["a"]=l},f557:function(e,t,r){}}]);
|
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-3f128364"],{"88aa":function(e,t,r){"use strict";r.r(t);var a=function(){var e=this,t=e.$createElement,r=e._self._c||t;return r("div",{staticStyle:{margin:"10px"}},[r("el-row",{attrs:{gutter:20}},[r("el-col",{attrs:{span:24}},[r("el-switch",{staticStyle:{float:"left",margin:"10px 20px"},attrs:{"active-color":"#13ce66","inactive-color":"#ff4949","active-text":"开启修改","inactive-text":"只查看"},model:{value:e.isUpdate,callback:function(t){e.isUpdate=t},expression:"isUpdate"}}),e.isUpdate?r("el-button",{staticStyle:{float:"left"},on:{click:e.editServerConfig}},[e._v("提交并刷新配置")]):e._e()],1),r("el-col",{attrs:{xs:24,md:12}},[r("el-card",{staticClass:"box-card"},[r("div",{staticClass:"clearfix",attrs:{slot:"header"},slot:"header"},[r("span",[e._v("负载均衡服务器配置")])]),r("div",{staticClass:"text item"},[r("el-form",{ref:"form",attrs:{model:e.serverConfig,"label-width":"120px"}},[r("el-form-item",{attrs:{label:"负载服务地址"}},[r("el-input",{attrs:{disabled:!e.isUpdate},model:{value:e.serverConfig.host,callback:function(t){e.$set(e.serverConfig,"host",t)},expression:"serverConfig.host"}})],1),r("el-form-item",{attrs:{label:"负载服务端口"}},[r("el-input",{attrs:{disabled:!e.isUpdate},model:{value:e.serverConfig.port,callback:function(t){e.$set(e.serverConfig,"port",t)},expression:"serverConfig.port"}})],1),r("el-form-item",{attrs:{label:"负载服务API地址"}},[r("el-input",{attrs:{disabled:!e.isUpdate},model:{value:e.serverConfig.loadUrl,callback:function(t){e.$set(e.serverConfig,"loadUrl",t)},expression:"serverConfig.loadUrl"}})],1)],1)],1)])],1),r("el-col",{attrs:{xs:24,md:12}},[r("el-card",{staticClass:"box-card"},[r("div",{staticClass:"clearfix",attrs:{slot:"header"},slot:"header"},[r("span",[e._v("默认MQTT配置")])]),r("div",{staticClass:"text item"},[r("el-form",{ref:"form",attrs:{model:e.serverConfig,"label-width":"120px"}},[r("el-form-item",{attrs:{label:"MQTT默认地址"}},[r("el-input",{attrs:{disabled:!e.isUpdate},model:{value:e.serverConfig.defaultMqttAddr,callback:function(t){e.$set(e.serverConfig,"defaultMqttAddr",t)},expression:"serverConfig.defaultMqttAddr"}})],1),r("el-form-item",{attrs:{label:"MQTT默认主题"}},[r("el-input",{attrs:{disabled:!e.isUpdate},model:{value:e.serverConfig.defaultMqttTopic,callback:function(t){e.$set(e.serverConfig,"defaultMqttTopic",t)},expression:"serverConfig.defaultMqttTopic"}})],1),r("el-form-item",{attrs:{label:"MQTT交付级别"}},[r("el-input",{attrs:{disabled:!e.isUpdate},model:{value:e.serverConfig.defaultMqttQos,callback:function(t){e.$set(e.serverConfig,"defaultMqttQos",t)},expression:"serverConfig.defaultMqttQos"}})],1)],1)],1)])],1)],1)],1)},s=[],l=r("b775");function i(){return Object(l["a"])({url:"/vehicle/server/config",method:"get"})}function o(e){return Object(l["a"])({url:"/vehicle/server/config",method:"PUT",data:e})}var n={name:"ServerConfig",data:function(){return{isUpdate:!1,serverConfig:{host:null,port:null,loadUrl:null,defaultMqttAddr:null,defaultMqttTopic:null,defaultMqttQos:null}}},created:function(){this.getServerConfig()},methods:{getServerConfig:function(){var e=this;i().then((function(t){e.serverConfig=t.data}))},editServerConfig:function(){var e=this;o(this.serverConfig).then((function(t){e.$notify({title:"操作提示",message:t.msg,type:200===t.code?"success":"error"}),200===t.code&&(e.isUpdate=!1)}))}}},d=n,f=(r("8bce"),r("2877")),c=Object(f["a"])(d,a,s,!1,null,"1fac6224",null);t["default"]=c.exports},"8bce":function(e,t,r){"use strict";r("f557")},f557:function(e,t,r){}}]);
|
|
@ -1 +0,0 @@
|
||||||
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-4a014042"],{7015:function(e,t,a){},8931:function(e,t,a){"use strict";a("7015")},9406:function(e,t,a){"use strict";a.r(t);var i=function(){var e=this,t=e.$createElement,a=e._self._c||t;return a("div",{staticClass:"dashboard-container"},[a("div",{staticClass:"dashboard-text"},[e._v(e._s(e.name))]),a("el-divider"),a("div",{style:{width:e.vehicleStatusWidth+"%",height:e.vehicleStatusHeight+"px",margin:"0 auto"},attrs:{id:"vehicleStatus"}})],1)},n=[],o=a("5530"),r=a("2f62"),s=a("313e"),c=a("b775");function u(){return Object(c["a"])({url:"/vehicle/overview",method:"get"})}var l={name:"Dashboard",data:function(){return{vehicleStatusChart:null,vehicleStatusWidth:50,vehicleStatusHeight:window.innerHeight-300,dataMap:{online:0,offline:2,pause:0}}},computed:Object(o["a"])({},Object(r["b"])(["name"])),watch:{dataMap:function(){this.initVehicleStatus()}},created:function(){setInterval(this.getVehicleOverview,5e3)},mounted:function(){this.vehicleStatusChart=s["a"](document.getElementById("vehicleStatus")),this.initVehicleStatus(),window.addEventListener("resize",this.initVehicleStatus)},methods:{getVehicleOverview:function(){var e=this;u().then((function(t){e.dataMap=t.data}))},initVehicleStatus:function(){this.vehicleStatusChart.setOption({title:{text:"系统模拟车辆状态统计一览",left:"center",textStyle:{fontWeight:1e3,fontSize:26}},tooltip:{trigger:"item"},legend:{top:"5%",left:"center"},series:[{type:"pie",radius:["40%","70%"],avoidLabelOverlap:!1,itemStyle:{borderRadius:10,borderColor:"#fff",borderWidth:10},label:{show:!0},emphasis:{label:{show:!0,fontSize:40,fontWeight:"bold"}},labelLine:{show:!0},data:[{value:this.dataMap.pause,name:"暂停车辆"},{value:this.dataMap.online,name:"在线车辆"},{value:this.dataMap.offline,name:"离线车辆"}]}]})}}},h=l,d=(a("8931"),a("2877")),f=Object(d["a"])(h,i,n,!1,null,"492ff9f3",null);t["default"]=f.exports},b775:function(e,t,a){"use strict";a("d3b7");var i=a("bc3a"),n=a.n(i),o=a("5c96"),r=a("4360"),s=a("5f87"),c=n.a.create({baseURL:"/",timeout:5e3});c.interceptors.request.use((function(e){return r["a"].getters.token&&(e.headers["X-Token"]=Object(s["a"])()),e}),(function(e){return console.log(e),Promise.reject(e)})),c.interceptors.response.use((function(e){var t=e.data;return 200!==t.code?(Object(o["Message"])({message:t.msg||"Error",type:"error",duration:5e3}),50008!==t.code&&50012!==t.code&&50014!==t.code||o["MessageBox"].confirm("You have been logged out, you can cancel to stay on this page, or log in again","Confirm logout",{confirmButtonText:"Re-Login",cancelButtonText:"Cancel",type:"warning"}).then((function(){r["a"].dispatch("user/resetToken").then((function(){location.reload()}))})),Promise.reject(new Error(t.msg||"Error"))):t}),(function(e){return console.log("err"+e),Object(o["Message"])({message:e.message,type:"error",duration:5e3}),Promise.reject(e)})),t["a"]=c}}]);
|
|
|
@ -1 +0,0 @@
|
||||||
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-510f32e7"],{3985:function(e,t,n){},"92f2":function(e,t,n){},"9ed6":function(e,t,n){"use strict";n.r(t);var r=function(){var e=this,t=e.$createElement,n=e._self._c||t;return n("div",{staticClass:"login-container"},[n("el-form",{ref:"loginForm",staticClass:"login-form",attrs:{model:e.loginForm,rules:e.loginRules,"auto-complete":"on","label-position":"left"}},[n("div",{staticClass:"title-container"},[n("h3",{staticClass:"title"},[e._v("车辆模拟")])]),n("el-form-item",{attrs:{prop:"username"}},[n("span",{staticClass:"svg-container"},[n("svg-icon",{attrs:{"icon-class":"user"}})],1),n("el-input",{ref:"username",attrs:{placeholder:"Username",name:"username",type:"text",tabindex:"1","auto-complete":"on",readonly:""},model:{value:e.loginForm.username,callback:function(t){e.$set(e.loginForm,"username",t)},expression:"loginForm.username"}})],1),n("el-form-item",{attrs:{prop:"password"}},[n("span",{staticClass:"svg-container"},[n("svg-icon",{attrs:{"icon-class":"password"}})],1),n("el-input",{ref:"password",attrs:{type:"text",placeholder:"Password",name:"password",tabindex:"2","auto-complete":"on"},nativeOn:{keyup:function(t){return!t.type.indexOf("key")&&e._k(t.keyCode,"enter",13,t.key,"Enter")?null:e.handleLogin(t)}},model:{value:e.loginForm.password,callback:function(t){e.$set(e.loginForm,"password",t)},expression:"loginForm.password"}})],1),n("el-button",{staticStyle:{width:"100%","margin-bottom":"30px"},attrs:{loading:e.loading,type:"primary"},nativeOn:{click:function(t){return t.preventDefault(),e.handleLogin(t)}}},[e._v("进入")])],1)],1)},o=[],s={name:"Login",data:function(){return{loginForm:{username:"你永远是最棒的",password:"加油,一切都是值得的"},loginRules:{username:[{required:!0,trigger:"blur"}],password:[{required:!0,trigger:"blur"}]},loading:!1,passwordType:"password",redirect:void 0}},watch:{$route:{handler:function(e){this.redirect=e.query&&e.query.redirect},immediate:!0}},methods:{handleLogin:function(){var e=this;this.$refs.loginForm.validate((function(t){if(!t)return console.log("error submit!!"),!1;e.loading=!0,e.$store.dispatch("user/login",e.loginForm).then((function(){e.$router.push({path:e.redirect||"/"}),e.loading=!1})).catch((function(){e.loading=!1})),e.$router.push({path:e.redirect||"/"})}))}}},a=s,i=(n("d1bd"),n("f8c5"),n("2877")),l=Object(i["a"])(a,r,o,!1,null,"5d9ae9a2",null);t["default"]=l.exports},d1bd:function(e,t,n){"use strict";n("92f2")},f8c5:function(e,t,n){"use strict";n("3985")}}]);
|
|
|
@ -0,0 +1 @@
|
||||||
|
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-5e598597"],{4927:function(e,t,r){"use strict";r("7ef9")},5709:function(e,t,r){},"7ef9":function(e,t,r){},"9ed6":function(e,t,r){"use strict";r.r(t);var o=function(){var e=this,t=e.$createElement,r=e._self._c||t;return r("div",{staticClass:"login-container"},[r("el-form",{ref:"loginForm",staticClass:"login-form",attrs:{model:e.loginForm,rules:e.loginRules,"auto-complete":"on","label-position":"left"}},[r("div",{staticClass:"title-container"},[r("h3",{staticClass:"title"},[e._v("车辆模拟")])]),r("el-form-item",{attrs:{prop:"userName"}},[r("span",{staticClass:"svg-container"},[r("svg-icon",{attrs:{"icon-class":"user"}})],1),r("el-input",{ref:"userName",attrs:{placeholder:"userName",name:"userName",type:"text",tabindex:"1","auto-complete":"on"},model:{value:e.loginForm.userName,callback:function(t){e.$set(e.loginForm,"userName",t)},expression:"loginForm.userName"}})],1),r("el-form-item",{attrs:{prop:"password"}},[r("span",{staticClass:"svg-container"},[r("svg-icon",{attrs:{"icon-class":"password"}})],1),r("el-input",{ref:"password",attrs:{type:"password",placeholder:"Password",name:"password",tabindex:"2","auto-complete":"on"},nativeOn:{keyup:function(t){return!t.type.indexOf("key")&&e._k(t.keyCode,"enter",13,t.key,"Enter")?null:e.handleLogin(t)}},model:{value:e.loginForm.password,callback:function(t){e.$set(e.loginForm,"password",t)},expression:"loginForm.password"}})],1),r("el-button",{staticStyle:{width:"100%","margin-bottom":"30px"},attrs:{loading:e.loading,type:"primary"},nativeOn:{click:function(t){return t.preventDefault(),e.handleLogin(t)}}},[e._v("进入")])],1)],1)},n=[],s={name:"Login",data:function(){return{loginForm:{userName:"",password:""},loginRules:{userName:[{required:!0,trigger:"blur"}],password:[{required:!0,trigger:"blur"}]},loading:!1,passwordType:"password",redirect:void 0}},watch:{$route:{handler:function(e){this.redirect=e.query&&e.query.redirect},immediate:!0}},methods:{handleLogin:function(){var e=this;this.$refs.loginForm.validate((function(t){if(!t)return console.log("error submit!!"),!1;e.loading=!0,e.$store.dispatch("user/login",e.loginForm).then((function(){e.$router.push({path:e.redirect||"/"}),e.loading=!1})).catch((function(){e.loading=!1})),e.$router.push({path:e.redirect||"/"})}))}}},i=s,a=(r("4927"),r("ce52"),r("2877")),l=Object(a["a"])(i,o,n,!1,null,"30d4a998",null);t["default"]=l.exports},ce52:function(e,t,r){"use strict";r("5709")}}]);
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue