package com.qmth.sop.common.contant;

import cn.hutool.core.date.DateUtil;
import com.aventrix.jnanoid.jnanoid.NanoIdUtils;
import com.qmth.boot.core.uid.service.UidService;
import com.qmth.sop.common.enums.ExceptionResultEnum;
import com.qmth.sop.common.enums.UploadFileEnum;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.LinkedMultiValueMap;

import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.charset.Charset;
import java.text.MessageFormat;
import java.time.Duration;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Description: 系统常量
 * @Param:
 * @return:
 * @Author: wangliang
 * @Date: 2019/10/11
 */
public class SystemConstant {


    private final static Logger log = LoggerFactory.getLogger(SystemConstant.class);

    /**
     * 系统常量
     */
    public static final String CHARSET_NAME = "UTF-8";
    //    public static final String CHARSET_GB2312 = "gb2312";
    public static final Charset CHARSET = Charset.forName(CHARSET_NAME);
    public static final String CHARSET_GBK = "gbk";
    public static final String SUCCESS = "success";
    public static final String RESULT_ERROR = "error";
    public static final String ALREADY_COUNT = "alreadyCount";
    public static final String ERROR_MSG = "errorMsg";
    public static final String UPDATE_TIME = "updateTime";
    public static final String SESSION = "session:";
    public static final String USER = "account";
    public static final String TASK = "task";
    public static final String QUERY = "query";
    public static final String PARAMS = "params";
    public static final String ORG = "org";
    public static final String ORG_ID = "orgId";
    public static final String MD5 = "MD5";
    public static final String SIGNATURE = "signature";
    public static final String GET = "get";
    public static final String GET_UNKNOWN = "?";
    public static final String GET_SYMBOL = "&";
    public static final String GET_EQUAL = "=";
    public static final String PATH_MATCH = "*";
    public static final String PATH_SUBSTR = "/#";
    public static final String METHOD = "post";
    public static final String ERROR = "/error";
    public static final String PT = "PT";
    public static final String USER_DIR = "user.dir";
    public static final String OS_NAME = "os.name";
    public static final String TMP_DIR = "java.io.tmpdir";
    public static final String FILE = "file";
    public static final String SIZE = "size";
    public static final String WINDOWS = "Windows";
    public static final String ORG_SPLIT = "/";
    public static final String HYPHEN = "-";
    public static final String SYS_ADMIN = "sysadmin";
    public static final String VERSION_VALUE = "1.0.0.1";
    public static final String PATH = "path";
    public static final String TYPE = "type";
    public static final String LOCAL = "local";
    public static final String OSS = "oss";
    public static final String UPLOAD_TYPE = "uploadType";
    public static final String TEMP = "temp";
    public static final String DEFAULT_DATE_PATTERN = "yyyy-MM-dd HH:mm:ss";
    public static final String DEFAULT_DATE_YMD_PATTERN = "yyyy-MM-dd";
    public static final String DEFAULT_DATE_CODE_PATTERN = "yyyyMMdd";
    public static final String DEFAULT_DATE_ATTACHMENT_PATTERN = "/yyyy/MM/dd";
    public static final String DEFAULT_DATE_DAY_PATTERN = "MM月dd日";
    public static final String DEFAULT_DATE_YEAR_PATTERN = "YYYY年";
    public static final String DEFAULT_DATE_YMD_S_PATTERN = "yyyy年MM月dd日";
    public static final String JSON_PREFIX = ".json";
    public static final String XLSX_PREFIX = ".xlsx";
    public static final String XLS_PREFIX = "xls";
    public static final String EXCEL_DATA = "excelData";
    public static final String EXCEL_DATA_ERROR = "excelDataError";
    public static final String EXCEL_ATTACHMENT = "excelAttachment";
    public static final int PAGE_SIZE_MIN = 10;
    public static final int PAGE_SIZE_MAX = 500;
    public static final int PAGE_SIZE_MAX_SELECT = 100000;
    public static final int IN_SIZE_MAX = 1000;
    public static final int PAGE_NUMBER_MIN = 1;
    public static final String STATIC = "static";
    public static final String CATALOG_LINK = "->";
    public static final int MAX_SEQUENCE_CIRCLE_COUNT = 20;
    public static final int SEQUENCE_THREAD_SLEEP = 500;
    public static final String ERROR_METHOD = "method";
    public static final String LIST_JOIN_SPLIT = ",";
    public static final String JOB_DATA = "jobData";
//    public static final String AND = " and ";
//    public static final String OR = " or ";
    //    public static final String APPROVE_MAP_VAR = "approve_map_var";
//    public static final String APPROVE_AUTO = "auto";
    public static final String SYSTEM_AUTO_APPROVE = "系统自动审批";
    public static final String VALUE = "value";
    public static final String SOP = "SOP";
    public static final String RTZF_TENANT_ID = "tenantId";
    public static final String LIMIT1 = "limit 1";

    /**
     * 微信app
     */
    public static final String PURE_PHONE_NUMBER = "purePhoneNumber";
    public static final String AES_CBC_PKCS5 = "AES/CBC/PKCS5Padding";
    public static final String AES = "AES";

    /**
     * sop列表转换字段
     */
    public static Map<String, String> SOP_TRANSFORM_MAP = new LinkedHashMap<>();//sop固定列转换map

    /**
     * 流程动态表单字段
     */
    //SOP
    public static final String SOP_DYNAMIC_TABLE_FILE_NAME = "db/dynamic_create_sop_table.sql";
    public static final String FLOW_DEPLOYMENT_ID_FIELD = "flow_deployment_id";
    public static final String VERSION = "version";
    public static final String CODE = "code";
    public static final String FLOW_ID = "flow_id";
    public static final String REGION_USER_ID = "region_user_id";
    public static final String ENGINEER_USER_ID = "engineer_user_id";
    public static final String ASSISTANT_ENGINEER_USER_ID = "assistant_engineer_user_id";
    public static final String APPROVE_RADIO_REGION = "approve_radio_region";
    public static final String APPROVE_REMARK_REGION = "approve_remark_region";
    public static final String SIGN_REGION = "sign_region";
    public static final String THIRD_SERVICE_REGION_CB = "third_service_region_cb";

    public static final String DEVICE_OUT_TIME = "device_out_time";//设备出库时间
    public static final String DEVICE_OUT_TABLE = "device_out_table";//设备出库
    public static final String DEVICE_IN_TIME = "device_in_time";//设备入库时间
    public static final String DEVICE_IN_TABLE = "device_in_table";//设备入库

    //质量问题反馈
    public static final String PROBLEM_POINT = "problem_point";
    public static final String PROBLEM_REMARK = "problem_remark";
    public static final String ATTACHMENT_INFO = "attachments_info";
    public static final String PROBLEM_TYPE = "problem_type";
    public static final String PROBLEM_REASON_RADIO = "problem_reason_radio";
    public static final String PROBLEM_DEGREE_RADIO = "problem_degree_radio";
    public static final String PROBLEM_USERS = "problem_users";
    public static final String APPROVE_CHECK_USERS = "approve_check_users";
    public static final String APPROVE_CHECK_THIRD_USERS = "approve_check_third_users";

    /**
     * 表达式
     */
    public static final String REGULAR_EXPRESSION_OF_PHONE = "((\\d{3,4})|(\\(\\d{3,4}\\)-))?\\d{7,8}";
    // 有效邮箱校验表达式
    public static final String EMAIL_REGEX = "^[A-Za-z0-9]+([._%+-][A-Za-z0-9]+)*@[A-Za-z0-9]+(\\.[A-Za-z0-9]+)*(\\.[A-Za-z]{2,})$";

    /**
     * 系统配置
     */
    public static final String SYS_CODE_ENABLE = "sys.code.enable";
    //    public static final String SYS_MESSAGE_ENABLE = "sys.message.enable";
//    public static final String SYS_MESSAGE_RESEND_COUNT = "sys.message.resendCount";
    public static final String SYS_CONFIG_KEY_CHARSETS = "sys.txt.charset";
    public static final String ADMIN_LOGO_URL = "admin.logo.url";
    public static final String ATTACHMENT_TYPE = "attachment.type";
    public static final String ATTACHMENT_LENGTH = "attachment.length";
    public static final String ATTACHMENT_SIZE = "attachment.size";
    public static final String THREAD_POOL_CORE_SIZE = "thread.pool.core.size";
    public static final String CUSTOM_THREAD_POOL_CORE_SIZE = "custom.thread.pool.core.size";
    public static final String SESSION_ACTIVE = "session.active";
    public static final String SMS_NORMAL_CODE = "sms.normal.code";
    public static final String CODE_EXPIRED_TIME = "code.expired.time";
    public static final String CODE_SEND_INTERVAL = "code.send.interval";
    public static final String SMS_SIGN_NAME = "sms.sign.name";
    public static final String SMS_TPL_CODE = "sms.tpl.code";
    public static final String FLOW_CODE_LENGTH = "flow.code.length";
    public static final String FLOW_JOB_BEFORE_TIME = "flow.job.before.time";
    public static final String FLOW_JOB_AFTER_TIME = "flow.job.after.time";
    public static final String NOTICE_JOB_AFTER_TIME = "notice.job.after.time";
    public static final String REMIND_JOB_POLL_TIME = "remind.job.poll.time";
    public static final String REMIND_JOB_DB_LIMIT = "remind.job.db.limit";
    public static final String SMS_NOTICE_CODE = "sms.notice.code";
    public static final String SMS_SOP_BEFORE_REMIND_CODE = "sms.sop.before.remind.code";
    public static final String SMS_SOP_DONE_CODE = "sms.sop.done.code";
    public static final String SMS_FLOW_PROJECT_EXCHANGE_FINISH_CODE = "sms.flow.project.exchange.finish.code";
    public static final String SMS_FLOW_DING_EXCEPTION_FINISH_CODE = "sms.flow.ding.exception.finish.code";
    public static final String SMS_SOP_AFTER_REMIND_CODE = "sms.sop.after.remind.code";
    public static final String SMS_VIOLATION_REMIND_CODE = "sms.violation.remind.code";
//    public static final String WXAPP_APP_ID = "wxapp.appid";
//    public static final String WXAPP_REQUEST_URL = "wxapp.request.url";
//    public static final String WXAPP_PHONE_BIND_NEW_URL = "wxapp.phone.bind.new.url";
//    public static final String FACE_VERIFY_BAIDU_LOCAL_APP_ID = "face.verify.baiduLocalAppId";
//    public static final String FACE_VERIFY_BAIDU_LOCAL_URL_PREFIX = "face.verify.baiduLocalUrlPrefix";
    public static final String BAIDU_FACE_COMPARE_URL = "baidu.face.compare.url";
    public static final String BAIDU_FACE_COMPARE_SCORE = "baidu.face.compare.score";
//    public static final String FXXK_APP_ID = "fxxk.app.id";
//    public static final String FXXK_APP_SECRET = "fxxk.app.secret";
//    public static final String FXXK_PERMANENT_CODE = "fxxk.permanent.code";
//    public static final String FXXK_CURRENT_OPEN_USER_ID = "fxxk.curren.open.user.id";
//    public static final String FXXK_API_NAME_CRM = "fxxk.api.name.crm";
//    public static final String FXXK_API_NAME_CRM_DETAIL = "fxxk.api.name.crm.detail";
    public static final String FXXK_APP_AUTH_URL = "fxxk.app.auth.url";
    public static final String FXXK_USER_BY_MOBILE_URL = "fxxk.user.by.mobile.url";
    public static final String FXXK_CUSTOM_QUERY_URL = "fxxk.custom.query.url";
    public static final String FXXK_USER_QUERY_URL = "fxxk.user.query.url";
    public static final String RTZF_OSS_LOGIN_URL = "rtzf.oss.login.url";

    /**
     * api前缀
     */
    public static final String PREFIX_URL_WIDGET = "/admin/widget";
    public static final String PREFIX_FLOW = "/admin/flow";
    public static final String PREFIX_URL_COMMON = "/admin/common";
    public static final String PREFIX_URL_WXAPP = "/admin/wxapp";
    public static final String PREFIX_URL_USER = "/admin/user";
    public static final String PREFIX_URL_USER_ARCHIVES = "/admin/user/archives";
    public static final String PREFIX_URL_USER_ARCHIVES_ALLOCATION = "/admin/user/archives/allocation";
    public static final String PREFIX_URL_TASK = "/admin/task";
    public static final String PREFIX_URL_SYS = "/admin/sys";
    public static final String PREFIX_URL_ORG = "/admin/org";
    public static final String PREFIX_URL_CUSTOM = "/sys/custom";
    public static final String PREFIX_URL_LEVEL = "/sys/level";
    public static final String PREFIX_URL_DEVICE = "/sys/device";
    public static final String PREFIX_URL_DING_GROUP = "/sys/ding/group";
    public static final String PREFIX_URL_SUPPLIER = "/sys/supplier";
    public static final String PREFIX_URL_LOG = "/sys/log";
    public static final String PREFIX_URL_NOTICE = "/sys/notice";
    public static final String PREFIX_URL_MESSAGE = "/sys/message";
    public static final String PREFIX_URL_SERVICE_SERVICE_UNIT = "/service/service/unit";
    public static final String PREFIX_URL_SERVICE_SERVICE_SCOPE = "/service/service/scope";
    public static final String PREFIX_URL_SERVICE_SERVICE_REGION = "/service/service/region";
    public static final String PREFIX_URL_ROLE = "/admin/role";
    public static final String PREFIX_URL_DELAY_WARN = "/admin/tb/delay/warn";
    public static final String PREFIX_URL_DELAY_WARN_DETAIL = "/admin/tb/delay/warn/detail";
    public static final String PREFIX_URL_VIOLATION = "/admin/tb/violation";
    public static final String PREFIX_URL_VIOLATION_DETAIL = "/admin/tb/violation/detail";
    public static final String PREFIX_URL_DING = "/admin/tb/ding";
    public static final String PREFIX_URL_DING_SUBMIT = "/admin/tb/ding/submit";
    public static final String PREFIX_URL_QUALITY_PROBLEM_APPLY = "/admin/tb/quality/problem/apply";
    public static final String PREFIX_URL_CRM = "/admin/tb/crm";
    public static final String PREFIX_URL_DING_EXCEPTION_APPLY = "/admin/ding/exception/apply";
    public static final String PREFIX_URL_PRODUCT = "/admin/tb/product";
    public static final String PREFIX_URL_MY_WORK_BENCH = "/admin/my/work_bench";
    public static final String PREFIX_URL_PROJECT_EXCHANGE = "/admin/project/exchange";
    public static final String PREFIX_URL_DEVICE_IN_OUT = "/admin/device/in/out";
    public static final String PREFIX_URL_SOP = "/admin/sop";
    public static final String PREFIX_URL_FXXK = "/open/fxxk";
    public static final String PREFIX_URL_SSO = "/sso";
    public static final String PREFIX_URL_DEVICE_DELIVERY = "/admin/device/delivery";

    /**
     * 缓存配置
     */
    public static final String USER_ACCOUNT_CACHE = "user:account:cache";
    public static final String SYS_CONFIG_CACHE = "sys:config:cache";
    public static final String USER_OAUTH_CACHE = "user:oauth:cache";
    public static final String ORG_CACHE = "org:cache";
    public static final String PRIVILEGE_URL_CACHE = "privilege:url:cache";
    public static final String ROLE_PRIVILEGE_CACHE = "role:privilege:cache";
    public static final String USER_ROLE_PRIVILEGE_CACHE = "user:role:privilege:cache";
    public static final String FORM_WIDGET_CACHE = "form:widget:cache";
    public static final String TABLE_PROP_CACHE = "table:prop:cache";
    public static final String ROLE_CACHE = "role:cache";
    public static final String USER_MENU_CACHE = "user:menu:cache";
    public static final String SCHOOL_CACHE = "school:cache";
    public static final String SCHOOL_CODE_CACHE = "school:code:cache";

    /**
     * 鉴权
     */
    public static final String HEADER_AUTHORIZATION = "Authorization";
    public static final String HEADER_TIME = "time";
    public static final String HEADER_PLATFORM = "platform";
    public static final String HEADER_DEVICE_ID = "deviceId";
    public static final String CURRENT_PRIVILEGE_ID = "privilegeId";
    public static final String TOKEN = "token";
    public static final String SIGN = "sign";
    public static final String LOG_ERROR = "请求出错:{}";

    public static final int DEFAULT_SESSION_EXPIRE = 1;//过期时间1天
    public static final long DEFAULT_EXPIRE_TIME = 24 * 60L * 60L;//过期时间24小时
    public static final long THIRD_USER_AUTH_EXPIRE_TIME = 2 * 60L;//过期时间2分钟

    /**
     * http设置
     */
    public static final int CONNECT_TIME_OUT = 1000 * 60 * 2;//请求超时
    public static final int SOCKET_CONNECT_TIME_OUT = 1000 * 60 * 30;//读取数据超时

    /**
     * 线程池配置
     */
    public static final String THREAD_POOL_NAME = "taskThreadPool";
    //    public static final int THREAD_POOL_CORE_POOL_SIZE = 5;
//    public static final int THREAD_POOL_MAX_POOL_SIZE = 100;
    public static final int THREAD_POOL_KEEP_ALIVE_SECONDS = 10;
    public static final int THREAD_POOL_QUEUE_CAPACITY = 500;

    /**
     * 流程相关
     */
    public static LinkedMultiValueMap<String, String> FLOW_MAP = new LinkedMultiValueMap<>();
    public static final String BPMN_PREFIX = ".bpmn";
    public static final String END_EVENT = "endEvent";
    public static final String USER_TASK = "userTask";
    public static final String START_EVENT = "startEvent";
    public static final String NAME = "name";
    public static final String ID = "id";
    public static final String FORM_KEY = "formKey";
    public static final String FLOW_FORM_ID_SPACE = "|";
    public static final String FLOW_FORM_ID_UNDERLINE = "_";
    public static final String FORM_PROPERTIES = "formProperties";
    public static final String FLOW_DEPLOYMENT_ID = "flowDeploymentId";
    public static final String APPROVE = "approve";//流程审核变量
    public static final String DEFAULT_ASSIGNEE_LIST = "assigneeList";
    public static final String ASSIGNEE = "assignee";
    public static final String NR_OF_COMPLETED_INSTANCES = "nrOfCompletedInstances";
    public static final String NR_OF_INSTANCES = "nrOfInstances";
    public static final String ARRROVE_REJECT_MAP = "approveRejectMap";
    public static final String FLOW_CUSTOM = "tfCustomFlow";
    public static final String FLOW_APPROVE = "tfFlowApprove";
    public static final String FLOW_APPROVE_LOG = "tfFlowApproveLog";
    public static final String FLOW_ENTITY = "tfCustomFlowEntity";
    public static final String FLOW_SYS_USER = "sysUser";
    public static final String CRM_INFO = "crmInfo";
    public static final String SOP_ID = "sopId";
    public static final String SOURCE = "source";

    /**
     * 锁
     */
    public static final String LOCK_FLOW_TASK_PREFIX = "lock:flow:task:";//流程节点锁
    public static final String LOCK_FLOW_END_PREFIX = "lock:flow:end:";//流程结束锁
    public static final String LOCK_FLOW_EXCHANGE_PREFIX = "lock:flow:exchange:";//流程转办锁
    public static final String LOCK_SEQUENCE_PREFIX = "lock:sequence:";//序列锁
    public static final String LOCK_JOB_PREFIX = "lock:job:";//定时任务锁

    public static final Long LOCK_FLOW_TIME_OUT = 60L * 2 * 1000;
    public static final Long LOCK_SEQUENCE_TIME_OUT = 60L * 1 * 1000;
    public static final Long LOCK_JOB_TIME_OUT = 60L * 5 * 1000;

    static {
        SOP_TRANSFORM_MAP.put("serviceName", "tbs.name");
        SOP_TRANSFORM_MAP.put("sopNo", "tbsi.sop_no");
        SOP_TRANSFORM_MAP.put("crmNo", "tbsi.crm_no");
        SOP_TRANSFORM_MAP.put("beginTime", "tbc.begin_time");
        SOP_TRANSFORM_MAP.put("customManagerName", "su1.real_name");
        SOP_TRANSFORM_MAP.put("customManagerType", "sc.type");
        SOP_TRANSFORM_MAP.put("customName", "sc.name");
        SOP_TRANSFORM_MAP.put("crmName", "tbc.name");
        SOP_TRANSFORM_MAP.put("productName", "tbp.name");
        SOP_TRANSFORM_MAP.put("examStartTime", "tbc.exam_start_time");
        SOP_TRANSFORM_MAP.put("examEndTime", "tbc.exam_end_time");
        SOP_TRANSFORM_MAP.put("flowCreateName", "su2.real_name");
        SOP_TRANSFORM_MAP.put("flowCreateTime", "tffa.create_time");
        SOP_TRANSFORM_MAP.put("status", "tffa.status");
        SOP_TRANSFORM_MAP.put("taskName", "art.NAME_");
        SOP_TRANSFORM_MAP.put("pendApproveName", "ari.USER_ID_");
    }

    /**
     * 获取数据库uuid
     *
     * @return
     */
    public static Long getDbUuid() {
        UidService uidservice = SpringContextHolder.getBean(UidService.class);
        return uidservice.getId();
    }

    /**
     * 获取全局uuid
     *
     * @return
     */
    public static String getNanoId() {
        return NanoIdUtils.randomNanoId();
    }

    /**
     * 获取dirname
     *
     * @param uploadFileEnum
     * @param fileSpearator
     * @return
     */
    public static StringJoiner getDirName(UploadFileEnum uploadFileEnum, boolean fileSpearator) {
        StringJoiner stringJoiner = new StringJoiner("");
        stringJoiner.add(MessageFormat.format("{0}{1}", uploadFileEnum.getTitle(), DateUtil.format(new Date(), SystemConstant.DEFAULT_DATE_ATTACHMENT_PATTERN)));
        stringJoiner = fileSpearator ? stringJoiner.add(File.separator) : stringJoiner;
        return stringJoiner;
    }

    /**
     * 获取当前年月日时间
     *
     * @return
     */
    public static String getNowTime() {
        return DateUtil.format(new Date(), SystemConstant.DEFAULT_DATE_CODE_PATTERN);
    }

    /**
     * 获取临时文件
     *
     * @param suffix
     * @return
     */
    public static File getFileTempVar(String suffix) throws IOException {
        File fileTmpDir = new File(System.getProperty(SystemConstant.TMP_DIR));
        if (!fileTmpDir.exists()) {
            fileTmpDir.mkdirs();
        }
        File file = File.createTempFile(SystemConstant.TEMP, suffix);
        log.info("getFileTempVar_absolutePath:{}", file.getAbsolutePath());
        return file;
    }

    /**
     * URL 编码, Encode默认为UTF-8.
     *
     * @param part
     * @return
     */
    public static String urlEncode(String part) {
        try {
            return URLEncoder.encode(part, SystemConstant.CHARSET_NAME);
        } catch (UnsupportedEncodingException e) {
            throw ExceptionResultEnum.ERROR.exception(e.getMessage());
        }
    }

    /**
     * 时间相加
     *
     * @param duration
     * @return
     */
    public static Long processMiniutePlus(Duration duration) {
        LocalDateTime nowTime = LocalDateTime.now();
        LocalDateTime newDateTime = nowTime.plus(duration);
        return newDateTime.toInstant(ZoneOffset.ofHours(8)).toEpochMilli();
    }

    /**
     * 时间相减
     *
     * @param duration
     * @return
     */
    public static Long processMiniuteMinus(Duration duration) {
        LocalDateTime nowTime = LocalDateTime.now();
        LocalDateTime newDateTime = nowTime.minus(duration);
        return newDateTime.toInstant(ZoneOffset.ofHours(8)).toEpochMilli();
    }

    /**
     * 指定时间相加
     *
     * @param duration
     * @return
     */
    public static Long processMiniutePlus(Long time, Duration duration) {
        LocalDateTime localDateTime = LocalDateTime.ofEpochSecond(time / 1000, 0, ZoneOffset.ofHours(8));
        LocalDateTime newDateTime = localDateTime.plus(duration);
        return newDateTime.toInstant(ZoneOffset.ofHours(8)).toEpochMilli();
    }

    /**
     * 指定时间相减
     *
     * @param duration
     * @return
     */
    public static Long processMiniuteMinus(Long time, Duration duration) {
        LocalDateTime localDateTime = LocalDateTime.ofEpochSecond(time / 1000, 0, ZoneOffset.ofHours(8));
        LocalDateTime newDateTime = localDateTime.minus(duration);
        return newDateTime.toInstant(ZoneOffset.ofHours(8)).toEpochMilli();
    }

    /**
     * string id 转化为long
     *
     * @param id string id
     * @return long id
     */
    public static Long convertIdToLong(String id) {
        return Objects.nonNull(id) && id.length() > 0 ? Long.parseLong(id) : null;
    }

    /**
     * 模糊查询时调用以去除符号"%","_"特殊字符对查询结果的影响
     *
     * @param param 要校验的参数
     * @return 转译后的参数
     */
    public static String translateSpecificSign(String param) {
        if (param == null) {
            return null;
        }
        if (param.contains("%")) {
            param = param.replaceAll("%", "\\\\%");
        }
        if (param.contains("_")) {
            param = param.replaceAll("_", "\\\\_");
        }
        return param;
    }

    /**
     * 参数只要有一个为空？
     *
     * @param objects 参数
     * @return true:只要有一个为空；false: 全部非空
     */
    public static boolean isOneNull(Object... objects) {
        boolean result = false;
        for (Object object : objects) {
            if (Objects.isNull(object)) {
                result = true;
            } else if (object instanceof String) {
                String param = String.valueOf(object);
                if (param.length() == 0 || param.equals("null")) {
                    result = true;
                }
            } else if (object instanceof Long) {
                Long param = SystemConstant.convertIdToLong(String.valueOf(object));
                if (param == null || param == 0) {
                    result = true;
                }
            } else if (object instanceof Integer) {
                int param = Integer.parseInt(String.valueOf(object));
                if (param == 0) {
                    result = true;
                }
            }
        }
        return result;
    }

    /**
     * 根据键值对的值倒序排序
     *
     * @param map 键值对
     * @param <K> 键
     * @param <V> 值
     * @return 排序结果
     */
    @SuppressWarnings({"unchecked", "rawtypes"})
    public static <K extends Comparable, V extends Comparable> Map<K, V> sortMapByValues(Map<K, V> map) {
        HashMap<K, V> finalMap = new LinkedHashMap<K, V>();
        //取出map键值对Entry<K,V>，然后按照值排序，最后组成一个新的列表集合
        List<Map.Entry<K, V>> list = map.entrySet()
                .stream()
                .sorted((p1, p2) -> p2.getValue().compareTo(p1.getValue()))
                .collect(Collectors.toList());
        //遍历集合，将排好序的键值对Entry<K,V>放入新的map并返回
        //因为HashMap默认是按照键排序，所以新的map还是HashMap，那么就还原了。达不到排序的效果。
        //所以新的map需要LinkedHashMap类型。这里也可以看出LinkedHashMap是按照顺序存储。
        list.forEach(ele -> finalMap.put(ele.getKey(), ele.getValue()));
        return finalMap;
    }
}