package cn.com.capcloud.api.action.service;

import cn.com.capcloud.ccui.core.common.json.JackJSON;
import cn.com.capcloud.ccui.core.common.json.JackJSONArray;
import cn.com.capcloud.ccui.core.common.json.JackJSONObject;
import cn.com.capcloud.core.lucene.SearchParam;
import cn.com.capcloud.core.noentitydb.BaseDao;
import cn.com.capcloud.core.noentitydb.DBCheck;
import cn.com.capcloud.core.util.sm.SM2Utils;
import cn.com.capcloud.core.util.sm.Util;
import cn.com.capcloud.core.cache.BaseConfigStaticCache;
import cn.com.capcloud.core.noentitydb.JtPage;
import cn.com.capcloud.core.system.user.User;
import cn.com.capcloud.core.system.user.UserService;
import cn.com.capcloud.core.websocket.RedisPublication;
import net.sourceforge.pinyin4j.PinyinHelper;
import net.sourceforge.pinyin4j.format.HanyuPinyinCaseType;
import net.sourceforge.pinyin4j.format.HanyuPinyinOutputFormat;
import net.sourceforge.pinyin4j.format.HanyuPinyinToneType;
import net.sourceforge.pinyin4j.format.exception.BadHanyuPinyinOutputFormatCombination;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.joda.time.DateTime;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;

import javax.servlet.http.HttpServletRequest;
import java.io.*;
import java.lang.reflect.Method;
import java.text.DateFormat;
import java.text.DecimalFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.regex.Pattern;

public class ApiDao {
    //PDF需要展示的字段
    private static final String SYSTEM_SETTINGS_DS_FORM_PDF_SHOWTYPE="system.settings.ds.form.pdf.show_type";
    /**
     * id 优先级最高，其次是dsCode
     */
    public static Map<String, Object> findDataSource(String uuid,String dsCode, JdbcTemplate jdbcTemplate) {
        String sql="SELECT * FROM tbl_data_source WHERE STATUS =0 ";
        if(uuid!=null){
            sql+=" AND uuid = '"+uuid+"'";
        }else if(dsCode!=null){
            sql+=" AND ds_code = '"+dsCode+"'";
        }
        List<Map<String, Object>> list = jdbcTemplate.queryForList(sql);
        if(list.size()==0){
            return null;
        }else{
            return list.get(0);
        }
    }
    /**
     * id 优先级最高，其次是dsCode
     */
    public static Map<String, Object> findNoSessionInfo(String uuid,String nosessionCcode, JdbcTemplate jdbcTemplate) {
        String sql="SELECT * FROM tbl_data_nosession WHERE STATUS =0 ";
        if(uuid!=null){
            sql+=" AND uuid = '"+uuid+"'";
        }else if(nosessionCcode!=null){
            sql+=" AND nosession_code = '"+nosessionCcode+"'";
        }
        List<Map<String, Object>> list = jdbcTemplate.queryForList(sql);
        if(list.size()==0){
            return null;
        }else{
            return list.get(0);
        }
    }
    /**
     * @param str 加密字符串
     */
    public static String smEncrypt(String str,String pubKey) {
        String cipherText ="";
        try {
            byte[] sourceData = str.getBytes();
            cipherText = SM2Utils.encrypt(Util.hexToByte(pubKey), sourceData);
        } catch (IOException e) {
        }
        return cipherText;
    }
    /**
     * @param str 解密字符串
     */
    public static String smDecrypt(String str,String priKey) {
        String plainText ="";
        try {
            plainText = new String(SM2Utils.decrypt(Util.hexToByte(priKey), Util.hexToByte(str)));
        } catch (IOException e) {
        }
        return plainText;
    }
    /**
     * @param dictCode 内部字典编码
     */
    public static List<Map<String, Object>> getDictInfoByDictCodeToList(String dictCode, JdbcTemplate jdbcTemplate) {
        String sqlChar= DBCheck.getIdentifierQuoteChar();
        String sql="SELECT dict_key as "+sqlChar+"key"+sqlChar+",dict_value as "+sqlChar+"value"+sqlChar+" FROM  tbl_data_dict_info  \n" +
                "WHERE STATUS=0 AND page_parent_uuid=\n" +
                "(SELECT uuid FROM tbl_data_dict WHERE STATUS=0 AND dict_code='"+dictCode+"') \n" +
                "AND dict_status=0 order by dict_sort asc ";
        List<Map<String, Object>> queryDictData = jdbcTemplate.queryForList(sql);
        return queryDictData;
    }
    /**
     * @param dictCode 外部字典编码
     */
    public static List<Map<String, Object>> getOutDictInfoByDictCodeToList(String dictCode, JdbcTemplate jdbcTemplate, User user) {
        String sql=ApiDao.getOutDictWhereSql(dictCode,jdbcTemplate,user);
        List<Map<String, Object>> returnQueryDictData=new ArrayList<>();
        if(sql!=null){
            List<Map<String, Object>> queryDictData=jdbcTemplate.queryForList(sql);
            //将key类型转为字符串
            for (int i = 0; i < queryDictData.size(); i++) {
                Map<String,Object> map=new HashMap<>();
                String key=String.valueOf(queryDictData.get(i).get("key"));
                String value=String.valueOf(queryDictData.get(i).get("value"));
                map.put("key",key);
                map.put("value",value);
                returnQueryDictData.add(map);
            }
        }
        return returnQueryDictData;
    }
    public static List<Map<String, Object>> getOutDictInfoByDictCodeToList(String dictCode, JdbcTemplate jdbcTemplate) {
        return getOutDictInfoByDictCodeToList(dictCode,jdbcTemplate,null);
    }
    /**
     * @param dictCode 第三方字典编码
     */
    public static List<Map<String, Object>> getTPDictInfoByDictCodeToList(String dictCode, JdbcTemplate jdbcTemplate) {
        List<Map<String, Object>> returnQueryDictData= null;
        try {
            String querySql="select * from tbl_data_dict_tp where tp_dict_code='"+dictCode+"'";
            List<Map<String, Object>> dictList=jdbcTemplate.queryForList(querySql);
            String myActionClass=String.valueOf(dictList.get(0).get("my_action_class"));
            String methodName=String.valueOf(dictList.get(0).get("method_name"));
            String whereJson=String.valueOf(dictList.get(0).get("where_json"));
            Class actionClass = Class.forName(myActionClass);
            Object myActionClassInstance=actionClass.newInstance();
            Method method = actionClass.getMethod(methodName,String.class);
            Object retObj=method.invoke(myActionClassInstance,whereJson);
            List<Map<String, Object>> queryDictData= (List<Map<String, Object>>) retObj;
            returnQueryDictData = new ArrayList<>();
            //将key类型转为字符串
            for (int i = 0; i < queryDictData.size(); i++) {
                Map<String,Object> map=new HashMap<>();
                String key=String.valueOf(queryDictData.get(i).get("key"));
                String value=String.valueOf(queryDictData.get(i).get("value"));
                map.put("key",key);
                map.put("value",value);
                returnQueryDictData.add(map);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return returnQueryDictData;
    }
    /**
     * @param treeCode tree字典编码
     */
    public static List<Map<String, Object>> getTreeInfoByTreeCodeToList(String treeCode,String pId,User user, JdbcTemplate jdbcTemplate) {
        String queryTreeInfo="SELECT * FROM tbl_data_tree WHERE status=0 and tree_code='"+treeCode+"'";
        List<Map<String, Object>> treeList=jdbcTemplate.queryForList(queryTreeInfo);
        if(treeList.size()==0){
            return new ArrayList<>();
        }
        Map<String, Object> treeInfo=treeList.get(0);
        if(pId==null||pId.equals("")||pId.length()==0){
            pId=String.valueOf(treeInfo.get("t_first_id_value"));
        }
        String whereSql="";
        String fromSql="";
        if(!"null".equals(pId)&&pId.length()>0){
            String queryFunctionSql="SHOW FUNCTION STATUS WHERE NAME='"+treeInfo.get("tree_code")+"' AND DB='"+ DBCheck.getDatabaseName()+"'";
            if(DBCheck.isKingbase()){
                queryFunctionSql="SELECT proname, proargtypes FROM pg_proc WHERE proname = '"+treeInfo.get("tree_code")+"';";
            }
            if(jdbcTemplate.queryForList(queryFunctionSql).size()==0){
                initTreeFunction(treeInfo,jdbcTemplate);
            }
            fromSql+=",(SELECT "+treeInfo.get("tree_code")+"('"+pId+"') ids)t";
            whereSql+=" AND (FIND_IN_SET("+treeInfo.get("t_p_id")+",ids) OR "+treeInfo.get("t_id")+"='"+pId+"')";
        }
        String name=String.valueOf(treeInfo.get("t_name"));
        String[] strArray=name.split(",");
        if(strArray.length>=2){
            String split=String.valueOf(treeInfo.get("split"));
            name="CONCAT(";
            for (int i = 0; i < strArray.length; i++) {
                name+=strArray[i]+",";
                name+="'"+split+"',";
            }
            name=name.substring(0,name.length()-(4+split.length()));//4是：,'', #所以减4，还需减去分割符的长度，也就是4+分隔符的长度
            name+=")";
        }
        String tWhereJsonStr=String.valueOf(treeInfo.get("t_where_json"));
        if(!"null".equals(tWhereJsonStr)&&tWhereJsonStr.length()>0){
            JackJSONObject json= JackJSONObject.fromObject(tWhereJsonStr);
            for(Object key:json.keySet()) {
                String value=String.valueOf(json.get(key));
                if((value.equals("${org_id}")||value.equals("${user_id}"))&&user==null){
                    continue;
                }
                whereSql+=" and "+key+"='"+json.get(key)+"'";
            }
            whereSql+=" order by "+treeInfo.get("t_default_sort_field") +" "+treeInfo.get("t_default_sort_type");
        }
        if(user!=null){
            whereSql=whereSql.replace("${org_id}",""+user.getOrgId());
            whereSql=whereSql.replace("${user_id}",""+user.getId());
        }
        String sqlChar= DBCheck.getIdentifierQuoteChar();
        String queryTreeSql="SELECT " +sqlChar+
                treeInfo.get("t_id")+sqlChar+" as id,"+sqlChar+
                treeInfo.get("t_p_id")+sqlChar+" as pId," +sqlChar+
                name+sqlChar+" as name," +sqlChar+
                treeInfo.get("t_level")+sqlChar+" as level " +
                " FROM "+treeInfo.get("t_table_name") +fromSql+
                " WHERE 1=1 " +whereSql;
        List<Map<String, Object>> queryDictData = jdbcTemplate.queryForList(queryTreeSql);
        return queryDictData;
    }
    public static void initTreeFunction(Map<String,Object> treeInfo,JdbcTemplate jdbcTemplate){
        if(DBCheck.isKingbase()){
            String dropSql="DROP FUNCTION IF EXISTS "+treeInfo.get("tree_code")+"(integer)";
            jdbcTemplate.execute(dropSql);
            String initSql="CREATE OR REPLACE FUNCTION "+treeInfo.get("tree_code")+"(p_id INT)\n" +
                    "RETURNS VARCHAR AS $$\n" +
                    "WITH RECURSIVE tree_"+treeInfo.get("t_table_name")+" AS (\n" +
                    "    SELECT "+treeInfo.get("t_id")+"\n" +
                    "    FROM "+treeInfo.get("t_table_name")+"\n" +
                    "    WHERE "+treeInfo.get("t_id")+" = p_id\n" +
                    "    UNION ALL\n" +
                    "    SELECT m."+treeInfo.get("t_id")+"\n" +
                    "    FROM "+treeInfo.get("t_table_name")+" m\n" +
                    "    JOIN tree_"+treeInfo.get("t_table_name")+" mt ON m."+treeInfo.get("t_p_id")+" = mt."+treeInfo.get("t_id")+"\n" +
                    ")\n" +
                    "SELECT ',' || STRING_AGG("+treeInfo.get("t_id")+"::VARCHAR, ',') \n" +
                    "FROM tree_"+treeInfo.get("t_table_name")+";\n" +
                    "$$ LANGUAGE SQL;" ;
            jdbcTemplate.execute(initSql);
            return;
        }
        String dropSql="DROP FUNCTION IF EXISTS "+treeInfo.get("tree_code")+" \n";
        jdbcTemplate.execute(dropSql);
        String initSql="CREATE FUNCTION "+treeInfo.get("tree_code")+"(in_id TEXT) RETURNS TEXT \n" +
                "BEGIN \n" +
                " DECLARE ids TEXT DEFAULT ''; \n" +
                " DECLARE tempids TEXT; \n" +
                " \n" +
                " SET tempids = in_id; \n" +
                " WHILE tempids IS NOT NULL DO \n" +
                "  SET ids = CONCAT_WS(',',ids,tempids); \n" +
                "  SELECT GROUP_CONCAT("+treeInfo.get("t_id")+") INTO tempids FROM "+treeInfo.get("t_table_name")+" WHERE FIND_IN_SET("+treeInfo.get("t_p_id")+",tempids)>0;  \n" +
                " END WHILE; \n" +
                " RETURN ids; \n" +
                "END  \n" ;
        jdbcTemplate.execute(initSql);
    }
    /**
     * 查询外部字典
     * isReversal 是false dict_key做为key
     * isReversal 是true dict_value做为key
     */
    public static Map<String, Object> getOutDictInfoByDictCodeToMap(String dictCode, Boolean isReversal, JdbcTemplate jdbcTemplate) {
        List<Map<String, Object>> queryDictData = jdbcTemplate.queryForList(getOutDictWhereSql(dictCode,jdbcTemplate,null));
        Map<String, Object> dictMap=new HashMap<>();
        for(Map<String,Object> map : queryDictData){
            Iterator<String> it=  map.keySet().iterator();
            Object dictKey="";
            Object dictValue="";
            while(it.hasNext()){
                String key = it.next();
                if(key.equals("key")){
                    dictKey=map.get(key);
                }else if(key.equals("value")){
                    dictValue= map.get(key);
                }
            }
            if(isReversal){
                dictMap.put(dictValue+"",dictKey);
            }else{
                dictMap.put(dictKey+"",dictValue);
            }
        }
        return dictMap;
    }
    /**
     * isReversal 是false dict_key做为key
     * isReversal 是true dict_value做为key
     */
    public static Map<String, Object> getDictInfoByDictCodeToMap(String dictCode, Boolean isReversal, JdbcTemplate jdbcTemplate) {
        String sql="SELECT dict_key as 'key',dict_value as 'value' FROM  tbl_data_dict_info  \n" +
                "WHERE STATUS=0 AND page_parent_uuid=\n" +
                "(SELECT uuid FROM tbl_data_dict WHERE STATUS=0 AND dict_code='"+dictCode+"') \n" +
                "AND dict_status=0";
        List<Map<String, Object>> queryDictData = jdbcTemplate.queryForList(sql);
        Map<String, Object> dictMap=new HashMap<>();
        for(Map<String,Object> map : queryDictData){
            Iterator<String> it=  map.keySet().iterator();
            Object dictKey="";
            Object dictValue="";
            while(it.hasNext()){
                String key = it.next();
                if(key.equals("key")){
                    dictKey=map.get(key);
                }else if(key.equals("value")){
                    dictValue= map.get(key);
                }
            }
            if(isReversal){
                dictMap.put(dictValue+"",dictKey);
            }else{
                dictMap.put(dictKey+"",dictValue);
            }
        }
        return dictMap;
    }
    /**
     * 展示选中名称
     * isReversal 是false dict_key做为key
     * isReversal 是true dict_value做为key
     */
    public static Map<String, Object> getTreeDictInfoByDictCodeToMap(String dictCode, Boolean isReversal,User user, JdbcTemplate jdbcTemplate) {
        String sql="SELECT * FROM tbl_data_tree WHERE status=0 and tree_code='"+dictCode+"'";
        List<Map<String, Object>> treeList=jdbcTemplate.queryForList(sql);
        Map<String, Object> treeInfo=treeList.get(0);
        String name=String.valueOf(treeInfo.get("t_name"));
        String[] strArray=name.split(",");
        if(strArray.length>=2){
            String split=String.valueOf(treeInfo.get("split"));
            name="CONCAT(";
            for (int i = 0; i < strArray.length; i++) {
                name+=strArray[i]+",";
                name+="'"+split+"',";
            }
            name=name.substring(0,name.length()-(4+split.length()));//4是：,'', #所以减4，还需减去分割符的长度，也就是4+分隔符的长度
            name+=")";
        }
        String queryTreeSql="SELECT " +
                treeInfo.get("t_id")+" as 'key',"+
                name+" as 'value'" +
                " FROM "+treeInfo.get("t_table_name");
        String tWhereJsonStr=String.valueOf(treeInfo.get("t_where_json"));
        queryTreeSql+=" where 1=1 ";
        if(!"null".equals(tWhereJsonStr)&&tWhereJsonStr.length()>0){
            JackJSONObject json= JackJSONObject.fromObject(tWhereJsonStr);
            for(Object key:json.keySet()) {
                String value=String.valueOf(json.get(key));
                if((value.equals("${org_id}")||value.equals("${user_id}"))&&user==null){
                    continue;
                }
                queryTreeSql+=" and "+key+"='"+json.get(key)+"'";
            }
            queryTreeSql+=" order by "+treeInfo.get("t_default_sort_field") +" "+treeInfo.get("t_default_sort_type");
        }
        if(user!=null){
            queryTreeSql=queryTreeSql.replace("${org_id}",""+user.getOrgId());
            queryTreeSql=queryTreeSql.replace("${user_id}",""+user.getId());
        }
        List<Map<String, Object>> queryDictData = jdbcTemplate.queryForList(queryTreeSql);
        Map<String, Object> dictMap=new HashMap<>();
        for(Map<String,Object> map : queryDictData){
            Iterator<String> it=  map.keySet().iterator();
            Object dictKey="";
            Object dictValue="";
            while(it.hasNext()){
                String key = it.next();
                if(key.equals("key")){
                    dictKey=map.get(key);
                }else if(key.equals("value")){
                    dictValue= map.get(key);
                }
            }
            if(isReversal){
                dictMap.put(dictValue+"",dictKey);
            }else{
                dictMap.put(dictKey+"",dictValue);
            }
        }
        return dictMap;
    }
    /**
     * 展示完整名称
     * isReversal 是false id做为key
     * isReversal 是true value做为key
     */
    public static Map<String, Object> getTreeDictInfoByDictCodeToFullMap(String dictCode, Boolean isReversal, JdbcTemplate jdbcTemplate) {
        return getTreeDictInfoByDictCodeToFullMap(dictCode,isReversal,null,jdbcTemplate,"");
    }
    public static Map<String, Object> getTreeDictInfoByDictCodeToFullMap(String dictCode, Boolean isReversal,User user, JdbcTemplate jdbcTemplate,String treeShowFullSplit) {
        String sql="SELECT * FROM tbl_data_tree WHERE status=0 and tree_code='"+dictCode+"'";
        List<Map<String, Object>> treeList=jdbcTemplate.queryForList(sql);
        Map<String, Object> treeInfo=treeList.get(0);
        String name=String.valueOf(treeInfo.get("t_name"));
        String[] strArray=name.split(",");
        if(strArray.length>=2){
            String split=String.valueOf(treeInfo.get("split"));
            name="CONCAT(";
            for (int i = 0; i < strArray.length; i++) {
                name+=strArray[i]+",";
                name+="'"+split+"',";
            }
            name=name.substring(0,name.length()-(4+split.length()));//4是：,'', #所以减4，还需减去分割符的长度，也就是4+分隔符的长度
            name+=")";
        }
        String queryTreeSql="SELECT " +
                treeInfo.get("t_id")+" as id,"+
                treeInfo.get("t_p_id")+" as pId," +
                name+" as name," +
                treeInfo.get("t_level")+" as level " +
                " FROM "+treeInfo.get("t_table_name") ;
        String tWhereJsonStr=String.valueOf(treeInfo.get("t_where_json"));
        queryTreeSql+=" where 1=1 ";
        if(!"null".equals(tWhereJsonStr)&&tWhereJsonStr.length()>0){
            JackJSONObject json=JackJSONObject.fromObject(tWhereJsonStr);
            for(Object key:json.keySet()) {
                String value=String.valueOf(json.get(key));
                if((value.equals("${org_id}")||value.equals("${user_id}"))&&user==null){
                    continue;
                }
                queryTreeSql+=" and "+key+"='"+json.get(key)+"'";
            }
            queryTreeSql+=" order by "+treeInfo.get("t_default_sort_field") +" "+treeInfo.get("t_default_sort_type");
        }
        if(user!=null){
            queryTreeSql=queryTreeSql.replace("${org_id}",""+user.getOrgId());
            queryTreeSql=queryTreeSql.replace("${user_id}",""+user.getId());
        }
        List<Map<String, Object>> queryDictData = jdbcTemplate.queryForList(queryTreeSql);
        Map<String, Map<String,Object>> idMap=new HashMap<>();
        for (int i = 0; i < queryDictData.size(); i++) {
            idMap.put(queryDictData.get(i).get("id")+"",queryDictData.get(i));
        }
        Map<String, Object> dictMap=new HashMap<>();
        for (int i = 0; i < queryDictData.size(); i++) {
            String level=String.valueOf(queryDictData.get(i).get("level"));
            if(!level.equals("0")){
                String id=String.valueOf(queryDictData.get(i).get("id"));
                String showValue=getTreeParentName(idMap,id,"",treeShowFullSplit);
                if(isReversal){
                    dictMap.put(showValue,id);
                }else{
                    dictMap.put(id,showValue);
                }
            }
        }
        return dictMap;
    }
    public static String getTreeParentName(Map<String,Map<String,Object>> idMap,String id,String showValue,String treeShowFullSplit){
        String name=String.valueOf(idMap.get(id).get("name"));
        String level=String.valueOf(idMap.get(id).get("level"));
        if(level.equals("1")){
            if(showValue.equals("")){
                return name+showValue;
            }else{
                return name+treeShowFullSplit+showValue;
            }
        }else{
            String pId=String.valueOf(idMap.get(id).get("pId"));
            if(showValue.equals("")){
                return getTreeParentName(idMap,pId,name+showValue,treeShowFullSplit);
            }else{
                return getTreeParentName(idMap,pId,name+treeShowFullSplit+showValue,treeShowFullSplit);
            }
        }
    }
    /**
     * 将一些字典值转换，数据库存储的是字典需要转换一下。
     */
    public static List<Map<String,Object>> changeFormDict(List<Map<String,Object>> fieldList, List<Map<String,Object>> dataList, JdbcTemplate jdbcTemplate) {
        for (int i = 0; i < fieldList.size(); i++) {//这个循环是提前将dict字典查询出来，避免每次循环都查询数据库
            Map<String,Object> field=fieldList.get(i);
            String code=String.valueOf(field.get("dict_code"));
            if(!"null".equals(code)&&code.length()>0){
                if(code.indexOf("tree_")==0){//tree字典
                    String treeShowValueType=String.valueOf(field.get("tree_show_value_type"));
                    Map<String,Object> dictMap;
                    if(treeShowValueType.equals("full")){
                        String treeShowFullSplit=String.valueOf(field.get("tree_show_full_split"));
                        dictMap=getTreeDictInfoByDictCodeToFullMap(code,false,null,jdbcTemplate,treeShowFullSplit);
                    }else{
                        dictMap=getTreeDictInfoByDictCodeToMap(code,false,null,jdbcTemplate);
                    }
                    fieldList.get(i).put("dictMap",dictMap);
                }else if(code.indexOf("o_")==0){//外部字典不放缓存。
                    Map<String,Object> dictMap=getOutDictInfoByDictCodeToMap(code,false,jdbcTemplate);
                    fieldList.get(i).put("dictMap",dictMap);
                }else{//内部字典
                    Map<String,Object> dictMap=getDictInfoByDictCodeToMap(code,false,jdbcTemplate);
                    fieldList.get(i).put("dictMap",dictMap);
                }
            }
        }
        for (int i = 0; i < dataList.size(); i++) {
            Map<String,Object> dataMap=dataList.get(i);
            for (int j = 0; j < fieldList.size(); j++) {
                Map<String,Object> field=fieldList.get(j);
                String code=String.valueOf(field.get("dict_code"));
                String showType=String.valueOf(field.get("show_type"));
                String dictValueSplit=String.valueOf(field.get("dict_value_split"));
                String name=String.valueOf(field.get("name"));
                String value=String.valueOf(dataList.get(i).get(name));
                if((!"null".equals(code)&&code.length()>0)&&(!"null".equals(value)&&value.length()>0)){
                    Map<String,Object> dictMap= (Map<String, Object>) field.get("dictMap");
                    String newValue="";
                    if(showType.equals("checkbox")||showType.equals("selectCheckbox")||showType.equals("treeCheckBox")){
                        if(dictValueSplit.equals("null")||dictValueSplit.length()==0){
                            dictValueSplit=",";
                        }
                        String[] checkboxArray=String.valueOf(dataMap.get(name)).split(",");
                        for (int k = 0; k < checkboxArray.length; k++) {
                            if(checkboxArray[k].equals("")){
                                continue;
                            }
                            newValue+=dictMap.get(checkboxArray[k])+" "+dictValueSplit+" ";
                        }
                        newValue=newValue.substring(0,newValue.length()-3);
                        dataList.get(i).put(name,newValue);
                    }else{
                        newValue=String.valueOf(dictMap.get(dataMap.get(name)));
                        dataList.get(i).put(name,newValue);
                    }
                }
            }
        }
        return dataList;
    }
    /**
     * 生成PDF默认模板HTML
     */
    public static String createOnePdfDefaultHtml(List<Map<String,Object>> fieldList, List<Map<String,Object>> dataList, JdbcTemplate jdbcTemplate) {
        List<String> showTypeArray= Arrays.asList(String.valueOf(BaseConfigStaticCache.get(SYSTEM_SETTINGS_DS_FORM_PDF_SHOWTYPE)).split(","));
        String html="";
        for (int i = 0; i < dataList.size(); i++) {
            for (int j = 0; j < fieldList.size(); j++) {
                if (showTypeArray.contains(String.valueOf(fieldList.get(j).get("show_type")))) {
                    String name=String.valueOf(fieldList.get(j).get("name"));
                    html+="                    <tr>\n";
                    html+="                        <td class=\"table_td_css\">"+fieldList.get(j).get("label_name")+"</td>\n";
                    html+="                        <td>"+dataList.get(i).get(name)+"</td>\n";
                    html+="                    </tr>\n";
                }
            }
        }
        return html;
    }
    public static List<Map<String, Object>> getMenuByParentId(long userId,String parentId,JdbcTemplate jdbcTemplate) {
        String sql="SELECT * FROM tbl_system_menu WHERE STATUS=0 AND menu_status=0 AND menu_parent_id='"+parentId+"' " +
                " AND menu_id IN (SELECT DISTINCT menu_id FROM tbl_system_roleuser ru,tbl_system_menurole mu WHERE ru.role_id=mu.role_id AND ru.user_id="+userId+") " +
                " ORDER BY menu_seq ASC ";
        List<Map<String, Object>> list=jdbcTemplate.queryForList(sql);
        for (int i = 0; i < list.size(); i++) {
            list.get(i).put("menu_child",getMenuByParentId(userId,list.get(i).get("menu_id")+"",jdbcTemplate));
        }
        return list;
    }
    public static List<Map<String, Object>> getMenuByParentIdAndRoleId(long roleId,String parentId,JdbcTemplate jdbcTemplate) {
        String sql="SELECT * FROM tbl_system_menu WHERE STATUS=0 AND menu_status=0 AND menu_parent_id='"+parentId+"' " +
                " AND menu_id IN (SELECT DISTINCT menu_id FROM tbl_system_roleuser ru,tbl_system_menurole mu WHERE ru.role_id=mu.role_id AND ru.role_id="+roleId+") " +
                " ORDER BY menu_seq ASC ";
        List<Map<String, Object>> list=jdbcTemplate.queryForList(sql);
        for (int i = 0; i < list.size(); i++) {
            list.get(i).put("menu_child",getMenuByParentIdAndRoleId(roleId,list.get(i).get("menu_id")+"",jdbcTemplate));
        }
        return list;
    }
    /**
     * @param parentUUID 组件id
     */
    public static List<Map<String, Object>> getButtonByParentUUID(String parentUUID,String whereSql, JdbcTemplate jdbcTemplate) {
        String sql="SELECT * FROM tbl_data_button WHERE STATUS=0 AND button_status=0 AND page_parent_uuid='"+parentUUID+"' "+whereSql+"  ORDER BY button_sort ASC ";
        return JackJSON.parseObject(ApiDao.nullToStrFilter(jdbcTemplate.queryForList(sql)), ArrayList.class);
    }
    /**
     * 生成指定长度随机密码
     * @param len 生成的密码的总长度
     * @return  密码的字符串
     */
    public static String getRandomNum(int len){
        //77是因为数组是从0开始的，52个字母+10个数字+10个特殊字符
        final int  maxNum = 72;
        int i;  //生成的随机数
        int count = 0; //生成的密码的长度
        StringBuffer buf = new StringBuffer("a,b,c,d,e,f,g,h,i,g,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z");
        buf.append(",A,B,C,D,E,F,G,H,I,G,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z");
        buf.append(",!,@,#,$,%,^,&,*,(,)");
        buf.append(",1,2,3,4,5,6,7,8,9,0");
        String[] arr = buf.toString().split(",");

        StringBuffer pwd = new StringBuffer();
        Random r = new Random();
        while(count < len){
            //生成随机数，取绝对值，防止生成负数，
            i = Math.abs(r.nextInt(maxNum));  //生成的数最大为36-1
            if (i >= 0 && i < arr.length) {
                pwd.append(arr[i]);
                count ++;
            }
        }
        return pwd.toString();
    }

    /**
     * 将对象中的所有 null 值转为空字符串
     * @param obj 需要处理的对象，可以是 Map、List 或其他类型
     * @return 转换后的 JSON 字符串
     */
    public static String nullToStrFilter(Object obj) {
        // 调用 convert 方法进行 null 转换
        convert(obj);
        // 返回转换后的 JSON 字符串
        return JackJSON.toJSONString(obj);
    }

    /**
     * 递归遍历对象，处理 Map 和 List 中的 null 值
     * @param obj 需要处理的对象
     */
    private static void convert(Object obj) {
        if (obj == null) return;

        if (obj instanceof Map) {
            convertMap((Map<String, Object>) obj);
        } else if (obj instanceof List) {
            convertList((List<Object>) obj);
        }
    }

    /**
     * 递归处理 Map 中的 null 值
     * @param map Map 对象
     */
    private static void convertMap(Map<String, Object> map) {
        for (Map.Entry<String, Object> entry : map.entrySet()) {
            if (entry.getValue() == null) {
                entry.setValue("");  // 将 null 值替换为空字符串
            } else if (entry.getValue() instanceof Map) {
                convertMap((Map<String, Object>) entry.getValue());  // 递归处理嵌套的 Map
            } else if (entry.getValue() instanceof List) {
                convertList((List<Object>) entry.getValue());  // 递归处理嵌套的 List
            }
        }
    }

    /**
     * 递归处理 List 中的 null 值
     * @param list List 对象
     */
    private static void convertList(List<Object> list) {
        for (int i = 0; i < list.size(); i++) {
            Object item = list.get(i);
            if (item == null) {
                list.set(i, "");  // 将 null 值替换为空字符串
            } else if (item instanceof Map) {
                convertMap((Map<String, Object>) item);  // 递归处理嵌套的 Map
            } else if (item instanceof List) {
                convertList((List<Object>) item);  // 递归处理嵌套的 List
            }
        }
    }



    /**
     * 中文转拼音 不分割
     */
    public static String chineseToPinyin(String chinese){
        return chineseToPinyin(chinese,"");
    }

    /**
     * 中文转拼音 允许传分隔符
     */
    public static String chineseToPinyin(String chinese,String separate){
        HanyuPinyinOutputFormat format = new HanyuPinyinOutputFormat();
        //拼音小写
        format.setCaseType(HanyuPinyinCaseType.LOWERCASE);
        //不带声调
        format.setToneType(HanyuPinyinToneType.WITHOUT_TONE);
        try {
            //参数解释：要转换的中文，格式，转换之后的拼音的分隔符，遇到不能转换的是否保留
            return PinyinHelper.toHanYuPinyinString(chinese, format, separate, true);
        } catch (BadHanyuPinyinOutputFormatCombination badHanyuPinyinOutputFormatCombination) {
            return "";
        }
    }

    public static Map<String, Object> getReturnDataByCode(String code, JdbcTemplate jdbcTemplate) {
        String sql="SELECT * FROM tbl_data_api_return WHERE STATUS =0 AND api_return_code = '"+code+"'";
        List<Map<String, Object>> list = jdbcTemplate.queryForList(sql);
        Map<String, Object> retMap = new HashMap<>();
        if(list.size()==0){
            retMap=new HashMap<>();
            retMap.put("status",code);
            retMap.put("message","no message");
        }else{
            Map<String, Object> map=list.get(0);
            if(!"".equals(String.valueOf(map.get("api_return_json")))&&!"{}".equals(String.valueOf(map.get("api_return_json")))){
                retMap.put("other", JackJSONObject.fromObject(map.get("api_return_json")));
            }
            retMap.put("status",map.get("api_return_code"));
            retMap.put("message",map.get("api_return_message"));
        }
        retMap.put("uuid",UUID.randomUUID().toString().replaceAll("-",""));
        return retMap;
    }
    public static String getOutDictWhereSql(String oDictCode,JdbcTemplate jdbcTemplate, User user){
        String queryDictInfo="SELECT * FROM tbl_data_dict_out WHERE o_dict_code='"+oDictCode+"'";
        List<Map<String, Object>> treeList=jdbcTemplate.queryForList(queryDictInfo);
        String whereSql=null;
        if(treeList.size()>0){
            Map<String, Object> dictInfo=treeList.get(0);
            String dictView=String.valueOf(dictInfo.get("o_dict_view"));
            String split=String.valueOf(dictInfo.get("split"));
            if(dictView.contains(",")){
                String[] arr = dictView.split(",");
                dictView="CONCAT(";
                for (int i = 0; i < arr.length; i++) {
                    dictView+=arr[i]+",'"+split+"',";
                }
                dictView=dictView.substring(0,dictView.length()-(4+split.length()));
                dictView+=")";
            }
            if(DBCheck.isKingbase()){
                whereSql="SELECT "+dictInfo.get("o_dict_option")+" AS \"key\","+dictView+" AS \"value\" FROM "+dictInfo.get("o_dict_table");
            }else{
                whereSql="SELECT "+dictInfo.get("o_dict_option")+" AS 'key',"+dictView+" AS 'value' FROM "+dictInfo.get("o_dict_table");
            }

            String oWhereJsonStr=String.valueOf(dictInfo.get("o_where_json"));
            String oWhereSql=String.valueOf(dictInfo.get("o_where_sql"));
            whereSql+=" where 1=1 ";
            if(!"null".equals(oWhereSql)&&oWhereSql.length()>0){
                oWhereSql=oWhereSql.replaceAll("&nbsp;"," ");
                oWhereSql=oWhereSql.replaceAll("&quot;","'");
                whereSql+=oWhereSql;
            }
            if(!"null".equals(oWhereJsonStr)&&oWhereJsonStr.length()>0){
                JackJSONObject json=JackJSONObject.fromObject(oWhereJsonStr);
                for(Object key:json.keySet()) {
                    String value=String.valueOf(json.get(key));
                    if((value.equals("${org_id}")||value.equals("${user_id}"))&&user==null){
                        continue;
                    }
                    whereSql+=" and "+key+"='"+json.get(key)+"'";
                }
                whereSql+=" order by "+dictInfo.get("o_default_sort_field") +" "+dictInfo.get("o_default_sort_type");
            }
            if(user!=null){
                whereSql=whereSql.replace("${org_id}",""+user.getOrgId());
                whereSql=whereSql.replace("${user_id}",""+user.getId());
            }
            whereSql=whereSql.replace("${database_id}",DBCheck.getDatabaseId());
        }
        return whereSql;
    }
    //tableSql这个参数是查询表名的。
    public static String getWhereSqlByFieldInfo(String tableSql,List<Map<String,Object>> fieldList, String jsonStr,JdbcTemplate jdbcTemplate,JackJSONObject retJson){
        JackJSONObject requestJson=JackJSONObject.fromObject(jsonStr);
        JackJSONObject queryParamJson=requestJson.getJackJSONObject("queryParam");
        Map<String,Object> map=new HashMap<>();
        List list=new ArrayList();
        String whereSql="";
        for (int i = 0; i < fieldList.size(); i++) {
            Map<String,Object> field=fieldList.get(i);
            String fieldName=String.valueOf(field.get("name"));
            map.put(fieldName,field);//map里存一份用fieldInfo,fieldName为key
            String queryParamValue=String.valueOf(queryParamJson.get(fieldName));//检索值
            String showType=String.valueOf(field.get("show_type"));//表单类型
            String isFuzzySearch=String.valueOf(field.get("is_fuzzy_search"));//查询类型：精确||模糊
            String queryType=String.valueOf(field.get("query_type"));
            String isQuery=String.valueOf(field.get("is_query"));
            // 点查询
            if (!"null".equals(isQuery) && isQuery.equals("Y")
                    && !"null".equals(queryType) && queryType.equals("0")
                    && !"null".equals(queryParamValue)) {
                if (!(fieldName.equals("starttime") || fieldName.equals("endtime"))) {
                    if (field.get("type").equals("String")) {
                        if (showType.equals("checkbox")||showType.equals("selectCheckbox")){
                            if(!"".equals(queryParamValue)){
                                String[] checkboxArray = queryParamValue.split(",");
                                for (int j = 0; j < checkboxArray.length; j++) {
                                    whereSql += " and FIND_IN_SET('" +checkboxArray[j]+"',"+ fieldName + ")";
                                }
                            }
                        }else if (showType.equals("tree")){
                            String isRecursion=String.valueOf(queryParamJson.get("isRecursion"));//是否递归
                            String treePkFieldName=String.valueOf(field.get("tree_pk_field_name"));
                            if(!"".equals(queryParamValue)&&("null".equals(isRecursion)||isRecursion.equals("Y"))){
                                String queryFunctionSql="SHOW FUNCTION STATUS WHERE NAME='"+field.get("dict_code")+"' AND DB ='"+ DBCheck.getDatabaseName()+"'";
                                if(DBCheck.isKingbase()){
                                    queryFunctionSql="SELECT proname, proargtypes FROM pg_proc WHERE proname = '"+field.get("dict_code")+"';";
                                }
                                if(jdbcTemplate.queryForList(queryFunctionSql).size()==0){
                                    retJson.putAll(JackJSONObject.fromObject(getReturnDataByCode("5050",jdbcTemplate)));
                                    retJson.put("message",retJson.get("message")+" tree_code:"+field.get("dict_code"));
                                    return "-1";
                                }
                                tableSql +=",(SELECT "+field.get("dict_code")+"('"+ queryParamValue + "') as _tree_ids_"+fieldName+") _khc_"+fieldName+" ";
                                whereSql += " and (FIND_IN_SET(" +fieldName+",_khc_"+fieldName+"._tree_ids_"+fieldName+")";
                                if(!treePkFieldName.equals("null")&&treePkFieldName.length()>0){
                                    whereSql+=" or "+treePkFieldName+"='"+queryParamValue+"'";
                                }
                                whereSql += ")";
                            }else if(!"".equals(queryParamValue)&&isRecursion.equals("N")){
                                whereSql += " and (" + fieldName + " = '"+queryParamValue+"'";
                                if(!treePkFieldName.equals("null")&&treePkFieldName.length()>0){
                                    whereSql+=" or "+treePkFieldName+"='"+queryParamValue+"'";
                                }
                                whereSql += ")";
                            }
                            if(DBCheck.isKingbase()){
                                whereSql += " and LENGTH("+fieldName+")>0";
                            }else{
                                whereSql += " and " + fieldName + " != ''";
                            }
                        }else if (showType.equals("tag")){
                            if(!"".equals(queryParamValue)){
                                String[] tagArray = queryParamValue.split(",");
                                for (int j = 0; j < tagArray.length; j++) {
                                    whereSql += " and FIND_IN_SET('" +tagArray[j]+"',"+ fieldName + ")";
                                }
                            }
                        }else if (!"null".equals(isFuzzySearch)&&isFuzzySearch.equals("0")) {
                            if (!"null".equals(queryParamValue) && queryParamValue.length() > 0) {
                                whereSql += " and " + fieldName + " like '%" + queryParamValue + "%'";
                            }
                        }else if (!"null".equals(isFuzzySearch)&&isFuzzySearch.equals("2")) {
                            if (!"null".equals(queryParamValue) && queryParamValue.length() > 0) {
                                whereSql += " and " + fieldName + " = '"+ queryParamValue + "'";
                            }
                        }else if (!"null".equals(isFuzzySearch)&&isFuzzySearch.equals("3")) {
                            if (!"null".equals(queryParamValue) && queryParamValue.length() > 0) {
                                whereSql += " and " + fieldName + " > "+ queryParamValue;
                            }
                        }else if (!"null".equals(isFuzzySearch)&&isFuzzySearch.equals("4")) {
                            if (!"null".equals(queryParamValue) && queryParamValue.length() > 0) {
                                whereSql += " and " + fieldName + " < "+ queryParamValue;
                            }
                        }else if (!"null".equals(isFuzzySearch)&&isFuzzySearch.equals("5")) {
                            if (!"null".equals(queryParamValue) && queryParamValue.length() > 0) {
                                whereSql += " and " + fieldName + " != '"+ queryParamValue + "'";
                            }
                        }else if (!"null".equals(isFuzzySearch)&&isFuzzySearch.equals("6")) {
                            if (!"null".equals(queryParamValue) && queryParamValue.length() > 0) {
                                whereSql += " and " + fieldName + " >= "+ queryParamValue;
                            }
                        }else if (!"null".equals(isFuzzySearch)&&isFuzzySearch.equals("7")) {
                            if (!"null".equals(queryParamValue) && queryParamValue.length() > 0) {
                                whereSql += " and " + fieldName + " <= "+ queryParamValue;
                            }
                        }
                    } else if (!"null".equals(queryParamValue) && queryParamValue.length() > 0) {
                        if(fieldName.equals("create_org_id")) {
                            whereSql += " and " + fieldName + " in ("
                                    + queryParamValue+")";
                        }else {
                            if (!"null".equals(isFuzzySearch)&&isFuzzySearch.equals("2")) {
                                if (!"null".equals(queryParamValue) && queryParamValue.length() > 0) {
                                    whereSql += " and " + fieldName + " = "+ queryParamValue;
                                }
                            }else if (!"null".equals(isFuzzySearch)&&isFuzzySearch.equals("3")) {
                                if (!"null".equals(queryParamValue) && queryParamValue.length() > 0) {
                                    whereSql += " and " + fieldName + " > "+ queryParamValue;
                                }
                            }else if (!"null".equals(isFuzzySearch)&&isFuzzySearch.equals("4")) {
                                if (!"null".equals(queryParamValue) && queryParamValue.length() > 0) {
                                    whereSql += " and " + fieldName + "< "+ queryParamValue;
                                }
                            }else if (!"null".equals(isFuzzySearch)&&isFuzzySearch.equals("5")) {
                                if (!"null".equals(queryParamValue) && queryParamValue.length() > 0) {
                                    whereSql += " and " + fieldName + "!= "+ queryParamValue;
                                }
                            }else if (!"null".equals(isFuzzySearch)&&isFuzzySearch.equals("6")) {
                                if (!"null".equals(queryParamValue) && queryParamValue.length() > 0) {
                                    whereSql += " and " + fieldName + ">= "+ queryParamValue;
                                }
                            }else if (!"null".equals(isFuzzySearch)&&isFuzzySearch.equals("7")) {
                                if (!"null".equals(queryParamValue) && queryParamValue.length() > 0) {
                                    whereSql += " and " + fieldName + "<= "+ queryParamValue;
                                }
                            }
                        }
                    }
                }
            } else if(!"null".equals(isQuery) && isQuery.equals("Y")
                    && !"null".equals(queryType) && queryType.equals("1")
                    && !"null".equals(String.valueOf(queryParamJson.get(fieldName)))) {
                //段查询（一个字段）
                String fieldValue = String.valueOf(queryParamJson.get(fieldName));
                String[] array = fieldValue.split(",");
                if (array.length!=0&&array[0].length()>0&&array[1].length()>0) {
                    String sql=" ";
                    if(!array[0].equals("null")&&array[0].length()>0){
                        sql=" and (";
                        sql+=fieldName+">='"+array[0]+" 00:00:00' ";
                        if(!array[1].equals("null")&&array[1].length()>0){
                            sql+=" and ";
                            sql+=fieldName+"<='"+array[1]+" 23:59:59' ";
                        }
                        sql+=" ) ";
                    }else{
                        if(!array[1].equals("null")&&array[1].length()>0){
                            sql+=" and ";
                            sql+=fieldName+"<='"+array[1]+" 23:59:59' ";
                        }
                    }
                    whereSql+=sql;
                }
            } else if(!"null".equals(isQuery) && isQuery.equals("Y")  && !"null".equals(queryType) && queryType.equals("2")
                    && !"null".equals(queryParamValue)) {
                //段查询（两个字段），有就先全部存到一个list里最后再拼接sql语句
                if (!"null".equals(queryParamValue) && queryParamValue.length() > 0) {
                    list.add(fieldName);//标识段查询的fieldName
                }
            } else {
                if (!"null".equals(queryParamValue) && queryParamValue.length() > 0) {
                    //除 page_parent_uuid 其他字段查询都需要在query组件配置，否则传参进来也不会做为检索条件，防止第三方通过请求传敏感字段查询如：id字段等
                    if(isQuery.equals("Y")||fieldName.equals("page_parent_uuid")){
                        if (field.get("type").equals("String")) {
                            whereSql += " and " + fieldName + " like '" + queryParamValue + "'";
                        } else {
                            if(fieldName.equals("create_org_id")) {
                                whereSql += " and " + fieldName + " in (" + queryParamValue+")";
                            }else {
                                whereSql += " and " + fieldName + " = " + queryParamValue;
                            }
                        }
                    }
                }
            }
        }
        //段查询(两个字段配对)
        for (int i = 0; i < list.size(); i++) {
            Map<String,Object> fieldInfo= (Map<String, Object>) map.get(list.get(i));
            String referenceField=String.valueOf(fieldInfo.get("segment_reference_field"));
            String referenceValue=String.valueOf(queryParamJson.get(referenceField));
            String field=String.valueOf(fieldInfo.get("name"));
            String value=String.valueOf(queryParamJson.get(list.get(i)));
            list.remove(i);
            i--;
            Boolean isNull=false;
            if("null".equals(referenceValue)||referenceValue.length()==0){
                isNull=true;
                referenceValue="";
            }else{
                list.remove(referenceField);
            }
            if("start".equals(String.valueOf(fieldInfo.get("segment_type")))){
                if(isNull){
                    whereSql += " and ((" +field+">='"+value+"')"
                            +"OR ("+referenceField+">='"+value+"'))";
                }else{
                    whereSql += " and ((" +field+">='"+value+"' and "+field+"<='"+referenceValue+"')"
                            +"OR ("+referenceField+">='"+value+"' and "+referenceField+"<='"+referenceValue+"'))";
                }
            }else if("end".equals(String.valueOf(fieldInfo.get("segment_type")))){
                if(isNull){
                    whereSql += " and (("+referenceField+"<='"+value+"')"
                            +"OR ("+field+"<='"+value+"'))";
                }else{
                    whereSql += " and ((" +referenceField+">='"+referenceValue+"' and "+referenceField+"<='"+value+"')"
                            +"OR ("+field+">='"+referenceValue+"' and "+field+"<='"+value+"'))";
                }
            }
        }
        //table search 表格搜索框
        String tableSearchValue=String.valueOf(queryParamJson.get("tableSearchValue"));
        String tableSearchField=String.valueOf(queryParamJson.get("tableSearchField"));
        if(!tableSearchValue.equals("null")&&tableSearchValue.length()>0){
            String tableSearchSql="";
            if(tableSearchField.equals("")){
                for (int i = 0; i < fieldList.size(); i++) {
                    String fieldName=String.valueOf(fieldList.get(i).get("name"));
                    String isQuery=String.valueOf(fieldList.get(i).get("is_query"));
                    if(isQuery.equals("Y")){
                        tableSearchSql+=" "+fieldName+" like'%"+tableSearchValue+"%' or";
                    }
                }
                if(tableSearchSql.length()>0){
                    tableSearchSql=tableSearchSql.substring(1,tableSearchSql.length()-2);//将最后的一个or去掉。
                    whereSql+= " and ("+tableSearchSql+")";
                }
            }else{
                whereSql+= " and "+tableSearchField+" like'%"+tableSearchValue+"%' ";
            }

        }
        String queryIds=String.valueOf(queryParamJson.get("queryIds"));//表单里套页面才会有此参数（并且表单类型是：page）
        if(!queryIds.equals("null")&&queryIds.length()>0){
            whereSql+=" and FIND_IN_SET(id ,'"+queryIds+"' ) ";
        }
        Map<String,Object> fieldInfo= (Map<String, Object>) map.get("status");
        if(fieldInfo==null){
            whereSql=tableSql+" where 1=1 "+whereSql+" ";
        }else{
            whereSql=tableSql+" where 1=1 and status='0' "+whereSql+" ";
        }
        return whereSql;
    }
    public static List<SearchParam> getLuceneSearchParam(String tableName, List<Map<String,Object>> fieldList, String jsonStr, JdbcTemplate jdbcTemplate, JackJSONObject retJson){
        JackJSONObject requestJson=JackJSONObject.fromObject(jsonStr);
        JackJSONObject queryParamJson=requestJson.getJackJSONObject("queryParam");
        Map<String,Object> map=new HashMap<>();
        List<SearchParam> listSearch=new ArrayList<>();
        for (int i = 0; i < fieldList.size(); i++) {
            Map<String,Object> fieldInfo=fieldList.get(i);
            String fieldName=String.valueOf(fieldInfo.get("name"));
            map.put(fieldName,fieldList.get(i));//map里存一份用fieldInfo,fieldName为key
            String queryParamValue=String.valueOf(queryParamJson.get(fieldName));//检索值
            String isFuzzySearch=String.valueOf(fieldInfo.get("is_fuzzy_search"));//查询类型：精确||模糊
            String queryType=String.valueOf(fieldInfo.get("query_type"));
            String isQuery=String.valueOf(fieldInfo.get("is_query"));
            // 点查询
            if (!"null".equals(isQuery) && isQuery.equals("Y")
                    && !"null".equals(queryType) && queryType.equals("0")
                    && !"null".equals(queryParamValue)) {
                if (!(fieldName.equals("starttime") || fieldName.equals("endtime"))) {
                    if (!"null".equals(isFuzzySearch)&&isFuzzySearch.equals("0")) {//模糊查询（分词）
                        if (!"null".equals(queryParamValue) && queryParamValue.length() > 0) {
                            SearchParam sear=new SearchParam(queryParamValue,fieldName,1,tableName);//todo 默认searchType：0 不分词，以后再适配分词
                            Map<String,Object> filterMap=new HashMap<>();
                            sear.setFilterMap(filterMap);
                            if(!queryParamValue.equals("null")&&queryParamValue.length()>0){
                                listSearch.add(sear);
                            }
                        }
                    }else if (!"null".equals(isFuzzySearch)&&isFuzzySearch.equals("2")) {//精确查询（不分词） todo 后续使用独立的字典
                        if (!"null".equals(queryParamValue) && queryParamValue.length() > 0) {
                            SearchParam sear=new SearchParam(queryParamValue,fieldName,0,tableName);
                            Map<String,Object> filterMap=new HashMap<>();
                            sear.setFilterMap(filterMap);
                            if(!queryParamValue.equals("null")&&queryParamValue.length()>0){
                                listSearch.add(sear);
                            }
                        }
                    }
                }
            } else {
                if (!"null".equals(queryParamValue) && queryParamValue.length() > 0) {
                    //除 page_parent_uuid 其他字段查询都需要在query组件配置，否则传参进来也不会做为检索条件，防止第三方通过请求传敏感字段查询如：id字段等
                    if(isQuery.equals("Y")||fieldName.equals("page_parent_uuid")){
                        SearchParam sear=new SearchParam(queryParamValue,fieldName,0,tableName);
                        Map<String,Object> filterMap=new HashMap<>();
                        sear.setFilterMap(filterMap);
                        if(!queryParamValue.equals("null")&&queryParamValue.length()>0){
                            listSearch.add(sear);
                        }
                    }
                }
            }
        }
        //table search 表格搜索框
        String tableSearchValue=String.valueOf(queryParamJson.get("tableSearchValue"));
        String tableSearchField=String.valueOf(queryParamJson.get("tableSearchField"));
        if(!tableSearchValue.equals("null")&&tableSearchValue.length()>0){
            String fieldNameStr="";
            if(tableSearchField.equals("")){
                for (int i = 0; i < fieldList.size(); i++) {
                    String fieldName=String.valueOf(fieldList.get(i).get("name"));
                    String isQuery=String.valueOf(fieldList.get(i).get("is_query"));
                    if(isQuery.equals("Y")){
                        fieldNameStr+=fieldName+",";
                    }
                }
                if(!fieldNameStr.equals("")){
                    fieldNameStr=fieldNameStr.substring(0,fieldNameStr.length()-1);
                }
                SearchParam sear=new SearchParam(tableSearchValue,fieldNameStr,1,tableName);//todo 默认searchType：1 不分词，以后再适配分词
                Map<String,Object> filterMap=new HashMap<>();
                sear.setFilterMap(filterMap);
                listSearch.add(sear);
            }else{
                SearchParam sear=new SearchParam(tableSearchValue,tableSearchField,1,tableName);//todo 默认searchType：1 不分词，以后再适配分词
                Map<String,Object> filterMap=new HashMap<>();
                sear.setFilterMap(filterMap);
                listSearch.add(sear);
            }

        }
        return listSearch;
    }
    public static List<Map<String, Object>> mySelfMethodRetListMap(String actionName,String methodName, String jsonStr, JackJSONObject retJson, HttpServletRequest request) {
        try {
            Class actionClass = Class.forName(actionName);
            Object myActionClassInstance=actionClass.newInstance();
            java.lang.reflect.Method method = actionClass.getMethod(methodName,String.class,JackJSONObject.class,HttpServletRequest.class);
            Object retObj=method.invoke(myActionClassInstance,jsonStr,retJson,request);
            return (List<Map<String, Object>>) retObj;
        } catch (Exception e) {
            e.printStackTrace();
            return new ArrayList<>();
        }
    }
    /**
     * 返回类型是JtPage
     */
    public static JtPage mySelfMethodRetJtPage(String actionName, String methodName, String jsonStr, JackJSONObject retJson, HttpServletRequest request, JtPage jtPage) {
        try {
            Class actionClass = Class.forName(actionName);
            Object myActionClassInstance=actionClass.newInstance();
            java.lang.reflect.Method method = actionClass.getMethod(methodName,String.class,JackJSONObject.class,HttpServletRequest.class,JtPage.class);
            Object retObj=method.invoke(myActionClassInstance,jsonStr,retJson,request,jtPage);
            return (JtPage) retObj;
        } catch (Exception e) {
            e.printStackTrace();
            return new JtPage();
        }
    }
    /**
     * 返回类型是JSONArray
     */
    public static JackJSONArray mySelfMethodRetListMap(String actionName, String methodName, String jsonStr, JackJSONObject retJson, HttpServletRequest request, JackJSONArray array) {
        try {
            Class actionClass = Class.forName(actionName);
            Object myActionClassInstance=actionClass.newInstance();
            java.lang.reflect.Method method = actionClass.getMethod(methodName,String.class,JackJSONObject.class,HttpServletRequest.class,JackJSONArray.class);
            Object retObj=method.invoke(myActionClassInstance,jsonStr,retJson,request,array);
            return (JackJSONArray) retObj;
        } catch (Exception e) {
            e.printStackTrace();
            return new JackJSONArray();
        }
    }
    public static Map<String, Object> mySelfMethodRetMap(String actionName, String methodName, String jsonStr, JackJSONObject retJson, HttpServletRequest request) {
        try {
            Class actionClass = Class.forName(actionName);
            Object myActionClassInstance=actionClass.newInstance();
            
            java.lang.reflect.Method method = actionClass.getMethod(methodName,String.class,JackJSONObject.class,HttpServletRequest.class);
            Object retObj=method.invoke(myActionClassInstance,jsonStr,retJson,request);
            return (Map<String, Object>) retObj;
        } catch (Exception e) {
        	e.printStackTrace();
            return new HashMap<>();
        }
    }
    public static Map<String, Object> mySelfMethodRetMap(String actionName,String methodName, String jsonStr, JackJSONObject retJson, HttpServletRequest request, Map<String,Object> map) {
        try {
            Class actionClass = Class.forName(actionName);
            Object myActionClassInstance=actionClass.newInstance();
            java.lang.reflect.Method method = actionClass.getMethod(methodName,String.class,JackJSONObject.class,HttpServletRequest.class, Map.class);
            Object retObj=method.invoke(myActionClassInstance,jsonStr,retJson,request,map);
            return (Map<String, Object>) retObj;
        } catch (Exception e) {
            e.printStackTrace();
            return new HashMap<>();
        }
    }
    public static String mySelfMethodRetStr(String actionName,String methodName, String jsonStr, JackJSONObject retJson, HttpServletRequest request) {
        try {
            Class actionClass = Class.forName(actionName);
            Object myActionClassInstance=actionClass.newInstance();
            Method method = null;
            try {
                method = actionClass.getMethod(methodName,String.class, JackJSONObject.class, HttpServletRequest.class);
            } catch (NoSuchMethodException e) {
                retJson.put("status","no_code");//后续补编码状态
                retJson.put("message","异常，扩展类找不多对应的方法，请检查 \""+methodName+"\" 方法是否正确，或是否更新");
                return "-1";
            } catch (SecurityException e) {
                return "-1";
            }
            Object retObj=method.invoke(myActionClassInstance,jsonStr,retJson,request);
            return String.valueOf(retObj);
        } catch (Exception e) {
            e.printStackTrace();
            return "-1";
        }
    }
    public static boolean isMethod(String actionClass, String methodName) {
        try {
            Class obj = Class.forName(actionClass);
            Class[] paraTypes = new Class[]{String.class,JackJSONObject.class,HttpServletRequest.class};
            return judgeMethodIsExist(obj.getDeclaredConstructor().newInstance(),methodName,paraTypes);
        } catch (Exception e) {
            return false;
        }
    }
    public static boolean judgeMethodIsExist(Object obj, String methodName, Class[] paraTypes) {
        boolean result = true;
        try {
            if (null != obj) {
                Method method =  obj.getClass().getMethod(methodName, paraTypes);
            }
        } catch (NoSuchMethodException ex) {
            result = false;
        }
        return result;
    }
    public static Map<String, String> getHtmlEntities() {
        Map<String, String> htmlEntities = new HashMap<>();
        htmlEntities.put("&nbsp;", " ");
        htmlEntities.put("&quot;", "\'");
        htmlEntities.put("&lt;", "<");
        htmlEntities.put("&gt;", ">");
        return htmlEntities;
    }
    /**
     * html解码器
     */
    public static String htmlDecode(String text) {
        Map<String, String> htmlEntities = getHtmlEntities();
        for (Map.Entry<String, String> entry : htmlEntities.entrySet()) {
            text = text.replace(entry.getKey(), entry.getValue());
        }
        return text;
    }
    /**
     * html转码器
     */
    public static String htmlEncode(String text) {
        Map<String, String> htmlEntities = getHtmlEntities();
        for (Map.Entry<String, String> entry : htmlEntities.entrySet()) {
            text = text.replace(entry.getValue(), entry.getKey());
        }
        return text;
    }

    /**
     * @param fieldList 字段信息
     * @param headMap   存取labelName做为列标题
     * @param headList  列标题顺序
     * @param dataList  查询的结果集
     * @param list      最终导出的结果集（将字典转换为对应的值）
     * @param jdbcTemplate
     */
    public static void exportExcelDataByXlsx(List<Map<String,Object>> fieldList,Map<String,Object>  headMap,List<String> headList,List<Map<String, Object>> dataList,List<Map<String,Object>> list,JdbcTemplate jdbcTemplate) {
        Map<String, Object> fieldInfoMap=new HashMap();
        Map<String,Map<String,Object>> dictList=new HashMap();
        for (int i = 0; i < fieldList.size(); i++) {
            if (fieldList.get(i).get("is_export_excel") != null && fieldList.get(i).get("is_export_excel").equals("Y")) {
                String fieldName=String.valueOf(fieldList.get(i).get("name"));
                String labelName=String.valueOf(fieldList.get(i).get("label_name")).replaceAll("\\*", "");
                headMap.put(fieldName,labelName);
                headList.add(fieldName);
            }
        }
        headMap.put("headList",null);//headList作用是排序。
        for(int i=0;i<fieldList.size();i++) {
            Map<String,Object> fieldInfo=fieldList.get(i);
            fieldInfoMap.put(String.valueOf(fieldInfo.get("name")), fieldInfo);
            if(dictList.get(fieldInfo.get("dict_code"))==null) {
                String dictCode=String.valueOf(fieldInfo.get("dict_code"));
                if(dictCode.equals("null")||dictCode.equals("")){
                    continue;
                }
                if(dictCode.indexOf("o_")==0) {
                    Map<String,Object> dictMap=getOutDictInfoByDictCodeToMap(dictCode,false,jdbcTemplate);
                    dictList.put(dictCode,dictMap);
                }else if(dictCode.indexOf("tree_")==0){
                    String treeShowValueType=String.valueOf(fieldInfo.get("tree_show_value_type"));
                    Map<String,Object> dictMap=new HashMap<>();
                    if(treeShowValueType.equals("full")){
                        String treeShowFullSplit=String.valueOf(fieldInfo.get("tree_show_full_split"));
                        dictMap=getTreeDictInfoByDictCodeToFullMap(dictCode,false,null,jdbcTemplate,treeShowFullSplit);
                    }else{
                        dictMap=getTreeDictInfoByDictCodeToMap(dictCode,false,null,jdbcTemplate);
                    }

                    dictList.put(dictCode,dictMap);
                }else if(dictCode.indexOf("tp_")==0){
                    //第三方字典
                }else{//内部字典
                    Map<String,Object> dictMap=getDictInfoByDictCodeToMap(dictCode,false,jdbcTemplate);
                    dictList.put(dictCode,dictMap);
                }
            }
        }
        // 输出表格内容
        for (int i = 0; i < dataList.size(); i++) {
            Map<String,Object> map=new HashMap<>();
            for (int xxx = 0; xxx < fieldList.size(); xxx++) {
                if (fieldList.get(xxx).get("is_export_excel") != null
                        && fieldList.get(xxx).get("is_export_excel").equals("Y")) {
                    String name=String.valueOf(fieldList.get(xxx).get("name"));
                    String value="";
                    String dictCode=String.valueOf(fieldList.get(xxx).get("dict_code"));
                    String showType=String.valueOf(fieldList.get(xxx).get("show_type"));
                    if(!dictCode.equals("null")&&dictCode.length()>0&&!showType.equals("autocomplete")) {
                        if(dictCode.indexOf("tree_")==0){//tree字典
                            String str=String.valueOf(dictList.get(dictCode));
                            if(str.equals("null")){
                                String treeShowValueType=String.valueOf(fieldList.get(i).get("tree_show_value_type"));
                                Map<String,Object> dictMap=new HashMap<>();
                                if(treeShowValueType.equals("full")){
                                    dictMap=getTreeDictInfoByDictCodeToFullMap(dictCode,false,jdbcTemplate);
                                }else{
                                    dictMap=getTreeDictInfoByDictCodeToMap(dictCode,false,null,jdbcTemplate);
                                }

                                dictList.put(dictCode,dictMap);
                            }
                            String key=String.valueOf(dataList.get(i).get(fieldList.get(xxx).get("name")));
                            value=String.valueOf(dictList.get(dictCode).get(key));
                        }else{//内部字典
                            if(fieldList.get(xxx).get("show_type").equals("checkbox")||fieldList.get(xxx).get("show_type").equals("selectCheckbox")) {
                                String fieldDataValue=String.valueOf(dataList.get(i).get(fieldList.get(xxx).get("name")));
                                String[] fieldDataValueArray=fieldDataValue.split(",");
                                String showValue="";
                                for(int yyy=0;yyy<fieldDataValueArray.length;yyy++) {
                                    if(fieldDataValueArray[yyy].equals(""))continue;
                                    showValue+=dictList.get(fieldList.get(xxx).get("dict_code")).get(fieldDataValueArray[yyy])+",";
                                }
                                if(!showValue.equals(""))value=showValue.substring(0,showValue.length()-1);
                            }else {
                                value=dictList.get(fieldList.get(xxx).get("dict_code")).get(String.valueOf(dataList.get(i).get(fieldList.get(xxx).get("name"))))+"";
                            }
                        }
                    }else {
                        String valueStr=String.valueOf(dataList.get(i).get(fieldList.get(xxx).get("name")));
                        value=htmlDecode(valueStr);
                    }
                    if(value.equals("null")){
                        value="";
                    }
                    map.put(name,value);
                }
            }
            list.add(map);
        }
    }
    public static Map<String,Object> importExcelDataByXls(String jsonStr,JackJSONObject retJson,Map<String,Object>  returnMap,Map<String,Object> fileInfo,
                                                          List<Map<String, Object>> dataMaps,List<Map<String, Object>> queryFieldList,
                                                          List<Map<String, Object>> formFieldList,InputStream inputStream,UserService userService,
                                                          User user,JdbcTemplate jdbcTemplate, RedisPublication redisPublication) {
        Date date = new Date();
        SimpleDateFormat timeFormat= new SimpleDateFormat("yyyy-MM-dd HH:mm"+":00");
        SimpleDateFormat dateFormat= new SimpleDateFormat("yyyy-MM-dd");
        // 创建一个 Map 来存储特定的字段名与布尔值的映射
        Map<String, Boolean> fieldMap = new HashMap<>();
        fieldMap.put("create_time", false);
        fieldMap.put("create_user", false);
        fieldMap.put("uuid", false);
        fieldMap.put("page_parent_uuid", false);
        //获取第0行 （标题第一行） 有多少列
        boolean isLegalFieldName=true;//是否是合法字段名。
        String field="";
        Map<String,Object> lableNameMap=new HashMap<>();
        List filedNameList=new ArrayList();
        HSSFWorkbook wb = null;
        try {
            wb = new HSSFWorkbook(inputStream);
        } catch (IOException e) {
        }
        HSSFSheet sheet = wb.getSheetAt(0);
        JackJSONObject jsonObject = JackJSONObject.fromObject(jsonStr);
        String wsCode=String.valueOf(jsonObject.get("queryCode"));
        redisPublication.sendMessage("{\"wsCode\":\""+wsCode+"\",\"message\":\"开始解析表头...\",\"status\":\"ok\",\"isHideMask\":\"N\"}",String.valueOf(user.getId()));
        Map<String,Map<String,Object>> dictList=new HashMap<>();
        Map<String,Object> canNullMap=new HashMap<>();
        if(formFieldList.size()>0){
            for (int i = 0; i < formFieldList.size(); i++) {
                String canNull=String.valueOf(formFieldList.get(i).get("can_null"));
                if(canNull.equals("Y")){
                    String fieldName=String.valueOf(formFieldList.get(i).get("name"));
                    canNullMap.put(fieldName,"Y");//标记不能为空的字段
                }
            }
        }
        //start 取出字段的中文名
        Map<String,Object> labelNameMap=new HashMap<>();
        for (int i = 0; i < queryFieldList.size(); i++) {
            String fieldName=String.valueOf(queryFieldList.get(i).get("name"));
            labelNameMap.put(fieldName,queryFieldList.get(i).get("label_name"));
        }
        //end 取出字段的中文名
        //第一次循环 循环第0行A列到第N列结束
        Integer readRow=Integer.valueOf(String.valueOf(jsonObject.get("readRow")));
        for (int xxx = 0; xxx <sheet.getRow(readRow-2).getLastCellNum() ; xxx++) {
            if(isLegalFieldName){
                //每一次循环第0行第n列的时候赋值给field
                field= String.valueOf(sheet.getRow(readRow-2).getCell(xxx));
                for (int i = 0; i < queryFieldList.size(); i++) {
                    String filedName=String.valueOf(queryFieldList.get(i).get("label_name")).replaceAll("\\*", "");
                    isLegalFieldName=false;
                    if(field.equals(filedName)){
                        String fieldName=String.valueOf(queryFieldList.get(i).get("name"));
                        lableNameMap.put(fieldName,field);
                        isLegalFieldName=true;
                        filedNameList.add(fieldName);
                        if(fieldMap.containsKey(fieldName)){
                            fieldMap.put(fieldName, true);
                        }
                        String dictCode=String.valueOf(queryFieldList.get(i).get("dict_code"));
                        if("null".equals(dictCode)||dictCode.length()==0){
                            break;
                        }
                        if(dictCode.indexOf("tree_")==0){//tree字典
                            String str=String.valueOf(dictList.get(dictCode));
                            if(str.equals("null")){
                                String treeShowValueType=String.valueOf(queryFieldList.get(i).get("tree_show_value_type"));
                                Map<String,Object> dictMap=new HashMap<>();
                                if(treeShowValueType.equals("full")){//full 代表完整名称
                                    String treeShowFullSplit=String.valueOf(queryFieldList.get(i).get("tree_show_full_split"));
                                    dictMap=getTreeDictInfoByDictCodeToFullMap(dictCode,true,null,jdbcTemplate,treeShowFullSplit);
                                }else{
                                    dictMap=getTreeDictInfoByDictCodeToMap(dictCode,true,null,jdbcTemplate);
                                }
                                dictList.put(dictCode,dictMap);
                            }
                        }else if(dictCode.indexOf("o_")==0){
                            Map<String,Object> dictMap=getOutDictInfoByDictCodeToMap(dictCode,true,jdbcTemplate);
                            dictList.put(dictCode,dictMap);
                        }else{
                            Map<String,Object> dictMap=getDictInfoByDictCodeToMap(dictCode,true,jdbcTemplate);
                            dictList.put(dictCode,dictMap);
                        }
                        break;
                    }
                }
                if(isLegalFieldName==false){
                    retJson.putAll(JackJSONObject.fromObject(getReturnDataByCode("5020",jdbcTemplate)));
                    redisPublication.sendMessage("{\"wsCode\":\""+wsCode+"\",\"message\":\""+retJson.get("message")+"："+field+"\",\"status\":\"5020\",\"isHideMask\":\"N\"}",String.valueOf(user.getId()));
                    return new HashMap<>();
                }
            }else{
                break;
            }
        }
        String parentUUID="";
        if(!fieldMap.get("page_parent_uuid")){
            parentUUID=String.valueOf(jsonObject.get("parentUUID"));
        }
        //循环第一行 就是标题行的下一行 xxx = 1 从第一行开始 到工作表的行数。 导入 就是读取 ，获得有效行数 sheet.getPhysicalNumberOfRows()
        for (int xxx = (readRow-1); xxx <sheet.getPhysicalNumberOfRows() ; xxx++) {
            //创建dataMap 用于存放需要执行的数据
            Map<String, Object> dataMap=new HashMap<>();
            dataMap.put("status","0");
            //start 这个循环是提前过滤数据，如果有一行所有单元格都是空则不入库
            boolean isCellAllNull=true;
            for (int i = 0; i <sheet.getRow(xxx).getLastCellNum() ; i++) {
                String cellStr= String.valueOf(sheet.getRow(xxx).getCell(i));
                if(cellStr.trim().length()!=0&&!cellStr.equals("null")){
                    isCellAllNull=false;
                }
            }
            if(isCellAllNull){
                break;
            }
            if((xxx+1) % 1000 == 0){
                redisPublication.sendMessage("{\"wsCode\":\""+wsCode+"\",\"message\":\"解析数据中，总共"+sheet.getPhysicalNumberOfRows()+"条，当前解析到"+(xxx+1)+"条...\",\"status\":\"ok\",\"isHideMask\":\"N\"}",String.valueOf(user.getId()));
            }
            //end 这个循环是提前过滤数据，如果有一行所有单元格都是空则不入库
            //getPhysicalNumberOfCells() 只会返回实际包含数据的单元格数量，如果某一列为空，它就不会计入。
            //为了确保读取到所有的列，可以使用 getLastCellNum() 来获取工作表中最后一个列的编号，即使某些列为空，也能被包括在内。
            for (int i = 0; i <sheet.getRow(xxx).getLastCellNum() ; i++) {
                //把每次第N列的值 获取 赋值给 fieldValue变量
                String fieldValue= String.valueOf(sheet.getRow(xxx).getCell(i));
                //如果再有效列数内获取到的值不为空就往下走  反之 把值赋为 "" 空字符串 fieldValue="";
                if(!fieldValue.equals("null")&&fieldValue!=null){
                    //对每个单元格的 数值类型进行操作 一行每一列的数值 setCellType(CellType.STRING); set为String 类型
                    //获取每一行的每一列 数据 的类型   这里判断的是  如果每一行每一列的值 == CellType.NUMERIC  NUMERIC  数值型  0
                    if (sheet.getRow(xxx).getCell(i).getCellTypeEnum() == CellType.NUMERIC){
                        try {//时间单元格
                            DateFormat df = new SimpleDateFormat("dd-MM-yyyy");
                            Date parseDate = df.parse(fieldValue);//有异常要捕获
                            SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
                            fieldValue=format.format(parseDate);
                        } catch (ParseException e) {//非时间单元格
                            //获取到的每行每列 数值型 的值 转换为String 赋值给 fieldValue
                            sheet.getRow(xxx).getCell(i).setCellType(CellType.STRING);
                            //获取值
                            fieldValue = sheet.getRow(xxx).getCell(i).getStringCellValue();
                        }
                    }
                }else{
                    fieldValue="";
                }
                //从excel读取整数要去小数点0
                Pattern pattern=Pattern.compile("^([1-9]\\d*(\\.[0-9]*[1-9])?)|(0\\.[0-9]*[1-9])|0$");
                if(!pattern.matcher(fieldValue).matches()){
                    try {
                        Double.parseDouble(fieldValue);//转一下double，
                        if(fieldValue.contains(".")) {
                            int indexOf = fieldValue.indexOf(".");
                            fieldValue = fieldValue.substring(0, indexOf);
                        }
                    } catch (NumberFormatException e) {
                        //转失败则说明是普通字符串
                    }
                }
                //每一次循环第0行第n列的时候赋值给field  标题行
                field= String.valueOf(sheet.getRow(readRow-2).getCell(i));
                //把之前取到的服务信息 循环遍历
                for (int j = 0; j < queryFieldList.size(); j++) {
                    String filedName = String.valueOf(queryFieldList.get(j).get("label_name")).replaceAll("\\*", "");
                    //从fieldList 中获取到字段名称和 field 标题行中字段是对应
                    if (field.equals(filedName)) {
                        //验证是否启用 字典值
                        String dictCode=String.valueOf(queryFieldList.get(j).get("dict_code"));
                        String showType=String.valueOf(queryFieldList.get(j).get("show_type"));
                        if (!"null".equals(dictCode)&&dictCode.length()>0) {
                            // 使用 Set 存储 showType 的合法值，减少多个 equals 的判断
                            Set<String> validShowTypes = new HashSet<>(Arrays.asList("checkbox", "selectCheckbox", "selectSearch"));
                            if(validShowTypes.contains(showType)){
                                String[] fieldDataValueArray=fieldValue.split(",");
                                String showValue="";
                                for(int yyy=0;yyy<fieldDataValueArray.length;yyy++) {
                                    showValue+= dictList.get(dictCode).get(fieldDataValueArray[yyy])+",";
                                }
                                if(!showValue.equals("")){
                                    fieldValue=","+showValue;
                                }else{
                                    fieldValue=showValue;
                                }
                            }else{
                                String dictValue=dictList.get(dictCode).get(fieldValue)+"";
                                if(!dictValue.equals("null")){
                                    fieldValue=dictValue;
                                }
                            }
                        }else if(showType.equals("date")){
                            // 检查是否已经是正确的格式，如果是则不转换
                            fieldValue = fieldValue.matches("\\d{8}") ?  // 检查是否是yyyyMMdd格式
                                    LocalDate.parse(fieldValue, DateTimeFormatter.ofPattern("yyyyMMdd"))
                                            .format(DateTimeFormatter.ofPattern("yyyy-MM-dd"))
                                    : fieldValue;  // 如果不是，直接使用原始字符串

                        }
                        break;
                    }
                }
                if(filedNameList.size()<=i){//大于或等于的时候说明数据列比标题列多，说明该列是无需入库
                    continue;
                }
                String fieldName=String.valueOf(filedNameList.get(i));
                String canNull=String.valueOf(canNullMap.get(fieldName));
                if(canNull.equals("Y")){//必填项
                    if(fieldValue.equals("")){
                        retJson.putAll(JackJSONObject.fromObject(getReturnDataByCode("5024",jdbcTemplate)));
                        retJson.put("message","\""+labelNameMap.get(fieldName)+"\"为必填项，请检查文件第"+(xxx+1)+"行数据后再重新上传");
                        redisPublication.sendMessage("{\"wsCode\":\""+wsCode+"\",\"message\":\""+labelNameMap.get(fieldName)+"为必填项，请检查文件第"+(xxx+1)+"行数据后再重新上传\",\"status\":\"5020\",\"isHideMask\":\"N\"}",String.valueOf(user.getId()));
                        return new HashMap<>();
                    }else{
                        dataMap.put(fieldName,fieldValue);
                    }
                }else{//非必填项
                    dataMap.put(fieldName,fieldValue);
                }
            }
            if(fieldMap.get("create_time")){
                //导入有create_time列,但未填写值 默认给当前时间
                if(dataMap.get("create_time")==null){
                    dataMap.put("create_time",timeFormat.format(date));
                    dataMap.put("create_date",dateFormat.format(date));
                }else{
                    try {
                        //导入有create_time列 有值，验证格式是否符合否则 走catch 获取系统当前时间
                        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                        format.setLenient(false);
                        format.parse((String) dataMap.get("create_time"));
                    } catch (ParseException e) {
                        dataMap.put("create_time",timeFormat.format(date));
                        dataMap.put("create_date",dateFormat.format(date));
                    }
                }
            }else{
                dataMap.put("create_time",timeFormat.format(date));
                dataMap.put("create_date",dateFormat.format(date));
            }
            if(!fieldMap.get("create_user")){
                BaseDao.setDefaultValue(dataMap,user);
            }else{
                String createUser=String.valueOf(dataMap.get("create_user"));
                String sql="select * from tbl_system_user where user_name='"+createUser+"'";
                List<Map<String, Object>> userList=jdbcTemplate.queryForList(sql);
                dataMap.put("create_user",userList.get(0).get("user_name"));
                dataMap.put("create_user_id",userList.get(0).get("id"));
                dataMap.put("create_org_id",userList.get(0).get("org_id"));
                dataMap.put("create_org_name",userList.get(0).get("org_name"));
            }
            if(!fieldMap.get("page_parent_uuid")&&(parentUUID.length()>0&&!parentUUID.equals("null"))){
                dataMap.put("page_parent_uuid",parentUUID);
            }
            dataMap.put("data_source","excel");
            dataMaps.add(dataMap);
            Integer sumRow=sheet.getPhysicalNumberOfRows();
            Integer errorRow=sumRow-xxx-(readRow-1);//总行数减去成功和标题行得出未导入的。
            String errorText="";
            if(errorRow>0){
                errorText="，失败："+errorRow+"条，请检查文件第"+(xxx+2)+"行";//加2是因为从0开始和去掉标题列
            }
            returnMap.put("importMessage"," 导入了"+(xxx-readRow+2)+"条"+errorText);//提前设置导入成功message
        }
        return returnMap;
    }
    public static Map<String,Object> importExcelDataByXlsx(String jsonStr,JackJSONObject retJson,Map<String,Object>  returnMap,Map<String,Object> fileInfo,
                                                           List<Map<String, Object>> dataMaps,List<Map<String, Object>> queryFieldList,
                                                           List<Map<String, Object>> formFieldList,InputStream inputStream,UserService userService,
                                                           User user,JdbcTemplate jdbcTemplate, RedisPublication redisPublication) {
        Date date = new Date();
        SimpleDateFormat timeFormat= new SimpleDateFormat("yyyy-MM-dd HH:mm"+":00");
        SimpleDateFormat dateFormat= new SimpleDateFormat("yyyy-MM-dd");
        Workbook wb = null;
        try {
            wb = new XSSFWorkbook(inputStream);
        } catch (IOException e) {
        }
        Sheet sheet = wb.getSheetAt(0);
        // 创建一个 Map 来存储特定的字段名与布尔值的映射
        Map<String, Boolean> fieldMap = new HashMap<>();
        fieldMap.put("create_time", false);
        fieldMap.put("create_user", false);
        fieldMap.put("uuid", false);
        fieldMap.put("page_parent_uuid", false);
        //获取第0行 （标题第一行） 有多少列
        boolean isLegalFieldName=true;//是否是合法字段名。
        String field="";
        Map<String,Object> lableNameMap=new HashMap<>();
        JackJSONObject jsonObject = JackJSONObject.fromObject(jsonStr);
        String wsCode=String.valueOf(jsonObject.get("queryCode"));
        redisPublication.sendMessage("{\"wsCode\":\""+wsCode+"\",\"message\":\"开始解析表头...\",\"status\":\"ok\",\"isHideMask\":\"N\"}",String.valueOf(user.getId()));
        List filedNameList=new ArrayList();
        Map<String,Map<String,Object>> dictList=new HashMap<>();
        Map<String,Object> canNullMap=new HashMap<>();
        if(formFieldList.size()>0){
            for (int i = 0; i < formFieldList.size(); i++) {
                String canNull=String.valueOf(formFieldList.get(i).get("can_null"));
                if(canNull.equals("Y")){
                    String fieldName=String.valueOf(formFieldList.get(i).get("name"));
                    canNullMap.put(fieldName,"Y");
                }
            }
        }
        //start 取出字段的中文名
        Map<String,Object> labelNameMap=new HashMap<>();
        for (int i = 0; i < queryFieldList.size(); i++) {
            String fieldName=String.valueOf(queryFieldList.get(i).get("name"));
            labelNameMap.put(fieldName,queryFieldList.get(i).get("label_name"));
        }
        //end 取出字段的中文名
        //第一次循环 循环第0行A列到第N列结束
        Integer readRow=Integer.valueOf(String.valueOf(jsonObject.get("readRow")));
        for (int xxx = 0; xxx <sheet.getRow(readRow-2).getLastCellNum() ; xxx++) {
            if(isLegalFieldName){
                //每一次循环第0行第n列的时候赋值给field
                field= String.valueOf(sheet.getRow(readRow-2).getCell(xxx));
                for (int i = 0; i < queryFieldList.size(); i++) {
                    String filedName=String.valueOf(queryFieldList.get(i).get("label_name")).replaceAll("\\*", "");
                    isLegalFieldName=false;
                    if(field.equals(filedName)){
                        String fieldName=String.valueOf(queryFieldList.get(i).get("name"));
                        lableNameMap.put(fieldName,field);
                        isLegalFieldName=true;
                        filedNameList.add(fieldName);
                        if(fieldMap.containsKey(fieldName)){
                            fieldMap.put(fieldName, true);
                        }
                        String dictCode=String.valueOf(queryFieldList.get(i).get("dict_code"));
                        if("null".equals(dictCode)||dictCode.length()==0){
                            break;
                        }
                        if(dictCode.indexOf("tree_")==0){//tree字典
                            String str=String.valueOf(dictList.get(dictCode));
                            if(str.equals("null")){
                                String treeShowValueType=String.valueOf(queryFieldList.get(i).get("tree_show_value_type"));
                                Map<String,Object> dictMap=new HashMap<>();
                                if(treeShowValueType.equals("full")){//full 代表完整名称
                                    String treeShowFullSplit=String.valueOf(queryFieldList.get(i).get("tree_show_full_split"));
                                    dictMap=getTreeDictInfoByDictCodeToFullMap(dictCode,true,null,jdbcTemplate,treeShowFullSplit);
                                }else{
                                    dictMap=getTreeDictInfoByDictCodeToMap(dictCode,true,null,jdbcTemplate);
                                }
                                dictList.put(dictCode,dictMap);
                            }
                        }else if(dictCode.indexOf("o_")==0){
                            Map<String,Object> dictMap=getOutDictInfoByDictCodeToMap(dictCode,false,jdbcTemplate);
                            dictList.put(dictCode,dictMap);
                        }else{
                            Map<String,Object> dictMap=getDictInfoByDictCodeToMap(dictCode,true,jdbcTemplate);
                            dictList.put(dictCode,dictMap);
                        }
                        break;
                    }
                }
                if(isLegalFieldName==false){
                    retJson.putAll(JackJSONObject.fromObject(getReturnDataByCode("5020",jdbcTemplate)));
                    redisPublication.sendMessage("{\"wsCode\":\""+wsCode+"\",\"message\":\""+retJson.get("message")+"："+field+"\",\"status\":\"5020\",\"isHideMask\":\"N\"}",String.valueOf(user.getId()));
                    return new HashMap<>();
                }
            }else{
                break;
            }
        }
        String parentUUID="";
        if(!fieldMap.get("page_parent_uuid")){
            parentUUID=String.valueOf(jsonObject.get("parentUUID"));
        }
        //循环第一行 就是标题行的下一行 xxx = 1 从第一行开始 到工作表的行数。 导入 就是读取 ，获得有效行数 sheet.getPhysicalNumberOfRows()
        for (int xxx = (readRow-1); xxx <sheet.getPhysicalNumberOfRows() ; xxx++) {
            //创建dataMap 用于存放需要执行的数据
            Map<String, Object> dataMap=new HashMap<>();
            dataMap.put("status","0");
            //start 这个循环是提前过滤数据，如果有一行所有单元格都是空则不入库
            boolean isCellAllNull=true;
            for (int i = 0; i <sheet.getRow(xxx).getLastCellNum() ; i++) {
                String cellStr= String.valueOf(sheet.getRow(xxx).getCell(i));
                if(cellStr.trim().length()!=0&&!cellStr.equals("null"))isCellAllNull=false;
            }
            if(isCellAllNull)break;
            if((xxx+1) % 1000 == 0){
                redisPublication.sendMessage("{\"wsCode\":\""+wsCode+"\",\"message\":\"解析数据中，总共"+sheet.getPhysicalNumberOfRows()+"条，当前解析到"+(xxx+1)+"条...\",\"status\":\"ok\",\"isHideMask\":\"N\"}",String.valueOf(user.getId()));
            }
            //end 这个循环是提前过滤数据，如果有一行所有单元格都是空则不入库
            //getPhysicalNumberOfCells() 只会返回实际包含数据的单元格数量，如果某一列为空，它就不会计入。
            //为了确保读取到所有的列，可以使用 getLastCellNum() 来获取工作表中最后一个列的编号，即使某些列为空，也能被包括在内。
            for (int i = 0; i <sheet.getRow(xxx).getLastCellNum() ; i++) {
                //把每次第N列的值 获取 赋值给 fieldValue变量
                String fieldValue= String.valueOf(sheet.getRow(xxx).getCell(i));
                //如果再有效列数内获取到的值不为空就往下走  反之 把值赋为 "" 空字符串 fieldValue="";
                if(!fieldValue.equals("null")&&fieldValue!=null){
                    //对每个单元格的 数值类型进行操作 一行每一列的数值 setCellType(CellType.STRING); set为String 类型
                    //获取每一行的每一列 数据 的类型   这里判断的是  如果每一行每一列的值 == CellType.NUMERIC  NUMERIC  数值型  0
                    if (sheet.getRow(xxx).getCell(i).getCellTypeEnum() == CellType.NUMERIC){
                        try {//时间单元格
                            DateFormat df = new SimpleDateFormat("dd-MM-yyyy");
                            Date parseDate = df.parse(fieldValue);//有异常要捕获
                            SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
                            fieldValue=format.format(parseDate);
                        } catch (ParseException e) {//非时间单元格
                            if(fieldValue.indexOf("E")!=-1){//”4000243621“长数值读取为”4.000243621E9“需要转成字符串读取
                                //获取到的每行每列 数值型 的值 转换为String 赋值给 fieldValue
                                sheet.getRow(xxx).getCell(i).setCellType(CellType.STRING);
                                //获取值
                                fieldValue = sheet.getRow(xxx).getCell(i).getStringCellValue();
                            }
                        }
                    }
                }else{
                    fieldValue="";
                }
                //从excel读取整数要去小数点0
                Pattern pattern=Pattern.compile("^([1-9]\\d*(\\.[0-9]*[1-9])?)|(0\\.[0-9]*[1-9])|0$");
                if(!pattern.matcher(fieldValue).matches()){
                    try {
                        Double.parseDouble(fieldValue);//转一下double，
                        if(fieldValue.contains(".")) {
                            int indexOf = fieldValue.indexOf(".");
                            fieldValue = fieldValue.substring(0, indexOf);
                        }
                    } catch (NumberFormatException e) {
                        //转失败则说明是普通字符串
                    }
                }
                //每一次循环第0行第n列的时候赋值给field  标题行
                field= String.valueOf(sheet.getRow(readRow-2).getCell(i));
                //把之前取到的服务信息 循环遍历
                for (int j = 0; j < queryFieldList.size(); j++) {
                    String filedName = String.valueOf(queryFieldList.get(j).get("label_name")).replaceAll("\\*", "");
                    //从fieldList 中获取到字段名称和 field 标题行中字段是对应
                    if (field.equals(filedName)) {
                        //验证是否启用 字典值
                        String dictCode=String.valueOf(queryFieldList.get(j).get("dict_code"));
                        String showType=String.valueOf(queryFieldList.get(j).get("show_type"));
                        if (!"null".equals(dictCode)&&dictCode.length()>0) {
                            // 使用 Set 存储 showType 的合法值，减少多个 equals 的判断
                            Set<String> validShowTypes = new HashSet<>(Arrays.asList("checkbox", "selectCheckbox", "selectSearch"));
                            if(validShowTypes.contains(showType)){
                                String[] fieldDataValueArray=fieldValue.split(",");
                                String showValue="";
                                for(int yyy=0;yyy<fieldDataValueArray.length;yyy++) {
                                    showValue+= dictList.get(dictCode).get(fieldDataValueArray[yyy])+",";
                                }
                                if(!showValue.equals("")){
                                    fieldValue=","+showValue;
                                }else{
                                    fieldValue=showValue;
                                }
                            }else{
                                String dictValue=dictList.get(dictCode).get(fieldValue)+"";
                                if(!dictValue.equals("null")){
                                    fieldValue=dictValue;
                                }
                            }
                        }else if(showType.equals("date")){
                            // 检查是否已经是正确的格式，如果是则不转换
                            fieldValue = fieldValue.matches("\\d{8}") ?  // 检查是否是yyyyMMdd格式
                                    LocalDate.parse(fieldValue, DateTimeFormatter.ofPattern("yyyyMMdd"))
                                            .format(DateTimeFormatter.ofPattern("yyyy-MM-dd"))
                                    : fieldValue;  // 如果不是，直接使用原始字符串

                        }
                        break;
                    }
                }
                if(filedNameList.size()<=i){//大于或等于的时候说明数据列比标题列多，说明该列是无需入库
                    continue;
                }
                String fieldName=String.valueOf(filedNameList.get(i));
                String canNull=String.valueOf(canNullMap.get(fieldName));
                if(canNull.equals("Y")){//必填项
                    if(fieldValue.equals("")){
                        retJson.putAll(JackJSONObject.fromObject(getReturnDataByCode("5024",jdbcTemplate)));
                        retJson.put("message","\""+labelNameMap.get(fieldName)+"\"为必填项，请检查文件第"+(xxx+1)+"行数据后再重新上传");
                        redisPublication.sendMessage("{\"wsCode\":\""+wsCode+"\",\"message\":\""+labelNameMap.get(fieldName)+"为必填项，请检查文件第"+(xxx+1)+"行数据后再重新上传\",\"status\":\"5020\",\"isHideMask\":\"N\"}",String.valueOf(user.getId()));
                        return new HashMap<>();
                    }else{
                        dataMap.put(fieldName,fieldValue);
                    }
                }else{//非必填项
                    dataMap.put(fieldName,fieldValue);
                }
            }
            if(fieldMap.get("create_time")){
                //导入有create_time列,但未填写值 默认给当前时间
                if(dataMap.get("create_time")==null){
                    dataMap.put("create_time",timeFormat.format(date));
                    dataMap.put("create_date",dateFormat.format(date));
                }else{
                    try {
                        //导入有create_time列 有值，验证格式是否符合否则 走catch 获取系统当前时间
                        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                        format.setLenient(false);
                        format.parse((String) dataMap.get("create_time"));
                    } catch (ParseException e) {
                        dataMap.put("create_time",timeFormat.format(date));
                        dataMap.put("create_date",dateFormat.format(date));
                    }
                }
            }else{
                dataMap.put("create_time",timeFormat.format(date));
                dataMap.put("create_date",dateFormat.format(date));
            }
            if(!fieldMap.get("create_user")){
                BaseDao.setDefaultValue(dataMap,user);
            }else{
                String createUser=String.valueOf(dataMap.get("create_user"));
                String sql="select * from tbl_system_user where user_name='"+createUser+"'";
                List<Map<String, Object>> userList=jdbcTemplate.queryForList(sql);//todo 导入用户不存在校验
                dataMap.put("create_user",userList.get(0).get("user_name"));
                dataMap.put("create_user_id",userList.get(0).get("id"));
                dataMap.put("create_org_id",userList.get(0).get("org_id"));
                dataMap.put("create_org_name",userList.get(0).get("org_name"));
            }
            if(!fieldMap.get("page_parent_uuid")&&(parentUUID.length()>0&&!parentUUID.equals("null"))){
                dataMap.put("page_parent_uuid",parentUUID);
            }
            dataMap.put("data_source","excel");
            dataMaps.add(dataMap);
            Integer sumRow=sheet.getPhysicalNumberOfRows();
            Integer errorRow=sumRow-xxx-(readRow-1);//总行数减去成功和标题行得出未导入的。
            String errorText="";
            if(errorRow>0){
                errorText="，失败："+errorRow+"条，请检查文件第"+(xxx+2)+"行";//加2是因为从0开始和去掉标题列
            }
            returnMap.put("importMessage"," 导入了"+(xxx-readRow+2)+"条"+errorText);//提前设置导入成功message
        }
        redisPublication.sendMessage("{\"wsCode\":\""+wsCode+"\",\"message\":\"解析完成共"+(sheet.getPhysicalNumberOfRows()-readRow+1)+"条，开始检测数据是否规范\",\"status\":\"ok\",\"isHideMask\":\"N\"}",String.valueOf(user.getId()));
        return returnMap;
    }
    public static Map<String,Object> importExcelData(String jsonStr,JackJSONObject retJson, Map<String,Object>  returnMap, Map<String,Object> fileInfo,
                                                     List<Map<String, Object>> dataMaps, List<Map<String, Object>> queryFieldList,
                                                     List<Map<String, Object>> formFieldList, InputStream inputStream, UserService userService,
                                                     User user, JdbcTemplate jdbcTemplate, RedisPublication redisPublication) {
        String suffix=String.valueOf(fileInfo.get("suffix"));
        if("xls".equals(suffix)){
            return importExcelDataByXls(jsonStr,retJson,returnMap,fileInfo,dataMaps,queryFieldList,formFieldList,inputStream,userService,user,jdbcTemplate,redisPublication);
        }else{
            return importExcelDataByXlsx(jsonStr,retJson,returnMap,fileInfo,dataMaps,queryFieldList,formFieldList,inputStream,userService,user,jdbcTemplate,redisPublication);
        }//todo csv待开发，目前仅支持xls和xlsx两种，csv待开发
    }
    public static Map<String,Object> uploadToService(String filePath,HttpServletRequest request) {
        Map<String,Object>  returnMap=new HashMap<>();
        MultipartHttpServletRequest multipartHttpServletRequest = (MultipartHttpServletRequest) request;
        List<MultipartFile> files = multipartHttpServletRequest.getFiles("uploadFile");
        String realFileName=files.get(0).getOriginalFilename();
        String suffix=realFileName.substring(realFileName.lastIndexOf(".")+1);
        String realName = realFileName.replace("."+suffix, "");
        DateTime d=new DateTime();
        String fileDir=filePath+d.toString("yyyyMM");
        File folder = new File(fileDir);
        if (!folder.exists()) {
            folder.mkdirs();
        }
        //文件上传组件
        DiskFileItemFactory factory = new DiskFileItemFactory();
        ServletFileUpload upload = new ServletFileUpload(factory);
        upload.setHeaderEncoding("UTF-8");
        try {
            for (MultipartFile fileItem : files) {
                // uuid当文件名
                String fileName= UUID.randomUUID().toString().replaceAll("-","");
                returnMap.put("uuid", fileName);
                //io 输入流读文件
                InputStream is = fileItem.getInputStream();
                //利用输出流写入对应的文件夹
                FileOutputStream fout = new FileOutputStream(new File(fileDir + "/" + fileName + "." + suffix));
                //写入数据
                byte[] buffer = new byte[1024];
                int len = 0;
                while ((len = (is.read(buffer))) > -1) {
                    fout.write(buffer, 0, len);
                }
                fout.close();
                is.close();
                returnMap.put("source", "service");
                returnMap.put("realFileName", realFileName);
                returnMap.put("realName", realName);
                returnMap.put("diskFileName", d.toString("yyyyMM")+"/"+fileName + "." + suffix);
                returnMap.put("suffix",  suffix);
                returnMap.put("fileSize",files.get(0).getSize());
                returnMap.put("fileShowSize",ApiDao.readableFileSize(files.get(0).getSize()));
                //判断如果是图片将宽高放到map里
                if(suffix.equalsIgnoreCase("jpg")||suffix.equalsIgnoreCase("png")||suffix.equalsIgnoreCase("jpeg")){
                    returnMap.put("width",  request.getParameter("width"));
                    returnMap.put("height",  request.getParameter("height"));
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return returnMap;
    }
    public static Map<String,Object> uploadToMinio(JackJSONObject retJson,MinioService minioService,HttpServletRequest request) {
        Map<String,Object>  returnMap= null;
        try {
            returnMap = minioService.uploadToMinio(retJson,request);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return returnMap;
    }
    public static String readableFileSize(long size){
        if (size <= 0) {
            return "0";
        }
        final String[] units = new String[]{"B", "KB", "MB", "GB", "TB"};
        int digitGroups = (int) (Math.log10(size) / Math.log10(1024));
        return new DecimalFormat("#,###.##").format(size / Math.pow(1024, digitGroups)) + " " + units[digitGroups];
    }
    /**
     * 判断文件路径是否包含非法字符，防止路径遍历攻击
     */
    public static boolean isInvalidPath(String fileName) {
        return fileName.contains("..");
    }
}
