Commit 34583954 by zwb

招聘会演示平台搭建与简历导入

parent 12ed3dbd
Showing with 6650 additions and 0 deletions
package com.bkty.service;
import com.bkty.domain.vo.LoginVo;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.utils.SpringUtils;
/**
* 授权策略
*
* @author Michelle.Chung
*/
public interface IAuthStrategy {
String BASE_NAME = "AuthStrategy";
/**
* 登录
*
* @param body 登录对象
* @param grantType 授权类型
* @return 登录验证信息
*/
static LoginVo login(String body, String grantType) {
// 授权类型和客户端id
String beanName = grantType + BASE_NAME;
if (!SpringUtils.containsBean(beanName)) {
throw new ServiceException("授权类型不正确!");
}
IAuthStrategy instance = SpringUtils.getBean(beanName);
return instance.login(body);
}
/**
* 登录
*
* @param body 登录对象
* @return 登录验证信息
*/
LoginVo login(String body);
}
package org.dromara.common.core.config;
import org.dromara.common.core.aspectj.RepeatSubmitAspect;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.data.redis.core.RedisTemplate;
@AutoConfiguration(after = RedisTemplate.class)
public class IdempotentAutoConfiguration {
@Bean
public RepeatSubmitAspect repeatSubmitAspect() {
return new RepeatSubmitAspect();
}
}
\ No newline at end of file
package org.dromara.common.core.constant;
/**
* 全局的key常量 (业务无关的key)
*
* @author Lion Li
*/
public interface GlobalConstants {
/**
* 全局 redis key (业务无关的key)
*/
String GLOBAL_REDIS_KEY = "global:";
/**
* 验证码 redis key
*/
String CAPTCHA_CODE_KEY = GLOBAL_REDIS_KEY + "captcha_codes:";
/**
* 防重提交 redis key
*/
String REPEAT_SUBMIT_KEY = GLOBAL_REDIS_KEY + "repeat_submit:";
/**
* 限流 redis key
*/
String RATE_LIMIT_KEY = GLOBAL_REDIS_KEY + "rate_limit:";
/**
* 三方认证 redis key
*/
String SOCIAL_AUTH_CODE_KEY = GLOBAL_REDIS_KEY + "social_auth_codes:";
}
package org.dromara.common.core.constant;
/**
* 返回状态码
*
* @author Lion Li
*/
public interface HttpStatus {
/**
* 操作成功
*/
int SUCCESS = 200;
/**
* 对象创建成功
*/
int CREATED = 201;
/**
* 请求已经被接受
*/
int ACCEPTED = 202;
/**
* 操作已经执行成功,但是没有返回数据
*/
int NO_CONTENT = 204;
/**
* 资源已被移除
*/
int MOVED_PERM = 301;
/**
* 重定向
*/
int SEE_OTHER = 303;
/**
* 资源没有被修改
*/
int NOT_MODIFIED = 304;
/**
* 参数列表错误(缺少,格式不匹配)
*/
int BAD_REQUEST = 400;
/**
* 未授权
*/
int UNAUTHORIZED = 401;
/**
* 访问受限,授权过期
*/
int FORBIDDEN = 403;
/**
* 资源,服务未找到
*/
int NOT_FOUND = 404;
/**
* 不允许的http方法
*/
int BAD_METHOD = 405;
/**
* 资源冲突,或者资源被锁
*/
int CONFLICT = 409;
/**
* 不支持的数据,媒体类型
*/
int UNSUPPORTED_TYPE = 415;
/**
* 系统内部错误
*/
int ERROR = 500;
/**
* 接口未实现
*/
int NOT_IMPLEMENTED = 501;
/**
* 系统警告消息
*/
int WARN = 601;
}
package org.dromara.common.core.enums;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.List;
/**
* 文件类型枚举类
*图片、音频类不超过5MB,其他支持的文件格式不超过10MB
* @author Herbert
* @history 2024/6/12 新建
* @since 17
*/
public enum FileTypeEnum {
DOC("application/msword", "doc", 50*1024*1024L, "50MB"),
DOCX("application/vnd.openxmlformats-officedocument.wordprocessingml.document", "docx", 50*1024*1024L, "50MB"),
XLS("application/vnd.ms-excel", "xls", 50*1024*1024L, "50MB"),
XLSX("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", "xlsx", 50*1024*1024L, "50MB"),
PDF("application/pdf","pdf", 50*1024*1024L, "50MB"),
JPG("image/jpeg","jpg", 50*1024*1024L, "5MB"),
BMP("image/bmp","bmp", 50*1024*1024L, "5MB"),
JPEG("image/jpeg","jpeg", 50*1024*1024L, "5MB"),
GIF("image/gif","gif", 50*1024*1024L, "5MB"),
PNG("image/png","png", 50*1024*1024L, "5MB"),
SVG("image/svg+xml","svg", 50*1024*1024L, "5MB"),
ICO("image/x-icon","ico", 50*1024*1024L, "5MB"),
;
private String contentType;
private String suffix;
private long maxSize;
private String sizeDescription;
FileTypeEnum(String contentType, String suffix, long maxSize, String sizeDescription) {
this.contentType = contentType;
this.suffix = suffix;
this.maxSize = maxSize;
this.sizeDescription = sizeDescription;
}
/**
*
* 根据文件后缀查找对应的文件类型枚举类,未找到则返回空
* @param suffix
* @return
* @author Herbert
* @history 2019/5/22 新建
*/
public static FileTypeEnum getEnumBySuffix(String suffix){
for (FileTypeEnum typeEnum : EnumSet.allOf(FileTypeEnum.class)) {
if(typeEnum.getSuffix().equalsIgnoreCase(suffix)){
return typeEnum;
}
}
return null;
}
/**
* 将枚举值转换成列表,方便下拉框使用
* @return
*/
public static List<String> getCollectType(){
List<String> lstResult = new ArrayList<>(10);
for (FileTypeEnum typeEnum : EnumSet.allOf(FileTypeEnum.class)) {
if(!typeEnum.getSuffix().equals("key") && !typeEnum.getSuffix().equals("cry")){
lstResult.add(typeEnum.getSuffix());
}
}
return lstResult;
}
public String getContentType() {
return contentType;
}
public void setContentType(String contentType) {
this.contentType = contentType;
}
public String getSuffix() {
return suffix;
}
public void setSuffix(String suffix) {
this.suffix = suffix;
}
public long getMaxSize() {
return maxSize;
}
public void setMaxSize(long maxSize) {
this.maxSize = maxSize;
}
public String getSizeDescription() {
return sizeDescription;
}
public void setSizeDescription(String sizeDescription) {
this.sizeDescription = sizeDescription;
}
}
package org.dromara.common.core.exception.file;
import org.dromara.common.core.exception.base.BaseException;
import java.io.Serial;
/**
* 文件信息异常类
*
* @author ruoyi
*/
public class FileException extends BaseException {
@Serial
private static final long serialVersionUID = 1L;
public FileException(String code, Object[] args) {
super("file", code, args, null);
}
}
package org.dromara.common.core.exception.file;
import java.io.Serial;
/**
* 文件名称超长限制异常类
*
* @author ruoyi
*/
public class FileNameLengthLimitExceededException extends FileException {
@Serial
private static final long serialVersionUID = 1L;
public FileNameLengthLimitExceededException(int defaultFileNameLength) {
super("upload.filename.exceed.length", new Object[]{defaultFileNameLength});
}
}
package org.dromara.common.core.exception.file;
import java.io.Serial;
/**
* 文件名大小限制异常类
*
* @author ruoyi
*/
public class FileSizeLimitExceededException extends FileException {
@Serial
private static final long serialVersionUID = 1L;
public FileSizeLimitExceededException(long defaultMaxSize) {
super("upload.exceed.maxSize", new Object[]{defaultMaxSize});
}
}
package org.dromara.common.core.utils;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.TableField;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.io.Serializable;
import java.time.LocalDateTime;
/**
* @Desc: 公共属性基类
* @author: jiangxiaoge
* @date: 2023/11/16 15:02
* @since: 1.8
*/
@Data
public class Entity implements Serializable {
public static final long serialVersionUID = 1L;
/**
* 创建人
*/
@TableField(fill = FieldFill.INSERT)
@Schema(description = "创建人")
private String createBy;
/**
* 修改人
*/
@TableField(fill = FieldFill.INSERT_UPDATE)
@Schema(description = "修改人")
private String updateBy;
/**
* 创建时间
*/
@Schema(description = "创建时间")
@TableField(fill = FieldFill.INSERT)
private LocalDateTime createTime;
/**
* 修改时间
*/
@Schema(description = "修改时间")
@TableField(fill = FieldFill.INSERT_UPDATE)
private LocalDateTime updateTime;
}
package org.dromara.common.core.utils.file;
import cn.hutool.core.io.FileUtil;
import jakarta.servlet.http.HttpServletResponse;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
/**
* 文件处理工具类
*
* @author Lion Li
*/
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class FileUtils extends FileUtil {
/**
* 下载文件名重新编码
*
* @param response 响应对象
* @param realFileName 真实文件名
*/
public static void setAttachmentResponseHeader(HttpServletResponse response, String realFileName) {
String percentEncodedFileName = percentEncode(realFileName);
String contentDispositionValue = "attachment; filename=%s;filename*=utf-8''%s".formatted(percentEncodedFileName, percentEncodedFileName);
response.addHeader("Access-Control-Expose-Headers", "Content-Disposition,download-filename");
response.setHeader("Content-disposition", contentDispositionValue);
response.setHeader("download-filename", percentEncodedFileName);
}
/**
* 百分号编码工具方法
*
* @param s 需要百分号编码的字符串
* @return 百分号编码后的字符串
*/
public static String percentEncode(String s) {
String encode = URLEncoder.encode(s, StandardCharsets.UTF_8);
return encode.replaceAll("\\+", "%20");
}
}
package org.dromara.common.encrypt.annotation;
import org.dromara.common.encrypt.enumd.AlgorithmType;
import org.dromara.common.encrypt.enumd.EncodeType;
import java.lang.annotation.*;
/**
* 字段加密注解
*
* @author 老马
*/
@Documented
@Inherited
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface EncryptField {
/**
* 加密算法
*/
AlgorithmType algorithm() default AlgorithmType.DEFAULT;
/**
* 秘钥。AES、SM4需要
*/
String password() default "";
/**
* 公钥。RSA、SM2需要
*/
String publicKey() default "";
/**
* 私钥。RSA、SM2需要
*/
String privateKey() default "";
/**
* 编码方式。对加密算法为BASE64的不起作用
*/
EncodeType encode() default EncodeType.DEFAULT;
}
package org.dromara.common.encrypt.config;
import com.baomidou.mybatisplus.autoconfigure.MybatisPlusAutoConfiguration;
import com.baomidou.mybatisplus.autoconfigure.MybatisPlusProperties;
import org.dromara.common.encrypt.core.EncryptorManager;
import org.dromara.common.encrypt.interceptor.MybatisDecryptInterceptor;
import org.dromara.common.encrypt.interceptor.MybatisEncryptInterceptor;
import org.dromara.common.encrypt.properties.EncryptorProperties;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
/**
* 加解密配置
*
* @author 老马
* @version 4.6.0
*/
@AutoConfiguration(after = MybatisPlusAutoConfiguration.class)
@EnableConfigurationProperties({EncryptorProperties.class, MybatisPlusProperties.class})
@ConditionalOnClass(MybatisPlusAutoConfiguration.class)
@ConditionalOnProperty(value = "mybatis-encryptor.enable", havingValue = "true")
public class EncryptorAutoConfiguration {
@Autowired
private EncryptorProperties properties;
@Bean
public EncryptorManager encryptorManager(MybatisPlusProperties mybatisPlusProperties) {
return new EncryptorManager(mybatisPlusProperties.getTypeAliasesPackage());
}
@Bean
public MybatisEncryptInterceptor mybatisEncryptInterceptor(EncryptorManager encryptorManager) {
return new MybatisEncryptInterceptor(encryptorManager, properties);
}
@Bean
public MybatisDecryptInterceptor mybatisDecryptInterceptor(EncryptorManager encryptorManager) {
return new MybatisDecryptInterceptor(encryptorManager, properties);
}
}
package org.dromara.common.encrypt.core;
import org.dromara.common.encrypt.enumd.AlgorithmType;
import org.dromara.common.encrypt.enumd.EncodeType;
import lombok.Data;
/**
* 加密上下文 用于encryptor传递必要的参数。
*
* @author 老马
* @version 4.6.0
*/
@Data
public class EncryptContext {
/**
* 默认算法
*/
private AlgorithmType algorithm;
/**
* 安全秘钥
*/
private String password;
/**
* 公钥
*/
private String publicKey;
/**
* 私钥
*/
private String privateKey;
/**
* 编码方式,base64/hex
*/
private EncodeType encode;
}
package org.dromara.common.encrypt.core;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.ReflectUtil;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.io.Resources;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.encrypt.annotation.EncryptField;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.core.type.ClassMetadata;
import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
import org.springframework.util.ClassUtils;
import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;
/**
* 加密管理类
*
* @author 老马
* @version 4.6.0
*/
@Slf4j
@NoArgsConstructor
public class EncryptorManager {
/**
* 缓存加密器
*/
Map<Integer, IEncryptor> encryptorMap = new ConcurrentHashMap<>();
/**
* 类加密字段缓存
*/
Map<Class<?>, Set<Field>> fieldCache = new ConcurrentHashMap<>();
/**
* 构造方法传入类加密字段缓存
*
* @param typeAliasesPackage 实体类包
*/
public EncryptorManager(String typeAliasesPackage) {
scanEncryptClasses(typeAliasesPackage);
}
/**
* 获取类加密字段缓存
*/
public Set<Field> getFieldCache(Class<?> sourceClazz) {
if (ObjectUtil.isNotNull(fieldCache)) {
return fieldCache.get(sourceClazz);
}
return null;
}
/**
* 注册加密执行者到缓存
*
* @param encryptContext 加密执行者需要的相关配置参数
*/
public IEncryptor registAndGetEncryptor(EncryptContext encryptContext) {
int key = encryptContext.hashCode();
if (encryptorMap.containsKey(key)) {
return encryptorMap.get(key);
}
IEncryptor encryptor = ReflectUtil.newInstance(encryptContext.getAlgorithm().getClazz(), encryptContext);
encryptorMap.put(key, encryptor);
return encryptor;
}
/**
* 移除缓存中的加密执行者
*
* @param encryptContext 加密执行者需要的相关配置参数
*/
public void removeEncryptor(EncryptContext encryptContext) {
this.encryptorMap.remove(encryptContext.hashCode());
}
/**
* 根据配置进行加密。会进行本地缓存对应的算法和对应的秘钥信息。
*
* @param value 待加密的值
* @param encryptContext 加密相关的配置信息
*/
public String encrypt(String value, EncryptContext encryptContext) {
IEncryptor encryptor = this.registAndGetEncryptor(encryptContext);
return encryptor.encrypt(value, encryptContext.getEncode());
}
/**
* 根据配置进行解密
*
* @param value 待解密的值
* @param encryptContext 加密相关的配置信息
*/
public String decrypt(String value, EncryptContext encryptContext) {
IEncryptor encryptor = this.registAndGetEncryptor(encryptContext);
return encryptor.decrypt(value);
}
/**
* 通过 typeAliasesPackage 设置的扫描包 扫描缓存实体
*/
private void scanEncryptClasses(String typeAliasesPackage) {
PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
CachingMetadataReaderFactory factory = new CachingMetadataReaderFactory();
String[] packagePatternArray = StringUtils.splitPreserveAllTokens(typeAliasesPackage, ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);
String classpath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX;
try {
for (String packagePattern : packagePatternArray) {
String path = ClassUtils.convertClassNameToResourcePath(packagePattern);
Resource[] resources = resolver.getResources(classpath + path + "/*.class");
for (Resource resource : resources) {
ClassMetadata classMetadata = factory.getMetadataReader(resource).getClassMetadata();
Class<?> clazz = Resources.classForName(classMetadata.getClassName());
Set<Field> encryptFieldSet = getEncryptFieldSetFromClazz(clazz);
if (CollUtil.isNotEmpty(encryptFieldSet)) {
fieldCache.put(clazz, encryptFieldSet);
}
}
}
} catch (Exception e) {
log.error("初始化数据安全缓存时出错:{}", e.getMessage());
}
}
/**
* 获得一个类的加密字段集合
*/
private Set<Field> getEncryptFieldSetFromClazz(Class<?> clazz) {
Set<Field> fieldSet = new HashSet<>();
// 判断clazz如果是接口,内部类,匿名类就直接返回
if (clazz.isInterface() || clazz.isMemberClass() || clazz.isAnonymousClass()) {
return fieldSet;
}
while (clazz != null) {
Field[] fields = clazz.getDeclaredFields();
fieldSet.addAll(Arrays.asList(fields));
clazz = clazz.getSuperclass();
}
fieldSet = fieldSet.stream().filter(field ->
field.isAnnotationPresent(EncryptField.class) && field.getType() == String.class)
.collect(Collectors.toSet());
for (Field field : fieldSet) {
field.setAccessible(true);
}
return fieldSet;
}
}
package org.dromara.common.encrypt.filter;
import cn.hutool.core.util.RandomUtil;
import jakarta.servlet.ServletOutputStream;
import jakarta.servlet.WriteListener;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpServletResponseWrapper;
import org.dromara.common.encrypt.utils.EncryptUtils;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.nio.charset.StandardCharsets;
/**
* 加密响应参数包装类
*
* @author Michelle.Chung
*/
public class EncryptResponseBodyWrapper extends HttpServletResponseWrapper {
private final ByteArrayOutputStream byteArrayOutputStream;
private final ServletOutputStream servletOutputStream;
private final PrintWriter printWriter;
public EncryptResponseBodyWrapper(HttpServletResponse response) throws IOException {
super(response);
this.byteArrayOutputStream = new ByteArrayOutputStream();
this.servletOutputStream = this.getOutputStream();
this.printWriter = new PrintWriter(new OutputStreamWriter(byteArrayOutputStream));
}
@Override
public PrintWriter getWriter() {
return printWriter;
}
@Override
public void flushBuffer() throws IOException {
if (servletOutputStream != null) {
servletOutputStream.flush();
}
if (printWriter != null) {
printWriter.flush();
}
}
@Override
public void reset() {
byteArrayOutputStream.reset();
}
public byte[] getResponseData() throws IOException {
flushBuffer();
return byteArrayOutputStream.toByteArray();
}
public String getContent() throws IOException {
flushBuffer();
return byteArrayOutputStream.toString();
}
/**
* 获取加密内容
*
* @param servletResponse response
* @param publicKey RSA公钥 (用于加密 AES 秘钥)
* @param headerFlag 请求头标志
* @return 加密内容
* @throws IOException
*/
public String getEncryptContent(HttpServletResponse servletResponse, String publicKey, String headerFlag) throws IOException {
// 生成秘钥
String aesPassword = RandomUtil.randomString(32);
// 秘钥使用 Base64 编码
String encryptAes = EncryptUtils.encryptByBase64(aesPassword);
// Rsa 公钥加密 Base64 编码
String encryptPassword = EncryptUtils.encryptByRsa(encryptAes, publicKey);
// 设置响应头
servletResponse.addHeader("Access-Control-Expose-Headers", headerFlag);
servletResponse.setHeader(headerFlag, encryptPassword);
servletResponse.setHeader("Access-Control-Allow-Origin", "*");
servletResponse.setHeader("Access-Control-Allow-Methods", "*");
servletResponse.setCharacterEncoding(StandardCharsets.UTF_8.toString());
// 获取原始内容
String originalBody = this.getContent();
// 对内容进行加密
return EncryptUtils.encryptByAes(originalBody, aesPassword);
}
@Override
public ServletOutputStream getOutputStream() throws IOException {
return new ServletOutputStream() {
@Override
public boolean isReady() {
return false;
}
@Override
public void setWriteListener(WriteListener writeListener) {
}
@Override
public void write(int b) throws IOException {
byteArrayOutputStream.write(b);
}
@Override
public void write(byte[] b) throws IOException {
byteArrayOutputStream.write(b);
}
@Override
public void write(byte[] b, int off, int len) throws IOException {
byteArrayOutputStream.write(b, off, len);
}
};
}
}
package org.dromara.common.encrypt.properties;
import org.dromara.common.encrypt.enumd.AlgorithmType;
import org.dromara.common.encrypt.enumd.EncodeType;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
/**
* 加解密属性配置类
*
* @author 老马
* @version 4.6.0
*/
@Data
@ConfigurationProperties(prefix = "mybatis-encryptor")
public class EncryptorProperties {
/**
* 过滤开关
*/
private Boolean enable;
/**
* 默认算法
*/
private AlgorithmType algorithm;
/**
* 安全秘钥
*/
private String password;
/**
* 公钥
*/
private String publicKey;
/**
* 私钥
*/
private String privateKey;
/**
* 编码方式,base64/hex
*/
private EncodeType encode;
}
package org.dromara.common.encrypt.utils;
import cn.hutool.core.codec.Base64;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.SmUtil;
import cn.hutool.crypto.asymmetric.KeyType;
import cn.hutool.crypto.asymmetric.RSA;
import cn.hutool.crypto.asymmetric.SM2;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
/**
* 安全相关工具类
*
* @author 老马
*/
public class EncryptUtils {
/**
* 公钥
*/
public static final String PUBLIC_KEY = "publicKey";
/**
* 私钥
*/
public static final String PRIVATE_KEY = "privateKey";
/**
* Base64加密
*
* @param data 待加密数据
* @return 加密后字符串
*/
public static String encryptByBase64(String data) {
return Base64.encode(data, StandardCharsets.UTF_8);
}
/**
* Base64解密
*
* @param data 待解密数据
* @return 解密后字符串
*/
public static String decryptByBase64(String data) {
return Base64.decodeStr(data, StandardCharsets.UTF_8);
}
/**
* AES加密
*
* @param data 待解密数据
* @param password 秘钥字符串
* @return 加密后字符串, 采用Base64编码
*/
public static String encryptByAes(String data, String password) {
if (StrUtil.isBlank(password)) {
throw new IllegalArgumentException("AES需要传入秘钥信息");
}
// aes算法的秘钥要求是16位、24位、32位
int[] array = {16, 24, 32};
if (!ArrayUtil.contains(array, password.length())) {
throw new IllegalArgumentException("AES秘钥长度要求为16位、24位、32位");
}
return SecureUtil.aes(password.getBytes(StandardCharsets.UTF_8)).encryptBase64(data, StandardCharsets.UTF_8);
}
/**
* AES加密
*
* @param data 待解密数据
* @param password 秘钥字符串
* @return 加密后字符串, 采用Hex编码
*/
public static String encryptByAesHex(String data, String password) {
if (StrUtil.isBlank(password)) {
throw new IllegalArgumentException("AES需要传入秘钥信息");
}
// aes算法的秘钥要求是16位、24位、32位
int[] array = {16, 24, 32};
if (!ArrayUtil.contains(array, password.length())) {
throw new IllegalArgumentException("AES秘钥长度要求为16位、24位、32位");
}
return SecureUtil.aes(password.getBytes(StandardCharsets.UTF_8)).encryptHex(data, StandardCharsets.UTF_8);
}
/**
* AES解密
*
* @param data 待解密数据
* @param password 秘钥字符串
* @return 解密后字符串
*/
public static String decryptByAes(String data, String password) {
if (StrUtil.isBlank(password)) {
throw new IllegalArgumentException("AES需要传入秘钥信息");
}
// aes算法的秘钥要求是16位、24位、32位
int[] array = {16, 24, 32};
if (!ArrayUtil.contains(array, password.length())) {
throw new IllegalArgumentException("AES秘钥长度要求为16位、24位、32位");
}
return SecureUtil.aes(password.getBytes(StandardCharsets.UTF_8)).decryptStr(data, StandardCharsets.UTF_8);
}
/**
* sm4加密
*
* @param data 待加密数据
* @param password 秘钥字符串
* @return 加密后字符串, 采用Base64编码
*/
public static String encryptBySm4(String data, String password) {
if (StrUtil.isBlank(password)) {
throw new IllegalArgumentException("SM4需要传入秘钥信息");
}
// sm4算法的秘钥要求是16位长度
int sm4PasswordLength = 16;
if (sm4PasswordLength != password.length()) {
throw new IllegalArgumentException("SM4秘钥长度要求为16位");
}
return SmUtil.sm4(password.getBytes(StandardCharsets.UTF_8)).encryptBase64(data, StandardCharsets.UTF_8);
}
/**
* sm4加密
*
* @param data 待加密数据
* @param password 秘钥字符串
* @return 加密后字符串, 采用Base64编码
*/
public static String encryptBySm4Hex(String data, String password) {
if (StrUtil.isBlank(password)) {
throw new IllegalArgumentException("SM4需要传入秘钥信息");
}
// sm4算法的秘钥要求是16位长度
int sm4PasswordLength = 16;
if (sm4PasswordLength != password.length()) {
throw new IllegalArgumentException("SM4秘钥长度要求为16位");
}
return SmUtil.sm4(password.getBytes(StandardCharsets.UTF_8)).encryptHex(data, StandardCharsets.UTF_8);
}
/**
* sm4解密
*
* @param data 待解密数据
* @param password 秘钥字符串
* @return 解密后字符串
*/
public static String decryptBySm4(String data, String password) {
if (StrUtil.isBlank(password)) {
throw new IllegalArgumentException("SM4需要传入秘钥信息");
}
// sm4算法的秘钥要求是16位长度
int sm4PasswordLength = 16;
if (sm4PasswordLength != password.length()) {
throw new IllegalArgumentException("SM4秘钥长度要求为16位");
}
return SmUtil.sm4(password.getBytes(StandardCharsets.UTF_8)).decryptStr(data, StandardCharsets.UTF_8);
}
/**
* 产生sm2加解密需要的公钥和私钥
*
* @return 公私钥Map
*/
public static Map<String, String> generateSm2Key() {
Map<String, String> keyMap = new HashMap<>(2);
SM2 sm2 = SmUtil.sm2();
keyMap.put(PRIVATE_KEY, sm2.getPrivateKeyBase64());
keyMap.put(PUBLIC_KEY, sm2.getPublicKeyBase64());
return keyMap;
}
/**
* sm2公钥加密
*
* @param data 待加密数据
* @param publicKey 公钥
* @return 加密后字符串, 采用Base64编码
*/
public static String encryptBySm2(String data, String publicKey) {
if (StrUtil.isBlank(publicKey)) {
throw new IllegalArgumentException("SM2需要传入公钥进行加密");
}
SM2 sm2 = SmUtil.sm2(null, publicKey);
return sm2.encryptBase64(data, StandardCharsets.UTF_8, KeyType.PublicKey);
}
/**
* sm2公钥加密
*
* @param data 待加密数据
* @param publicKey 公钥
* @return 加密后字符串, 采用Hex编码
*/
public static String encryptBySm2Hex(String data, String publicKey) {
if (StrUtil.isBlank(publicKey)) {
throw new IllegalArgumentException("SM2需要传入公钥进行加密");
}
SM2 sm2 = SmUtil.sm2(null, publicKey);
return sm2.encryptHex(data, StandardCharsets.UTF_8, KeyType.PublicKey);
}
/**
* sm2私钥解密
*
* @param data 待加密数据
* @param privateKey 私钥
* @return 解密后字符串
*/
public static String decryptBySm2(String data, String privateKey) {
if (StrUtil.isBlank(privateKey)) {
throw new IllegalArgumentException("SM2需要传入私钥进行解密");
}
SM2 sm2 = SmUtil.sm2(privateKey, null);
return sm2.decryptStr(data, KeyType.PrivateKey, StandardCharsets.UTF_8);
}
/**
* 产生RSA加解密需要的公钥和私钥
*
* @return 公私钥Map
*/
public static Map<String, String> generateRsaKey() {
Map<String, String> keyMap = new HashMap<>(2);
RSA rsa = SecureUtil.rsa();
keyMap.put(PRIVATE_KEY, rsa.getPrivateKeyBase64());
keyMap.put(PUBLIC_KEY, rsa.getPublicKeyBase64());
return keyMap;
}
/**
* rsa公钥加密
*
* @param data 待加密数据
* @param publicKey 公钥
* @return 加密后字符串, 采用Base64编码
*/
public static String encryptByRsa(String data, String publicKey) {
if (StrUtil.isBlank(publicKey)) {
throw new IllegalArgumentException("RSA需要传入公钥进行加密");
}
RSA rsa = SecureUtil.rsa(null, publicKey);
return rsa.encryptBase64(data, StandardCharsets.UTF_8, KeyType.PublicKey);
}
/**
* rsa公钥加密
*
* @param data 待加密数据
* @param publicKey 公钥
* @return 加密后字符串, 采用Hex编码
*/
public static String encryptByRsaHex(String data, String publicKey) {
if (StrUtil.isBlank(publicKey)) {
throw new IllegalArgumentException("RSA需要传入公钥进行加密");
}
RSA rsa = SecureUtil.rsa(null, publicKey);
return rsa.encryptHex(data, StandardCharsets.UTF_8, KeyType.PublicKey);
}
/**
* rsa私钥解密
*
* @param data 待加密数据
* @param privateKey 私钥
* @return 解密后字符串
*/
public static String decryptByRsa(String data, String privateKey) {
if (StrUtil.isBlank(privateKey)) {
throw new IllegalArgumentException("RSA需要传入私钥进行解密");
}
RSA rsa = SecureUtil.rsa(privateKey, null);
return rsa.decryptStr(data, KeyType.PrivateKey, StandardCharsets.UTF_8);
}
/**
* md5加密
*
* @param data 待加密数据
* @return 加密后字符串, 采用Hex编码
*/
public static String encryptByMd5(String data) {
return SecureUtil.md5(data);
}
/**
* sha256加密
*
* @param data 待加密数据
* @return 加密后字符串, 采用Hex编码
*/
public static String encryptBySha256(String data) {
return SecureUtil.sha256(data);
}
/**
* sm3加密
*
* @param data 待加密数据
* @return 加密后字符串, 采用Hex编码
*/
public static String encryptBySm3(String data) {
return SmUtil.sm3(data);
}
}
package org.dromara.common.excel.annotation;
import org.dromara.common.core.utils.StringUtils;
import java.lang.annotation.*;
/**
* 字典格式化
*
* @author Lion Li
*/
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface ExcelDictFormat {
/**
* 如果是字典类型,请设置字典的type值 (如: sys_user_sex)
*/
String dictType() default "";
/**
* 读取内容转表达式 (如: 0=男,1=女,2=未知)
*/
String readConverterExp() default "";
/**
* 分隔符,读取字符串组内容
*/
String separator() default StringUtils.SEPARATOR;
}
package org.dromara.common.excel.annotation;
import java.lang.annotation.*;
/**
* 枚举格式化
*
* @author Liang
*/
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface ExcelEnumFormat {
/**
* 字典枚举类型
*/
Class<? extends Enum<?>> enumClass();
/**
* 字典枚举类中对应的code属性名称,默认为code
*/
String codeField() default "code";
/**
* 字典枚举类中对应的text属性名称,默认为text
*/
String textField() default "text";
}
package org.dromara.common.excel.convert;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.excel.converters.Converter;
import com.alibaba.excel.enums.CellDataTypeEnum;
import com.alibaba.excel.metadata.GlobalConfiguration;
import com.alibaba.excel.metadata.data.ReadCellData;
import com.alibaba.excel.metadata.data.WriteCellData;
import com.alibaba.excel.metadata.property.ExcelContentProperty;
import lombok.extern.slf4j.Slf4j;
import java.math.BigDecimal;
/**
* 大数值转换
* Excel 数值长度位15位 大于15位的数值转换位字符串
*
* @author Lion Li
*/
@Slf4j
public class ExcelBigNumberConvert implements Converter<Long> {
@Override
public Class<Long> supportJavaTypeKey() {
return Long.class;
}
@Override
public CellDataTypeEnum supportExcelTypeKey() {
return CellDataTypeEnum.STRING;
}
@Override
public Long convertToJavaData(ReadCellData<?> cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) {
return Convert.toLong(cellData.getData());
}
@Override
public WriteCellData<Object> convertToExcelData(Long object, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) {
if (ObjectUtil.isNotNull(object)) {
String str = Convert.toStr(object);
if (str.length() > 15) {
return new WriteCellData<>(str);
}
}
WriteCellData<Object> cellData = new WriteCellData<>(new BigDecimal(object));
cellData.setType(CellDataTypeEnum.NUMBER);
return cellData;
}
}
package org.dromara.common.excel.convert;
import cn.hutool.core.annotation.AnnotationUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.excel.converters.Converter;
import com.alibaba.excel.enums.CellDataTypeEnum;
import com.alibaba.excel.metadata.GlobalConfiguration;
import com.alibaba.excel.metadata.data.ReadCellData;
import com.alibaba.excel.metadata.data.WriteCellData;
import com.alibaba.excel.metadata.property.ExcelContentProperty;
import org.dromara.common.excel.annotation.ExcelDictFormat;
import org.dromara.common.core.service.DictService;
import org.dromara.common.core.utils.SpringUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.excel.utils.ExcelUtil;
import lombok.extern.slf4j.Slf4j;
import java.lang.reflect.Field;
/**
* 字典格式化转换处理
*
* @author Lion Li
*/
@Slf4j
public class ExcelDictConvert implements Converter<Object> {
@Override
public Class<Object> supportJavaTypeKey() {
return Object.class;
}
@Override
public CellDataTypeEnum supportExcelTypeKey() {
return null;
}
@Override
public Object convertToJavaData(ReadCellData<?> cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) {
ExcelDictFormat anno = getAnnotation(contentProperty.getField());
String type = anno.dictType();
String label = cellData.getStringValue();
String value;
if (StringUtils.isBlank(type)) {
value = ExcelUtil.reverseByExp(label, anno.readConverterExp(), anno.separator());
} else {
value = SpringUtils.getBean(DictService.class).getDictValue(type, label, anno.separator());
}
return Convert.convert(contentProperty.getField().getType(), value);
}
@Override
public WriteCellData<String> convertToExcelData(Object object, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) {
if (ObjectUtil.isNull(object)) {
return new WriteCellData<>("");
}
ExcelDictFormat anno = getAnnotation(contentProperty.getField());
String type = anno.dictType();
String value = Convert.toStr(object);
String label;
if (StringUtils.isBlank(type)) {
label = ExcelUtil.convertByExp(value, anno.readConverterExp(), anno.separator());
} else {
label = SpringUtils.getBean(DictService.class).getDictLabel(type, value, anno.separator());
}
return new WriteCellData<>(label);
}
private ExcelDictFormat getAnnotation(Field field) {
return AnnotationUtil.getAnnotation(field, ExcelDictFormat.class);
}
}
package org.dromara.common.excel.convert;
import cn.hutool.core.annotation.AnnotationUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.excel.converters.Converter;
import com.alibaba.excel.enums.CellDataTypeEnum;
import com.alibaba.excel.metadata.GlobalConfiguration;
import com.alibaba.excel.metadata.data.ReadCellData;
import com.alibaba.excel.metadata.data.WriteCellData;
import com.alibaba.excel.metadata.property.ExcelContentProperty;
import org.dromara.common.core.utils.reflect.ReflectUtils;
import org.dromara.common.excel.annotation.ExcelEnumFormat;
import lombok.extern.slf4j.Slf4j;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
/**
* 枚举格式化转换处理
*
* @author Liang
*/
@Slf4j
public class ExcelEnumConvert implements Converter<Object> {
@Override
public Class<Object> supportJavaTypeKey() {
return Object.class;
}
@Override
public CellDataTypeEnum supportExcelTypeKey() {
return null;
}
@Override
public Object convertToJavaData(ReadCellData<?> cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) {
cellData.checkEmpty();
// Excel中填入的是枚举中指定的描述
Object textValue = switch (cellData.getType()) {
case STRING, DIRECT_STRING, RICH_TEXT_STRING -> cellData.getStringValue();
case NUMBER -> cellData.getNumberValue();
case BOOLEAN -> cellData.getBooleanValue();
default -> throw new IllegalArgumentException("单元格类型异常!");
};
// 如果是空值
if (ObjectUtil.isNull(textValue)) {
return null;
}
Map<Object, String> enumCodeToTextMap = beforeConvert(contentProperty);
// 从Java输出至Excel是code转text
// 因此从Excel转Java应该将text与code对调
Map<Object, Object> enumTextToCodeMap = new HashMap<>();
enumCodeToTextMap.forEach((key, value) -> enumTextToCodeMap.put(value, key));
// 应该从text -> code中查找
Object codeValue = enumTextToCodeMap.get(textValue);
return Convert.convert(contentProperty.getField().getType(), codeValue);
}
@Override
public WriteCellData<String> convertToExcelData(Object object, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) {
if (ObjectUtil.isNull(object)) {
return new WriteCellData<>("");
}
Map<Object, String> enumValueMap = beforeConvert(contentProperty);
String value = Convert.toStr(enumValueMap.get(object), "");
return new WriteCellData<>(value);
}
private Map<Object, String> beforeConvert(ExcelContentProperty contentProperty) {
ExcelEnumFormat anno = getAnnotation(contentProperty.getField());
Map<Object, String> enumValueMap = new HashMap<>();
Enum<?>[] enumConstants = anno.enumClass().getEnumConstants();
for (Enum<?> enumConstant : enumConstants) {
Object codeValue = ReflectUtils.invokeGetter(enumConstant, anno.codeField());
String textValue = ReflectUtils.invokeGetter(enumConstant, anno.textField());
enumValueMap.put(codeValue, textValue);
}
return enumValueMap;
}
private ExcelEnumFormat getAnnotation(Field field) {
return AnnotationUtil.getAnnotation(field, ExcelEnumFormat.class);
}
}
package org.dromara.common.excel.core;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.EnumUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.excel.metadata.FieldCache;
import com.alibaba.excel.metadata.FieldWrapper;
import com.alibaba.excel.util.ClassUtils;
import com.alibaba.excel.write.handler.SheetWriteHandler;
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
import com.alibaba.excel.write.metadata.holder.WriteWorkbookHolder;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddressList;
import org.apache.poi.ss.util.WorkbookUtil;
import org.apache.poi.xssf.usermodel.XSSFDataValidation;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.service.DictService;
import org.dromara.common.core.utils.SpringUtils;
import org.dromara.common.core.utils.StreamUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.excel.annotation.ExcelDictFormat;
import org.dromara.common.excel.annotation.ExcelEnumFormat;
import java.lang.reflect.Field;
import java.util.*;
/**
* <h1>Excel表格下拉选操作</h1>
* 考虑到下拉选过多可能导致Excel打开缓慢的问题,只校验前1000行
* <p>
* 即只有前1000行的数据可以用下拉框,超出的自行通过限制数据量的形式,第二次输出
*
* @author Emil.Zhang
*/
@Slf4j
public class ExcelDownHandler implements SheetWriteHandler {
/**
* Excel表格中的列名英文
* 仅为了解析列英文,禁止修改
*/
private static final String EXCEL_COLUMN_NAME = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
/**
* 单选数据Sheet名
*/
private static final String OPTIONS_SHEET_NAME = "options";
/**
* 联动选择数据Sheet名的头
*/
private static final String LINKED_OPTIONS_SHEET_NAME = "linkedOptions";
/**
* 下拉可选项
*/
private final List<DropDownOptions> dropDownOptions;
/**
* 当前单选进度
*/
private int currentOptionsColumnIndex;
/**
* 当前联动选择进度
*/
private int currentLinkedOptionsSheetIndex;
private final DictService dictService;
public ExcelDownHandler(List<DropDownOptions> options) {
this.dropDownOptions = options;
this.currentOptionsColumnIndex = 0;
this.currentLinkedOptionsSheetIndex = 0;
this.dictService = SpringUtils.getBean(DictService.class);
}
/**
* <h2>开始创建下拉数据</h2>
* 1.通过解析传入的@ExcelProperty同级是否标注有@DropDown选项
* 如果有且设置了value值,则将其直接置为下拉可选项
* <p>
* 2.或者在调用ExcelUtil时指定了可选项,将依据传入的可选项做下拉
* <p>
* 3.二者并存,注意调用方式
*/
@Override
public void afterSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) {
Sheet sheet = writeSheetHolder.getSheet();
// 开始设置下拉框 HSSFWorkbook
DataValidationHelper helper = sheet.getDataValidationHelper();
Workbook workbook = writeWorkbookHolder.getWorkbook();
FieldCache fieldCache = ClassUtils.declaredFields(writeWorkbookHolder.getClazz(), writeWorkbookHolder);
for (Map.Entry<Integer, FieldWrapper> entry : fieldCache.getSortedFieldMap().entrySet()) {
Integer index = entry.getKey();
FieldWrapper wrapper = entry.getValue();
Field field = wrapper.getField();
// 循环实体中的每个属性
// 可选的下拉值
List<String> options = new ArrayList<>();
if (field.isAnnotationPresent(ExcelDictFormat.class)) {
// 如果指定了@ExcelDictFormat,则使用字典的逻辑
ExcelDictFormat format = field.getDeclaredAnnotation(ExcelDictFormat.class);
String dictType = format.dictType();
String converterExp = format.readConverterExp();
if (StringUtils.isNotBlank(dictType)) {
// 如果传递了字典名,则依据字典建立下拉
Collection<String> values = Optional.ofNullable(dictService.getAllDictByDictType(dictType))
.orElseThrow(() -> new ServiceException(String.format("字典 %s 不存在", dictType)))
.values();
options = new ArrayList<>(values);
} else if (StringUtils.isNotBlank(converterExp)) {
// 如果指定了确切的值,则直接解析确切的值
List<String> strList = StringUtils.splitList(converterExp, format.separator());
options = StreamUtils.toList(strList, s -> StringUtils.split(s, "=")[1]);
}
} else if (field.isAnnotationPresent(ExcelEnumFormat.class)) {
// 否则如果指定了@ExcelEnumFormat,则使用枚举的逻辑
ExcelEnumFormat format = field.getDeclaredAnnotation(ExcelEnumFormat.class);
List<Object> values = EnumUtil.getFieldValues(format.enumClass(), format.textField());
options = StreamUtils.toList(values, String::valueOf);
}
if (ObjectUtil.isNotEmpty(options)) {
// 仅当下拉可选项不为空时执行
if (options.size() > 20) {
// 这里限制如果可选项大于20,则使用额外表形式
dropDownWithSheet(helper, workbook, sheet, index, options);
} else {
// 否则使用固定值形式
dropDownWithSimple(helper, sheet, index, options);
}
}
}
if (CollUtil.isEmpty(dropDownOptions)) {
return;
}
dropDownOptions.forEach(everyOptions -> {
// 如果传递了下拉框选择器参数
if (!everyOptions.getNextOptions().isEmpty()) {
// 当二级选项不为空时,使用额外关联表的形式
dropDownLinkedOptions(helper, workbook, sheet, everyOptions);
} else if (everyOptions.getOptions().size() > 10) {
// 当一级选项参数个数大于10,使用额外表的形式
dropDownWithSheet(helper, workbook, sheet, everyOptions.getIndex(), everyOptions.getOptions());
} else if (everyOptions.getOptions().size() != 0) {
// 当一级选项个数不为空,使用默认形式
dropDownWithSimple(helper, sheet, everyOptions.getIndex(), everyOptions.getOptions());
}
});
}
/**
* <h2>简单下拉框</h2>
* 直接将可选项拼接为指定列的数据校验值
*
* @param celIndex 列index
* @param value 下拉选可选值
*/
private void dropDownWithSimple(DataValidationHelper helper, Sheet sheet, Integer celIndex, List<String> value) {
if (ObjectUtil.isEmpty(value)) {
return;
}
this.markOptionsToSheet(helper, sheet, celIndex, helper.createExplicitListConstraint(ArrayUtil.toArray(value, String.class)));
}
/**
* <h2>额外表格形式的级联下拉框</h2>
*
* @param options 额外表格形式存储的下拉可选项
*/
private void dropDownLinkedOptions(DataValidationHelper helper, Workbook workbook, Sheet sheet, DropDownOptions options) {
String linkedOptionsSheetName = String.format("%s_%d", LINKED_OPTIONS_SHEET_NAME, currentLinkedOptionsSheetIndex);
// 创建联动下拉数据表
Sheet linkedOptionsDataSheet = workbook.createSheet(WorkbookUtil.createSafeSheetName(linkedOptionsSheetName));
// 将下拉表隐藏
workbook.setSheetHidden(workbook.getSheetIndex(linkedOptionsDataSheet), true);
// 完善横向的一级选项数据表
List<String> firstOptions = options.getOptions();
Map<String, List<String>> secoundOptionsMap = options.getNextOptions();
// 创建名称管理器
Name name = workbook.createName();
// 设置名称管理器的别名
name.setNameName(linkedOptionsSheetName);
// 以横向第一行创建一级下拉拼接引用位置
String firstOptionsFunction = String.format("%s!$%s$1:$%s$1",
linkedOptionsSheetName,
getExcelColumnName(0),
getExcelColumnName(firstOptions.size())
);
// 设置名称管理器的引用位置
name.setRefersToFormula(firstOptionsFunction);
// 设置数据校验为序列模式,引用的是名称管理器中的别名
this.markOptionsToSheet(helper, sheet, options.getIndex(), helper.createFormulaListConstraint(linkedOptionsSheetName));
for (int columIndex = 0; columIndex < firstOptions.size(); columIndex++) {
// 先提取主表中一级下拉的列名
String firstOptionsColumnName = getExcelColumnName(columIndex);
// 一次循环是每一个一级选项
int finalI = columIndex;
// 本次循环的一级选项值
String thisFirstOptionsValue = firstOptions.get(columIndex);
// 创建第一行的数据
Optional.ofNullable(linkedOptionsDataSheet.getRow(0))
// 如果不存在则创建第一行
.orElseGet(() -> linkedOptionsDataSheet.createRow(finalI))
// 第一行当前列
.createCell(columIndex)
// 设置值为当前一级选项值
.setCellValue(thisFirstOptionsValue);
// 第二行开始,设置第二级别选项参数
List<String> secondOptions = secoundOptionsMap.get(thisFirstOptionsValue);
if (CollUtil.isEmpty(secondOptions)) {
// 必须保证至少有一个关联选项,否则将导致Excel解析错误
secondOptions = Collections.singletonList("暂无_0");
}
// 以该一级选项值创建子名称管理器
Name sonName = workbook.createName();
// 设置名称管理器的别名
sonName.setNameName(thisFirstOptionsValue);
// 以第二行该列数据拼接引用位置
String sonFunction = String.format("%s!$%s$2:$%s$%d",
linkedOptionsSheetName,
firstOptionsColumnName,
firstOptionsColumnName,
secondOptions.size() + 1
);
// 设置名称管理器的引用位置
sonName.setRefersToFormula(sonFunction);
// 数据验证为序列模式,引用到每一个主表中的二级选项位置
// 创建子项的名称管理器,只是为了使得Excel可以识别到数据
String mainSheetFirstOptionsColumnName = getExcelColumnName(options.getIndex());
for (int i = 0; i < 100; i++) {
// 以一级选项对应的主体所在位置创建二级下拉
String secondOptionsFunction = String.format("=INDIRECT(%s%d)", mainSheetFirstOptionsColumnName, i + 1);
// 二级只能主表每一行的每一列添加二级校验
markLinkedOptionsToSheet(helper, sheet, i, options.getNextIndex(), helper.createFormulaListConstraint(secondOptionsFunction));
}
for (int rowIndex = 0; rowIndex < secondOptions.size(); rowIndex++) {
// 从第二行开始填充二级选项
int finalRowIndex = rowIndex + 1;
int finalColumIndex = columIndex;
Row row = Optional.ofNullable(linkedOptionsDataSheet.getRow(finalRowIndex))
// 没有则创建
.orElseGet(() -> linkedOptionsDataSheet.createRow(finalRowIndex));
Optional
// 在本级一级选项所在的列
.ofNullable(row.getCell(finalColumIndex))
// 不存在则创建
.orElseGet(() -> row.createCell(finalColumIndex))
// 设置二级选项值
.setCellValue(secondOptions.get(rowIndex));
}
}
currentLinkedOptionsSheetIndex++;
}
/**
* <h2>额外表格形式的普通下拉框</h2>
* 由于下拉框可选值数量过多,为提升Excel打开效率,使用额外表格形式做下拉
*
* @param celIndex 下拉选
* @param value 下拉选可选值
*/
private void dropDownWithSheet(DataValidationHelper helper, Workbook workbook, Sheet sheet, Integer celIndex, List<String> value) {
// 创建下拉数据表
Sheet simpleDataSheet = Optional.ofNullable(workbook.getSheet(WorkbookUtil.createSafeSheetName(OPTIONS_SHEET_NAME)))
.orElseGet(() -> workbook.createSheet(WorkbookUtil.createSafeSheetName(OPTIONS_SHEET_NAME)));
// 将下拉表隐藏
workbook.setSheetHidden(workbook.getSheetIndex(simpleDataSheet), true);
// 完善纵向的一级选项数据表
for (int i = 0; i < value.size(); i++) {
int finalI = i;
// 获取每一选项行,如果没有则创建
Row row = Optional.ofNullable(simpleDataSheet.getRow(i))
.orElseGet(() -> simpleDataSheet.createRow(finalI));
// 获取本级选项对应的选项列,如果没有则创建
Cell cell = Optional.ofNullable(row.getCell(currentOptionsColumnIndex))
.orElseGet(() -> row.createCell(currentOptionsColumnIndex));
// 设置值
cell.setCellValue(value.get(i));
}
// 创建名称管理器
Name name = workbook.createName();
// 设置名称管理器的别名
String nameName = String.format("%s_%d", OPTIONS_SHEET_NAME, celIndex);
name.setNameName(nameName);
// 以纵向第一列创建一级下拉拼接引用位置
String function = String.format("%s!$%s$1:$%s$%d",
OPTIONS_SHEET_NAME,
getExcelColumnName(currentOptionsColumnIndex),
getExcelColumnName(currentOptionsColumnIndex),
value.size());
// 设置名称管理器的引用位置
name.setRefersToFormula(function);
// 设置数据校验为序列模式,引用的是名称管理器中的别名
this.markOptionsToSheet(helper, sheet, celIndex, helper.createFormulaListConstraint(nameName));
currentOptionsColumnIndex++;
}
/**
* 挂载下拉的列,仅限一级选项
*/
private void markOptionsToSheet(DataValidationHelper helper, Sheet sheet, Integer celIndex,
DataValidationConstraint constraint) {
// 设置数据有效性加载在哪个单元格上,四个参数分别是:起始行、终止行、起始列、终止列
CellRangeAddressList addressList = new CellRangeAddressList(1, 1000, celIndex, celIndex);
markDataValidationToSheet(helper, sheet, constraint, addressList);
}
/**
* 挂载下拉的列,仅限二级选项
*/
private void markLinkedOptionsToSheet(DataValidationHelper helper, Sheet sheet, Integer rowIndex,
Integer celIndex, DataValidationConstraint constraint) {
// 设置数据有效性加载在哪个单元格上,四个参数分别是:起始行、终止行、起始列、终止列
CellRangeAddressList addressList = new CellRangeAddressList(rowIndex, rowIndex, celIndex, celIndex);
markDataValidationToSheet(helper, sheet, constraint, addressList);
}
/**
* 应用数据校验
*/
private void markDataValidationToSheet(DataValidationHelper helper, Sheet sheet,
DataValidationConstraint constraint, CellRangeAddressList addressList) {
// 数据有效性对象
DataValidation dataValidation = helper.createValidation(constraint, addressList);
// 处理Excel兼容性问题
if (dataValidation instanceof XSSFDataValidation) {
//数据校验
dataValidation.setSuppressDropDownArrow(true);
//错误提示
dataValidation.setErrorStyle(DataValidation.ErrorStyle.STOP);
dataValidation.createErrorBox("提示", "此值与单元格定义数据不一致");
dataValidation.setShowErrorBox(true);
//选定提示
dataValidation.createPromptBox("填写说明:", "填写内容只能为下拉中数据,其他数据将导致导入失败");
dataValidation.setShowPromptBox(true);
sheet.addValidationData(dataValidation);
} else {
dataValidation.setSuppressDropDownArrow(false);
}
sheet.addValidationData(dataValidation);
}
/**
* <h2>依据列index获取列名英文</h2>
* 依据列index转换为Excel中的列名英文
* <p>例如第1列,index为0,解析出来为A列</p>
* 第27列,index为26,解析为AA列
* <p>第28列,index为27,解析为AB列</p>
*
* @param columnIndex 列index
* @return 列index所在得英文名
*/
private String getExcelColumnName(int columnIndex) {
// 26一循环的次数
int columnCircleCount = columnIndex / 26;
// 26一循环内的位置
int thisCircleColumnIndex = columnIndex % 26;
// 26一循环的次数大于0,则视为栏名至少两位
String columnPrefix = columnCircleCount == 0
? StrUtil.EMPTY
: StrUtil.subWithLength(EXCEL_COLUMN_NAME, columnCircleCount - 1, 1);
// 从26一循环内取对应的栏位名
String columnNext = StrUtil.subWithLength(EXCEL_COLUMN_NAME, thisCircleColumnIndex, 1);
// 将二者拼接即为最终的栏位名
return columnPrefix + columnNext;
}
}
package org.dromara.common.excel.core;
import com.alibaba.excel.read.listener.ReadListener;
/**
* Excel 导入监听
*
* @author Lion Li
*/
public interface ExcelListener<T> extends ReadListener<T> {
ExcelResult<T> getExcelResult();
}
package org.dromara.common.excel.core;
import java.util.List;
/**
* excel返回对象
*
* @author Lion Li
*/
public interface ExcelResult<T> {
/**
* 对象列表
*/
List<T> getList();
/**
* 错误列表
*/
List<String> getErrorList();
/**
* 导入回执
*/
String getAnalysis();
}
package org.dromara.common.excel.utils;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.io.resource.ClassPathResource;
import cn.hutool.core.util.IdUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.builder.ExcelWriterSheetBuilder;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.metadata.fill.FillConfig;
import com.alibaba.excel.write.metadata.fill.FillWrapper;
import com.alibaba.excel.write.style.column.LongestMatchColumnWidthStyleStrategy;
import jakarta.servlet.ServletOutputStream;
import jakarta.servlet.http.HttpServletResponse;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.core.utils.file.FileUtils;
import org.dromara.common.excel.convert.ExcelBigNumberConvert;
import org.dromara.common.excel.core.*;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.util.Collection;
import java.util.List;
import java.util.Map;
/**
* Excel相关处理
*
* @author Lion Li
*/
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class ExcelUtil {
/**
* 同步导入(适用于小数据量)
*
* @param is 输入流
* @return 转换后集合
*/
public static <T> List<T> importExcel(InputStream is, Class<T> clazz) {
return EasyExcel.read(is).head(clazz).autoCloseStream(false).sheet().doReadSync();
}
/**
* 使用校验监听器 异步导入 同步返回
*
* @param is 输入流
* @param clazz 对象类型
* @param isValidate 是否 Validator 检验 默认为是
* @return 转换后集合
*/
public static <T> ExcelResult<T> importExcel(InputStream is, Class<T> clazz, boolean isValidate) {
DefaultExcelListener<T> listener = new DefaultExcelListener<>(isValidate);
EasyExcel.read(is, clazz, listener).sheet().doRead();
return listener.getExcelResult();
}
/**
* 使用自定义监听器 异步导入 自定义返回
*
* @param is 输入流
* @param clazz 对象类型
* @param listener 自定义监听器
* @return 转换后集合
*/
public static <T> ExcelResult<T> importExcel(InputStream is, Class<T> clazz, ExcelListener<T> listener) {
EasyExcel.read(is, clazz, listener).sheet().doRead();
return listener.getExcelResult();
}
/**
* 导出excel
*
* @param list 导出数据集合
* @param sheetName 工作表的名称
* @param clazz 实体类
* @param response 响应体
*/
public static <T> void exportExcel(List<T> list, String sheetName, Class<T> clazz, HttpServletResponse response) {
try {
resetResponse(sheetName, response);
ServletOutputStream os = response.getOutputStream();
exportExcel(list, sheetName, clazz, false, os, null);
} catch (IOException e) {
throw new RuntimeException("导出Excel异常");
}
}
/**
* 导出excel
*
* @param list 导出数据集合
* @param sheetName 工作表的名称
* @param clazz 实体类
* @param response 响应体
* @param options 级联下拉选
*/
public static <T> void exportExcel(List<T> list, String sheetName, Class<T> clazz, HttpServletResponse response, List<DropDownOptions> options) {
try {
resetResponse(sheetName, response);
ServletOutputStream os = response.getOutputStream();
exportExcel(list, sheetName, clazz, false, os, options);
} catch (IOException e) {
throw new RuntimeException("导出Excel异常");
}
}
/**
* 导出excel
*
* @param list 导出数据集合
* @param sheetName 工作表的名称
* @param clazz 实体类
* @param merge 是否合并单元格
* @param response 响应体
*/
public static <T> void exportExcel(List<T> list, String sheetName, Class<T> clazz, boolean merge, HttpServletResponse response) {
try {
resetResponse(sheetName, response);
ServletOutputStream os = response.getOutputStream();
exportExcel(list, sheetName, clazz, merge, os, null);
} catch (IOException e) {
throw new RuntimeException("导出Excel异常");
}
}
/**
* 导出excel
*
* @param list 导出数据集合
* @param sheetName 工作表的名称
* @param clazz 实体类
* @param merge 是否合并单元格
* @param response 响应体
* @param options 级联下拉选
*/
public static <T> void exportExcel(List<T> list, String sheetName, Class<T> clazz, boolean merge, HttpServletResponse response, List<DropDownOptions> options) {
try {
resetResponse(sheetName, response);
ServletOutputStream os = response.getOutputStream();
exportExcel(list, sheetName, clazz, merge, os, options);
} catch (IOException e) {
throw new RuntimeException("导出Excel异常");
}
}
/**
* 导出excel
*
* @param list 导出数据集合
* @param sheetName 工作表的名称
* @param clazz 实体类
* @param os 输出流
*/
public static <T> void exportExcel(List<T> list, String sheetName, Class<T> clazz, OutputStream os) {
exportExcel(list, sheetName, clazz, false, os, null);
}
/**
* 导出excel
*
* @param list 导出数据集合
* @param sheetName 工作表的名称
* @param clazz 实体类
* @param os 输出流
* @param options 级联下拉选内容
*/
public static <T> void exportExcel(List<T> list, String sheetName, Class<T> clazz, OutputStream os, List<DropDownOptions> options) {
exportExcel(list, sheetName, clazz, false, os, options);
}
/**
* 导出excel
*
* @param list 导出数据集合
* @param sheetName 工作表的名称
* @param clazz 实体类
* @param merge 是否合并单元格
* @param os 输出流
*/
public static <T> void exportExcel(List<T> list, String sheetName, Class<T> clazz, boolean merge,
OutputStream os, List<DropDownOptions> options) {
ExcelWriterSheetBuilder builder = EasyExcel.write(os, clazz)
.autoCloseStream(false)
// 自动适配
.registerWriteHandler(new LongestMatchColumnWidthStyleStrategy())
// 大数值自动转换 防止失真
.registerConverter(new ExcelBigNumberConvert())
.sheet(sheetName);
if (merge) {
// 合并处理器
builder.registerWriteHandler(new CellMergeStrategy(list, true));
}
// 添加下拉框操作
if (options != null && options.size() > 0) {
builder.registerWriteHandler(new ExcelDownHandler(options));
}
builder.doWrite(list);
}
/**
* 单表多数据模板导出 模板格式为 {.属性}
*
* @param filename 文件名
* @param templatePath 模板路径 resource 目录下的路径包括模板文件名
* 例如: excel/temp.xlsx
* 重点: 模板文件必须放置到启动类对应的 resource 目录下
* @param data 模板需要的数据
* @param response 响应体
*/
public static void exportTemplate(List<Object> data, String filename, String templatePath, HttpServletResponse response) {
try {
resetResponse(filename, response);
ServletOutputStream os = response.getOutputStream();
exportTemplate(data, templatePath, os);
} catch (IOException e) {
throw new RuntimeException("导出Excel异常");
}
}
/**
* 单表多数据模板导出 模板格式为 {.属性}
*
* @param templatePath 模板路径 resource 目录下的路径包括模板文件名
* 例如: excel/temp.xlsx
* 重点: 模板文件必须放置到启动类对应的 resource 目录下
* @param data 模板需要的数据
* @param os 输出流
*/
public static void exportTemplate(List<Object> data, String templatePath, OutputStream os) {
ClassPathResource templateResource = new ClassPathResource(templatePath);
ExcelWriter excelWriter = EasyExcel.write(os)
.withTemplate(templateResource.getStream())
.autoCloseStream(false)
// 大数值自动转换 防止失真
.registerConverter(new ExcelBigNumberConvert())
.build();
WriteSheet writeSheet = EasyExcel.writerSheet().build();
if (CollUtil.isEmpty(data)) {
throw new IllegalArgumentException("数据为空");
}
// 单表多数据导出 模板格式为 {.属性}
for (Object d : data) {
excelWriter.fill(d, writeSheet);
}
excelWriter.finish();
}
/**
* 多表多数据模板导出 模板格式为 {key.属性}
*
* @param filename 文件名
* @param templatePath 模板路径 resource 目录下的路径包括模板文件名
* 例如: excel/temp.xlsx
* 重点: 模板文件必须放置到启动类对应的 resource 目录下
* @param data 模板需要的数据
* @param response 响应体
*/
public static void exportTemplateMultiList(Map<String, Object> data, String filename, String templatePath, HttpServletResponse response) {
try {
resetResponse(filename, response);
ServletOutputStream os = response.getOutputStream();
exportTemplateMultiList(data, templatePath, os);
} catch (IOException e) {
throw new RuntimeException("导出Excel异常");
}
}
/**
* 多sheet模板导出 模板格式为 {key.属性}
*
* @param filename 文件名
* @param templatePath 模板路径 resource 目录下的路径包括模板文件名
* 例如: excel/temp.xlsx
* 重点: 模板文件必须放置到启动类对应的 resource 目录下
* @param data 模板需要的数据
* @param response 响应体
*/
public static void exportTemplateMultiSheet(List<Map<String, Object>> data, String filename, String templatePath, HttpServletResponse response) {
try {
resetResponse(filename, response);
ServletOutputStream os = response.getOutputStream();
exportTemplateMultiSheet(data, templatePath, os);
} catch (IOException e) {
throw new RuntimeException("导出Excel异常");
}
}
/**
* 多表多数据模板导出 模板格式为 {key.属性}
*
* @param templatePath 模板路径 resource 目录下的路径包括模板文件名
* 例如: excel/temp.xlsx
* 重点: 模板文件必须放置到启动类对应的 resource 目录下
* @param data 模板需要的数据
* @param os 输出流
*/
public static void exportTemplateMultiList(Map<String, Object> data, String templatePath, OutputStream os) {
ClassPathResource templateResource = new ClassPathResource(templatePath);
ExcelWriter excelWriter = EasyExcel.write(os)
.withTemplate(templateResource.getStream())
.autoCloseStream(false)
// 大数值自动转换 防止失真
.registerConverter(new ExcelBigNumberConvert())
.build();
WriteSheet writeSheet = EasyExcel.writerSheet().build();
if (CollUtil.isEmpty(data)) {
throw new IllegalArgumentException("数据为空");
}
for (Map.Entry<String, Object> map : data.entrySet()) {
// 设置列表后续还有数据
FillConfig fillConfig = FillConfig.builder().forceNewRow(Boolean.TRUE).build();
if (map.getValue() instanceof Collection) {
// 多表导出必须使用 FillWrapper
excelWriter.fill(new FillWrapper(map.getKey(), (Collection<?>) map.getValue()), fillConfig, writeSheet);
} else {
excelWriter.fill(map.getValue(), writeSheet);
}
}
excelWriter.finish();
}
/**
* 多sheet模板导出 模板格式为 {key.属性}
*
* @param templatePath 模板路径 resource 目录下的路径包括模板文件名
* 例如: excel/temp.xlsx
* 重点: 模板文件必须放置到启动类对应的 resource 目录下
* @param data 模板需要的数据
* @param os 输出流
*/
public static void exportTemplateMultiSheet(List<Map<String, Object>> data, String templatePath, OutputStream os) {
ClassPathResource templateResource = new ClassPathResource(templatePath);
ExcelWriter excelWriter = EasyExcel.write(os)
.withTemplate(templateResource.getStream())
.autoCloseStream(false)
// 大数值自动转换 防止失真
.registerConverter(new ExcelBigNumberConvert())
.build();
if (CollUtil.isEmpty(data)) {
throw new IllegalArgumentException("数据为空");
}
for (int i = 0; i < data.size(); i++) {
WriteSheet writeSheet = EasyExcel.writerSheet(i).build();
for (Map.Entry<String, Object> map : data.get(i).entrySet()) {
// 设置列表后续还有数据
FillConfig fillConfig = FillConfig.builder().forceNewRow(Boolean.TRUE).build();
if (map.getValue() instanceof Collection) {
// 多表导出必须使用 FillWrapper
excelWriter.fill(new FillWrapper(map.getKey(), (Collection<?>) map.getValue()), fillConfig, writeSheet);
} else {
excelWriter.fill(map.getValue(), writeSheet);
}
}
}
excelWriter.finish();
}
/**
* 重置响应体
*/
public static void resetResponse(String sheetName, HttpServletResponse response) throws UnsupportedEncodingException {
String filename = encodingFilename(sheetName);
FileUtils.setAttachmentResponseHeader(response, filename);
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=UTF-8");
}
/**
* 解析导出值 0=男,1=女,2=未知
*
* @param propertyValue 参数值
* @param converterExp 翻译注解
* @param separator 分隔符
* @return 解析后值
*/
public static String convertByExp(String propertyValue, String converterExp, String separator) {
StringBuilder propertyString = new StringBuilder();
String[] convertSource = converterExp.split(StringUtils.SEPARATOR);
for (String item : convertSource) {
String[] itemArray = item.split("=");
if (StringUtils.containsAny(propertyValue, separator)) {
for (String value : propertyValue.split(separator)) {
if (itemArray[0].equals(value)) {
propertyString.append(itemArray[1] + separator);
break;
}
}
} else {
if (itemArray[0].equals(propertyValue)) {
return itemArray[1];
}
}
}
return StringUtils.stripEnd(propertyString.toString(), separator);
}
/**
* 反向解析值 男=0,女=1,未知=2
*
* @param propertyValue 参数值
* @param converterExp 翻译注解
* @param separator 分隔符
* @return 解析后值
*/
public static String reverseByExp(String propertyValue, String converterExp, String separator) {
StringBuilder propertyString = new StringBuilder();
String[] convertSource = converterExp.split(StringUtils.SEPARATOR);
for (String item : convertSource) {
String[] itemArray = item.split("=");
if (StringUtils.containsAny(propertyValue, separator)) {
for (String value : propertyValue.split(separator)) {
if (itemArray[1].equals(value)) {
propertyString.append(itemArray[0] + separator);
break;
}
}
} else {
if (itemArray[1].equals(propertyValue)) {
return itemArray[0];
}
}
}
return StringUtils.stripEnd(propertyString.toString(), separator);
}
/**
* 编码文件名
*/
public static String encodingFilename(String filename) {
return IdUtil.fastSimpleUUID() + "_" + filename + ".xlsx";
}
}
package org.dromara.common.web.config;
import jakarta.servlet.DispatcherType;
import org.dromara.common.web.config.properties.XssProperties;
import org.dromara.common.web.filter.XssFilter;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
/**
* Filter配置
*
* @author Lion Li
*/
@AutoConfiguration
@EnableConfigurationProperties(XssProperties.class)
public class FilterConfig {
@Bean
@ConditionalOnProperty(value = "xss.enabled", havingValue = "true")
public FilterRegistrationBean<XssFilter> xssFilterRegistration() {
FilterRegistrationBean<XssFilter> registration = new FilterRegistrationBean<>();
registration.setDispatcherTypes(DispatcherType.REQUEST);
registration.setFilter(new XssFilter());
registration.addUrlPatterns("/*");
registration.setName("xssFilter");
registration.setOrder(FilterRegistrationBean.HIGHEST_PRECEDENCE + 1);
return registration;
}
}
package org.dromara.common.web.config;
import org.dromara.common.web.core.I18nLocaleResolver;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.web.servlet.LocaleResolver;
/**
* 国际化配置
*
* @author Lion Li
*/
@AutoConfiguration(before = WebMvcAutoConfiguration.class)
public class I18nConfig {
@Bean
public LocaleResolver localeResolver() {
return new I18nLocaleResolver();
}
}
package org.dromara.common.web.core;
import org.springframework.web.servlet.LocaleResolver;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.util.Locale;
/**
* 获取请求头国际化信息
*
* @author Lion Li
*/
public class I18nLocaleResolver implements LocaleResolver {
@Override
public Locale resolveLocale(HttpServletRequest httpServletRequest) {
String language = httpServletRequest.getHeader("content-language");
Locale locale = Locale.getDefault();
if (language != null && language.length() > 0) {
String[] split = language.split("_");
locale = new Locale(split[0], split[1]);
}
return locale;
}
@Override
public void setLocale(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Locale locale) {
}
}
package org.dromara.common.web.handler;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.http.HttpStatus;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.validation.ConstraintViolation;
import jakarta.validation.ConstraintViolationException;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.domain.R;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.exception.SseException;
import org.dromara.common.core.exception.base.BaseException;
import org.dromara.common.core.utils.StreamUtils;
import org.dromara.common.json.utils.JsonUtils;
import org.springframework.context.support.DefaultMessageSourceResolvable;
import org.springframework.validation.BindException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingPathVariableException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;
import org.springframework.web.servlet.NoHandlerFoundException;
import java.io.IOException;
/**
* 全局异常处理器
*
* @author Lion Li
*/
@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {
/**
* 请求方式不支持
*/
@ExceptionHandler(HttpRequestMethodNotSupportedException.class)
public R<Void> handleHttpRequestMethodNotSupported(HttpRequestMethodNotSupportedException e,
HttpServletRequest request) {
String requestURI = request.getRequestURI();
log.error("请求地址'{}',不支持'{}'请求", requestURI, e.getMethod());
return R.fail(HttpStatus.HTTP_BAD_METHOD, e.getMessage());
}
/**
* 业务异常
*/
@ExceptionHandler(ServiceException.class)
public R<Void> handleServiceException(ServiceException e, HttpServletRequest request) {
log.error(e.getMessage());
Integer code = e.getCode();
return ObjectUtil.isNotNull(code) ? R.fail(code, e.getMessage()) : R.fail(e.getMessage());
}
/**
* 认证失败
*/
@ResponseStatus(org.springframework.http.HttpStatus.UNAUTHORIZED)
@ExceptionHandler(SseException.class)
public String handleNotLoginException(SseException e, HttpServletRequest request) {
String requestURI = request.getRequestURI();
log.error("请求地址'{}',认证失败'{}',无法访问系统资源", requestURI, e.getMessage());
return JsonUtils.toJsonString(R.fail(HttpStatus.HTTP_UNAUTHORIZED, "认证失败,无法访问系统资源"));
}
/**
* servlet异常
*/
@ExceptionHandler(ServletException.class)
public R<Void> handleServletException(ServletException e, HttpServletRequest request) {
String requestURI = request.getRequestURI();
log.error("请求地址'{}',发生未知异常.", requestURI, e);
return R.fail(e.getMessage());
}
/**
* 业务异常
*/
@ExceptionHandler(BaseException.class)
public R<Void> handleBaseException(BaseException e, HttpServletRequest request) {
log.error(e.getMessage());
return R.fail(e.getMessage());
}
/**
* 请求路径中缺少必需的路径变量
*/
@ExceptionHandler(MissingPathVariableException.class)
public R<Void> handleMissingPathVariableException(MissingPathVariableException e, HttpServletRequest request) {
String requestURI = request.getRequestURI();
log.error("请求路径中缺少必需的路径变量'{}',发生系统异常.", requestURI);
return R.fail(String.format("请求路径中缺少必需的路径变量[%s]", e.getVariableName()));
}
/**
* 请求参数类型不匹配
*/
@ExceptionHandler(MethodArgumentTypeMismatchException.class)
public R<Void> handleMethodArgumentTypeMismatchException(MethodArgumentTypeMismatchException e, HttpServletRequest request) {
String requestURI = request.getRequestURI();
log.error("请求参数类型不匹配'{}',发生系统异常.", requestURI);
return R.fail(String.format("请求参数类型不匹配,参数[%s]要求类型为:'%s',但输入值为:'%s'", e.getName(), e.getRequiredType().getName(), e.getValue()));
}
/**
* 找不到路由
*/
@ExceptionHandler(NoHandlerFoundException.class)
public R<Void> handleNoHandlerFoundException(NoHandlerFoundException e, HttpServletRequest request) {
String requestURI = request.getRequestURI();
log.error("请求地址'{}'不存在.", requestURI);
return R.fail(HttpStatus.HTTP_NOT_FOUND, e.getMessage());
}
/**
* 拦截未知的运行时异常
*/
@ResponseStatus(org.springframework.http.HttpStatus.INTERNAL_SERVER_ERROR)
@ExceptionHandler(IOException.class)
public void handleRuntimeException(IOException e, HttpServletRequest request) {
String requestURI = request.getRequestURI();
if (requestURI.contains("sse")) {
// sse 经常性连接中断 例如关闭浏览器 直接屏蔽
return;
}
log.error("请求地址'{}',连接中断", requestURI, e);
}
/**
* 拦截未知的运行时异常
*/
@ExceptionHandler(RuntimeException.class)
public R<Void> handleRuntimeException(RuntimeException e, HttpServletRequest request) {
String requestURI = request.getRequestURI();
log.error("请求地址'{}',发生未知异常.", requestURI, e);
return R.fail(e.getMessage());
}
/**
* 系统异常
*/
@ExceptionHandler(Exception.class)
public R<Void> handleException(Exception e, HttpServletRequest request) {
String requestURI = request.getRequestURI();
log.error("请求地址'{}',发生系统异常.", requestURI, e);
return R.fail(e.getMessage());
}
/**
* 自定义验证异常
*/
@ExceptionHandler(BindException.class)
public R<Void> handleBindException(BindException e) {
log.error(e.getMessage());
String message = StreamUtils.join(e.getAllErrors(), DefaultMessageSourceResolvable::getDefaultMessage, ", ");
return R.fail(message);
}
/**
* 自定义验证异常
*/
@ExceptionHandler(ConstraintViolationException.class)
public R<Void> constraintViolationException(ConstraintViolationException e) {
log.error(e.getMessage());
String message = StreamUtils.join(e.getConstraintViolations(), ConstraintViolation::getMessage, ", ");
return R.fail(message);
}
/**
* 自定义验证异常
*/
@ExceptionHandler(MethodArgumentNotValidException.class)
public R<Void> handleMethodArgumentNotValidException(MethodArgumentNotValidException e) {
log.error(e.getMessage());
String message = StreamUtils.join(e.getBindingResult().getAllErrors(), DefaultMessageSourceResolvable::getDefaultMessage, ", ");
return R.fail(message);
}
}
package com.bkty.gateway.filter;
import cn.dev33.satoken.SaManager;
import cn.dev33.satoken.same.SaSameUtil;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
/**
* 转发认证过滤器(内部服务外网隔离)
*
* @author Lion Li
*/
@Component
public class ForwardAuthFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
// 未开启配置则直接跳过
if (!SaManager.getConfig().getCheckSameToken()) {
return chain.filter(exchange);
}
ServerHttpRequest newRequest = exchange
.getRequest()
.mutate()
// 为请求追加 Same-Token 参数
.header(SaSameUtil.SAME_TOKEN, SaSameUtil.getToken())
.build();
ServerWebExchange newExchange = exchange.mutate().request(newRequest).build();
return chain.filter(newExchange);
}
@Override
public int getOrder() {
return -100;
}
}
package com.bkty.gateway.filter;
import com.bkty.gateway.utils.WebFluxUtils;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.cloud.gateway.support.ServerWebExchangeUtils;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
/**
* 全局缓存获取body请求数据(解决流不能重复读取问题)
*
* @author Lion Li
*/
@Component
public class GlobalCacheRequestFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
// 只缓存json类型请求
if (!WebFluxUtils.isJsonRequest(exchange)) {
return chain.filter(exchange);
}
return ServerWebExchangeUtils.cacheRequestBody(exchange, (serverHttpRequest) -> {
if (serverHttpRequest == exchange.getRequest()) {
return chain.filter(exchange);
}
return chain.filter(exchange.mutate().request(serverHttpRequest).build());
});
}
@Override
public int getOrder() {
return Ordered.HIGHEST_PRECEDENCE + 1;
}
}
package com.bkty.gateway.filter;
import org.springframework.core.Ordered;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.cors.reactive.CorsUtils;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.WebFilter;
import org.springframework.web.server.WebFilterChain;
import reactor.core.publisher.Mono;
/**
* 跨域配置
*
* @author Lion Li
*/
@Component
public class GlobalCorsFilter implements WebFilter, Ordered {
/**
* 这里为支持的请求头,如果有自定义的header字段请自己添加
*/
private static final String ALLOWED_HEADERS =
"X-Requested-With, Content-Language, Content-Type, " +
"Authorization, clientid, credential, X-XSRF-TOKEN, " +
"isToken, token, Admin-Token, App-Token, Encrypt-Key, isEncrypt";
/**
* 允许的请求方法
*/
private static final String ALLOWED_METHODS = "GET,POST,PUT,DELETE,OPTIONS,HEAD";
/**
* 允许的请求来源,使用 * 表示允许任何来源
*/
private static final String ALLOWED_ORIGIN = "*";
/**
* 允许前端访问的响应头,使用 * 表示允许任何响应头
*/
private static final String ALLOWED_EXPOSE = "*";
/**
* 预检请求的缓存时间,单位为秒(此处设置为 5 小时)
*/
private static final String MAX_AGE = "18000L";
/**
* 实现跨域配置的 Web 过滤器
*
* @param exchange ServerWebExchange 对象,表示一次 Web 交换
* @param chain WebFilterChain 对象,表示一组 Web 过滤器链
* @return Mono<Void> 表示异步的过滤器链处理结果
*/
@Override
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
ServerHttpRequest request = exchange.getRequest();
// 判断请求是否为跨域请求
if (CorsUtils.isCorsRequest(request)) {
ServerHttpResponse response = exchange.getResponse();
HttpHeaders headers = response.getHeaders();
headers.add("Access-Control-Allow-Headers", ALLOWED_HEADERS);
headers.add("Access-Control-Allow-Methods", ALLOWED_METHODS);
headers.add("Access-Control-Allow-Origin", ALLOWED_ORIGIN);
headers.add("Access-Control-Expose-Headers", ALLOWED_EXPOSE);
headers.add("Access-Control-Max-Age", MAX_AGE);
headers.add("Access-Control-Allow-Credentials", "true");
// 处理预检请求的 OPTIONS 方法,直接返回成功状态码
if (request.getMethod() == HttpMethod.OPTIONS) {
response.setStatusCode(HttpStatus.OK);
return Mono.empty();
}
}
return chain.filter(exchange);
}
@Override
public int getOrder() {
return Ordered.HIGHEST_PRECEDENCE;
}
}
package com.bkty.gateway.filter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.context.i18n.SimpleLocaleContext;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
import java.util.Locale;
/**
* 全局国际化处理
*
* @author Lion Li
*/
@Slf4j
@Component
public class GlobalI18nFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
String language = exchange.getRequest().getHeaders().getFirst("content-language");
Locale locale = Locale.getDefault();
if (language != null && language.length() > 0) {
String[] split = language.split("_");
locale = new Locale(split[0], split[1]);
}
LocaleContextHolder.setLocaleContext(new SimpleLocaleContext(locale), true);
return chain.filter(exchange);
}
@Override
public int getOrder() {
return Ordered.HIGHEST_PRECEDENCE;
}
}
package com.bkty.gateway.filter;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ObjectUtil;
import com.bkty.gateway.config.properties.ApiDecryptProperties;
import com.bkty.gateway.config.properties.CustomGatewayProperties;
import com.bkty.gateway.utils.WebFluxUtils;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.json.utils.JsonUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.util.MultiValueMap;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
/**
* 全局日志过滤器
* <p>
* 用于打印请求执行参数与响应时间等等
*
* @author Lion Li
*/
@Slf4j
@Component
public class GlobalLogFilter implements GlobalFilter, Ordered {
@Autowired
private CustomGatewayProperties customGatewayProperties;
@Autowired
private ApiDecryptProperties apiDecryptProperties;
private static final String START_TIME = "startTime";
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
if (!customGatewayProperties.getRequestLog()) {
return chain.filter(exchange);
}
ServerHttpRequest request = exchange.getRequest();
String path = WebFluxUtils.getOriginalRequestUrl(exchange);
String url = request.getMethod().name() + " " + path;
// 打印请求参数
if (WebFluxUtils.isJsonRequest(exchange)) {
if (apiDecryptProperties.getEnabled()
&& ObjectUtil.isNotNull(request.getHeaders().getFirst(apiDecryptProperties.getHeaderFlag()))) {
log.info("[PLUS]开始请求 => URL[{}],参数类型[encrypt]", url);
} else {
String jsonParam = WebFluxUtils.resolveBodyFromCacheRequest(exchange);
log.info("[PLUS]开始请求 => URL[{}],参数类型[json],参数:[{}]", url, jsonParam);
}
} else {
MultiValueMap<String, String> parameterMap = request.getQueryParams();
if (MapUtil.isNotEmpty(parameterMap)) {
String parameters = JsonUtils.toJsonString(parameterMap);
log.info("[PLUS]开始请求 => URL[{}],参数类型[param],参数:[{}]", url, parameters);
} else {
log.info("[PLUS]开始请求 => URL[{}],无参数", url);
}
}
exchange.getAttributes().put(START_TIME, System.currentTimeMillis());
return chain.filter(exchange).then(Mono.fromRunnable(() -> {
Long startTime = exchange.getAttribute(START_TIME);
if (startTime != null) {
long executeTime = (System.currentTimeMillis() - startTime);
log.info("[PLUS]结束请求 => URL[{}],耗时:[{}]毫秒", url, executeTime);
}
}));
}
@Override
public int getOrder() {
// 日志处理器在负载均衡器之后执行 负载均衡器会导致线程切换 无法获取上下文内容
// 如需在日志内操作线程上下文 例如获取登录用户数据等 可以打开下方注释代码
// return ReactiveLoadBalancerClientFilter.LOAD_BALANCER_CLIENT_FILTER_ORDER - 1;
return Ordered.LOWEST_PRECEDENCE;
}
}
package com.bkty.gateway.handler;
import com.bkty.gateway.utils.WebFluxUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.web.reactive.error.ErrorWebExceptionHandler;
import org.springframework.cloud.gateway.support.NotFoundException;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.web.server.ResponseStatusException;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
/**
* 网关统一异常处理
*
* @author ruoyi
*/
@Slf4j
@Order(-1)
@Configuration
public class GatewayExceptionHandler implements ErrorWebExceptionHandler {
@Override
public Mono<Void> handle(ServerWebExchange exchange, Throwable ex) {
ServerHttpResponse response = exchange.getResponse();
if (exchange.getResponse().isCommitted()) {
return Mono.error(ex);
}
String msg;
if (ex instanceof NotFoundException) {
msg = "服务未找到";
} else if (ex instanceof ResponseStatusException responseStatusException) {
msg = responseStatusException.getMessage();
} else {
msg = "内部服务器错误";
}
log.error("[网关异常处理]请求路径:{},异常信息:{}", exchange.getRequest().getPath(), ex.getMessage());
return WebFluxUtils.webFluxResponseWriter(response, msg);
}
}
package com.bkty.system.domain.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import org.dromara.common.core.annotation.JxgInitField;
import org.dromara.common.mybatis.core.domain.BaseEntity;
/**
* @author jiangxiaoge
* @description 个人简历数据主表
* @data 2024/12/16
**/
@Data
@TableName("function_resume_base")
public class FunctionResumeBase extends BaseEntity {
/**
* 主键ID
*/
@TableId(value = "id", type = IdType.ASSIGN_ID)
private Long id;
/**简历使用人*/
private Long userId;
/**创建类型 0.未来简历*/
private Integer createType;
/**对应平台的简历id*/
private String platformId;
/**简历名称*/
private String resumeName;
/**生日*/
@JxgInitField("birthday")
private String birthday;
/**头像url*/
@JxgInitField("avatar")
private String avatar;
/**城市*/
@JxgInitField("city")
private String city;
/**名族*/
@JxgInitField("ethnic")
private String ethnic;
/**岗位*/
@JxgInitField("jobInt")
private String jobInt;
/**邮箱*/
@JxgInitField("email")
private String email;
/**名字*/
@JxgInitField("username")
private String username;
/**薪资*/
@JxgInitField("pay")
private String pay;
/**手机号*/
@JxgInitField("phone")
private String phone;
/**政治面貌*/
@JxgInitField("polStatus")
private String polStatus;
/**性别*/
@JxgInitField("sex")
private String sex;
/**工作状态*/
@JxgInitField("workStatus")
private String workStatus;
/**微信号*/
@JxgInitField("wechat")
private String wechat;
/**参加工作时间*/
@JxgInitField(value = "workTime")
private String workTime;
/**简历导入状态 0.已完成 1.导入中 2.导入失败*/
private Integer runType;
/**简历发布状态 0.未发布 1.已发布*/
private Integer publicStatus;
/**默认状态 0=默认 1=不默认*/
private Integer defaultStatus;
/**模版ID*/
private String templateId;
/**模版名称*/
private String templateName;
}
package com.bkty.system.domain.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import org.dromara.common.mybatis.core.domain.BaseEntity;
/**
* @author jiangxiaoge
* @description 个人简历完整优化记录表
* @data 2025/5/19
**/
@Data
@TableName("function_resume_base_optimization")
public class FunctionResumeBaseOptimization extends BaseEntity {
@TableId(value = "id", type = IdType.ASSIGN_ID)
private Long id;
private Long userId;
private Long resumeId;
// 简历评分
private Integer resumeScore;
// 使用状态 0=可用 1=作废
private Integer useStatus;
private String appraise;
// 优化建议
private String optimizationDesc;
// 优化详情
private String optimizationDetail;
}
package com.bkty.system.domain.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import org.dromara.common.core.annotation.JxgInitField;
import org.dromara.common.mybatis.core.domain.BaseEntity;
/**
* @author jiangxiaoge
* @description 个人简历学校社团经历
* @data 2024/12/16
**/
@Data
@TableName("function_resume_club")
public class FunctionResumeClub extends BaseEntity {
/**
* 主键ID
*/
@TableId(value = "id", type = IdType.ASSIGN_ID)
private Long id;
/**简历id*/
private Long resumeId;
private Long modelId;
/**社团名称*/
@JxgInitField("clubName")
private String clubName;
/**担任角色*/
@JxgInitField("roleName")
private String roleName;
/**开始时间*/
@JxgInitField("startTime")
private String startTime;
/**结束时间*/
@JxgInitField("endTime")
private String endTime;
/**详情*/
@JxgInitField("description")
private String description;
@JxgInitField("performance")
private String performance;
/**排序*/
private Integer dataSort;
}
package com.bkty.system.domain.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableLogic;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import org.dromara.common.core.utils.Entity;
/**
* @author Herbert
* @description 简历下载次数表
* @data 2025/04/08
**/
@Data
@TableName("function_resume_download_number")
public class FunctionResumeDownloadNumber extends Entity {
/**主键ID*/
@TableId(value = "id", type = IdType.ASSIGN_ID)
private Long id;
/**用户id*/
private String userId;
/**简历id*/
private String resumeId;
/**下载次数*/
private Integer downloadCounts;
/**简历优化次数*/
private Integer optimizeCounts;
/**
* 是否删除(true:已删除,false:未删除)
*/
@TableLogic
@Schema(description = "是否删除(true:已删除,false:未删除)")
private Boolean isDeleted = false;
}
package com.bkty.system.domain.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import org.dromara.common.core.annotation.JxgInitField;
import org.dromara.common.mybatis.core.domain.BaseEntity;
/**
* @author jiangxiaoge
* @description 个人简历教育经历
* @data 2024/12/16
**/
@Data
@TableName("function_resume_edu")
public class FunctionResumeEdu extends BaseEntity {
/**
* 主键ID
*/
@TableId(value = "id", type = IdType.ASSIGN_ID)
private Long id;
/**简历id*/
private Long resumeId;
/**模块id*/
private Long modelId;
/**学历*/
@JxgInitField("degree")
private String degree;
/**开始时间*/
@JxgInitField("startTime")
private String startTime;
/**结束时间*/
@JxgInitField("endTime")
private String endTime;
/**专业*/
@JxgInitField("major")
private String major;
/**学校*/
@JxgInitField("school")
private String school;
/**详情*/
@JxgInitField("description")
private String description;
/**排序*/
private Integer dataSort;
}
package com.bkty.system.domain.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import org.dromara.common.mybatis.core.domain.BaseEntity;
/**
* @author jiangxiaoge
* @description 个人简历额外信息
* @data 2024/12/16
**/
@Data
@TableName("function_resume_extra")
public class FunctionResumeExtra extends BaseEntity {
/**
* 主键ID
*/
@TableId(value = "id", type = IdType.ASSIGN_ID)
private Long id;
/**简历id*/
private Long resumeId;
private Long modelId;
/**数据类型 0.专业技能1.个人优势.获奖信息3.兴趣爱好*/
private Integer dataType;
/**详情*/
private String description;
}
package com.bkty.system.domain.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import org.dromara.common.core.annotation.JxgInitField;
import org.dromara.common.mybatis.core.domain.BaseEntity;
/**
* @author jiangxiaoge
* @description 个人简历实习经历
* @data 2024/12/16
**/
@Data
@TableName("function_resume_internship")
public class FunctionResumeInternship extends BaseEntity {
/**
* 主键ID
*/
@TableId(value = "id", type = IdType.ASSIGN_ID)
private Long id;
/**简历id*/
private Long resumeId;
private Long modelId;
/**实习公司*/
@JxgInitField("internshipCorp")
private String internshipCorp;
/**实习岗位*/
@JxgInitField("internshipPost")
private String internshipPost;
/**成果*/
@JxgInitField("performance")
private String performance;
/**开始时间*/
@JxgInitField("startTime")
private String startTime;
/**结束时间*/
@JxgInitField("endTime")
private String endTime;
/**详情*/
@JxgInitField("description")
private String description;
private Integer dataSort;
}
package com.bkty.system.domain.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import org.dromara.common.mybatis.core.domain.BaseEntity;
/**
* @author jiangxiaoge
* @description 个人简历自定义模块
* @data 2024/12/16
**/
@Data
@TableName("function_resume_model")
public class FunctionResumeModel extends BaseEntity {
/**
* 主键ID
*/
@TableId(value = "id", type = IdType.ASSIGN_ID)
private Long id;
/**简历id*/
private Long resumeId;
/**平台自定义id*/
private String platformCustomId;
/**模块类型 ResumeEnum.ResumeModel枚举类型*/
private Integer modelType;
/**模块名称*/
private String modelName;
/**是否展示0.显示 1.不显示*/
private Integer isShow;
/**排序*/
private Integer dataSort;
}
package com.bkty.system.domain.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import org.dromara.common.core.annotation.JxgInitField;
import org.dromara.common.mybatis.core.domain.BaseEntity;
/**
* @author jiangxiaoge
* @description 个人简历自定义模块详情
* @data 2024/12/16
**/
@Data
@TableName("function_resume_model_custom")
public class FunctionResumeModelCustom extends BaseEntity {
/**
* 主键ID
*/
@TableId(value = "id", type = IdType.ASSIGN_ID)
private Long id;
/**简历id*/
private Long resumeId;
/**模块id*/
private Long modelId;
/**自定义模块名称*/
@JxgInitField("infoName")
private String infoName;
/**详情*/
@JxgInitField("description")
private String description;
/**开始时间*/
@JxgInitField("startTime")
private String startTime;
/**结束时间*/
@JxgInitField("endTime")
private String endTime;
private Integer dataSort;
}
package com.bkty.system.domain.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import org.dromara.common.mybatis.core.domain.BaseEntity;
import lombok.Data;
/**
* @author jiangxiaoge
* @description 简历模块优化建议表
* @data 2025/5/19
**/
@Data
@TableName("function_resume_model_optimization")
public class FunctionResumeModelOptimization extends BaseEntity {
@TableId(value = "id", type = IdType.ASSIGN_ID)
private Long id;
private Long userId;
private Long resumeId;
// ResumeEnum.ResumeModel枚举
private String modelCode;
// 运行状态 0=未优化 1=优化失败 2=优化成功 3=优化中
private Integer runStatus;
// 优化建议
private String optimizationDesc;
}
package com.bkty.system.domain.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import org.dromara.common.core.annotation.JxgInitField;
import org.dromara.common.mybatis.core.domain.BaseEntity;
import lombok.Data;
/**
* @author jiangxiaoge
* @description 个人简历项目经历
* @data 2024/12/16
**/
@Data
@TableName("function_resume_project")
public class FunctionResumeProject extends BaseEntity {
/**
* 主键ID
*/
@TableId(value = "id", type = IdType.ASSIGN_ID)
private Long id;
/**简历id*/
private Long resumeId;
/**模块id*/
private Long modelId;
/**项目名称*/
@JxgInitField("projectName")
private String projectName;
/**职位名称*/
@JxgInitField("roleName")
private String roleName;
/**开始时间*/
@JxgInitField("startTime")
private String startTime;
/**结束时间*/
@JxgInitField("endTime")
private String endTime;
/**职位描述*/
@JxgInitField("description")
private String description;
/**项目描述*/
@JxgInitField("performance")
private String performance;
/**排序*/
private Integer dataSort;
}
package com.bkty.system.domain.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import org.dromara.common.mybatis.core.domain.BaseEntity;
import lombok.Data;
/**
* @author jiangxiaoge
* @description 简历描述向量信息
* @data 2025/3/16
**/
@Data
@TableName("function_resume_sketch")
public class FunctionResumeSketch extends BaseEntity {
@TableId(value = "id", type = IdType.ASSIGN_ID)
private Long id;
private Long resumeId;
private String sketch;
private String vectorQuantity;
}
package com.bkty.system.domain.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import org.dromara.common.mybatis.core.domain.BaseEntity;
import lombok.Data;
/**
* @author jiangxiaoge
* @description 简历模版
* @data 2025/1/7
**/
@Data
@TableName("function_resume_template")
public class FunctionResumeTemplate extends BaseEntity {
/**
* 主键ID
*/
@TableId(value = "id", type = IdType.ASSIGN_ID)
private Long id;
/**模版路径*/
private String templatePath;
/**模版名称*/
private String templateName;
}
package com.bkty.system.domain.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import org.dromara.common.core.annotation.JxgInitField;
import org.dromara.common.mybatis.core.domain.BaseEntity;
import lombok.Data;
/**
* @author jiangxiaoge
* @description 个人简历工作经历
* @data 2024/12/16
**/
@Data
@TableName("function_resume_work_exp")
public class FunctionResumeWorkExp extends BaseEntity {
/**
* 主键ID
*/
@TableId(value = "id", type = IdType.ASSIGN_ID)
private Long id;
/**简历id*/
private Long resumeId;
private Long modelId;
/** 工作内容 */
@JxgInitField("workContent")
private String workContent;
/**公司名称*/
@JxgInitField("corpName")
private String corpName;
/**开始时间*/
@JxgInitField("startTime")
private String startTime;
/**结束时间*/
@JxgInitField("endTime")
private String endTime;
/**岗位名称*/
@JxgInitField("postName")
private String postName;
/**工作成绩*/
@JxgInitField("performance")
private String performance;
/**排序*/
private Integer dataSort;
}
package com.bkty.system.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.bkty.system.domain.dto.ResumeListItemCache;
import com.bkty.system.domain.entity.FunctionResumeBase;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;
import java.util.List;
/**
* @author jiangxiaoge
* @description 个人简历主表
* @data 2024/12/16
**/
@Mapper
public interface FunctionResumeBaseMapper extends BaseMapper<FunctionResumeBase> {
@Select("select t1.public_status as publicStatus," +
" t1.id as resumeId," +
" t1.resume_name as resumeName," +
" t1.run_type as runType," +
" t1.sex as sex," +
" t1.avatar as avatar," +
" DATE_FORMAT(t1.update_time, '%Y-%m-%d %H:%i:%s') as updateTime," +
" t2.resume_score as resumeScore," +
" t2.use_status as useStatus," +
" t2.appraise," +
" t1.default_status as defaultStatus " +
"from function_resume_base t1 " +
" left join function_resume_base_optimization t2 on t1.id = t2.resume_id " +
"where t1.user_id = #{userId} " +
" and t1.is_deleted = false order by t1.default_status ASC,t1.update_time ASC")
List<ResumeListItemCache> queryResumeListV2(@Param("userId") Long userId);
@Update("""
UPDATE function_resume_base
SET default_status = CASE
WHEN id = #{resumeId} THEN 0
ELSE 1
END
WHERE user_id = #{userId};
""")
void defultResume(@Param("resumeId") Long resumeId, @Param("userId") Long userId);
@Select("select * from function_resume_base where id = #{resumeId}")
FunctionResumeBase selectResumeById(@Param("resumeId") Long resumeId);
}
package com.bkty.system.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.bkty.system.domain.entity.FunctionResumeBaseOptimization;
import org.apache.ibatis.annotations.Delete;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
/**
* @author jiangxiaoge
* @description
* @data 2025/5/19
**/
@Mapper
public interface FunctionResumeBaseOptimizationMapper extends BaseMapper<FunctionResumeBaseOptimization> {
@Delete("""
delete from function_resume_base_optimization where resume_id = #{resumeId} and user_id = #{userId}
""")
int deleteData(@Param("resumeId") Long resumeId, @Param("userId") Long userId);
}
package com.bkty.system.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.bkty.system.domain.entity.FunctionResumeClub;
import org.apache.ibatis.annotations.Mapper;
/**
* @author jiangxiaoge
* @description 学校经历
* @data 2024/12/16
**/
@Mapper
public interface FunctionResumeClubMapper extends BaseMapper<FunctionResumeClub> {
}
package com.bkty.system.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.bkty.system.domain.entity.FunctionResumeDownloadNumber;
import org.apache.ibatis.annotations.Mapper;
/**
* @author Herbert
* @description 简历下载次数表
* @data 2025/05/07
**/
@Mapper
public interface FunctionResumeDownloadNumberMapper extends BaseMapper<FunctionResumeDownloadNumber> {
}
package com.bkty.system.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.bkty.system.domain.entity.FunctionResumeEdu;
import org.apache.ibatis.annotations.Mapper;
/**
* @author jiangxiaoge
* @description
* @data 2024/12/16
**/
@Mapper
public interface FunctionResumeEduMapper extends BaseMapper<FunctionResumeEdu> {
}
package com.bkty.system.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.bkty.system.domain.entity.FunctionResumeExtra;
import org.apache.ibatis.annotations.Mapper;
/**
* @author jiangxiaoge
* @description
* @data 2024/12/16
**/
@Mapper
public interface FunctionResumeExtraMapper extends BaseMapper<FunctionResumeExtra> {
}
package com.bkty.system.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.bkty.system.domain.entity.FunctionResumeInternship;
import org.apache.ibatis.annotations.Mapper;
/**
* @author jiangxiaoge
* @description
* @data 2024/12/16
**/
@Mapper
public interface FunctionResumeInternshipMapper extends BaseMapper<FunctionResumeInternship> {
}
package com.bkty.system.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.bkty.system.domain.entity.FunctionResumeModelCustom;
import org.apache.ibatis.annotations.Mapper;
/**
* @author jiangxiaoge
* @description
* @data 2024/12/16
**/
@Mapper
public interface FunctionResumeModelCustomMapper extends BaseMapper<FunctionResumeModelCustom> {
}
package com.bkty.system.mapper;
import com.github.yulichang.base.MPJBaseMapper;
import com.bkty.system.domain.entity.FunctionResumeModel;
import org.apache.ibatis.annotations.*;
import java.util.List;
import java.util.Map;
/**
* @author jiangxiaoge
* @description 个人简历模块Mapper
* @data 2024/12/16
**/
@Mapper
public interface FunctionResumeModelMapper extends MPJBaseMapper<FunctionResumeModel> {
@Select("""
select t1.*
from function_resume_model t1
inner join function_resume_base t2 on t1.resume_id = t2.id
where t2.is_deleted = false
and t1.is_deleted = false
and t1.model_type = #{modelType}
and t2.id = #{resumeId}
""")
List<FunctionResumeModel> selectResumeModelByResumeId(@Param("resumeId") Long resumeId,
@Param("modelType") Integer modelType);
/**
* 查询最大排序
* @param resumeId
* @return
*/
@Select("select max(data_sort) from function_resume_model where resume_id = #{resumeId} and is_deleted = 0")
int selectResumeModelMaxSort(@Param("resumeId") Long resumeId);
@Update({
"<script>",
"UPDATE function_resume_model",
"SET is_show = 0, data_sort = CASE id",
"<foreach collection='updates' index='id' item='dataSort'>",
"WHEN #{id} THEN #{dataSort}",
"</foreach>",
"END",
"WHERE id IN",
"<foreach collection='updates.keySet()' item='id' open='(' separator=',' close=')'>",
"#{id}",
"</foreach>",
"</script>"
})
void updateDataSortByIds(@Param("updates") Map<Long, Integer> updates);
@Insert({
"<script>",
"INSERT INTO function_resume_model (id, resume_id, platform_custom_id, model_type, model_name, is_show, data_sort, create_by, create_time, update_by, update_time, is_deleted) ",
"VALUES ",
"<foreach collection='models' item='item' separator=','>",
"(#{item.id}, #{item.resumeId}, #{item.platformCustomId}, #{item.modelType}, #{item.modelName}, #{item.isShow}, #{item.dataSort}, #{item.createBy}, #{item.createTime}, #{item.updateBy}, #{item.updateTime}, #{item.isDeleted})",
"</foreach>",
"</script>"
})
void insertBatch(@Param("models") List<FunctionResumeModel> models);
}
package com.bkty.system.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.bkty.system.domain.entity.FunctionResumeModelOptimization;
import org.apache.ibatis.annotations.Delete;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
/**
* @author jiangxiaoge
* @description 简历模块优化建议
* @data 2025/5/19
**/
@Mapper
public interface FunctionResumeModelOptimizationMapper extends BaseMapper<FunctionResumeModelOptimization> {
@Delete("delete from function_resume_model_optimization where resume_id = #{resumeId} and model_code = #{modelCode}")
int deleteData(@Param("resumeId") Long resumeId, @Param("modelCode") String modelCode);
}
package com.bkty.system.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.bkty.system.domain.entity.FunctionResumeProject;
import org.apache.ibatis.annotations.Mapper;
/**
* @author jiangxiaoge
* @description
* @data 2024/12/16
**/
@Mapper
public interface FunctionResumeProjectMapper extends BaseMapper<FunctionResumeProject> {
}
package com.bkty.system.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.bkty.system.domain.entity.FunctionResumeSketch;
import org.apache.ibatis.annotations.Mapper;
/**
* @author jiangxiaoge
* @description
* @data 2025/3/16
**/
@Mapper
public interface FunctionResumeSketchMapper extends BaseMapper<FunctionResumeSketch> {
}
package com.bkty.system.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.bkty.system.domain.entity.FunctionResumeTemplate;
import org.apache.ibatis.annotations.Mapper;
/**
* @author jiangxiaoge
* @description 简历模版Mapper
* @data 2025/1/7
**/
@Mapper
public interface FunctionResumeTemplateMapper extends BaseMapper<FunctionResumeTemplate> {
}
package com.bkty.system.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.bkty.system.domain.entity.FunctionResumeWorkExp;
import org.apache.ibatis.annotations.Mapper;
/**
* @author jiangxiaoge
* @description
* @data 2024/12/16
**/
@Mapper
public interface FunctionResumeWorkExpMapper extends BaseMapper<FunctionResumeWorkExp> {
}
/*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.alibaba.nacos.console.controller;
import com.alibaba.nacos.console.paramcheck.ConsoleDefaultHttpParamExtractor;
import com.alibaba.nacos.core.cluster.health.ModuleHealthCheckerHolder;
import com.alibaba.nacos.core.cluster.health.ReadinessResult;
import com.alibaba.nacos.core.paramcheck.ExtractorManager;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
/**
* Health Controller.
*
* @author <a href="mailto:huangxiaoyu1018@gmail.com">hxy1991</a>
*/
@RestController("consoleHealth")
@RequestMapping("/v1/console/health")
@ExtractorManager.Extractor(httpExtractor = ConsoleDefaultHttpParamExtractor.class)
public class HealthController {
/**
* Whether the Nacos is in broken states or not, and cannot recover except by being restarted.
*
* @return HTTP code equal to 200 indicates that Nacos is in right states. HTTP code equal to 500 indicates that
* Nacos is in broken states.
*/
@GetMapping("/liveness")
public ResponseEntity<String> liveness() {
return ResponseEntity.ok().body("OK");
}
/**
* Ready to receive the request or not.
*
* @return HTTP code equal to 200 indicates that Nacos is ready. HTTP code equal to 500 indicates that Nacos is not
* ready.
*/
@GetMapping("/readiness")
public ResponseEntity<String> readiness(HttpServletRequest request) {
ReadinessResult result = ModuleHealthCheckerHolder.getInstance().checkReadiness();
if (result.isSuccess()) {
return ResponseEntity.ok().body("OK");
}
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(result.getResultMessage());
}
}
/*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.alibaba.nacos.console.controller.v2;
import com.alibaba.nacos.api.model.v2.Result;
import com.alibaba.nacos.console.paramcheck.ConsoleDefaultHttpParamExtractor;
import com.alibaba.nacos.core.cluster.health.ModuleHealthCheckerHolder;
import com.alibaba.nacos.core.cluster.health.ReadinessResult;
import com.alibaba.nacos.core.paramcheck.ExtractorManager;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
/**
* Health ControllerV2.
*
* @author DiligenceLai
*/
@RestController("consoleHealthV2")
@RequestMapping("/v2/console/health")
@ExtractorManager.Extractor(httpExtractor = ConsoleDefaultHttpParamExtractor.class)
public class HealthControllerV2 {
/**
* Whether the Nacos is in broken states or not, and cannot recover except by being restarted.
*
* @return HTTP code equal to 200 indicates that Nacos is in right states. HTTP code equal to 500 indicates that
* Nacos is in broken states.
*/
@GetMapping("/liveness")
public Result<String> liveness() {
return Result.success("ok");
}
/**
* Ready to receive the request or not.
*
* @return HTTP code equal to 200 indicates that Nacos is ready. HTTP code equal to 500 indicates that Nacos is not
* ready.
*/
@GetMapping("/readiness")
public Result<String> readiness(HttpServletRequest request) {
ReadinessResult result = ModuleHealthCheckerHolder.getInstance().checkReadiness();
if (result.isSuccess()) {
return Result.success("ok");
}
return Result.failure(result.getResultMessage());
}
}
/*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*!
* Font Awesome 4.5.0 by @davegandy - http://fontawesome.io - @fontawesome
* License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License)
*/
/* FONT PATH
* -------------------------- */
@font-face {
font-family: 'FontAwesome';
src: url('../fonts/fontawesome-webfont.eot?v=4.5.0');
src: url('../fonts/fontawesome-webfont.eot?#iefix&v=4.5.0') format('embedded-opentype'), url('../fonts/fontawesome-webfont.woff2?v=4.5.0') format('woff2'), url('../fonts/fontawesome-webfont.woff?v=4.5.0') format('woff'), url('../fonts/fontawesome-webfont.ttf?v=4.5.0') format('truetype'), url('../fonts/fontawesome-webfont.svg?v=4.5.0#fontawesomeregular') format('svg');
font-weight: normal;
font-style: normal;
}
.fa {
display: inline-block;
font: normal normal normal 14px/1 FontAwesome;
font-size: inherit;
text-rendering: auto;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
/* makes the font 33% larger relative to the icon container */
.fa-lg {
font-size: 1.33333333em;
line-height: 0.75em;
vertical-align: -15%;
}
.fa-2x {
font-size: 2em;
}
.fa-3x {
font-size: 3em;
}
.fa-4x {
font-size: 4em;
}
.fa-5x {
font-size: 5em;
}
.fa-fw {
width: 1.28571429em;
text-align: center;
}
.fa-ul {
padding-left: 0;
margin-left: 2.14285714em;
list-style-type: none;
}
.fa-ul > li {
position: relative;
}
.fa-li {
position: absolute;
left: -2.14285714em;
width: 2.14285714em;
top: 0.14285714em;
text-align: center;
}
.fa-li.fa-lg {
left: -1.85714286em;
}
.fa-border {
padding: .2em .25em .15em;
border: solid 0.08em #eeeeee;
border-radius: .1em;
}
.fa-pull-left {
float: left;
}
.fa-pull-right {
float: right;
}
.fa.fa-pull-left {
margin-right: .3em;
}
.fa.fa-pull-right {
margin-left: .3em;
}
/* Deprecated as of 4.4.0 */
.pull-right {
float: right;
}
.pull-left {
float: left;
}
.fa.pull-left {
margin-right: .3em;
}
.fa.pull-right {
margin-left: .3em;
}
.fa-spin {
-webkit-animation: fa-spin 2s infinite linear;
animation: fa-spin 2s infinite linear;
}
.fa-pulse {
-webkit-animation: fa-spin 1s infinite steps(8);
animation: fa-spin 1s infinite steps(8);
}
@-webkit-keyframes fa-spin {
0% {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(359deg);
transform: rotate(359deg);
}
}
@keyframes fa-spin {
0% {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(359deg);
transform: rotate(359deg);
}
}
.fa-rotate-90 {
filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=1);
-webkit-transform: rotate(90deg);
-ms-transform: rotate(90deg);
transform: rotate(90deg);
}
.fa-rotate-180 {
filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=2);
-webkit-transform: rotate(180deg);
-ms-transform: rotate(180deg);
transform: rotate(180deg);
}
.fa-rotate-270 {
filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=3);
-webkit-transform: rotate(270deg);
-ms-transform: rotate(270deg);
transform: rotate(270deg);
}
.fa-flip-horizontal {
filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1);
-webkit-transform: scale(-1, 1);
-ms-transform: scale(-1, 1);
transform: scale(-1, 1);
}
.fa-flip-vertical {
filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1);
-webkit-transform: scale(1, -1);
-ms-transform: scale(1, -1);
transform: scale(1, -1);
}
:root .fa-rotate-90,
:root .fa-rotate-180,
:root .fa-rotate-270,
:root .fa-flip-horizontal,
:root .fa-flip-vertical {
filter: none;
}
.fa-stack {
position: relative;
display: inline-block;
width: 2em;
height: 2em;
line-height: 2em;
vertical-align: middle;
}
.fa-stack-1x,
.fa-stack-2x {
position: absolute;
left: 0;
width: 100%;
text-align: center;
}
.fa-stack-1x {
line-height: inherit;
}
.fa-stack-2x {
font-size: 2em;
}
.fa-inverse {
color: #ffffff;
}
/* Font Awesome uses the Unicode Private Use Area (PUA) to ensure screen
readers do not read off random characters that represent icons */
.fa-glass:before {
content: "\f000";
}
.fa-music:before {
content: "\f001";
}
.fa-search:before {
content: "\f002";
}
.fa-envelope-o:before {
content: "\f003";
}
.fa-heart:before {
content: "\f004";
}
.fa-star:before {
content: "\f005";
}
.fa-star-o:before {
content: "\f006";
}
.fa-user:before {
content: "\f007";
}
.fa-film:before {
content: "\f008";
}
.fa-th-large:before {
content: "\f009";
}
.fa-th:before {
content: "\f00a";
}
.fa-th-list:before {
content: "\f00b";
}
.fa-check:before {
content: "\f00c";
}
.fa-remove:before,
.fa-close:before,
.fa-times:before {
content: "\f00d";
}
.fa-search-plus:before {
content: "\f00e";
}
.fa-search-minus:before {
content: "\f010";
}
.fa-power-off:before {
content: "\f011";
}
.fa-signal:before {
content: "\f012";
}
.fa-gear:before,
.fa-cog:before {
content: "\f013";
}
.fa-trash-o:before {
content: "\f014";
}
.fa-home:before {
content: "\f015";
}
.fa-file-o:before {
content: "\f016";
}
.fa-clock-o:before {
content: "\f017";
}
.fa-road:before {
content: "\f018";
}
.fa-download:before {
content: "\f019";
}
.fa-arrow-circle-o-down:before {
content: "\f01a";
}
.fa-arrow-circle-o-up:before {
content: "\f01b";
}
.fa-inbox:before {
content: "\f01c";
}
.fa-play-circle-o:before {
content: "\f01d";
}
.fa-rotate-right:before,
.fa-repeat:before {
content: "\f01e";
}
.fa-refresh:before {
content: "\f021";
}
.fa-list-alt:before {
content: "\f022";
}
.fa-lock:before {
content: "\f023";
}
.fa-flag:before {
content: "\f024";
}
.fa-headphones:before {
content: "\f025";
}
.fa-volume-off:before {
content: "\f026";
}
.fa-volume-down:before {
content: "\f027";
}
.fa-volume-up:before {
content: "\f028";
}
.fa-qrcode:before {
content: "\f029";
}
.fa-barcode:before {
content: "\f02a";
}
.fa-tag:before {
content: "\f02b";
}
.fa-tags:before {
content: "\f02c";
}
.fa-book:before {
content: "\f02d";
}
.fa-bookmark:before {
content: "\f02e";
}
.fa-print:before {
content: "\f02f";
}
.fa-camera:before {
content: "\f030";
}
.fa-font:before {
content: "\f031";
}
.fa-bold:before {
content: "\f032";
}
.fa-italic:before {
content: "\f033";
}
.fa-text-height:before {
content: "\f034";
}
.fa-text-width:before {
content: "\f035";
}
.fa-align-left:before {
content: "\f036";
}
.fa-align-center:before {
content: "\f037";
}
.fa-align-right:before {
content: "\f038";
}
.fa-align-justify:before {
content: "\f039";
}
.fa-list:before {
content: "\f03a";
}
.fa-dedent:before,
.fa-outdent:before {
content: "\f03b";
}
.fa-indent:before {
content: "\f03c";
}
.fa-video-camera:before {
content: "\f03d";
}
.fa-photo:before,
.fa-image:before,
.fa-picture-o:before {
content: "\f03e";
}
.fa-pencil:before {
content: "\f040";
}
.fa-map-marker:before {
content: "\f041";
}
.fa-adjust:before {
content: "\f042";
}
.fa-tint:before {
content: "\f043";
}
.fa-edit:before,
.fa-pencil-square-o:before {
content: "\f044";
}
.fa-share-square-o:before {
content: "\f045";
}
.fa-check-square-o:before {
content: "\f046";
}
.fa-arrows:before {
content: "\f047";
}
.fa-step-backward:before {
content: "\f048";
}
.fa-fast-backward:before {
content: "\f049";
}
.fa-backward:before {
content: "\f04a";
}
.fa-play:before {
content: "\f04b";
}
.fa-pause:before {
content: "\f04c";
}
.fa-stop:before {
content: "\f04d";
}
.fa-forward:before {
content: "\f04e";
}
.fa-fast-forward:before {
content: "\f050";
}
.fa-step-forward:before {
content: "\f051";
}
.fa-eject:before {
content: "\f052";
}
.fa-chevron-left:before {
content: "\f053";
}
.fa-chevron-right:before {
content: "\f054";
}
.fa-plus-circle:before {
content: "\f055";
}
.fa-minus-circle:before {
content: "\f056";
}
.fa-times-circle:before {
content: "\f057";
}
.fa-check-circle:before {
content: "\f058";
}
.fa-question-circle:before {
content: "\f059";
}
.fa-info-circle:before {
content: "\f05a";
}
.fa-crosshairs:before {
content: "\f05b";
}
.fa-times-circle-o:before {
content: "\f05c";
}
.fa-check-circle-o:before {
content: "\f05d";
}
.fa-ban:before {
content: "\f05e";
}
.fa-arrow-left:before {
content: "\f060";
}
.fa-arrow-right:before {
content: "\f061";
}
.fa-arrow-up:before {
content: "\f062";
}
.fa-arrow-down:before {
content: "\f063";
}
.fa-mail-forward:before,
.fa-share:before {
content: "\f064";
}
.fa-expand:before {
content: "\f065";
}
.fa-compress:before {
content: "\f066";
}
.fa-plus:before {
content: "\f067";
}
.fa-minus:before {
content: "\f068";
}
.fa-asterisk:before {
content: "\f069";
}
.fa-exclamation-circle:before {
content: "\f06a";
}
.fa-gift:before {
content: "\f06b";
}
.fa-leaf:before {
content: "\f06c";
}
.fa-fire:before {
content: "\f06d";
}
.fa-eye:before {
content: "\f06e";
}
.fa-eye-slash:before {
content: "\f070";
}
.fa-warning:before,
.fa-exclamation-triangle:before {
content: "\f071";
}
.fa-plane:before {
content: "\f072";
}
.fa-calendar:before {
content: "\f073";
}
.fa-random:before {
content: "\f074";
}
.fa-comment:before {
content: "\f075";
}
.fa-magnet:before {
content: "\f076";
}
.fa-chevron-up:before {
content: "\f077";
}
.fa-chevron-down:before {
content: "\f078";
}
.fa-retweet:before {
content: "\f079";
}
.fa-shopping-cart:before {
content: "\f07a";
}
.fa-folder:before {
content: "\f07b";
}
.fa-folder-open:before {
content: "\f07c";
}
.fa-arrows-v:before {
content: "\f07d";
}
.fa-arrows-h:before {
content: "\f07e";
}
.fa-bar-chart-o:before,
.fa-bar-chart:before {
content: "\f080";
}
.fa-twitter-square:before {
content: "\f081";
}
.fa-facebook-square:before {
content: "\f082";
}
.fa-camera-retro:before {
content: "\f083";
}
.fa-key:before {
content: "\f084";
}
.fa-gears:before,
.fa-cogs:before {
content: "\f085";
}
.fa-comments:before {
content: "\f086";
}
.fa-thumbs-o-up:before {
content: "\f087";
}
.fa-thumbs-o-down:before {
content: "\f088";
}
.fa-star-half:before {
content: "\f089";
}
.fa-heart-o:before {
content: "\f08a";
}
.fa-sign-out:before {
content: "\f08b";
}
.fa-linkedin-square:before {
content: "\f08c";
}
.fa-thumb-tack:before {
content: "\f08d";
}
.fa-external-link:before {
content: "\f08e";
}
.fa-sign-in:before {
content: "\f090";
}
.fa-trophy:before {
content: "\f091";
}
.fa-github-square:before {
content: "\f092";
}
.fa-upload:before {
content: "\f093";
}
.fa-lemon-o:before {
content: "\f094";
}
.fa-phone:before {
content: "\f095";
}
.fa-square-o:before {
content: "\f096";
}
.fa-bookmark-o:before {
content: "\f097";
}
.fa-phone-square:before {
content: "\f098";
}
.fa-twitter:before {
content: "\f099";
}
.fa-facebook-f:before,
.fa-facebook:before {
content: "\f09a";
}
.fa-github:before {
content: "\f09b";
}
.fa-unlock:before {
content: "\f09c";
}
.fa-credit-card:before {
content: "\f09d";
}
.fa-feed:before,
.fa-rss:before {
content: "\f09e";
}
.fa-hdd-o:before {
content: "\f0a0";
}
.fa-bullhorn:before {
content: "\f0a1";
}
.fa-bell:before {
content: "\f0f3";
}
.fa-certificate:before {
content: "\f0a3";
}
.fa-hand-o-right:before {
content: "\f0a4";
}
.fa-hand-o-left:before {
content: "\f0a5";
}
.fa-hand-o-up:before {
content: "\f0a6";
}
.fa-hand-o-down:before {
content: "\f0a7";
}
.fa-arrow-circle-left:before {
content: "\f0a8";
}
.fa-arrow-circle-right:before {
content: "\f0a9";
}
.fa-arrow-circle-up:before {
content: "\f0aa";
}
.fa-arrow-circle-down:before {
content: "\f0ab";
}
.fa-globe:before {
content: "\f0ac";
}
.fa-wrench:before {
content: "\f0ad";
}
.fa-tasks:before {
content: "\f0ae";
}
.fa-filter:before {
content: "\f0b0";
}
.fa-briefcase:before {
content: "\f0b1";
}
.fa-arrows-alt:before {
content: "\f0b2";
}
.fa-group:before,
.fa-users:before {
content: "\f0c0";
}
.fa-chain:before,
.fa-link:before {
content: "\f0c1";
}
.fa-cloud:before {
content: "\f0c2";
}
.fa-flask:before {
content: "\f0c3";
}
.fa-cut:before,
.fa-scissors:before {
content: "\f0c4";
}
.fa-copy:before,
.fa-files-o:before {
content: "\f0c5";
}
.fa-paperclip:before {
content: "\f0c6";
}
.fa-save:before,
.fa-floppy-o:before {
content: "\f0c7";
}
.fa-square:before {
content: "\f0c8";
}
.fa-navicon:before,
.fa-reorder:before,
.fa-bars:before {
content: "\f0c9";
}
.fa-list-ul:before {
content: "\f0ca";
}
.fa-list-ol:before {
content: "\f0cb";
}
.fa-strikethrough:before {
content: "\f0cc";
}
.fa-underline:before {
content: "\f0cd";
}
.fa-table:before {
content: "\f0ce";
}
.fa-magic:before {
content: "\f0d0";
}
.fa-truck:before {
content: "\f0d1";
}
.fa-pinterest:before {
content: "\f0d2";
}
.fa-pinterest-square:before {
content: "\f0d3";
}
.fa-google-plus-square:before {
content: "\f0d4";
}
.fa-google-plus:before {
content: "\f0d5";
}
.fa-money:before {
content: "\f0d6";
}
.fa-caret-down:before {
content: "\f0d7";
}
.fa-caret-up:before {
content: "\f0d8";
}
.fa-caret-left:before {
content: "\f0d9";
}
.fa-caret-right:before {
content: "\f0da";
}
.fa-columns:before {
content: "\f0db";
}
.fa-unsorted:before,
.fa-sort:before {
content: "\f0dc";
}
.fa-sort-down:before,
.fa-sort-desc:before {
content: "\f0dd";
}
.fa-sort-up:before,
.fa-sort-asc:before {
content: "\f0de";
}
.fa-envelope:before {
content: "\f0e0";
}
.fa-linkedin:before {
content: "\f0e1";
}
.fa-rotate-left:before,
.fa-undo:before {
content: "\f0e2";
}
.fa-legal:before,
.fa-gavel:before {
content: "\f0e3";
}
.fa-dashboard:before,
.fa-tachometer:before {
content: "\f0e4";
}
.fa-comment-o:before {
content: "\f0e5";
}
.fa-comments-o:before {
content: "\f0e6";
}
.fa-flash:before,
.fa-bolt:before {
content: "\f0e7";
}
.fa-sitemap:before {
content: "\f0e8";
}
.fa-umbrella:before {
content: "\f0e9";
}
.fa-paste:before,
.fa-clipboard:before {
content: "\f0ea";
}
.fa-lightbulb-o:before {
content: "\f0eb";
}
.fa-exchange:before {
content: "\f0ec";
}
.fa-cloud-download:before {
content: "\f0ed";
}
.fa-cloud-upload:before {
content: "\f0ee";
}
.fa-user-md:before {
content: "\f0f0";
}
.fa-stethoscope:before {
content: "\f0f1";
}
.fa-suitcase:before {
content: "\f0f2";
}
.fa-bell-o:before {
content: "\f0a2";
}
.fa-coffee:before {
content: "\f0f4";
}
.fa-cutlery:before {
content: "\f0f5";
}
.fa-file-text-o:before {
content: "\f0f6";
}
.fa-building-o:before {
content: "\f0f7";
}
.fa-hospital-o:before {
content: "\f0f8";
}
.fa-ambulance:before {
content: "\f0f9";
}
.fa-medkit:before {
content: "\f0fa";
}
.fa-fighter-jet:before {
content: "\f0fb";
}
.fa-beer:before {
content: "\f0fc";
}
.fa-h-square:before {
content: "\f0fd";
}
.fa-plus-square:before {
content: "\f0fe";
}
.fa-angle-double-left:before {
content: "\f100";
}
.fa-angle-double-right:before {
content: "\f101";
}
.fa-angle-double-up:before {
content: "\f102";
}
.fa-angle-double-down:before {
content: "\f103";
}
.fa-angle-left:before {
content: "\f104";
}
.fa-angle-right:before {
content: "\f105";
}
.fa-angle-up:before {
content: "\f106";
}
.fa-angle-down:before {
content: "\f107";
}
.fa-desktop:before {
content: "\f108";
}
.fa-laptop:before {
content: "\f109";
}
.fa-tablet:before {
content: "\f10a";
}
.fa-mobile-phone:before,
.fa-mobile:before {
content: "\f10b";
}
.fa-circle-o:before {
content: "\f10c";
}
.fa-quote-left:before {
content: "\f10d";
}
.fa-quote-right:before {
content: "\f10e";
}
.fa-spinner:before {
content: "\f110";
}
.fa-circle:before {
content: "\f111";
}
.fa-mail-reply:before,
.fa-reply:before {
content: "\f112";
}
.fa-github-alt:before {
content: "\f113";
}
.fa-folder-o:before {
content: "\f114";
}
.fa-folder-open-o:before {
content: "\f115";
}
.fa-smile-o:before {
content: "\f118";
}
.fa-frown-o:before {
content: "\f119";
}
.fa-meh-o:before {
content: "\f11a";
}
.fa-gamepad:before {
content: "\f11b";
}
.fa-keyboard-o:before {
content: "\f11c";
}
.fa-flag-o:before {
content: "\f11d";
}
.fa-flag-checkered:before {
content: "\f11e";
}
.fa-terminal:before {
content: "\f120";
}
.fa-code:before {
content: "\f121";
}
.fa-mail-reply-all:before,
.fa-reply-all:before {
content: "\f122";
}
.fa-star-half-empty:before,
.fa-star-half-full:before,
.fa-star-half-o:before {
content: "\f123";
}
.fa-location-arrow:before {
content: "\f124";
}
.fa-crop:before {
content: "\f125";
}
.fa-code-fork:before {
content: "\f126";
}
.fa-unlink:before,
.fa-chain-broken:before {
content: "\f127";
}
.fa-question:before {
content: "\f128";
}
.fa-info:before {
content: "\f129";
}
.fa-exclamation:before {
content: "\f12a";
}
.fa-superscript:before {
content: "\f12b";
}
.fa-subscript:before {
content: "\f12c";
}
.fa-eraser:before {
content: "\f12d";
}
.fa-puzzle-piece:before {
content: "\f12e";
}
.fa-microphone:before {
content: "\f130";
}
.fa-microphone-slash:before {
content: "\f131";
}
.fa-shield:before {
content: "\f132";
}
.fa-calendar-o:before {
content: "\f133";
}
.fa-fire-extinguisher:before {
content: "\f134";
}
.fa-rocket:before {
content: "\f135";
}
.fa-maxcdn:before {
content: "\f136";
}
.fa-chevron-circle-left:before {
content: "\f137";
}
.fa-chevron-circle-right:before {
content: "\f138";
}
.fa-chevron-circle-up:before {
content: "\f139";
}
.fa-chevron-circle-down:before {
content: "\f13a";
}
.fa-html5:before {
content: "\f13b";
}
.fa-css3:before {
content: "\f13c";
}
.fa-anchor:before {
content: "\f13d";
}
.fa-unlock-alt:before {
content: "\f13e";
}
.fa-bullseye:before {
content: "\f140";
}
.fa-ellipsis-h:before {
content: "\f141";
}
.fa-ellipsis-v:before {
content: "\f142";
}
.fa-rss-square:before {
content: "\f143";
}
.fa-play-circle:before {
content: "\f144";
}
.fa-ticket:before {
content: "\f145";
}
.fa-minus-square:before {
content: "\f146";
}
.fa-minus-square-o:before {
content: "\f147";
}
.fa-level-up:before {
content: "\f148";
}
.fa-level-down:before {
content: "\f149";
}
.fa-check-square:before {
content: "\f14a";
}
.fa-pencil-square:before {
content: "\f14b";
}
.fa-external-link-square:before {
content: "\f14c";
}
.fa-share-square:before {
content: "\f14d";
}
.fa-compass:before {
content: "\f14e";
}
.fa-toggle-down:before,
.fa-caret-square-o-down:before {
content: "\f150";
}
.fa-toggle-up:before,
.fa-caret-square-o-up:before {
content: "\f151";
}
.fa-toggle-right:before,
.fa-caret-square-o-right:before {
content: "\f152";
}
.fa-euro:before,
.fa-eur:before {
content: "\f153";
}
.fa-gbp:before {
content: "\f154";
}
.fa-dollar:before,
.fa-usd:before {
content: "\f155";
}
.fa-rupee:before,
.fa-inr:before {
content: "\f156";
}
.fa-cny:before,
.fa-rmb:before,
.fa-yen:before,
.fa-jpy:before {
content: "\f157";
}
.fa-ruble:before,
.fa-rouble:before,
.fa-rub:before {
content: "\f158";
}
.fa-won:before,
.fa-krw:before {
content: "\f159";
}
.fa-bitcoin:before,
.fa-btc:before {
content: "\f15a";
}
.fa-file:before {
content: "\f15b";
}
.fa-file-text:before {
content: "\f15c";
}
.fa-sort-alpha-asc:before {
content: "\f15d";
}
.fa-sort-alpha-desc:before {
content: "\f15e";
}
.fa-sort-amount-asc:before {
content: "\f160";
}
.fa-sort-amount-desc:before {
content: "\f161";
}
.fa-sort-numeric-asc:before {
content: "\f162";
}
.fa-sort-numeric-desc:before {
content: "\f163";
}
.fa-thumbs-up:before {
content: "\f164";
}
.fa-thumbs-down:before {
content: "\f165";
}
.fa-youtube-square:before {
content: "\f166";
}
.fa-youtube:before {
content: "\f167";
}
.fa-xing:before {
content: "\f168";
}
.fa-xing-square:before {
content: "\f169";
}
.fa-youtube-play:before {
content: "\f16a";
}
.fa-dropbox:before {
content: "\f16b";
}
.fa-stack-overflow:before {
content: "\f16c";
}
.fa-instagram:before {
content: "\f16d";
}
.fa-flickr:before {
content: "\f16e";
}
.fa-adn:before {
content: "\f170";
}
.fa-bitbucket:before {
content: "\f171";
}
.fa-bitbucket-square:before {
content: "\f172";
}
.fa-tumblr:before {
content: "\f173";
}
.fa-tumblr-square:before {
content: "\f174";
}
.fa-long-arrow-down:before {
content: "\f175";
}
.fa-long-arrow-up:before {
content: "\f176";
}
.fa-long-arrow-left:before {
content: "\f177";
}
.fa-long-arrow-right:before {
content: "\f178";
}
.fa-apple:before {
content: "\f179";
}
.fa-windows:before {
content: "\f17a";
}
.fa-android:before {
content: "\f17b";
}
.fa-linux:before {
content: "\f17c";
}
.fa-dribbble:before {
content: "\f17d";
}
.fa-skype:before {
content: "\f17e";
}
.fa-foursquare:before {
content: "\f180";
}
.fa-trello:before {
content: "\f181";
}
.fa-female:before {
content: "\f182";
}
.fa-male:before {
content: "\f183";
}
.fa-gittip:before,
.fa-gratipay:before {
content: "\f184";
}
.fa-sun-o:before {
content: "\f185";
}
.fa-moon-o:before {
content: "\f186";
}
.fa-archive:before {
content: "\f187";
}
.fa-bug:before {
content: "\f188";
}
.fa-vk:before {
content: "\f189";
}
.fa-weibo:before {
content: "\f18a";
}
.fa-renren:before {
content: "\f18b";
}
.fa-pagelines:before {
content: "\f18c";
}
.fa-stack-exchange:before {
content: "\f18d";
}
.fa-arrow-circle-o-right:before {
content: "\f18e";
}
.fa-arrow-circle-o-left:before {
content: "\f190";
}
.fa-toggle-left:before,
.fa-caret-square-o-left:before {
content: "\f191";
}
.fa-dot-circle-o:before {
content: "\f192";
}
.fa-wheelchair:before {
content: "\f193";
}
.fa-vimeo-square:before {
content: "\f194";
}
.fa-turkish-lira:before,
.fa-try:before {
content: "\f195";
}
.fa-plus-square-o:before {
content: "\f196";
}
.fa-space-shuttle:before {
content: "\f197";
}
.fa-slack:before {
content: "\f198";
}
.fa-envelope-square:before {
content: "\f199";
}
.fa-wordpress:before {
content: "\f19a";
}
.fa-openid:before {
content: "\f19b";
}
.fa-institution:before,
.fa-bank:before,
.fa-university:before {
content: "\f19c";
}
.fa-mortar-board:before,
.fa-graduation-cap:before {
content: "\f19d";
}
.fa-yahoo:before {
content: "\f19e";
}
.fa-google:before {
content: "\f1a0";
}
.fa-reddit:before {
content: "\f1a1";
}
.fa-reddit-square:before {
content: "\f1a2";
}
.fa-stumbleupon-circle:before {
content: "\f1a3";
}
.fa-stumbleupon:before {
content: "\f1a4";
}
.fa-delicious:before {
content: "\f1a5";
}
.fa-digg:before {
content: "\f1a6";
}
.fa-pied-piper:before {
content: "\f1a7";
}
.fa-pied-piper-alt:before {
content: "\f1a8";
}
.fa-drupal:before {
content: "\f1a9";
}
.fa-joomla:before {
content: "\f1aa";
}
.fa-language:before {
content: "\f1ab";
}
.fa-fax:before {
content: "\f1ac";
}
.fa-building:before {
content: "\f1ad";
}
.fa-child:before {
content: "\f1ae";
}
.fa-paw:before {
content: "\f1b0";
}
.fa-spoon:before {
content: "\f1b1";
}
.fa-cube:before {
content: "\f1b2";
}
.fa-cubes:before {
content: "\f1b3";
}
.fa-behance:before {
content: "\f1b4";
}
.fa-behance-square:before {
content: "\f1b5";
}
.fa-steam:before {
content: "\f1b6";
}
.fa-steam-square:before {
content: "\f1b7";
}
.fa-recycle:before {
content: "\f1b8";
}
.fa-automobile:before,
.fa-car:before {
content: "\f1b9";
}
.fa-cab:before,
.fa-taxi:before {
content: "\f1ba";
}
.fa-tree:before {
content: "\f1bb";
}
.fa-spotify:before {
content: "\f1bc";
}
.fa-deviantart:before {
content: "\f1bd";
}
.fa-soundcloud:before {
content: "\f1be";
}
.fa-database:before {
content: "\f1c0";
}
.fa-file-pdf-o:before {
content: "\f1c1";
}
.fa-file-word-o:before {
content: "\f1c2";
}
.fa-file-excel-o:before {
content: "\f1c3";
}
.fa-file-powerpoint-o:before {
content: "\f1c4";
}
.fa-file-photo-o:before,
.fa-file-picture-o:before,
.fa-file-image-o:before {
content: "\f1c5";
}
.fa-file-zip-o:before,
.fa-file-archive-o:before {
content: "\f1c6";
}
.fa-file-sound-o:before,
.fa-file-audio-o:before {
content: "\f1c7";
}
.fa-file-movie-o:before,
.fa-file-video-o:before {
content: "\f1c8";
}
.fa-file-code-o:before {
content: "\f1c9";
}
.fa-vine:before {
content: "\f1ca";
}
.fa-codepen:before {
content: "\f1cb";
}
.fa-jsfiddle:before {
content: "\f1cc";
}
.fa-life-bouy:before,
.fa-life-buoy:before,
.fa-life-saver:before,
.fa-support:before,
.fa-life-ring:before {
content: "\f1cd";
}
.fa-circle-o-notch:before {
content: "\f1ce";
}
.fa-ra:before,
.fa-rebel:before {
content: "\f1d0";
}
.fa-ge:before,
.fa-empire:before {
content: "\f1d1";
}
.fa-git-square:before {
content: "\f1d2";
}
.fa-git:before {
content: "\f1d3";
}
.fa-y-combinator-square:before,
.fa-yc-square:before,
.fa-hacker-news:before {
content: "\f1d4";
}
.fa-tencent-weibo:before {
content: "\f1d5";
}
.fa-qq:before {
content: "\f1d6";
}
.fa-wechat:before,
.fa-weixin:before {
content: "\f1d7";
}
.fa-send:before,
.fa-paper-plane:before {
content: "\f1d8";
}
.fa-send-o:before,
.fa-paper-plane-o:before {
content: "\f1d9";
}
.fa-history:before {
content: "\f1da";
}
.fa-circle-thin:before {
content: "\f1db";
}
.fa-header:before {
content: "\f1dc";
}
.fa-paragraph:before {
content: "\f1dd";
}
.fa-sliders:before {
content: "\f1de";
}
.fa-share-alt:before {
content: "\f1e0";
}
.fa-share-alt-square:before {
content: "\f1e1";
}
.fa-bomb:before {
content: "\f1e2";
}
.fa-soccer-ball-o:before,
.fa-futbol-o:before {
content: "\f1e3";
}
.fa-tty:before {
content: "\f1e4";
}
.fa-binoculars:before {
content: "\f1e5";
}
.fa-plug:before {
content: "\f1e6";
}
.fa-slideshare:before {
content: "\f1e7";
}
.fa-twitch:before {
content: "\f1e8";
}
.fa-yelp:before {
content: "\f1e9";
}
.fa-newspaper-o:before {
content: "\f1ea";
}
.fa-wifi:before {
content: "\f1eb";
}
.fa-calculator:before {
content: "\f1ec";
}
.fa-paypal:before {
content: "\f1ed";
}
.fa-google-wallet:before {
content: "\f1ee";
}
.fa-cc-visa:before {
content: "\f1f0";
}
.fa-cc-mastercard:before {
content: "\f1f1";
}
.fa-cc-discover:before {
content: "\f1f2";
}
.fa-cc-amex:before {
content: "\f1f3";
}
.fa-cc-paypal:before {
content: "\f1f4";
}
.fa-cc-stripe:before {
content: "\f1f5";
}
.fa-bell-slash:before {
content: "\f1f6";
}
.fa-bell-slash-o:before {
content: "\f1f7";
}
.fa-trash:before {
content: "\f1f8";
}
.fa-copyright:before {
content: "\f1f9";
}
.fa-at:before {
content: "\f1fa";
}
.fa-eyedropper:before {
content: "\f1fb";
}
.fa-paint-brush:before {
content: "\f1fc";
}
.fa-birthday-cake:before {
content: "\f1fd";
}
.fa-area-chart:before {
content: "\f1fe";
}
.fa-pie-chart:before {
content: "\f200";
}
.fa-line-chart:before {
content: "\f201";
}
.fa-lastfm:before {
content: "\f202";
}
.fa-lastfm-square:before {
content: "\f203";
}
.fa-toggle-off:before {
content: "\f204";
}
.fa-toggle-on:before {
content: "\f205";
}
.fa-bicycle:before {
content: "\f206";
}
.fa-bus:before {
content: "\f207";
}
.fa-ioxhost:before {
content: "\f208";
}
.fa-angellist:before {
content: "\f209";
}
.fa-cc:before {
content: "\f20a";
}
.fa-shekel:before,
.fa-sheqel:before,
.fa-ils:before {
content: "\f20b";
}
.fa-meanpath:before {
content: "\f20c";
}
.fa-buysellads:before {
content: "\f20d";
}
.fa-connectdevelop:before {
content: "\f20e";
}
.fa-dashcube:before {
content: "\f210";
}
.fa-forumbee:before {
content: "\f211";
}
.fa-leanpub:before {
content: "\f212";
}
.fa-sellsy:before {
content: "\f213";
}
.fa-shirtsinbulk:before {
content: "\f214";
}
.fa-simplybuilt:before {
content: "\f215";
}
.fa-skyatlas:before {
content: "\f216";
}
.fa-cart-plus:before {
content: "\f217";
}
.fa-cart-arrow-down:before {
content: "\f218";
}
.fa-diamond:before {
content: "\f219";
}
.fa-ship:before {
content: "\f21a";
}
.fa-user-secret:before {
content: "\f21b";
}
.fa-motorcycle:before {
content: "\f21c";
}
.fa-street-view:before {
content: "\f21d";
}
.fa-heartbeat:before {
content: "\f21e";
}
.fa-venus:before {
content: "\f221";
}
.fa-mars:before {
content: "\f222";
}
.fa-mercury:before {
content: "\f223";
}
.fa-intersex:before,
.fa-transgender:before {
content: "\f224";
}
.fa-transgender-alt:before {
content: "\f225";
}
.fa-venus-double:before {
content: "\f226";
}
.fa-mars-double:before {
content: "\f227";
}
.fa-venus-mars:before {
content: "\f228";
}
.fa-mars-stroke:before {
content: "\f229";
}
.fa-mars-stroke-v:before {
content: "\f22a";
}
.fa-mars-stroke-h:before {
content: "\f22b";
}
.fa-neuter:before {
content: "\f22c";
}
.fa-genderless:before {
content: "\f22d";
}
.fa-facebook-official:before {
content: "\f230";
}
.fa-pinterest-p:before {
content: "\f231";
}
.fa-whatsapp:before {
content: "\f232";
}
.fa-server:before {
content: "\f233";
}
.fa-user-plus:before {
content: "\f234";
}
.fa-user-times:before {
content: "\f235";
}
.fa-hotel:before,
.fa-bed:before {
content: "\f236";
}
.fa-viacoin:before {
content: "\f237";
}
.fa-train:before {
content: "\f238";
}
.fa-subway:before {
content: "\f239";
}
.fa-medium:before {
content: "\f23a";
}
.fa-yc:before,
.fa-y-combinator:before {
content: "\f23b";
}
.fa-optin-monster:before {
content: "\f23c";
}
.fa-opencart:before {
content: "\f23d";
}
.fa-expeditedssl:before {
content: "\f23e";
}
.fa-battery-4:before,
.fa-battery-full:before {
content: "\f240";
}
.fa-battery-3:before,
.fa-battery-three-quarters:before {
content: "\f241";
}
.fa-battery-2:before,
.fa-battery-half:before {
content: "\f242";
}
.fa-battery-1:before,
.fa-battery-quarter:before {
content: "\f243";
}
.fa-battery-0:before,
.fa-battery-empty:before {
content: "\f244";
}
.fa-mouse-pointer:before {
content: "\f245";
}
.fa-i-cursor:before {
content: "\f246";
}
.fa-object-group:before {
content: "\f247";
}
.fa-object-ungroup:before {
content: "\f248";
}
.fa-sticky-note:before {
content: "\f249";
}
.fa-sticky-note-o:before {
content: "\f24a";
}
.fa-cc-jcb:before {
content: "\f24b";
}
.fa-cc-diners-club:before {
content: "\f24c";
}
.fa-clone:before {
content: "\f24d";
}
.fa-balance-scale:before {
content: "\f24e";
}
.fa-hourglass-o:before {
content: "\f250";
}
.fa-hourglass-1:before,
.fa-hourglass-start:before {
content: "\f251";
}
.fa-hourglass-2:before,
.fa-hourglass-half:before {
content: "\f252";
}
.fa-hourglass-3:before,
.fa-hourglass-end:before {
content: "\f253";
}
.fa-hourglass:before {
content: "\f254";
}
.fa-hand-grab-o:before,
.fa-hand-rock-o:before {
content: "\f255";
}
.fa-hand-stop-o:before,
.fa-hand-paper-o:before {
content: "\f256";
}
.fa-hand-scissors-o:before {
content: "\f257";
}
.fa-hand-lizard-o:before {
content: "\f258";
}
.fa-hand-spock-o:before {
content: "\f259";
}
.fa-hand-pointer-o:before {
content: "\f25a";
}
.fa-hand-peace-o:before {
content: "\f25b";
}
.fa-trademark:before {
content: "\f25c";
}
.fa-registered:before {
content: "\f25d";
}
.fa-creative-commons:before {
content: "\f25e";
}
.fa-gg:before {
content: "\f260";
}
.fa-gg-circle:before {
content: "\f261";
}
.fa-tripadvisor:before {
content: "\f262";
}
.fa-odnoklassniki:before {
content: "\f263";
}
.fa-odnoklassniki-square:before {
content: "\f264";
}
.fa-get-pocket:before {
content: "\f265";
}
.fa-wikipedia-w:before {
content: "\f266";
}
.fa-safari:before {
content: "\f267";
}
.fa-chrome:before {
content: "\f268";
}
.fa-firefox:before {
content: "\f269";
}
.fa-opera:before {
content: "\f26a";
}
.fa-internet-explorer:before {
content: "\f26b";
}
.fa-tv:before,
.fa-television:before {
content: "\f26c";
}
.fa-contao:before {
content: "\f26d";
}
.fa-500px:before {
content: "\f26e";
}
.fa-amazon:before {
content: "\f270";
}
.fa-calendar-plus-o:before {
content: "\f271";
}
.fa-calendar-minus-o:before {
content: "\f272";
}
.fa-calendar-times-o:before {
content: "\f273";
}
.fa-calendar-check-o:before {
content: "\f274";
}
.fa-industry:before {
content: "\f275";
}
.fa-map-pin:before {
content: "\f276";
}
.fa-map-signs:before {
content: "\f277";
}
.fa-map-o:before {
content: "\f278";
}
.fa-map:before {
content: "\f279";
}
.fa-commenting:before {
content: "\f27a";
}
.fa-commenting-o:before {
content: "\f27b";
}
.fa-houzz:before {
content: "\f27c";
}
.fa-vimeo:before {
content: "\f27d";
}
.fa-black-tie:before {
content: "\f27e";
}
.fa-fonticons:before {
content: "\f280";
}
.fa-reddit-alien:before {
content: "\f281";
}
.fa-edge:before {
content: "\f282";
}
.fa-credit-card-alt:before {
content: "\f283";
}
.fa-codiepie:before {
content: "\f284";
}
.fa-modx:before {
content: "\f285";
}
.fa-fort-awesome:before {
content: "\f286";
}
.fa-usb:before {
content: "\f287";
}
.fa-product-hunt:before {
content: "\f288";
}
.fa-mixcloud:before {
content: "\f289";
}
.fa-scribd:before {
content: "\f28a";
}
.fa-pause-circle:before {
content: "\f28b";
}
.fa-pause-circle-o:before {
content: "\f28c";
}
.fa-stop-circle:before {
content: "\f28d";
}
.fa-stop-circle-o:before {
content: "\f28e";
}
.fa-shopping-bag:before {
content: "\f290";
}
.fa-shopping-basket:before {
content: "\f291";
}
.fa-hashtag:before {
content: "\f292";
}
.fa-bluetooth:before {
content: "\f293";
}
.fa-bluetooth-b:before {
content: "\f294";
}
.fa-percent:before {
content: "\f295";
}
/*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
@font-face {
/*无边框*/
font-family: "iconfont-1";
src: url('icon1/iconfont.eot?t=1458627591'); /* IE9*/
src: url('icon1/iconfont.eot?t=1458627591#iefix') format('embedded-opentype'), /* IE6-IE8 */ url('icon1/iconfont.woff?t=1458627591') format('woff'), /* chrome, firefox */ url('icon1/iconfont.ttf?t=1458627591') format('truetype'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+*/ url('icon1/iconfont.svg?t=1458627591#iconfont') format('svg'); /* iOS 4.1- */
}
@font-face {
/*有边框*/
font-family: "iconfont-2";
src: url('icon/iconfont.eot'); /* IE9*/
src: url('icon/iconfont.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */ url('icon/iconfont.woff') format('woff'), /* chrome, firefox */ url('icon/iconfont.ttf') format('truetype'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+*/ url('icon/iconfont.svg#iconfont') format('svg'); /* iOS 4.1- */
}
.iconfont {
/* 有边框 */
font-family: "iconfont" !important;
font-size: 16px;
font-style: normal;
-webkit-font-smoothing: antialiased;
-webkit-text-stroke-width: 0.2px;
-moz-osx-font-smoothing: grayscale;
}
.iconfont-1 {
/*无边框*/
font-family: "iconfont-1" !important;
font-size: 16px;
font-style: normal;
-webkit-font-smoothing: antialiased;
-webkit-text-stroke-width: 0.2px;
-moz-osx-font-smoothing: grayscale;
}
.iconfont-2 {
/*有边框*/
font-family: "iconfont-2" !important;
font-size: 16px;
font-style: normal;
-webkit-font-smoothing: antialiased;
-webkit-text-stroke-width: 0.2px;
-moz-osx-font-smoothing: grayscale;
}
.logo {
}
.panel-logo {
padding-right: 2px;
font-size: 18px;
display: inline-block;
color: #333;
}
.icon-lg {
font-size: 80px !important;
}
.icon-size-md {
font-size: 40px !important;
vertical-align: middle;
}
.icon-size-lg {
font-size: 80px !important;
vertical-align: middle;
}
.icon-hsf:before {
content: "\e62f" !important;
}
.icon-rocketmq:before {
content: "\e632" !important;
}
.icon-notify:before {
content: "\e61e" !important;
}
.icon-tddl:before {
content: "\e61e" !important;
}
.icon-pandora:before {
content: "\e622" !important;
}
.icon-ailtomcat:before {
content: "\e628" !important;
}
.icon-configserver:before {
content: "\e61e" !important;
}
.icon-diamondserver:before {
content: "\e62a" !important;
}
.icon-vipserver:before {
content: "\e625" !important;
}
.icon-eagleeye:before {
content: "\e62c" !important;
}
.icon-tengine:before {
content: "\e635" !important;
}
.icon-tair:before {
content: "\e634" !important;
}
.icon-hbase:before {
content: "\e62d" !important;
}
.icon-jstorm:before {
content: "\e627" !important;
}
.icon-histore:before {
content: "\e62e" !important;
}
.icon-jingwei:before {
content: "\e61e" !important;
}
.icon-txc:before {
content: "\e636" !important;
}
.icon-edas:before {
content: "\e620" !important;
}
.icon-csb:before {
content: "\e61e" !important;
}
.icon-ons:before {
content: "\e630" !important;
}
.icon-drds:before {
content: "\e61f" !important;
}
.icon-duct:before {
content: "\e62b" !important;
}
.icon-amazon:before {
content: "\e61e" !important;
}
.icon-autoload:before {
content: "\e61e" !important;
}
.icon-switch:before {
content: "\e633" !important;
}
.icon-sentinel:before {
content: "\e623" !important;
}
.icon-preplan:before {
content: "\e631" !important;
}
.icon-moses:before {
content: "\e61e" !important;
}
.icon-zeus:before {
content: "\e61e" !important;
}
.icon-athena:before {
content: "\e61e" !important;
}
.icon-bcp:before {
content: "\e61e" !important;
}
.icon-lark:before {
content: "\e61e" !important;
}
.icon-nest:before {
content: "\e61e" !important;
}
.icon-monkeyking:before {
content: "\e61e" !important;
}
.icon-tab:before {
content: "\e61e" !important;
}
.icon-oceanus:before {
content: "\e61e" !important;
}
.icon-eos :before {
content: "\e61e" !important;
}
.icon-sonar:before {
content: "\e61e" !important;
}
.icon-ai:before {
content: "\e605" !important;
}
.icon-hotcode:before {
content: "\e621" !important;
}
.icon-taokeeper:before {
content: "\e624" !important;
}
.icon-mdl:before {
content: "\e61e" !important;
}
.icon-mw:before {
content: "\e61e" !important;
}
.icon-default:before {
content: "\e607" !important;
}
.icon-alitomcat:before {
content: "\e607" !important;
}
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
<!--
2013-9-30: Created.
-->
<svg>
<metadata>
Created by iconfont
</metadata>
<defs>
<font id="iconfont" horiz-adv-x="1024" >
<font-face
font-family="iconfont"
font-weight="500"
font-stretch="normal"
units-per-em="1024"
ascent="896"
descent="-128"
/>
<missing-glyph />
<glyph glyph-name="x" unicode="x" horiz-adv-x="1001"
d="M281 543q-27 -1 -53 -1h-83q-18 0 -36.5 -6t-32.5 -18.5t-23 -32t-9 -45.5v-76h912v41q0 16 -0.5 30t-0.5 18q0 13 -5 29t-17 29.5t-31.5 22.5t-49.5 9h-133v-97h-438v97zM955 310v-52q0 -23 0.5 -52t0.5 -58t-10.5 -47.5t-26 -30t-33 -16t-31.5 -4.5q-14 -1 -29.5 -0.5
t-29.5 0.5h-32l-45 128h-439l-44 -128h-29h-34q-20 0 -45 1q-25 0 -41 9.5t-25.5 23t-13.5 29.5t-4 30v167h911zM163 247q-12 0 -21 -8.5t-9 -21.5t9 -21.5t21 -8.5q13 0 22 8.5t9 21.5t-9 21.5t-22 8.5zM316 123q-8 -26 -14 -48q-5 -19 -10.5 -37t-7.5 -25t-3 -15t1 -14.5
t9.5 -10.5t21.5 -4h37h67h81h80h64h36q23 0 34 12t2 38q-5 13 -9.5 30.5t-9.5 34.5q-5 19 -11 39h-368zM336 498v228q0 11 2.5 23t10 21.5t20.5 15.5t34 6h188q31 0 51.5 -14.5t20.5 -52.5v-227h-327z" />
<glyph glyph-name="upload" unicode="&#59374;" d="M546.443364 882.023649A47.689428 47.689428 0 0 1 512.720297 896c-12.637659 0-24.775805-5.027091-33.719072-13.976351L215.553499 618.5519449999999c-18.630806-18.630806-18.630806-48.817327 0-67.45013 18.630806-18.629807 48.818326-18.629807 67.449131 0l182.022244 182.052214v-584.293401c0-26.331286 21.364137-47.695422 47.695423-47.695422 26.333284 0 47.695422 21.36114 47.695422 47.695422V733.159024l182.058209-182.057209c18.629807-18.629807 48.812332-18.629807 67.444136 0 18.630806 18.631805 18.630806 48.818326 0 67.45013L546.443364 882.023649zM931.211614 268.88741500000003v-263.925261c0-24.33024-19.656804-43.987044-43.988043-43.987044H136.278915c-24.33024 0-43.987044 19.656804-43.987044 43.987044V268.88741500000003c0 24.332238-19.656804 43.988043-43.987044 43.988043-24.33024 0-43.988043-19.655805-43.988043-43.988043v-307.912305c0-48.522615 39.451473-87.976086 87.975087-87.976086h838.920742c48.524613 0 87.976086 39.452472 87.976086 87.976086V268.88741500000003c0 24.332238-19.658802 43.988043-43.988043 43.988043-24.331239 0-43.989042-19.655805-43.989042-43.988043z" horiz-adv-x="1024" />
<glyph glyph-name="loading" unicode="&#58950;" d="M814.161762 173.760115c0-2.759851 2.510165-5.268993 5.265923-5.268993s5.2649 2.509142 5.2649 5.268993c0 2.755758-2.506072 5.270016-5.2649 5.270016C816.673974 179.031155 814.161762 176.516897 814.161762 173.760115M697.949203 53.731654c0-2.749618 1.129728-5.474677 3.067866-7.413839 1.937115-1.940185 4.66115-3.069912 7.400536-3.069912 2.746548 0 5.468537 1.129728 7.404629 3.069912s3.067866 4.666267 3.067866 7.413839c0 2.743478-1.130751 5.469561-3.067866 7.405652-1.937115 1.940185-4.66115 3.070936-7.404629 3.070936-2.742455 0-5.464444-1.129728-7.400536-3.070936C699.077907 59.201215 697.949203 56.475133 697.949203 53.731654M541.301803-8.05238c0-4.121869 1.692545-8.222249 4.606915-11.137642 2.912324-2.916417 7.007587-4.613055 11.126386-4.613055 4.114706 0 8.209969 1.696638 11.124339 4.613055 2.91437 2.915394 4.608962 7.013727 4.608962 11.137642 0 4.119823-1.694592 8.219179-4.608962 11.135596-2.91437 2.91744-7.009633 4.614078-11.124339 4.614078-4.118799 0-8.214062-1.696638-11.126386-4.614078C542.994348 0.166799 541.301803-3.931535 541.301803-8.05238M372.673558 0.225127c0-5.48491 2.259456-10.937075 6.133685-14.819491 3.87423-3.878323 9.324347-6.135732 14.808234-6.135732 5.480817 0 10.931958 2.257409 14.806188 6.135732 3.879346 3.882416 6.134708 9.33458 6.134708 14.819491 0 5.492073-2.255362 10.942191-6.134708 14.826654-3.87423 3.877299-9.324347 6.134708-14.806188 6.134708-5.482864 0-10.934005-2.257409-14.808234-6.134708C374.933014 11.167318 372.673558 5.7172 372.673558 0.225127M223.080817 77.065036c0-6.870464 2.824319-13.694879 7.674781-18.550458 4.850462-4.853532 11.669761-7.681944 18.533062-7.681944 6.856138 0 13.675437 2.828413 18.525898 7.681944 4.850462 4.855578 7.674781 11.679994 7.674781 18.550458 0 6.865348-2.824319 13.690786-7.674781 18.544318-4.850462 4.854555-11.669761 7.682968-18.525898 7.682968-6.863301 0-13.6826-2.828413-18.533062-7.682968C225.904113 90.755822 223.080817 83.930383 223.080817 77.065036M119.476388 207.691858c0-8.248855 3.390207-16.441428 9.214854-22.274262 5.826694-5.830787 14.018244-9.22918 22.252772-9.22918 8.240668 0 16.427102 3.39737 22.252772 9.22918 5.824647 5.830787 9.218947 14.025407 9.218947 22.274262 0 8.242715-3.393277 16.437335-9.218947 22.269145-5.825671 5.830787-14.012104 9.22918-22.252772 9.22918-8.234529 0-16.426078-3.396346-22.252772-9.22918C122.865571 224.129192 119.476388 215.934572 119.476388 207.691858M80.602087 368.079434c0-9.613943 3.955071-19.16444 10.742647-25.96225 6.787576-6.792693 16.329888-10.74674 25.933597-10.74674s19.144997 3.954047 25.933597 10.74674c6.787576 6.799856 10.742647 16.350354 10.742647 25.96225 0 9.609849-3.955071 19.160347-10.742647 25.958156-6.7886 6.79474-16.329888 10.748787-25.933597 10.748787s-19.146021-3.954047-25.933597-10.748787C84.55818 387.238758 80.602087 377.68826 80.602087 368.079434M112.591598 527.425287c0-10.990287 4.518911-21.916105 12.287836-29.686053 7.762785-7.770972 18.672231-12.293976 29.653308-12.293976s21.891546 4.523004 29.654331 12.293976c7.767902 7.769948 12.286813 18.695767 12.286813 29.686053 0 10.986193-4.518911 21.910989-12.286813 29.680937-7.762785 7.771995-18.673254 12.294999-29.654331 12.294999s-21.890522-4.523004-29.653308-12.294999C117.110509 549.337299 112.591598 538.41148 112.591598 527.425287M208.560131 655.90624c0-12.367654 5.089915-24.65856 13.827909-33.405764 8.739017-8.746181 21.021737-13.839165 33.378135-13.839165 12.357421 0 24.635024 5.095031 33.373018 13.839165 8.740041 8.747204 13.827909 21.03811 13.827909 33.405764 0 12.370724-5.087868 24.6647-13.827909 33.409857-8.737994 8.747204-21.015597 13.839165-33.373018 13.839165-12.356398 0-24.639117-5.092985-33.378135-13.839165C213.650046 680.569916 208.560131 668.276964 208.560131 655.90624M349.477299 729.503298c0-13.733765 5.648639-27.385666 15.348539-37.093752 9.703993-9.714226 23.338498-15.364912 37.059983-15.364912s27.357013 5.649662 37.05896 15.364912c9.705017 9.708087 15.354679 23.359987 15.354679 37.093752 0 13.734788-5.649662 27.379526-15.354679 37.094776-9.700923 9.708087-23.337475 15.363889-37.05896 15.363889s-27.354967-5.654779-37.059983-15.363889C355.125938 756.8818 349.477299 743.237063 349.477299 729.503298M507.749706 734.073374c0-15.112156 6.21248-30.131191 16.890658-40.817556 10.675109-10.686365 25.680841-16.911124 40.778671-16.911124 15.103969 0 30.109701 6.224759 40.783787 16.911124 10.675109 10.685342 16.890658 25.7054 16.890658 40.817556 0 15.113179-6.213503 30.132214-16.890658 40.822673-10.677156 10.686365-25.680841 16.906008-40.783787 16.906008-15.097829 0-30.103562-6.219643-40.778671-16.906008C513.962186 764.207635 507.749706 749.186553 507.749706 734.073374M652.653668 668.817268c0-16.477243 6.77939-32.852157 18.417428-44.500428 11.642131-11.655434 28.002718-18.435848 44.465635-18.435848 16.460871 0 32.821457 6.780413 44.459496 18.435848 11.642131 11.648271 18.417428 28.024208 18.417428 44.500428 0 16.478267-6.775297 32.85318-18.417428 44.507591-11.638038 11.649294-27.998625 18.434824-44.459496 18.434824-16.462917 0-32.823504-6.78553-44.465635-18.434824C659.433058 701.670448 652.653668 685.295535 652.653668 668.817268M755.621601 546.241804c0-17.856657 7.345277-35.601775 19.958524-48.232418 12.61734-12.625527 30.347108-19.97592 48.187393-19.97592s35.572099 7.351417 48.185346 19.97592c12.613247 12.630643 19.956478 30.37576 19.956478 48.232418 0 17.858704-7.343231 35.604845-19.956478 48.230371-12.613247 12.62962-30.345061 19.980014-48.185346 19.980014s-35.570052-7.351417-48.187393-19.980014C762.966879 581.846648 755.621601 564.099484 755.621601 546.241804M796.580373 387.472071c0-19.233002 7.909118-38.352416 21.501667-51.954175 13.590502-13.602782 32.687405-21.523156 51.90915-21.523156 19.214582 0 38.315577 7.920374 51.905057 21.523156 13.590502 13.600735 21.501667 32.721174 21.501667 51.954175 0 19.239141-7.910141 38.357533-21.501667 51.959292-13.588456 13.601759-32.689451 21.517016-51.905057 21.517016-19.220722 0-38.317624-7.915258-51.90915-21.517016C804.488468 425.830627 796.580373 406.712236 796.580373 387.472071" horiz-adv-x="1024" />
<glyph glyph-name="minus-font" unicode="&#58881;" d="M970.74 330.304H54.264C24.842 330.304 1 354.13 1 383.549c0 29.419 23.842 53.248 53.264 53.248H970.74c29.42 0 53.26-23.829 53.26-53.248s-23.84-53.245-53.26-53.245z" horiz-adv-x="1024" />
<glyph glyph-name="email" unicode="&#58885;" d="M1024.512 584.249v197.659c0 26.512-21.51 48.023-48.023 48.023h-928.442c-26.512 0-48.023-21.51-48.023-48.023v-197.66c-0.023-0.874-0.025-1.748 0-2.62v-595.537c0-26.512 21.51-48.023 48.023-48.023h928.442c26.512 0 48.023 21.51 48.023 48.023v595.537c0.025 0.872 0.023 1.746 0 2.621zM928.466 733.885v-123.066l-416.198-237.793-416.198 237.793v123.066h832.396zM96.070 34.115v466.063l392.374-224.199c7.378-4.19 15.601-6.315 23.824-6.315 8.223 0 16.446 2.126 23.824 6.315l392.374 224.199v-466.063h-832.396z" horiz-adv-x="1025" />
<glyph glyph-name="atm" unicode="&#58886;" d="M512.202-128c-282.422 0-512.199 214.896-512.199 479.061 0 145.306 68.714 279.796 186.479 369.893-27.917 24.134-58.241 43.080-90.598 56.585-17.944 7.441-29.605 25.009-29.574 44.392 0.032 19.445 11.755 36.889 29.667 44.33 122.672 50.645 263.352 35.701 373.551-37.953 14.099 1.125 28.574 1.813 42.673 1.813 282.423 0 512.199-214.896 512.199-479.061s-229.776-479.060-512.198-479.060zM241.409 800.299c19.789-16.381 38.577-34.701 56.272-54.897 9.41-10.755 13.536-25.135 11.286-39.203-2.251-14.131-10.66-26.448-22.946-33.763-118.953-70.465-189.98-190.636-189.98-321.375 0-211.208 186.698-383.024 416.162-383.024s416.162 171.817 416.162 383.024-186.698 383.024-416.162 383.024c-16.788 0-34.201-1.188-50.364-3.002-11.974-1.188-24.072 1.876-33.794 9.004-55.084 40.579-119.235 62.399-186.635 60.211zM384.139 384.22c0-53.040 28.665-96.037 64.025-96.037s64.025 42.997 64.025 96.037c0 53.040-28.665 96.037-64.025 96.037-35.36 0-64.025-42.997-64.025-96.037zM640.239 384.22c-0-0-0-0-0-0 0-53.040 28.665-96.037 64.025-96.037 35.36 0 64.025 42.997 64.025 96.037 0 0 0 0 0 0 0 53.040-28.665 96.037-64.025 96.037-35.36 0-64.025-42.997-64.025-96.037z" horiz-adv-x="1024" />
<glyph glyph-name="calendar" unicode="&#58887;" d="M975.99 763.408h-84.562v84.593c0 26.499-21.499 48-47.999 48s-48-21.499-48-48v-84.593h-235.434v84.593c0 26.499-21.499 48-48 48s-47.999-21.499-47.999-48v-84.593h-235.402v84.593c0 26.499-21.499 48-48 48s-48-21.499-48-48v-84.593h-84.593c-26.499 0-48-21.499-48-48v-795.396c0-26.499 21.499-48 48-48h927.988c26.499 0 47.999 21.499 47.999 48v795.397c0.001 26.499-21.499 47.999-47.999 47.999zM927.991-31.988h-831.989v699.397h831.989v-699.397zM478.872 468.568h66.281c26.499 0 48 21.499 48 48s-21.499 48-48 48h-66.281c-26.499 0-48-21.499-48-48s21.5-48 48-48zM478.872 269.695h66.281c26.499 0 48 21.499 48 48s-21.499 48-48 48h-66.281c-26.499 0-48-21.499-48-48s21.5-48 48-48zM478.872 70.855h66.281c26.499 0 48 21.499 48 48s-21.499 48-48 48h-66.281c-26.499 0-48-21.499-48-48s21.5-48 48-48zM213.719 468.568h66.281c26.499 0 48 21.499 48 48s-21.499 48-48 48h-66.281c-26.499 0-48-21.499-48-48s21.5-48 48-48zM213.719 269.695h66.281c26.499 0 48 21.499 48 48s-21.499 48-48 48h-66.281c-26.499 0-48-21.499-48-48s21.5-48 48-48zM213.719 70.855h66.281c26.499 0 48 21.499 48 48s-21.499 48-48 48h-66.281c-26.499 0-48-21.499-48-48s21.5-48 48-48zM743.993 468.568h66.312c26.499 0 48 21.499 48 48s-21.499 48-48 48h-66.312c-26.499 0-47.999-21.499-47.999-48s21.499-48 47.999-48zM743.993 269.695h66.312c26.499 0 48 21.499 48 48s-21.499 48-48 48h-66.312c-26.499 0-47.999-21.499-47.999-48s21.499-48 47.999-48z" horiz-adv-x="1024" />
<glyph glyph-name="account" unicode="&#58888;" d="M680.049 469.398c48.199 45.082 78.797 108.735 78.797 179.789 0 136.062-110.719 246.813-246.844 246.813s-246.875-110.75-246.875-246.813c0-71.055 30.614-134.707 78.82-179.793-199.898-69.765-343.945-259.699-343.945-483.081v-66.312c0-26.5 21.5-48 48-48s48 21.5 48 48v66.312c0 229.375 186.625 416 416 416s416-186.625 416-416v-66.312c0-26.5 21.5-48 48-48s47.999 21.5 47.999 48v66.312c-0.001 223.386-144.052 413.32-343.955 483.085zM361.128 649.187c0 83.188 67.688 150.813 150.875 150.813s150.844-67.625 150.844-150.813-67.656-150.875-150.844-150.875-150.875 67.688-150.875 150.875z" horiz-adv-x="1024" />
<glyph glyph-name="success" unicode="&#58890;" d="M512.00307-128c-282.311999 0-512 229.686977-512 512S229.690047 896 512.00307 896 1024.00307 666.311999 1024.00307 384 794.31507-128 512.00307-128z m0 928.000064c-229.374854 0-416.000064-186.62521-416.000064-416.000064s186.62521-416.000064 416.000064-416.000064 416.000064 186.62521 416.000064 416.000064S741.377924 800.000064 512.00307 800.000064zM463.99645 160.006972a47.919635 47.919635 0 0 0-33.937531 14.062948L302.058663 302.069152c-18.749916 18.749916-18.749916 49.125147 0 67.875063s49.125147 18.749916 67.875063 0l85.687585-85.687585 191.875022 301.500935c14.187798 22.37464 43.81291 28.937417 66.249975 14.749619 22.37464-14.250222 28.999842-43.875335 14.74962-66.249974L504.495736 182.256762a47.87563 47.87563 0 0 0-35.250497-21.937667c-1.748914-0.187274-3.498852-0.312123-5.248789-0.312123z" horiz-adv-x="1024" />
<glyph glyph-name="warning" unicode="&#58891;" d="M1007.756059 120.994577L605.837042 764.028349c-20.264738 32.46126-55.290831 51.850577-93.568784 51.850577s-73.304046-19.389316-93.568784-51.850577L16.779433 120.994577c-21.265074-34.024733-22.391348-76.931672-2.939575-112.019198 19.389316-35.08855 56.416081-56.854304 96.508359-56.854305h803.839058c40.092278 0 77.119043 21.765754 96.508359 56.854305 19.451773 35.087526 18.326523 77.994465-2.939575 112.019198z m-81.058953-65.423201c-1.501016-2.752204-5.191099-7.380165-12.508807-7.380165H110.348217c-7.317708 0-11.007791 4.627962-12.508807 7.380165-1.501016 2.752204-3.502712 8.255587 0.375766 14.510503l401.920041 643.033772c3.627626 5.816693 9.19449 6.692114 12.134065 6.692115s8.506439-0.875422 12.134065-6.692115l401.920041-643.033772c3.87643-6.253892 1.874734-11.758299 0.373718-14.510503zM512.268258 271.918345c26.519654 0 48.03558 21.515926 48.03558 48.03558V501.773433c0 26.519654-21.515926 48.03558-48.03558 48.03558s-48.03558-21.515926-48.03558-48.03558v-181.820532c0-26.519654 21.515926-48.034556 48.03558-48.034556zM512.268258 159.825428m-64.047099 0a64.047099 64.047099 0 1 1 128.094198 0 64.047099 64.047099 0 1 1-128.094198 0Z" horiz-adv-x="1024" />
<glyph glyph-name="prompt" unicode="&#58892;" d="M512.00307 896c-282.313023 0-512-229.686977-512-512s229.686977-512 512-512S1024.00307 101.688001 1024.00307 384 794.31507 896 512.00307 896z m0-928.000064c-229.374854 0-416.000064 186.62521-416.000064 416.000064S282.628216 800.000064 512.00307 800.000064s416.000064-186.62521 416.000064-416.000064-186.62521-416.000064-416.000064-416.000064zM512.00307 501.679718c-26.499785 0-48.00048-21.499671-48.00048-48.00048v-309.687777c0-26.499785 21.499671-48.00048 48.00048-48.000479 26.499785 0 48.00048 21.499671 48.00048 47.999456v309.687777c-0.001023 26.501832-21.500695 48.001503-48.00048 48.001503zM512.00307 613.690047m-63.999616 0a63.999616 63.999616 0 1 1 127.999232 0 63.999616 63.999616 0 1 1-127.999232 0Z" horiz-adv-x="1024" />
<glyph glyph-name="error" unicode="&#58893;" d="M512.00307-128c-282.311999 0-512 229.686977-512 512S229.690047 896 512.00307 896 1024.00307 666.311999 1024.00307 384 794.31507-128 512.00307-128z m0 928.000064c-229.374854 0-416.000064-186.62521-416.000064-416.000064s186.62521-416.000064 416.000064-416.000064 416.000064 186.62521 416.000064 416.000064S741.377924 800.000064 512.00307 800.000064zM579.878133 384l126.062021 126.062021c18.749916 18.749916 18.749916 49.125147 0 67.875063-18.749916 18.749916-49.125147 18.749916-67.875063 0L512.00307 451.875063 385.940026 577.937084c-18.749916 18.749916-49.125147 18.749916-67.875063 0-18.749916-18.749916-18.749916-49.125147 0-67.875063l126.062021-126.062021-126.062021-126.062021c-18.749916-18.749916-18.749916-49.125147 0-67.875063 9.374958-9.374958 21.624521-14.062948 33.937531-14.062948s24.562574 4.687991 33.937532 14.062948l126.062021 126.062021L638.065091 190.062916c9.374958-9.374958 21.624521-14.062948 33.937531-14.062948s24.562574 4.687991 33.937532 14.062948c18.749916 18.749916 18.749916 49.125147 0 67.875063L579.878133 384z" horiz-adv-x="1024" />
<glyph glyph-name="favorites-filling" unicode="&#58894;" d="M798.746-126.805c-0.007-0-0.014-0-0.022-0-8.102 0-15.734 2.012-22.424 5.563l-264.3 137.997-264.559-138.123c-15.875-8.312-35.437-7-50.187 3.562s-22.25 28.562-19.437 46.437l49.937 317.308-213.371 209.185c-13 12.75-17.687 31.75-12 49.062 5.823 17.635 21.129 30.568 39.729 32.851l293.141 43.46 133.185 288.808c15.625 33.999 71.499 33.999 87.124 0l133.185-288.808 294.308-43.624c18.693-2.862 33.662-16.179 38.889-33.697 5.36-16.302 0.673-35.302-12.327-48.052l-213.371-209.184 49.937-317.308c2.812-17.875-4.687-35.874-19.437-46.437-7.779-5.624-17.507-8.996-28.024-9z" horiz-adv-x="1024" />
<glyph glyph-name="arrow-right" unicode="&#58905;" d="M224.064 846.129c20.656 17.708 51.778 15.332 69.489-5.323l513.385-423.824c15.848-18.479 15.848-45.688 0-64.167L293.554-71.01300000000003c-17.711-20.666-48.833-23.037-69.489-5.324-20.604 17.709-23.035 48.789-5.326 69.486l485.887 391.746L218.738 776.64c-7.992 9.298-11.871 20.688-11.871 32.046 0 13.894 5.84 27.685 17.197 37.443z" horiz-adv-x="1024" />
<glyph glyph-name="arrow-left" unicode="&#58909;" d="M827.824 808.686c0-11.358-3.879-22.748-11.871-32.045L330.067 384.896 815.953-6.850000000000023c17.709-20.696 15.278-51.776-5.326-69.486-20.656-17.712-51.778-15.341-69.489 5.324L227.753 352.81399999999996c-15.848 18.479-15.848 45.688 0 64.167L741.138 840.806c17.711 20.656 48.833 23.031 69.489 5.323 11.357-9.758 17.197-23.549 17.197-37.443z" horiz-adv-x="1024" />
<glyph glyph-name="arrow-up" unicode="&#58917;" d="M936.638 78.91499999999996c-11.358 0-22.748 3.879-32.046 11.871L512.848 576.673 121.101 90.78599999999994c-20.696-17.709-51.776-15.278-69.486 5.326-17.712 20.656-15.341 51.778 5.324 69.489l423.828 513.385c18.479 15.848 45.688 15.848 64.167 0l423.824-513.385c20.655-17.711 23.031-48.833 5.323-69.489-9.758-11.357-23.549-17.197-37.443-17.197z" horiz-adv-x="1024" />
<glyph glyph-name="arrow-down" unicode="&#58941;" d="M974.081 673.675c17.708-20.656 15.332-51.778-5.323-69.489L544.934 90.80100000000004c-18.479-15.848-45.688-15.848-64.167 0L56.939 604.1859999999999c-20.665 17.711-23.036 48.833-5.324 69.489 17.71 20.604 48.79 23.035 69.486 5.326l391.747-485.887 391.744 485.887c9.298 7.992 20.688 11.871 32.046 11.871 13.894 0 27.685-5.84 37.443-17.197z" horiz-adv-x="1024" />
<glyph glyph-name="add" unicode="&#58965;" d="M970.74 330.304H54.264C24.842 330.304 1 354.13 1 383.549c0 29.419 23.842 53.248 53.264 53.248H970.74c29.42 0 53.26-23.829 53.26-53.248s-23.84-53.245-53.26-53.245zM565.497 841.7909999999999v-916.476c0-29.422-23.825-53.264-53.243-53.264-29.42 0-53.249 23.842-53.249 53.264V841.7909999999999c0 29.42 23.829 53.26 53.249 53.26 29.418 0 53.243-23.84 53.243-53.26z" horiz-adv-x="1024" />
<glyph glyph-name="arrow-double-left" unicode="&#58969;" d="M1024 808.686c0-11.357-3.88-22.748-11.871-32.046L526.241 384.895l485.888-391.746c17.709-20.697 15.277-51.777-5.326-69.486-20.656-17.713-51.778-15.342-69.489 5.324L423.929 352.81399999999996c-15.848 18.479-15.848 45.688 0 64.167L937.313 840.806c17.711 20.655 48.833 23.031 69.489 5.323C1018.159 836.371 1024 822.58 1024 808.686zM611.957 808.688c0-11.357-3.879-22.748-11.871-32.046L114.199 384.896l485.887-391.745c17.709-20.697 15.278-51.777-5.325-69.486-20.656-17.713-51.778-15.342-69.489 5.324L11.887 352.81600000000003c-15.849 18.479-15.849 45.688 0 64.167L525.272 840.808c17.711 20.655 48.833 23.031 69.489 5.323 11.356-9.758 17.196-23.549 17.196-37.443z" horiz-adv-x="1024" />
<glyph glyph-name="arrow-double-right" unicode="&#58974;" d="M17.2 846.129c20.656 17.708 51.778 15.332 69.489-5.323l513.385-423.824c15.848-18.479 15.848-45.688 0-64.167L86.69-71.01300000000003c-17.711-20.666-48.833-23.037-69.489-5.324-20.604 17.709-23.035 48.789-5.326 69.486l485.887 391.746L11.874 776.64C3.883 785.938 0.004 797.328 0.004 808.686 0.003 822.58 5.843 836.371 17.2 846.129zM429.376 846.131c20.656 17.708 51.778 15.332 69.489-5.323l513.385-423.824c15.849-18.479 15.849-45.688 0-64.167L498.865-71.01099999999997c-17.711-20.666-48.833-23.037-69.489-5.324-20.604 17.709-23.034 48.789-5.325 69.486l485.887 391.745-485.888 391.746c-7.992 9.298-11.871 20.688-11.871 32.046 0 13.894 5.84 27.685 17.197 37.443z" horiz-adv-x="1024" />
<glyph glyph-name="close" unicode="&#58918;" d="M579.87 383.992l430.070 430.070c18.75 18.75 18.75 49.125 0 67.875s-49.125 18.75-67.875 0l-430.070-430.070-430.055 430.070c-18.75 18.75-49.125 18.75-67.875 0s-18.75-49.125 0-67.875l430.055-430.070-430.055-430.054c-18.75-18.75-18.75-49.125 0-67.875 9.375-9.375 21.656-14.063 33.938-14.063s24.563 4.688 33.938 14.063l430.055 430.055 430.040-430.055c9.375-9.375 21.656-14.063 33.938-14.063s24.563 4.688 33.938 14.063c18.75 18.75 18.75 49.125 0 67.875l-430.040 430.054z" horiz-adv-x="1024" />
<glyph glyph-name="search" unicode="&#58966;" d="M1011.652-54.011999999999944L725.986 232.029c56.988 70.097 91.285 159.354 91.285 256.541C817.271 713.249 634.524 896 409.841 896 185.165 896 2.409 713.249 2.409 488.57c0-224.681 182.755-407.431 407.431-407.431 97.186 0 186.444 34.298 256.541 91.289l285.67-286.045c8.233-8.228 18.989-12.346 29.799-12.346 10.813 0 21.57 4.118 29.802 12.346 16.464 16.464 16.464 43.141 0 59.605zM86.705 488.57c0 178.199 144.941 323.134 323.135 323.134 178.199 0 323.134-144.936 323.134-323.134S588.038 165.43499999999995 409.84 165.43499999999995c-178.193 0-323.135 144.936-323.135 323.135z" horiz-adv-x="1024" />
<glyph glyph-name="ascending" unicode="&#58910;" d="M750.794525 542.875168c-20.81262-16.437641-51.03119-12.812804-67.37468 8.062243L558.857281 709.31268v-789.312762c0-26.499581-21.500336-47.999918-47.999918-47.999918s-47.999918 21.500336-47.999918 47.999918V848.000031c0 20.468762 12.968359 38.656395 32.312419 45.37493a47.762492 47.762492 0 0 0 15.687499 2.624988c14.437943 0 28.468578-6.531255 37.718972-18.344211L758.85779 610.248824c16.405916-20.810573 12.780056-50.998441-8.063265-67.373656z" horiz-adv-x="1024" />
<glyph glyph-name="descending" unicode="&#58911;" d="M269.62971 225.123808c20.81262 16.437641 51.03119 12.812804 67.37468-8.062242l124.562564-158.375269V848.000082c0 26.499581 21.500336 47.999918 47.999918 47.999918s47.999918-21.500336 47.999918-47.999918v-928.000113c0-20.468762-12.968359-38.656395-32.31242-45.37493a47.762492 47.762492 0 0 0-15.687498-2.624988c-14.437943 0-28.468578 6.531255-37.718972 18.344211L261.566445 157.749129c-16.405916 20.81262-12.781079 51.000488 8.063265 67.374679z" horiz-adv-x="1024" />
<glyph glyph-name="clock" unicode="&#58913;" d="M512.00307 896c-282.311999 0-512-229.686977-512-512s229.686977-512 512-512S1024.00307 101.688001 1024.00307 384 794.31507 896 512.00307 896z m0-928.000064c-229.374854 0-416.000064 186.62521-416.000064 416.000064S282.628216 800.000064 512.00307 800.000064s416.000064-186.62521 416.000064-416.000064-186.62521-416.000064-416.000064-416.000064zM513.565734 384l98.656566 98.624842c18.749916 18.749916 18.749916 49.125147 0 67.875063s-49.125147 18.749916-67.875063 0L411.75314 417.937531a48.017877 48.017877 0 0 1-14.062949-33.937531 48.019923 48.019923 0 0 1 14.062949-33.937531l198.874772-198.874773c9.374958-9.374958 21.656245-14.062948 33.937532-14.062949s24.562574 4.687991 33.937531 14.062949c18.749916 18.749916 18.749916 49.125147 0 67.875062L513.565734 384z" horiz-adv-x="1024" />
<glyph glyph-name="cry" unicode="&#58973;" d="M512.00307 896c-282.311999 0-512-229.686977-512-512s229.686977-512 512-512S1024.00307 101.688001 1024.00307 384 794.31507 896 512.00307 896z m0-928.000064c-229.374854 0-416.000064 186.62521-416.000064 416.000064S282.628216 800.000064 512.00307 800.000064s416.000064-186.62521 416.000064-416.000064-186.62521-416.000064-416.000064-416.000064zM710.674195 516.55828m-63.999616 0a63.999616 63.999616 0 1 1 127.999232 0 63.999616 63.999616 0 1 1-127.999232 0ZM312.963537 516.55828m-63.999616 0a63.999616 63.999616 0 1 1 127.999232 0 63.999616 63.999616 0 1 1-127.999232 0ZM512.00307 328.500373c-86.687403 0-165.468363-44.187458-210.719087-118.187302-13.84395-22.593638-6.718327-52.156326 15.906011-65.968552 22.593638-13.781526 52.156326-6.750051 65.968552 15.906011 27.687901 45.249701 75.84393 72.249907 128.843501 72.249907s101.187324-27.062631 128.875224-72.40648c9.062834-14.812044 24.843996-22.969209 40.999707-22.96921 8.531713 0 17.187252 2.281059 24.999546 7.031475 22.625362 13.812226 29.749962 43.374914 15.937735 66.000275-45.280401 74.093993-124.093085 118.343875-210.811189 118.343876z" horiz-adv-x="1024" />
<glyph glyph-name="delete-filling" unicode="&#58915;" d="M512.00307 896c-282.769439 0-512-229.230561-512-512s229.230561-512 512-512S1024.00307 101.230561 1024.00307 384 794.772509 896 512.00307 896z m237.262876-658.769615c24.999546-24.999546 24.999546-65.499855 0-90.500425-12.500285-12.500285-28.874993-18.749916-45.2497-18.749915s-32.750439 6.249631-45.249701 18.749915L512.016374 293.480132l-146.750172-146.749149c-12.500285-12.500285-28.874993-18.749916-45.2497-18.749915s-32.750439 6.249631-45.249701 18.749915c-24.999546 24.999546-24.999546 65.499855 0 90.500425l146.750171 146.750172-146.751194 146.749148c-24.999546 24.999546-24.999546 65.499855 0 90.500424s65.499855 24.999546 90.500424 0l146.750172-146.750171 146.750171 146.750171c24.999546 24.999546 65.499855 24.999546 90.500425 0s24.999546-65.499855 0-90.500424L602.515775 383.980556l146.750171-146.750171z" horiz-adv-x="1024" />
<glyph glyph-name="download" unicode="&#58920;" d="M478.996 114.37900000000002a47.736 47.736 0 0 1 33.756-13.99c12.65 0 24.8 5.032 33.752 13.99l263.705 263.729c18.649 18.649 18.649 48.865 0 67.516-18.649 18.648-48.866 18.648-67.515 0l-182.2-182.23V848.258C560.494 874.615 539.11 896 512.752 896c-26.36 0-47.743-21.382-47.743-47.742v-584.869L282.774 445.624c-18.648 18.648-48.86 18.648-67.51 0-18.649-18.65-18.649-48.866 0-67.516l263.732-263.729zM931.621 269.275v-264.183c0-24.354-19.676-44.03-44.031-44.03H135.912c-24.354 0-44.03 19.676-44.03 44.03V269.275c0 24.356-19.676 44.031-44.03 44.031-24.354 0-44.031-19.675-44.031-44.031v-308.213c0-48.57 39.49-88.062 88.061-88.062h839.74c48.572 0 88.062 39.491 88.062 88.062V269.275c0 24.356-19.678 44.031-44.031 44.031-24.355 0-44.032-19.675-44.032-44.031z" horiz-adv-x="1024" />
<glyph glyph-name="filter" unicode="&#58919;" d="M644.560784-127.988743c-26.499467 0-47.999904 21.499413-47.999904 47.999904V405.224134a48.044931 48.044931 0 0 0 15.15571 34.999355l226.966224 212.84102c16.093092 15.093286 25.312389 36.343004 25.312389 58.374555V800.000192H160.003774v-88.592852c0-22.030528 9.187574-43.280246 25.249965-58.342831l227.841182-213.810126a48.043908 48.043908 0 0 0 15.15571-34.999355v-484.243867c0-26.499467-21.499413-47.999904-47.999904-47.999904-26.499467 0-47.999904 21.499413-47.999904 47.999904V383.474002L119.567398 583.064776C84.2549 616.189366 64.006012 662.970469 64.006012 711.40734V847.999073c0 26.499467 21.499413 47.999904 47.999904 47.999904h799.990214c26.499467 0 47.998881-21.499413 47.998881-47.999904v-136.561032c0-48.468595-20.280612-95.248674-55.655533-128.404988l-211.779813-198.589945v-464.431947c0-26.500491-21.499413-47.999904-47.998881-47.999904z" horiz-adv-x="1024" />
<glyph glyph-name="help" unicode="&#58995;" d="M512.00307 896c-282.311999 0-512-229.686977-512-512s229.686977-512 512-512S1024.00307 101.688001 1024.00307 384 794.31507 896 512.00307 896z m0-928.000064c-229.374854 0-416.000064 186.62521-416.000064 416.000064S282.628216 800.000064 512.00307 800.000064s416.000064-186.62521 416.000064-416.000064-186.62521-416.000064-416.000064-416.000064zM512.00307 687.999968c-97.062179 0-175.999712-78.969257-175.999712-175.999712 0-26.499785 21.499671-48.00048 48.00048-48.00048s48.00048 21.499671 48.000479 48.00048c0 44.125033 35.874743 79.999776 79.999776 79.999776s79.999776-35.874743 79.999777-79.999776c0-30.031384-16.561982-57.281289-43.280766-71.093515-53.031294-27.499603-84.718467-76.59405-84.718467-131.343558 0-26.499785 21.499671-47.999456 48.00048-47.999456s48.00048 21.499671 48.000479 47.999456c0 18.18707 12.311987 35.43777 32.875289 46.093969 58.687379 30.375232 95.124967 90.281427 95.124967 156.344127-0.00307 97.030455-78.940603 175.998689-176.002782 175.998689zM511.99079 159.988551m-63.999616 0a63.999616 63.999616 0 1 1 127.999232 0 63.999616 63.999616 0 1 1-127.999232 0Z" horiz-adv-x="1024" />
<glyph glyph-name="picture" unicode="&#58929;" d="M976.508103 829.949158H48.027389c-26.51351 0-48.025341-21.510807-48.025341-48.025341v-795.849681c0-2.063129 0.922521-3.822164 1.176444-5.815669 0.421841-3.368583 0.860064-6.58563 1.977123-9.790391 1.015694-2.91193 2.450158-5.432736 3.974722-8.059002 1.544019-2.67746 3.056298-5.221815 5.119427-7.585966 2.180876-2.497256 4.701681-4.4324 7.351497-6.433072 1.649479-1.250164 2.755275-2.970291 4.600316-4.025917 0.7116-0.410578 1.531732-0.230374 2.254596-0.597949 6.523173-3.345033 13.612555-5.667205 21.441182-5.690754 0.034812 0 0.062457-0.027645 0.09727-0.027645 0.004096 0 0.008191 0.004096 0.011262 0.004095 0.008191 0 0.011263-0.004096 0.019454-0.004095h928.480714c26.51351 0 48.024317 21.510807 48.024318 48.025341V781.92484c0.003072 26.51351-21.508759 48.024317-48.02227 48.024318z m-48.024317-96.049659v-536.227174L606.12885 423.301838c-11.099941 7.753884-24.981778 10.693458-38.050651 7.504056a47.937287 47.937287 0 0 1-31.203929-23.011823l-22.574624-39.52095-173.46358 121.375462c-11.130657 7.753884-24.919321 10.631001-38.05065 7.504056-13.16307-2.938551-24.481098-11.318028-31.203929-23.011823L96.05273 166.94655V733.899499h832.431056zM130.789064 34.100501l198.07164 346.67938 173.464604-121.375462c11.0682-7.691427 24.856864-10.56752 38.05065-7.504056a47.937287 47.937287 0 0 1 31.203929 23.011823l22.574624 39.520949 334.329275-233.988513v-46.344121H130.789064zM777.366503 582.947062m-66.3191 0a66.3191 66.3191 0 1 1 132.6382 0 66.3191 66.3191 0 1 1-132.6382 0Z" horiz-adv-x="1024" />
<glyph glyph-name="refresh" unicode="&#58999;" d="M974.914297 431.375028c-26.470236 0-47.946957-21.475698-47.946957-47.946957 0-229.119089-186.417113-415.536202-415.536202-415.536202S95.895958 154.310004 95.895958 383.429093 282.313071 798.965296 511.43216 798.965296c95.49525 0 185.960184-32.171125 259.370496-91.082352L639.277422 576.357711h319.643311V896.001022L838.937321 776.017609C747.164975 852.858472 632.558408 894.858187 511.43216 894.858187c-281.997207 0-511.429093-229.430864-511.429093-511.429094s229.430864-511.429093 511.429093-511.429093S1022.861253 101.430864 1022.861253 383.429093c0 26.470236-21.47672 47.945934-47.946956 47.945935z" horiz-adv-x="1024" />
<glyph glyph-name="select" unicode="&#58930;" d="M384.21604-64.21604a102.513446 102.513446 0 0 0-71.722143 29.264691L30.72987 241.245812C-9.664454 280.828195-10.320764 345.734334 29.292335 386.129681c39.675556 40.394324 104.520262 41.082375 144.883869 1.438559l199.723167-195.783256 467.291024 600.856864c34.704593 44.64652 99.111076 52.776169 143.789335 17.946662 44.64652-34.704593 52.713712-99.111076 17.977379-143.757595l-537.8572-691.526005c-17.946662-23.07428-44.865631-37.330859-74.005408-39.331531-2.313981-0.126962-4.596221-0.189419-6.878461-0.189419z" horiz-adv-x="1024" />
<glyph glyph-name="semi-select" unicode="&#58931;" d="M922.077335 281.57563200000004H102.459181c-56.590142 0-102.456109 45.83525-102.456109 102.424368s45.865967 102.425392 102.456109 102.425392h819.618154c56.590142 0 102.456109-45.83525 102.456109-102.425392s-45.865967-102.424368-102.456109-102.424368z" horiz-adv-x="1024" />
<glyph glyph-name="smile" unicode="&#58975;" d="M512.00307 896c-282.311999 0-512-229.686977-512-512s229.686977-512 512-512S1024.00307 101.688001 1024.00307 384 794.31507 896 512.00307 896z m0-928.000064c-229.374854 0-416.000064 186.62521-416.000064 416.000064S282.628216 800.000064 512.00307 800.000064s416.000064-186.62521 416.000064-416.000064-186.62521-416.000064-416.000064-416.000064zM710.674195 516.55828m-63.999616 0a63.999616 63.999616 0 1 1 127.999232 0 63.999616 63.999616 0 1 1-127.999232 0ZM312.963537 516.55828m-63.999616 0a63.999616 63.999616 0 1 1 127.999232 0 63.999616 63.999616 0 1 1-127.999232 0ZM706.877547 321.468899c-22.625362 13.749802-52.187026 6.687627-66.000276-15.937736-27.687901-45.343849-75.874631-72.40648-128.875224-72.40648s-101.156623 27.030907-128.843501 72.281631c-13.812226 22.625362-43.344213 29.719261-65.968552 15.906011s-29.749962-43.374914-15.906011-65.968552c45.249701-74.031568 124.031684-118.219026 210.719087-118.219026 86.719127 0 165.530788 44.249883 210.812212 118.343876 13.812226 22.625362 6.687627 52.18805-15.937735 66.000276z" horiz-adv-x="1024" />
<glyph glyph-name="sorting" unicode="&#58932;" d="M121.218406 225.120501c20.811762 16.436964 51.029087 12.812276 67.371902-8.06191L313.148762 58.689849V847.971104c0 26.498489 21.49945 47.997939 47.99794 47.99794s47.997939-21.49945 47.997939-47.99794v-927.961867c0-20.467919-12.967825-38.654802-32.311087-45.37306a47.760523 47.760523 0 0 0-15.686852-2.624879c-14.437348 0-28.467405 6.530986-37.717418 18.343455L113.156496 157.748599c-16.40524 20.811762-12.780553 50.998386 8.06191 67.371902zM647.166446 893.344165c19.249115 6.718258 40.810989 0.406268 53.40427-15.718576L910.843504 610.198996c16.40524-20.811762 12.780553-50.998386-8.06191-67.371903-20.811762-16.436964-51.029087-12.812276-67.371902 8.06191L710.851238 709.257745v-789.249531c0-26.498489-21.49945-47.997939-47.99794-47.99794s-47.997939 21.49945-47.997939 47.99794V847.971104c0 20.467919 12.967825 38.653778 32.311087 45.373061z" horiz-adv-x="1024" />
<glyph glyph-name="ashbin" unicode="&#58937;" d="M832 608c-26.5 0-48-21.5-48-48v-592h-64v592c0 26.5-21.5 48-48 48s-48-21.5-48-48v-592h-64v592c0 26.5-21.5 48-48 48s-48-21.5-48-48v-592h-64v592c0 26.5-21.5 48-48 48s-48-21.5-48-48v-592h-64v592c0 26.5-21.5 48-48 48s-48-21.5-48-48v-640c0-26.5 21.5-48 48-48h640c26.5 0 48 21.5 48 48v640c0 26.5-21.5 48-48 48zM928 752h-240v96c0 26.5-21.5 48-48 48h-256c-26.5 0-48-21.5-48-48v-96h-240c-26.5 0-48-21.5-48-48s21.5-48 48-48h832c26.5 0 48 21.5 48 48s-21.5 48-48 48zM432 800h160v-48h-160v48z" horiz-adv-x="1024" />
<glyph glyph-name="success-filling" unicode="&#58938;" d="M512 896C229.23 896 0 666.77 0 384s229.23-512 512-512 512 229.23 512 512S794.77 896 512 896z m278.043-359.34l-298.625-384a64.114 64.114 0 0 0-46.188-24.562c-1.438-0.062-2.875-0.125-4.312-0.125-16.688 0-32.812 6.562-44.812 18.312l-156.5 153.438c-25.25 24.75-25.625 65.25-0.875 90.5 24.688 25.188 65.312 25.688 90.5 0.875L434.48 287.91l254.562 327.375c21.75 27.812 61.875 33 89.812 11.188 27.876-21.688 32.939-61.875 11.189-89.813z" horiz-adv-x="1024" />
<glyph glyph-name="edit" unicode="&#58939;" d="M975.969501 699.416143h-58.064186l87.313272 87.309272-0.012 0.011999C1016.796225 798.319053 1023.968001 814.322552 1023.968001 832.002c0 35.346895-28.651105 63.998-63.998 63.998-17.722446 0-33.736946-7.218774-45.326584-18.854411L736.906972 699.416143H47.9985c-26.499172 0-47.9985-21.499328-47.9985-47.9985v-731.415143c0-26.499172 21.499328-47.9985 47.9985-47.9985h927.971001c26.499172 0 47.9985 21.499328 47.9985 47.9985V651.417643c0 26.499172-21.499328 47.9985-47.9985 47.9985z m-47.9985-731.415143H95.997V603.419143h544.904972L337.583451 300.115621l90.497171-90.497172 393.819694 393.799694H927.971001v-635.417143zM191.994 64.025999l191.994 95.997-95.997 95.997z" horiz-adv-x="1024" />
<glyph glyph-name="set" unicode="&#59011;" d="M976 528h-76.562l-11.688 28.156 54.125 54.125c18.75 18.75 18.75 49.125 0 67.875l-135.75 135.75c-18.75 18.75-49.125 18.75-67.875 0l-54.125-54.125L656 771.438V848c0 26.5-21.5 48-48 48H416c-26.5 0-48-21.5-48-48v-76.562l-28.188-11.656-54.125 54.125c-18.75 18.75-49.125 18.75-67.875 0l-135.75-135.75c-18.75-18.75-18.75-49.125 0-67.875l54.125-54.156L124.562 528H48c-26.5 0-48-21.5-48-48v-192c0-26.5 21.5-48 48-48h76.562l11.625-28.125-54.125-54.125c-18.75-18.75-18.75-49.125 0-67.875l135.75-135.812c9-9 21.188-14.062 33.938-14.062s24.938 5.062 33.938 14.062l54.125 54.125L368-3.438V-80c0-26.5 21.5-48 48-48h192c26.5 0 48 21.5 48 48v76.562l28.125 11.625 54.125-54.125c18-18 49.875-18 67.875 0l135.75 135.812c18.75 18.75 18.75 49.125 0 67.875l-54.125 54.125L899.438 240H976c26.5 0 48 21.5 48 48V480c0 26.5-21.5 48-48 48z m-48-192h-60.625c-19.375 0-36.875-11.688-44.312-29.625L786.812 219c-7.438-17.938-3.375-38.562 10.375-52.312l42.875-42.875-67.875-67.938-42.875 42.875c-13.75 13.75-34.375 17.75-52.312 10.438L589.625 73C571.688 65.562 560 48.062 560 28.625V-32h-96v60.625c0 19.438-11.688 36.938-29.625 44.375l-87.438 36.188C329 116.5 308.375 112.5 294.625 98.75l-42.875-42.875-67.875 67.938 42.875 42.875c13.75 13.75 17.812 34.375 10.438 52.312L201 306.375C193.562 324.312 176.062 336 156.625 336H96v96h60.625c19.438 0 36.938 11.688 44.375 29.625l36.188 87.406c7.375 17.938 3.312 38.594-10.438 52.312l-42.875 42.875 67.875 67.875 42.875-42.875c13.75-13.719 34.375-17.844 52.312-10.406l87.438 36.219C452.312 702.469 464 719.969 464 739.375V800h96v-60.625c0-19.406 11.688-36.906 29.625-44.344L677 658.812c17.938-7.438 38.562-3.312 52.312 10.406l42.875 42.875 67.875-67.875-42.875-42.875c-13.75-13.719-17.812-34.375-10.375-52.312l36.25-87.406C830.5 443.688 847.938 432 867.375 432H928v-96zM512 560c-97.062 0-176-78.938-176-176s78.938-176 176-176 176 78.938 176 176-78.938 176-176 176z m0-256c-44.125 0-80 35.875-80 80s35.875 80 80 80 80-35.875 80-80-35.875-80-80-80z" horiz-adv-x="1024" />
<glyph glyph-name="ellipsis" unicode="&#58964;" d="M896 384m-128 0a128 128 0 1 1 256 0 128 128 0 1 1-256 0ZM127.999 384m-128 0a128 128 0 1 1 256 0 128 128 0 1 1-256 0ZM512 384m-128 0a128 128 0 1 1 256 0 128 128 0 1 1-256 0Z" horiz-adv-x="1024" />
<glyph glyph-name="attachment" unicode="&#58981;" d="M956.762 709.347c-86.609 86.734-237.831 86.734-324.566 0l-412.799-412.8c-34.931-34.931-40.18-75.799-40.18-97.045 0-21.246 5.249-62.114 43.992-100.857 34.931-34.931 75.799-40.18 97.045-40.18 21.246 0 62.051 5.249 96.982 40.18l323.253 323.253c18.747 18.747 18.747 49.116 0 67.863s-49.116 18.747-67.863 0L349.374 166.509c-9.998-9.998-21.371-12.06-29.12-12.06-7.811 0-19.184 2.062-33.056 15.997-9.936 9.873-11.998 21.246-11.998 29.057s2.062 19.184 12.06 29.182l412.799 412.799c50.553 50.491 138.412 50.491 188.84 0 25.245-25.245 39.118-58.739 39.118-94.42 0-35.618-13.872-69.175-39.118-94.42L476.1 39.844c-85.984-85.922-225.834-85.922-315.567 3.812-85.922 85.922-85.922 225.771 0 311.693l451.23 451.23c18.747 18.747 18.747 49.116 0 67.863s-49.116 18.747-67.863 0L92.67 423.212C32.931 363.473 0 284.05 0 199.503s32.931-163.97 96.545-227.521c61.676-61.676 142.661-92.483 223.709-92.483 80.985 0 162.033 30.807 223.709 92.483l412.799 412.799C1000.129 428.148 1024 485.763 1024 547.064s-23.871 118.978-67.238 162.283z" horiz-adv-x="1024" />
<glyph glyph-name="switch" unicode="&#59059;" d="M867.053 272.98400000000004H153.007c-45.901 0-66.28-56.091-35.712-86.659L321.279-17.659999999999968c20.378-20.377 51.047-20.377 71.424 0 20.379 20.379 20.379 51.047 0 71.426L280.522 170.99099999999999h586.531c30.566 0 51.047 20.378 51.047 51.046s-20.481 50.947-51.047 50.947zM153.007 476.968h714.046c45.9 0 66.279 56.091 35.712 86.657L698.781 767.71c-20.378 20.379-51.046 20.379-71.425 0-20.379-20.378-20.379-51.046 0-71.424L744.682 578.96H153.007c-30.567 0-51.046-20.378-51.046-51.047 0.1-30.568 25.522-50.945 51.046-50.945z" horiz-adv-x="1024" />
</font>
</defs></svg>
/*!-----------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* monaco-languages version: 0.9.0(e162b4ba29044167bc7181c42b3270fa8a467424)
* Released under the MIT license
* https://github.com/Microsoft/monaco-languages/blob/master/LICENSE.md
*-----------------------------------------------------------------------------*/
define("vs/basic-languages/src/fsharp",["require","exports"],function(e,t){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.conf={comments:{lineComment:"//",blockComment:["(*","*)"]},brackets:[["{","}"],["[","]"],["(",")"]],autoClosingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:'"',close:'"'}],surroundingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:'"',close:'"'},{open:"'",close:"'"}]},t.language={defaultToken:"",tokenPostfix:".fs",keywords:["abstract","and","atomic","as","assert","asr","base","begin","break","checked","component","const","constraint","constructor","continue","class","default","delegate","do","done","downcast","downto","elif","else","end","exception","eager","event","external","extern","false","finally","for","fun","function","fixed","functor","global","if","in","include","inherit","inline","interface","internal","land","lor","lsl","lsr","lxor","lazy","let","match","member","mod","module","mutable","namespace","method","mixin","new","not","null","of","open","or","object","override","private","parallel","process","protected","pure","public","rec","return","static","sealed","struct","sig","then","to","true","tailcall","trait","try","type","upcast","use","val","void","virtual","volatile","when","while","with","yield"],symbols:/[=><!~?:&|+\-*\^%;\.,\/]+/,escapes:/\\(?:[abfnrtv\\"']|x[0-9A-Fa-f]{1,4}|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8})/,integersuffix:/[uU]?[yslnLI]?/,floatsuffix:/[fFmM]?/,tokenizer:{root:[[/[a-zA-Z_]\w*/,{cases:{"@keywords":{token:"keyword.$0"},"@default":"identifier"}}],{include:"@whitespace"},[/\[<.*>\]/,"annotation"],[/^#(if|else|endif)/,"keyword"],[/[{}()\[\]]/,"@brackets"],[/[<>](?!@symbols)/,"@brackets"],[/@symbols/,"delimiter"],[/\d*\d+[eE]([\-+]?\d+)?(@floatsuffix)/,"number.float"],[/\d*\.\d+([eE][\-+]?\d+)?(@floatsuffix)/,"number.float"],[/0x[0-9a-fA-F]+LF/,"number.float"],[/0x[0-9a-fA-F]+(@integersuffix)/,"number.hex"],[/0b[0-1]+(@integersuffix)/,"number.bin"],[/\d+(@integersuffix)/,"number"],[/[;,.]/,"delimiter"],[/"([^"\\]|\\.)*$/,"string.invalid"],[/"""/,"string",'@string."""'],[/"/,"string",'@string."'],[/\@"/,{token:"string.quote",next:"@litstring"}],[/'[^\\']'B?/,"string"],[/(')(@escapes)(')/,["string","string.escape","string"]],[/'/,"string.invalid"]],whitespace:[[/[ \t\r\n]+/,""],[/\(\*/,"comment","@comment"],[/\/\/.*$/,"comment"]],comment:[[/[^\*]+/,"comment"],[/\*\)/,"comment","@pop"],[/\*/,"comment"]],string:[[/[^\\"]+/,"string"],[/@escapes/,"string.escape"],[/\\./,"string.escape.invalid"],[/("""|"B?)/,{cases:{"$#==$S2":{token:"string",next:"@pop"},"@default":"string"}}]],litstring:[[/[^"]+/,"string"],[/""/,"string.escape"],[/"/,{token:"string.quote",next:"@pop"}]]}}});
\ No newline at end of file
/*!-----------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* monaco-languages version: 0.9.0(e162b4ba29044167bc7181c42b3270fa8a467424)
* Released under the MIT license
* https://github.com/Microsoft/monaco-languages/blob/master/LICENSE.md
*-----------------------------------------------------------------------------*/
define("vs/basic-languages/src/go",["require","exports"],function(e,n){"use strict";Object.defineProperty(n,"__esModule",{value:!0}),n.conf={comments:{lineComment:"//",blockComment:["/*","*/"]},brackets:[["{","}"],["[","]"],["(",")"]],autoClosingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:"`",close:"`",notIn:["string"]},{open:'"',close:'"',notIn:["string"]},{open:"'",close:"'",notIn:["string","comment"]}],surroundingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:"`",close:"`"},{open:'"',close:'"'},{open:"'",close:"'"}]},n.language={defaultToken:"",tokenPostfix:".go",keywords:["break","case","chan","const","continue","default","defer","else","fallthrough","for","func","go","goto","if","import","interface","map","package","range","return","select","struct","switch","type","var","bool","true","false","uint8","uint16","uint32","uint64","int8","int16","int32","int64","float32","float64","complex64","complex128","byte","rune","uint","int","uintptr","string","nil"],operators:["+","-","*","/","%","&","|","^","<<",">>","&^","+=","-=","*=","/=","%=","&=","|=","^=","<<=",">>=","&^=","&&","||","<-","++","--","==","<",">","=","!","!=","<=",">=",":=","...","(",")","","]","{","}",",",";",".",":"],symbols:/[=><!~?:&|+\-*\/\^%]+/,escapes:/\\(?:[abfnrtv\\"']|x[0-9A-Fa-f]{1,4}|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8})/,tokenizer:{root:[[/[a-zA-Z_]\w*/,{cases:{"@keywords":{token:"keyword.$0"},"@default":"identifier"}}],{include:"@whitespace"},[/\[\[.*\]\]/,"annotation"],[/^\s*#\w+/,"keyword"],[/[{}()\[\]]/,"@brackets"],[/[<>](?!@symbols)/,"@brackets"],[/@symbols/,{cases:{"@operators":"delimiter","@default":""}}],[/\d*\d+[eE]([\-+]?\d+)?/,"number.float"],[/\d*\.\d+([eE][\-+]?\d+)?/,"number.float"],[/0[xX][0-9a-fA-F']*[0-9a-fA-F]/,"number.hex"],[/0[0-7']*[0-7]/,"number.octal"],[/0[bB][0-1']*[0-1]/,"number.binary"],[/\d[\d']*/,"number"],[/\d/,"number"],[/[;,.]/,"delimiter"],[/"([^"\\]|\\.)*$/,"string.invalid"],[/"/,"string","@string"],[/`/,"string","@rawstring"],[/'[^\\']'/,"string"],[/(')(@escapes)(')/,["string","string.escape","string"]],[/'/,"string.invalid"]],whitespace:[[/[ \t\r\n]+/,""],[/\/\*\*(?!\/)/,"comment.doc","@doccomment"],[/\/\*/,"comment","@comment"],[/\/\/.*$/,"comment"]],comment:[[/[^\/*]+/,"comment"],[/\*\//,"comment","@pop"],[/[\/*]/,"comment"]],doccomment:[[/[^\/*]+/,"comment.doc"],[/\/\*/,"comment.doc.invalid"],[/\*\//,"comment.doc","@pop"],[/[\/*]/,"comment.doc"]],string:[[/[^\\"]+/,"string"],[/@escapes/,"string.escape"],[/\\./,"string.escape.invalid"],[/"/,"string","@pop"]],rawstring:[[/[^\`]/,"string"],[/`/,"string","@pop"]]}}});
\ No newline at end of file
/*!-----------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* monaco-languages version: 0.9.0(e162b4ba29044167bc7181c42b3270fa8a467424)
* Released under the MIT license
* https://github.com/Microsoft/monaco-languages/blob/master/LICENSE.md
*-----------------------------------------------------------------------------*/
define("vs/basic-languages/src/handlebars",["require","exports"],function(e,t){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var n="undefined"==typeof monaco?self.monaco:monaco,a=["area","base","br","col","embed","hr","img","input","keygen","link","menuitem","meta","param","source","track","wbr"];t.conf={wordPattern:/(-?\d*\.\d\w*)|([^\`\~\!\@\$\^\&\*\(\)\=\+\[\{\]\}\\\|\;\:\'\"\,\.\<\>\/\s]+)/g,comments:{blockComment:["{{!--","--}}"]},brackets:[["\x3c!--","--\x3e"],["<",">"],["{{","}}"],["{","}"],["(",")"]],autoClosingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:'"',close:'"'},{open:"'",close:"'"}],surroundingPairs:[{open:"<",close:">"},{open:'"',close:'"'},{open:"'",close:"'"}],onEnterRules:[{beforeText:new RegExp("<(?!(?:"+a.join("|")+"))(\\w[\\w\\d]*)([^/>]*(?!/)>)[^<]*$","i"),afterText:/^<\/(\w[\w\d]*)\s*>$/i,action:{indentAction:n.languages.IndentAction.IndentOutdent}},{beforeText:new RegExp("<(?!(?:"+a.join("|")+"))(\\w[\\w\\d]*)([^/>]*(?!/)>)[^<]*$","i"),action:{indentAction:n.languages.IndentAction.Indent}}]},t.language={defaultToken:"",tokenPostfix:"",tokenizer:{root:[[/\{\{/,{token:"@rematch",switchTo:"@handlebarsInSimpleState.root"}],[/<!DOCTYPE/,"metatag.html","@doctype"],[/<!--/,"comment.html","@comment"],[/(<)(\w+)(\/>)/,["delimiter.html","tag.html","delimiter.html"]],[/(<)(script)/,["delimiter.html",{token:"tag.html",next:"@script"}]],[/(<)(style)/,["delimiter.html",{token:"tag.html",next:"@style"}]],[/(<)([:\w]+)/,["delimiter.html",{token:"tag.html",next:"@otherTag"}]],[/(<\/)(\w+)/,["delimiter.html",{token:"tag.html",next:"@otherTag"}]],[/</,"delimiter.html"],[/\{/,"delimiter.html"],[/[^<{]+/]],doctype:[[/\{\{/,{token:"@rematch",switchTo:"@handlebarsInSimpleState.comment"}],[/[^>]+/,"metatag.content.html"],[/>/,"metatag.html","@pop"]],comment:[[/\{\{/,{token:"@rematch",switchTo:"@handlebarsInSimpleState.comment"}],[/-->/,"comment.html","@pop"],[/[^-]+/,"comment.content.html"],[/./,"comment.content.html"]],otherTag:[[/\{\{/,{token:"@rematch",switchTo:"@handlebarsInSimpleState.otherTag"}],[/\/?>/,"delimiter.html","@pop"],[/"([^"]*)"/,"attribute.value"],[/'([^']*)'/,"attribute.value"],[/[\w\-]+/,"attribute.name"],[/=/,"delimiter"],[/[ \t\r\n]+/]],script:[[/\{\{/,{token:"@rematch",switchTo:"@handlebarsInSimpleState.script"}],[/type/,"attribute.name","@scriptAfterType"],[/"([^"]*)"/,"attribute.value"],[/'([^']*)'/,"attribute.value"],[/[\w\-]+/,"attribute.name"],[/=/,"delimiter"],[/>/,{token:"delimiter.html",next:"@scriptEmbedded.text/javascript",nextEmbedded:"text/javascript"}],[/[ \t\r\n]+/],[/(<\/)(script\s*)(>)/,["delimiter.html","tag.html",{token:"delimiter.html",next:"@pop"}]]],scriptAfterType:[[/\{\{/,{token:"@rematch",switchTo:"@handlebarsInSimpleState.scriptAfterType"}],[/=/,"delimiter","@scriptAfterTypeEquals"],[/>/,{token:"delimiter.html",next:"@scriptEmbedded.text/javascript",nextEmbedded:"text/javascript"}],[/[ \t\r\n]+/],[/<\/script\s*>/,{token:"@rematch",next:"@pop"}]],scriptAfterTypeEquals:[[/\{\{/,{token:"@rematch",switchTo:"@handlebarsInSimpleState.scriptAfterTypeEquals"}],[/"([^"]*)"/,{token:"attribute.value",switchTo:"@scriptWithCustomType.$1"}],[/'([^']*)'/,{token:"attribute.value",switchTo:"@scriptWithCustomType.$1"}],[/>/,{token:"delimiter.html",next:"@scriptEmbedded.text/javascript",nextEmbedded:"text/javascript"}],[/[ \t\r\n]+/],[/<\/script\s*>/,{token:"@rematch",next:"@pop"}]],scriptWithCustomType:[[/\{\{/,{token:"@rematch",switchTo:"@handlebarsInSimpleState.scriptWithCustomType.$S2"}],[/>/,{token:"delimiter.html",next:"@scriptEmbedded.$S2",nextEmbedded:"$S2"}],[/"([^"]*)"/,"attribute.value"],[/'([^']*)'/,"attribute.value"],[/[\w\-]+/,"attribute.name"],[/=/,"delimiter"],[/[ \t\r\n]+/],[/<\/script\s*>/,{token:"@rematch",next:"@pop"}]],scriptEmbedded:[[/\{\{/,{token:"@rematch",switchTo:"@handlebarsInEmbeddedState.scriptEmbedded.$S2",nextEmbedded:"@pop"}],[/<\/script/,{token:"@rematch",next:"@pop",nextEmbedded:"@pop"}]],style:[[/\{\{/,{token:"@rematch",switchTo:"@handlebarsInSimpleState.style"}],[/type/,"attribute.name","@styleAfterType"],[/"([^"]*)"/,"attribute.value"],[/'([^']*)'/,"attribute.value"],[/[\w\-]+/,"attribute.name"],[/=/,"delimiter"],[/>/,{token:"delimiter.html",next:"@styleEmbedded.text/css",nextEmbedded:"text/css"}],[/[ \t\r\n]+/],[/(<\/)(style\s*)(>)/,["delimiter.html","tag.html",{token:"delimiter.html",next:"@pop"}]]],styleAfterType:[[/\{\{/,{token:"@rematch",switchTo:"@handlebarsInSimpleState.styleAfterType"}],[/=/,"delimiter","@styleAfterTypeEquals"],[/>/,{token:"delimiter.html",next:"@styleEmbedded.text/css",nextEmbedded:"text/css"}],[/[ \t\r\n]+/],[/<\/style\s*>/,{token:"@rematch",next:"@pop"}]],styleAfterTypeEquals:[[/\{\{/,{token:"@rematch",switchTo:"@handlebarsInSimpleState.styleAfterTypeEquals"}],[/"([^"]*)"/,{token:"attribute.value",switchTo:"@styleWithCustomType.$1"}],[/'([^']*)'/,{token:"attribute.value",switchTo:"@styleWithCustomType.$1"}],[/>/,{token:"delimiter.html",next:"@styleEmbedded.text/css",nextEmbedded:"text/css"}],[/[ \t\r\n]+/],[/<\/style\s*>/,{token:"@rematch",next:"@pop"}]],styleWithCustomType:[[/\{\{/,{token:"@rematch",switchTo:"@handlebarsInSimpleState.styleWithCustomType.$S2"}],[/>/,{token:"delimiter.html",next:"@styleEmbedded.$S2",nextEmbedded:"$S2"}],[/"([^"]*)"/,"attribute.value"],[/'([^']*)'/,"attribute.value"],[/[\w\-]+/,"attribute.name"],[/=/,"delimiter"],[/[ \t\r\n]+/],[/<\/style\s*>/,{token:"@rematch",next:"@pop"}]],styleEmbedded:[[/\{\{/,{token:"@rematch",switchTo:"@handlebarsInEmbeddedState.styleEmbedded.$S2",nextEmbedded:"@pop"}],[/<\/style/,{token:"@rematch",next:"@pop",nextEmbedded:"@pop"}]],handlebarsInSimpleState:[[/\{\{\{?/,"delimiter.handlebars"],[/\}\}\}?/,{token:"delimiter.handlebars",switchTo:"@$S2.$S3"}],{include:"handlebarsRoot"}],handlebarsInEmbeddedState:[[/\{\{\{?/,"delimiter.handlebars"],[/\}\}\}?/,{token:"delimiter.handlebars",switchTo:"@$S2.$S3",nextEmbedded:"$S3"}],{include:"handlebarsRoot"}],handlebarsRoot:[[/[#/][^\s}]+/,"keyword.helper.handlebars"],[/else\b/,"keyword.helper.handlebars"],[/[\s]+/],[/[^}]/,"variable.parameter.handlebars"]]}}});
\ No newline at end of file
/*!-----------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* monaco-languages version: 0.9.0(e162b4ba29044167bc7181c42b3270fa8a467424)
* Released under the MIT license
* https://github.com/Microsoft/monaco-languages/blob/master/LICENSE.md
*-----------------------------------------------------------------------------*/
define("vs/basic-languages/src/html",["require","exports"],function(e,t){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var n="undefined"==typeof monaco?self.monaco:monaco,i=["area","base","br","col","embed","hr","img","input","keygen","link","menuitem","meta","param","source","track","wbr"];t.conf={wordPattern:/(-?\d*\.\d\w*)|([^\`\~\!\@\$\^\&\*\(\)\=\+\[\{\]\}\\\|\;\:\'\"\,\.\<\>\/\s]+)/g,comments:{blockComment:["\x3c!--","--\x3e"]},brackets:[["\x3c!--","--\x3e"],["<",">"],["{","}"],["(",")"]],autoClosingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:'"',close:'"'},{open:"'",close:"'"}],surroundingPairs:[{open:'"',close:'"'},{open:"'",close:"'"},{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:"<",close:">"}],onEnterRules:[{beforeText:new RegExp("<(?!(?:"+i.join("|")+"))([_:\\w][_:\\w-.\\d]*)([^/>]*(?!/)>)[^<]*$","i"),afterText:/^<\/([_:\w][_:\w-.\d]*)\s*>$/i,action:{indentAction:n.languages.IndentAction.IndentOutdent}},{beforeText:new RegExp("<(?!(?:"+i.join("|")+"))(\\w[\\w\\d]*)([^/>]*(?!/)>)[^<]*$","i"),action:{indentAction:n.languages.IndentAction.Indent}}]},t.language={defaultToken:"",tokenPostfix:".html",ignoreCase:!0,tokenizer:{root:[[/<!DOCTYPE/,"metatag","@doctype"],[/<!--/,"comment","@comment"],[/(<)((?:[\w\-]+:)?[\w\-]+)(\s*)(\/>)/,["delimiter","tag","","delimiter"]],[/(<)(script)/,["delimiter",{token:"tag",next:"@script"}]],[/(<)(style)/,["delimiter",{token:"tag",next:"@style"}]],[/(<)((?:[\w\-]+:)?[\w\-]+)/,["delimiter",{token:"tag",next:"@otherTag"}]],[/(<\/)((?:[\w\-]+:)?[\w\-]+)/,["delimiter",{token:"tag",next:"@otherTag"}]],[/</,"delimiter"],[/[^<]+/]],doctype:[[/[^>]+/,"metatag.content"],[/>/,"metatag","@pop"]],comment:[[/-->/,"comment","@pop"],[/[^-]+/,"comment.content"],[/./,"comment.content"]],otherTag:[[/\/?>/,"delimiter","@pop"],[/"([^"]*)"/,"attribute.value"],[/'([^']*)'/,"attribute.value"],[/[\w\-]+/,"attribute.name"],[/=/,"delimiter"],[/[ \t\r\n]+/]],script:[[/type/,"attribute.name","@scriptAfterType"],[/"([^"]*)"/,"attribute.value"],[/'([^']*)'/,"attribute.value"],[/[\w\-]+/,"attribute.name"],[/=/,"delimiter"],[/>/,{token:"delimiter",next:"@scriptEmbedded",nextEmbedded:"text/javascript"}],[/[ \t\r\n]+/],[/(<\/)(script\s*)(>)/,["delimiter","tag",{token:"delimiter",next:"@pop"}]]],scriptAfterType:[[/=/,"delimiter","@scriptAfterTypeEquals"],[/>/,{token:"delimiter",next:"@scriptEmbedded",nextEmbedded:"text/javascript"}],[/[ \t\r\n]+/],[/<\/script\s*>/,{token:"@rematch",next:"@pop"}]],scriptAfterTypeEquals:[[/"([^"]*)"/,{token:"attribute.value",switchTo:"@scriptWithCustomType.$1"}],[/'([^']*)'/,{token:"attribute.value",switchTo:"@scriptWithCustomType.$1"}],[/>/,{token:"delimiter",next:"@scriptEmbedded",nextEmbedded:"text/javascript"}],[/[ \t\r\n]+/],[/<\/script\s*>/,{token:"@rematch",next:"@pop"}]],scriptWithCustomType:[[/>/,{token:"delimiter",next:"@scriptEmbedded.$S2",nextEmbedded:"$S2"}],[/"([^"]*)"/,"attribute.value"],[/'([^']*)'/,"attribute.value"],[/[\w\-]+/,"attribute.name"],[/=/,"delimiter"],[/[ \t\r\n]+/],[/<\/script\s*>/,{token:"@rematch",next:"@pop"}]],scriptEmbedded:[[/<\/script/,{token:"@rematch",next:"@pop",nextEmbedded:"@pop"}],[/[^<]+/,""]],style:[[/type/,"attribute.name","@styleAfterType"],[/"([^"]*)"/,"attribute.value"],[/'([^']*)'/,"attribute.value"],[/[\w\-]+/,"attribute.name"],[/=/,"delimiter"],[/>/,{token:"delimiter",next:"@styleEmbedded",nextEmbedded:"text/css"}],[/[ \t\r\n]+/],[/(<\/)(style\s*)(>)/,["delimiter","tag",{token:"delimiter",next:"@pop"}]]],styleAfterType:[[/=/,"delimiter","@styleAfterTypeEquals"],[/>/,{token:"delimiter",next:"@styleEmbedded",nextEmbedded:"text/css"}],[/[ \t\r\n]+/],[/<\/style\s*>/,{token:"@rematch",next:"@pop"}]],styleAfterTypeEquals:[[/"([^"]*)"/,{token:"attribute.value",switchTo:"@styleWithCustomType.$1"}],[/'([^']*)'/,{token:"attribute.value",switchTo:"@styleWithCustomType.$1"}],[/>/,{token:"delimiter",next:"@styleEmbedded",nextEmbedded:"text/css"}],[/[ \t\r\n]+/],[/<\/style\s*>/,{token:"@rematch",next:"@pop"}]],styleWithCustomType:[[/>/,{token:"delimiter",next:"@styleEmbedded.$S2",nextEmbedded:"$S2"}],[/"([^"]*)"/,"attribute.value"],[/'([^']*)'/,"attribute.value"],[/[\w\-]+/,"attribute.name"],[/=/,"delimiter"],[/[ \t\r\n]+/],[/<\/style\s*>/,{token:"@rematch",next:"@pop"}]],styleEmbedded:[[/<\/style/,{token:"@rematch",next:"@pop",nextEmbedded:"@pop"}],[/[^<]+/,""]]}}});
\ No newline at end of file
/*!-----------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* monaco-html version: 1.3.2(5ec45016d73d25ccf42bc1626de18d4329aabe34)
* Released under the MIT license
* https://github.com/Microsoft/monaco-html/blob/master/LICENSE.md
*-----------------------------------------------------------------------------*/
!function(e){if("object"==typeof module&&"object"==typeof module.exports){var t=e(require,exports);void 0!==t&&(module.exports=t)}else"function"==typeof define&&define.amd&&define("vs/language/html/workerManager",["require","exports"],e)}(function(e,t){function n(e){var t,n,i=new r(function(e,r){t=e,n=r},function(){});return e.then(t,n),i}Object.defineProperty(t,"__esModule",{value:!0});var r=monaco.Promise,i=12e4,o=function(){function e(e){var t=this;this._defaults=e,this._worker=null,this._idleCheckInterval=setInterval(function(){return t._checkIfIdle()},3e4),this._lastUsedTime=0,this._configChangeListener=this._defaults.onDidChange(function(){return t._stopWorker()})}return e.prototype._stopWorker=function(){this._worker&&(this._worker.dispose(),this._worker=null),this._client=null},e.prototype.dispose=function(){clearInterval(this._idleCheckInterval),this._configChangeListener.dispose(),this._stopWorker()},e.prototype._checkIfIdle=function(){if(this._worker){var e=Date.now()-this._lastUsedTime;e>i&&this._stopWorker()}},e.prototype._getClient=function(){return this._lastUsedTime=Date.now(),this._client||(this._worker=monaco.editor.createWebWorker({moduleId:"vs/language/html/htmlWorker",createData:{languageSettings:this._defaults.options,languageId:this._defaults.languageId},label:this._defaults.languageId}),this._client=this._worker.getProxy()),this._client},e.prototype.getLanguageServiceWorker=function(){for(var e=this,t=[],r=0;r<arguments.length;r++)t[r]=arguments[r];var i;return n(this._getClient().then(function(e){i=e}).then(function(n){return e._worker.withSyncedResources(t)}).then(function(e){return i}))},e}();t.WorkerManager=o}),function(e){if("object"==typeof module&&"object"==typeof module.exports){var t=e(require,exports);void 0!==t&&(module.exports=t)}else"function"==typeof define&&define.amd&&define("vscode-languageserver-types/main",["require","exports"],e)}(function(e,t){Object.defineProperty(t,"__esModule",{value:!0});var n;!function(e){function t(e,t){return{line:e,character:t}}function n(e){var t=e;return K.defined(t)&&K.number(t.line)&&K.number(t.character)}e.create=t,e.is=n}(n=t.Position||(t.Position={}));var r;!function(e){function t(e,t,r,i){if(K.number(e)&&K.number(t)&&K.number(r)&&K.number(i))return{start:n.create(e,t),end:n.create(r,i)};if(n.is(e)&&n.is(t))return{start:e,end:t};throw new Error("Range#create called with invalid arguments["+e+", "+t+", "+r+", "+i+"]")}function r(e){var t=e;return K.defined(t)&&n.is(t.start)&&n.is(t.end)}e.create=t,e.is=r}(r=t.Range||(t.Range={}));var i;!function(e){function t(e,t){return{uri:e,range:t}}function n(e){var t=e;return K.defined(t)&&r.is(t.range)&&(K.string(t.uri)||K.undefined(t.uri))}e.create=t,e.is=n}(i=t.Location||(t.Location={}));var o;!function(e){e.Error=1,e.Warning=2,e.Information=3,e.Hint=4}(o=t.DiagnosticSeverity||(t.DiagnosticSeverity={}));var a;!function(e){function t(e,t,n,r,i){var o={range:e,message:t};return K.defined(n)&&(o.severity=n),K.defined(r)&&(o.code=r),K.defined(i)&&(o.source=i),o}function n(e){var t=e;return K.defined(t)&&r.is(t.range)&&K.string(t.message)&&(K.number(t.severity)||K.undefined(t.severity))&&(K.number(t.code)||K.string(t.code)||K.undefined(t.code))&&(K.string(t.source)||K.undefined(t.source))}e.create=t,e.is=n}(a=t.Diagnostic||(t.Diagnostic={}));var u;!function(e){function t(e,t){for(var n=[],r=2;r<arguments.length;r++)n[r-2]=arguments[r];var i={title:e,command:t};return K.defined(n)&&n.length>0&&(i.arguments=n),i}function n(e){var t=e;return K.defined(t)&&K.string(t.title)&&K.string(t.title)}e.create=t,e.is=n}(u=t.Command||(t.Command={}));var s;!function(e){function t(e,t){return{range:e,newText:t}}function n(e,t){return{range:{start:e,end:e},newText:t}}function r(e){return{range:e,newText:""}}e.replace=t,e.insert=n,e.del=r}(s=t.TextEdit||(t.TextEdit={}));var c;!function(e){function t(e,t){return{textDocument:e,edits:t}}function n(e){var t=e;return K.defined(t)&&g.is(t.textDocument)&&Array.isArray(t.edits)}e.create=t,e.is=n}(c=t.TextDocumentEdit||(t.TextDocumentEdit={}));var d=function(){function e(e){this.edits=e}return e.prototype.insert=function(e,t){this.edits.push(s.insert(e,t))},e.prototype.replace=function(e,t){this.edits.push(s.replace(e,t))},e.prototype["delete"]=function(e){this.edits.push(s.del(e))},e.prototype.add=function(e){this.edits.push(e)},e.prototype.all=function(){return this.edits},e.prototype.clear=function(){this.edits.splice(0,this.edits.length)},e}(),f=function(){function e(e){var t=this;this._textEditChanges=Object.create(null),e&&(this._workspaceEdit=e,e.documentChanges?e.documentChanges.forEach(function(e){var n=new d(e.edits);t._textEditChanges[e.textDocument.uri]=n}):e.changes&&Object.keys(e.changes).forEach(function(n){var r=new d(e.changes[n]);t._textEditChanges[n]=r}))}return Object.defineProperty(e.prototype,"edit",{get:function(){return this._workspaceEdit},enumerable:!0,configurable:!0}),e.prototype.getTextEditChange=function(e){if(g.is(e)){if(this._workspaceEdit||(this._workspaceEdit={documentChanges:[]}),!this._workspaceEdit.documentChanges)throw new Error("Workspace edit is not configured for versioned document changes.");var t=e,n=this._textEditChanges[t.uri];if(!n){var r=[],i={textDocument:t,edits:r};this._workspaceEdit.documentChanges.push(i),n=new d(r),this._textEditChanges[t.uri]=n}return n}if(this._workspaceEdit||(this._workspaceEdit={changes:Object.create(null)}),!this._workspaceEdit.changes)throw new Error("Workspace edit is not configured for normal text edit changes.");var n=this._textEditChanges[e];if(!n){var r=[];this._workspaceEdit.changes[e]=r,n=new d(r),this._textEditChanges[e]=n}return n},e}();t.WorkspaceChange=f;var l;!function(e){function t(e){return{uri:e}}function n(e){var t=e;return K.defined(t)&&K.string(t.uri)}e.create=t,e.is=n}(l=t.TextDocumentIdentifier||(t.TextDocumentIdentifier={}));var g;!function(e){function t(e,t){return{uri:e,version:t}}function n(e){var t=e;return K.defined(t)&&K.string(t.uri)&&K.number(t.version)}e.create=t,e.is=n}(g=t.VersionedTextDocumentIdentifier||(t.VersionedTextDocumentIdentifier={}));var m;!function(e){function t(e,t,n,r){return{uri:e,languageId:t,version:n,text:r}}function n(e){var t=e;return K.defined(t)&&K.string(t.uri)&&K.string(t.languageId)&&K.number(t.version)&&K.string(t.text)}e.create=t,e.is=n}(m=t.TextDocumentItem||(t.TextDocumentItem={}));var p;!function(e){e.Text=1,e.Method=2,e.Function=3,e.Constructor=4,e.Field=5,e.Variable=6,e.Class=7,e.Interface=8,e.Module=9,e.Property=10,e.Unit=11,e.Value=12,e.Enum=13,e.Keyword=14,e.Snippet=15,e.Color=16,e.File=17,e.Reference=18}(p=t.CompletionItemKind||(t.CompletionItemKind={}));var h;!function(e){e.PlainText=1,e.Snippet=2}(h=t.InsertTextFormat||(t.InsertTextFormat={}));var v;!function(e){function t(e){return{label:e}}e.create=t}(v=t.CompletionItem||(t.CompletionItem={}));var _;!function(e){function t(e,t){return{items:e?e:[],isIncomplete:!!t}}e.create=t}(_=t.CompletionList||(t.CompletionList={}));var y;!function(e){function t(e){return e.replace(/[\\`*_{}[\]()#+\-.!]/g,"\\$&")}e.fromPlainText=t}(y=t.MarkedString||(t.MarkedString={}));var b;!function(e){function t(e,t){return t?{label:e,documentation:t}:{label:e}}e.create=t}(b=t.ParameterInformation||(t.ParameterInformation={}));var x;!function(e){function t(e,t){for(var n=[],r=2;r<arguments.length;r++)n[r-2]=arguments[r];var i={label:e};return K.defined(t)&&(i.documentation=t),K.defined(n)?i.parameters=n:i.parameters=[],i}e.create=t}(x=t.SignatureInformation||(t.SignatureInformation={}));var C;!function(e){e.Text=1,e.Read=2,e.Write=3}(C=t.DocumentHighlightKind||(t.DocumentHighlightKind={}));var I;!function(e){function t(e,t){var n={range:e};return K.number(t)&&(n.kind=t),n}e.create=t}(I=t.DocumentHighlight||(t.DocumentHighlight={}));var k;!function(e){e.File=1,e.Module=2,e.Namespace=3,e.Package=4,e.Class=5,e.Method=6,e.Property=7,e.Field=8,e.Constructor=9,e.Enum=10,e.Interface=11,e.Function=12,e.Variable=13,e.Constant=14,e.String=15,e.Number=16,e.Boolean=17,e.Array=18}(k=t.SymbolKind||(t.SymbolKind={}));var w;!function(e){function t(e,t,n,r,i){var o={name:e,kind:t,location:{uri:r,range:n}};return i&&(o.containerName=i),o}e.create=t}(w=t.SymbolInformation||(t.SymbolInformation={}));var D;!function(e){function t(e){return{diagnostics:e}}function n(e){var t=e;return K.defined(t)&&K.typedArray(t.diagnostics,a.is)}e.create=t,e.is=n}(D=t.CodeActionContext||(t.CodeActionContext={}));var E;!function(e){function t(e,t){var n={range:e};return K.defined(t)&&(n.data=t),n}function n(e){var t=e;return K.defined(t)&&r.is(t.range)&&(K.undefined(t.command)||u.is(t.command))}e.create=t,e.is=n}(E=t.CodeLens||(t.CodeLens={}));var S;!function(e){function t(e,t){return{tabSize:e,insertSpaces:t}}function n(e){var t=e;return K.defined(t)&&K.number(t.tabSize)&&K["boolean"](t.insertSpaces)}e.create=t,e.is=n}(S=t.FormattingOptions||(t.FormattingOptions={}));var T=function(){function e(){}return e}();t.DocumentLink=T,function(e){function t(e,t){return{range:e,target:t}}function n(e){var t=e;return K.defined(t)&&r.is(t.range)&&(K.undefined(t.target)||K.string(t.target))}e.create=t,e.is=n}(T=t.DocumentLink||(t.DocumentLink={})),t.DocumentLink=T,t.EOL=["\n","\r\n","\r"];var M;!function(e){function t(e,t,n,r){return new F(e,t,n,r)}function n(e){var t=e;return!!(K.defined(t)&&K.string(t.uri)&&(K.undefined(t.languageId)||K.string(t.languageId))&&K.number(t.lineCount)&&K.func(t.getText)&&K.func(t.positionAt)&&K.func(t.offsetAt))}e.create=t,e.is=n}(M=t.TextDocument||(t.TextDocument={}));var P;!function(e){e.Manual=1,e.AfterDelay=2,e.FocusOut=3}(P=t.TextDocumentSaveReason||(t.TextDocumentSaveReason={}));var K,F=function(){function e(e,t,n,r){this._uri=e,this._languageId=t,this._version=n,this._content=r,this._lineOffsets=null}return Object.defineProperty(e.prototype,"uri",{get:function(){return this._uri},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"languageId",{get:function(){return this._languageId},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"version",{get:function(){return this._version},enumerable:!0,configurable:!0}),e.prototype.getText=function(){return this._content},e.prototype.update=function(e,t){this._content=e.text,this._version=t,this._lineOffsets=null},e.prototype.getLineOffsets=function(){if(null===this._lineOffsets){for(var e=[],t=this._content,n=!0,r=0;r<t.length;r++){n&&(e.push(r),n=!1);var i=t.charAt(r);n="\r"===i||"\n"===i,"\r"===i&&r+1<t.length&&"\n"===t.charAt(r+1)&&r++}n&&t.length>0&&e.push(t.length),this._lineOffsets=e}return this._lineOffsets},e.prototype.positionAt=function(e){e=Math.max(Math.min(e,this._content.length),0);var t=this.getLineOffsets(),r=0,i=t.length;if(0===i)return n.create(0,e);for(;r<i;){var o=Math.floor((r+i)/2);t[o]>e?i=o:r=o+1}var a=r-1;return n.create(a,e-t[a])},e.prototype.offsetAt=function(e){var t=this.getLineOffsets();if(e.line>=t.length)return this._content.length;if(e.line<0)return 0;var n=t[e.line],r=e.line+1<t.length?t[e.line+1]:this._content.length;return Math.max(Math.min(n+e.character,r),n)},Object.defineProperty(e.prototype,"lineCount",{get:function(){return this.getLineOffsets().length},enumerable:!0,configurable:!0}),e}();!function(e){function t(e){return"undefined"!=typeof e}function n(e){return"undefined"==typeof e}function r(e){return e===!0||e===!1}function i(e){return"[object String]"===s.call(e)}function o(e){return"[object Number]"===s.call(e)}function a(e){return"[object Function]"===s.call(e)}function u(e,t){return Array.isArray(e)&&e.every(t)}var s=Object.prototype.toString;e.defined=t,e.undefined=n,e["boolean"]=r,e.string=i,e.number=o,e.func=a,e.typedArray=u}(K||(K={}))}),define("vscode-languageserver-types",["vscode-languageserver-types/main"],function(e){return e}),function(e){if("object"==typeof module&&"object"==typeof module.exports){var t=e(require,exports);void 0!==t&&(module.exports=t)}else"function"==typeof define&&define.amd&&define("vs/language/html/languageFeatures",["require","exports","vscode-languageserver-types"],e)}(function(e,t){function n(e){switch(e){case l.DiagnosticSeverity.Error:return monaco.Severity.Error;case l.DiagnosticSeverity.Warning:return monaco.Severity.Warning;case l.DiagnosticSeverity.Information:case l.DiagnosticSeverity.Hint:default:return monaco.Severity.Info}}function r(e,t){var r="number"==typeof t.code?String(t.code):t.code;return{severity:n(t.severity),startLineNumber:t.range.start.line+1,startColumn:t.range.start.character+1,endLineNumber:t.range.end.line+1,endColumn:t.range.end.character+1,message:t.message,code:r,source:t.source}}function i(e){if(e)return{character:e.column-1,line:e.lineNumber-1}}function o(e){if(e)return{start:i(e.getStartPosition()),end:i(e.getEndPosition())}}function a(e){if(e)return new g(e.start.line+1,e.start.character+1,e.end.line+1,e.end.character+1)}function u(e){var t=monaco.languages.CompletionItemKind;switch(e){case l.CompletionItemKind.Text:return t.Text;case l.CompletionItemKind.Method:return t.Method;case l.CompletionItemKind.Function:return t.Function;case l.CompletionItemKind.Constructor:return t.Constructor;case l.CompletionItemKind.Field:return t.Field;case l.CompletionItemKind.Variable:return t.Variable;case l.CompletionItemKind.Class:return t.Class;case l.CompletionItemKind.Interface:return t.Interface;case l.CompletionItemKind.Module:return t.Module;case l.CompletionItemKind.Property:return t.Property;case l.CompletionItemKind.Unit:return t.Unit;case l.CompletionItemKind.Value:return t.Value;case l.CompletionItemKind.Enum:return t.Enum;case l.CompletionItemKind.Keyword:return t.Keyword;case l.CompletionItemKind.Snippet:return t.Snippet;case l.CompletionItemKind.Color:return t.Color;case l.CompletionItemKind.File:return t.File;case l.CompletionItemKind.Reference:return t.Reference}return t.Property}function s(e){if(e)return{range:a(e.range),text:e.newText}}function c(e){var t=monaco.languages.DocumentHighlightKind;switch(e){case l.DocumentHighlightKind.Read:return t.Read;case l.DocumentHighlightKind.Write:return t.Write;case l.DocumentHighlightKind.Text:return t.Text}return t.Text}function d(e){return{tabSize:e.tabSize,insertSpaces:e.insertSpaces}}function f(e,t){return t.cancel&&e.onCancellationRequested(function(){return t.cancel()}),t}Object.defineProperty(t,"__esModule",{value:!0});var l=e("vscode-languageserver-types"),g=(monaco.Uri,monaco.Range),m=function(){function e(e,t){var n=this;this._languageId=e,this._worker=t,this._disposables=[],this._listener=Object.create(null);var r=function(e){var t=e.getModeId();if(t===n._languageId){var r;n._listener[e.uri.toString()]=e.onDidChangeContent(function(){clearTimeout(r),r=setTimeout(function(){return n._doValidate(e.uri,t)},500)}),n._doValidate(e.uri,t)}},i=function(e){monaco.editor.setModelMarkers(e,n._languageId,[]);var t=e.uri.toString(),r=n._listener[t];r&&(r.dispose(),delete n._listener[t])};this._disposables.push(monaco.editor.onDidCreateModel(r)),this._disposables.push(monaco.editor.onWillDisposeModel(function(e){i(e)})),this._disposables.push(monaco.editor.onDidChangeModelLanguage(function(e){i(e.model),r(e.model)})),this._disposables.push({dispose:function(){for(var e in n._listener)n._listener[e].dispose()}}),monaco.editor.getModels().forEach(r)}return e.prototype.dispose=function(){this._disposables.forEach(function(e){return e&&e.dispose()}),this._disposables=[]},e.prototype._doValidate=function(e,t){this._worker(e).then(function(n){return n.doValidation(e.toString()).then(function(n){var i=n.map(function(t){return r(e,t)});monaco.editor.setModelMarkers(monaco.editor.getModel(e),t,i)})}).then(void 0,function(e){console.error(e)})},e}();t.DiagnostcsAdapter=m;var p=function(){function e(e){this._worker=e}return Object.defineProperty(e.prototype,"triggerCharacters",{get:function(){return[".",":","<",'"',"=","/"]},enumerable:!0,configurable:!0}),e.prototype.provideCompletionItems=function(e,t,n){var r=(e.getWordUntilPosition(t),e.uri);return f(n,this._worker(r).then(function(e){return e.doComplete(r.toString(),i(t))}).then(function(e){if(e){var t=e.items.map(function(e){var t={label:e.label,insertText:e.insertText,sortText:e.sortText,filterText:e.filterText,documentation:e.documentation,detail:e.detail,kind:u(e.kind)};return e.textEdit&&(t.range=a(e.textEdit.range),t.insertText=e.textEdit.newText),e.insertTextFormat===l.InsertTextFormat.Snippet&&(t.insertText={value:t.insertText}),t});return{isIncomplete:e.isIncomplete,items:t}}}))},e}();t.CompletionAdapter=p;var h=function(){function e(e){this._worker=e}return e.prototype.provideDocumentHighlights=function(e,t,n){var r=e.uri;return f(n,this._worker(r).then(function(e){return e.findDocumentHighlights(r.toString(),i(t))}).then(function(e){if(e)return e.map(function(e){return{range:a(e.range),kind:c(e.kind)}})}))},e}();t.DocumentHighlightAdapter=h;var v=function(){function e(e){this._worker=e}return e.prototype.provideLinks=function(e,t){var n=e.uri;return f(t,this._worker(n).then(function(e){return e.findDocumentLinks(n.toString())}).then(function(e){if(e)return e.map(function(e){return{range:a(e.range),url:e.target}})}))},e}();t.DocumentLinkAdapter=v;var _=function(){function e(e){this._worker=e}return e.prototype.provideDocumentFormattingEdits=function(e,t,n){var r=e.uri;return f(n,this._worker(r).then(function(e){return e.format(r.toString(),null,d(t)).then(function(e){if(e&&0!==e.length)return e.map(s)})}))},e}();t.DocumentFormattingEditProvider=_;var y=function(){function e(e){this._worker=e}return e.prototype.provideDocumentRangeFormattingEdits=function(e,t,n,r){var i=e.uri;return f(r,this._worker(i).then(function(e){return e.format(i.toString(),o(t),d(n)).then(function(e){if(e&&0!==e.length)return e.map(s)})}))},e}();t.DocumentRangeFormattingEditProvider=y}),function(e){if("object"==typeof module&&"object"==typeof module.exports){var t=e(require,exports);void 0!==t&&(module.exports=t)}else"function"==typeof define&&define.amd&&define("vs/language/html/htmlMode",["require","exports","./workerManager","./languageFeatures"],e)}(function(e,t){function n(e){var t=[],n=new r.WorkerManager(e);t.push(n);var o=function(){for(var e=[],t=0;t<arguments.length;t++)e[t]=arguments[t];return n.getLanguageServiceWorker.apply(n,e)},a=e.languageId;t.push(monaco.languages.registerCompletionItemProvider(a,new i.CompletionAdapter(o))),t.push(monaco.languages.registerDocumentHighlightProvider(a,new i.DocumentHighlightAdapter(o))),t.push(monaco.languages.registerLinkProvider(a,new i.DocumentLinkAdapter(o))),"html"===a&&(t.push(monaco.languages.registerDocumentFormattingEditProvider(a,new i.DocumentFormattingEditProvider(o))),t.push(monaco.languages.registerDocumentRangeFormattingEditProvider(a,new i.DocumentRangeFormattingEditProvider(o))),t.push(new i.DiagnostcsAdapter(a,o)))}Object.defineProperty(t,"__esModule",{value:!0});var r=e("./workerManager"),i=e("./languageFeatures");t.setupMode=n});
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment