All Downloads are FREE. Search and download functionalities are using the official Maven repository.

cn.benma666.sjsj.web.DefaultLjq Maven / Gradle / Ivy

/**
 * Project Name:myutils
 * Date:2018年12月16日
 * Copyright (c) 2018, jingma All Rights Reserved.
 */

package cn.benma666.sjsj.web;

import cn.benma666.constants.SysAuth;
import cn.benma666.crypt.MD5Util;
import cn.benma666.dict.*;
import cn.benma666.domain.*;
import cn.benma666.excel.ImageConverter;
import cn.benma666.excel.ImageConverterKey;
import cn.benma666.excel.MyLongestMatchColumnWidthStyleStrategy;
import cn.benma666.exception.DictException;
import cn.benma666.exception.MyException;
import cn.benma666.exception.QxException;
import cn.benma666.exception.VerifyRuleException;
import cn.benma666.json.JsonUtil;
import cn.benma666.iframe.*;
import cn.benma666.myutils.DateUtil;
import cn.benma666.myutils.*;
import cn.benma666.params.other.Dcsjycl;
import cn.benma666.sjsj.myutils.Msg;
import cn.benma666.sjsj.myutils.MyTransactional;
import cn.benma666.sjsj.myutils.ThreadPool;
import cn.benma666.sjsj.znjh.MyZnjh;
import cn.benma666.sjzt.*;
import cn.benma666.sjzt.bdwj.BdwjFile;
import cn.benma666.vo.WebSocketKhdxxVo;
import com.alibaba.druid.util.Utils;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.converters.ConverterKeyBuild;
import com.alibaba.excel.support.ExcelTypeEnum;
import com.alibaba.excel.write.builder.ExcelWriterSheetBuilder;
import com.alibaba.excel.write.handler.CellWriteHandler;
import com.alibaba.excel.write.handler.SheetWriteHandler;
import com.alibaba.excel.write.handler.context.CellWriteHandlerContext;
import com.alibaba.excel.write.handler.context.SheetWriteHandlerContext;
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
import com.alibaba.excel.write.metadata.holder.WriteWorkbookHolder;
import com.alibaba.excel.write.metadata.style.WriteCellStyle;
import com.alibaba.excel.write.style.column.AbstractColumnWidthStyleStrategy;
import com.alibaba.excel.write.style.row.SimpleRowHeightStyleStrategy;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.parser.Feature;
import com.alibaba.fastjson.util.TypeUtils;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddressList;
import org.beetl.sql.clazz.SQLType;
import org.beetl.sql.core.*;
import org.beetl.sql.core.mapping.BeanProcessor;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.springframework.context.annotation.Scope;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.nio.charset.StandardCharsets;
import java.sql.*;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 默认拦截器 
* date: 2018年12月16日
* * @author jingma */ @Component("MyDefaultLjq") @Scope("prototype") public class DefaultLjq extends BasicObject implements LjqInterface { /** * 去重字段列表缓存后缀 */ public static final String QCZD_LIST = "_qczdList"; /** * 数据对象Map<对象key,对象> */ protected static final JSONObject sjdxMap = CacheFactory.use(KEY_SJDX); /** * 字段信息缓存 */ protected static JSONObject fieldsCache = CacheFactory.use(KEY_FIELDS, CacheFactory.TYPE_MEMORY); /** * 允许的文件类型 */ protected static Collection yxdwjlx = Arrays.asList( valByDef(Conf.getUtilConfig().getService().getYxscwjlx(), "xls,xlsx,txt,csv,zip,rar,7z,png,jpg,json,xml").split(",")); public DefaultLjq(){ } /** * 获取处理类型 * * @param myParams 参数对象 * @return 处理类型 */ public static String getCllx(MyParams myParams) { return myParams.sys().getCllx(); } public Result initSjdx(MyParams myParams) throws MyException{ if (StringUtil.isBlank(getCllx(myParams))) { throw new MyException(Msg.msg("interceptor.bxsscllx", "sys.cllx")); } //记录请求开始时间 myParams.sys().setQqkssj(System.currentTimeMillis()); //获取用户信息 @Nullable SysQxYhxx user = LjqManager.getUser(myParams); myParams.put(KEY_USER, user); //穿透场景不进行对象处理 if(isCt(myParams)){ //记录操作日志 initCzrz(myParams, user); return success("获取基础信息成功",myParams); } SysSjglSjdx sjdx; //读取缓存 String cacheKey = StringUtil.fastNotNull(myParams.sys().getDlsjdxid(), myParams.sys().getDlsjdxdm(),myParams.sys().getAuthCode(), myParams.sjdx().getId(),myParams.sjdx().getDxdm()); if(!isBlank(cacheKey)){ synchronized (sjdxMap){ //进行同步操作,不免重复查询,缓存加载完成后这里应该耗时很少,应该不会成为瓶颈 Object obj = sjdxMap.get(cacheKey); if (obj != null && !valByDef(myParams.sys().getClearCache(),false)) { sjdx = (SysSjglSjdx) obj; } else { JSONObject jsonObj = Db.use().findFirst(SqlId.of("sjsj", "findSjdx"), myParams); if (jsonObj == null) { throw new MyException(Msg.msg("interceptor.sjdxbwy", cacheKey), myParams); } sjdx = jsonObj.toJavaObject(SysSjglSjdx.class); //设置缓存 sjdxMap.put(cacheKey,sjdx); } } }else { throw new MyException("该请求没有设置数据对象信息"); } JSONObject defParams = JSONObject.parseObject(Conf.getVal("sjdx.jcxx1"), Feature.OrderedField); //合并新配置与默认配置 myParams.putAll(JsonUtil.mergeJSONObjects(defParams,myParams)); if(!myParams.sys().getNbdy()&&!UserManager.hasAuth(user, SysAuth.QTQX_SYS.name())){ //非内部调用且没有最高权限 defParams= JSONObject.parseObject(Conf.getVal("sjdx.jcxx2"), Feature.OrderedField); //合并优先级高于用户传参的默认配置2(核心关键配置),对前端传参进行控制,避免前端传参权力太大,入侵系统 JsonUtil.mergeJSONObjects(myParams,defParams); } //合并数据对象的扩展信息到系统参数中 if(sjdx!=null){ if(valByDef(Conf.getUtilConfig().getZnjh().getZdctdy(), true)){ log.trace("开始进行自动补充穿透调用:{},{},{}",sjdx,sjdx.getSjztObj(),myParams.sys().getCtapp()); if(!isBlank(sjdx.getSjztObj().getSsyy())&&isBlank(myParams.sys().getCtapp())){ //数据载体设置了所属应用且外部没有设置穿透app时自动补充 myParams.sys().setCtapp(sjdx.getSjztObj().getSsyy()); } if(!isBlank(myParams.sys().getCtapp())){ //自动设置穿透调用,有穿透app时,查看是否需要进行穿透调用 SysZnjhCtdy ctdy = MyZnjh.getCtdyByMbjd(myParams.sys().getCtapp()); if (!isBlank(ctdy.getDm())) { myParams.sys().setCtdy(ctdy.getDm()); } } } //设置从数据库中读取的数据对象 myParams.put(KEY_SJDX, sjdx); //通过大字典扩展对象,对象本地的扩展信息字段大小限制4000可能存不下,较少使用 String kzxx = Conf.getVal(sjdx.getDxdm() + ".kzxx"); if(!isBlank(kzxx)){ JsonUtil.mergeJSONObjects(myParams, JSONObject.parseObject(kzxx, Feature.OrderedField)); } JsonUtil.mergeJSONObjects(myParams, sjdx.getKzxxObj()); //对rest接口的支持(支持路径参数传递一个关键参数):SEARCHKEY处理,非查询场景,设置了该参数时,且原始参数没有设置主键,自动设置为对象主键 if(!Cllx.select.name().equals(myParams.sys().getCllx()) &&StringUtil.isNotBlank(myParams.sys().getSearchKey()) &&isBlank(myParams.get("$.yobj."+sjdx.getZddmZjzd()))){ myParams.set("$.yobj."+sjdx.getZddmZjzd(),myParams.sys().getSearchKey()); } } //穿透场景不获字段等信息 if(isCt(myParams)){ //记录操作日志 initCzrz(myParams, user); return success("获取基础信息成功",myParams); } //获取基础信息 return success("获取基础信息成功",LjqManager.jcxx(myParams)); } /** * 是否穿透 */ public boolean isCt(MyParams myParams){ //穿透场景不获字段等信息 if(!isBlank(myParams.sys().getCtqapp())&&!Conf.getAppdm() .equals(myParams.sys().getCtqapp())){ //穿透前app调用 return true; }else if(!isBlank(myParams.sys().getCtdy())){ return true; }else if(!isBlank(myParams.sys().getCtapp())&&!Conf.getAppdm() .equals(myParams.sys().getCtapp())){ return true; } return false; } public Result jcxx(MyParams myParams) { SysQxYhxx user = myParams.user(); //处理权限码 if(isBlank(myParams.sys().getAuthCode())){ //若前端没有传入权限码 if(user!=null&&getSjdx()!=null&&user.getDxqxys().get(getSjdx().getDxdm())!=null){ //优先取当前用户获得授权的权限码 myParams.sys().setAuthCode(user.getDxqxys().get(getSjdx().getDxdm()).getString("qxm")); }else if(getSjdx()!=null){ //若都没有授权则随机取,其实取哪个已经没意义了,反正都一样没权限 myParams.sys().setAuthCode(getSjdx().getAuthCode()); }else if(isBlank(myParams.sys().getController())&&user!=null &&user.getDxqxys().get(myParams.sys().getController())!=null){ //定制场景 myParams.sys().setAuthCode(user.getDxqxys().get(myParams.sys() .getController()).getString("qxm")); } } //获取字段信息 if(getSjdx()!=null){ //没有数据对象不获取字段 try{ getFields(myParams, user); }catch (MyException e){ //权限鉴定 auth(myParams); throw e; } } //记录操作日志 initCzrz(myParams, user); //权限鉴定 auth(myParams); //非定制场景 if(getSjdx()!=null){ if (myParams.getBooleanValue("$.cllxkz."+getCllx(myParams)+".putobj")) { //设置需要处理的对象 putObj(myParams,false); } //转换规则 zhgz(myParams); //参数预处理 csycl(myParams); //验证规则 yzgz(myParams); } log.trace("基础信息获取完成"); return success("获取基础信息成功",myParams); } /** * 参数预处理 */ protected void csycl(MyParams myParams) { JSONObject yobj = myParams.getJSONObject(KEY_YOBJ); if(isBlank(yobj)){ return; } String cllx = getCllx(myParams); Map fields = (Map) myParams.get(KEY_FIELDS); for(Map.Entry e:fields.entrySet()){ if (isBlank(yobj.get(e.getKey()))){ //空值忽略 continue; } SysSjglSjzd f = e.getValue(); JSONArray list; if(f.getZdywlb().contains("plcz")){ //混合保存支持 list = yobj.getJSONArray(e.getKey()); //参数重组 yobj.remove(e.getKey()); if("MyFile".equals(f.getKjlx())){ //文件控件,表示通过文件批量上传的数据 myParams.sys().setFiles(list); //转为批量保存 if(Cllx.insert.name().equals(cllx)||Cllx.update.name().equals(cllx) ||Cllx.save.name().equals(cllx)){ //一般保存转为数据批量上传 myParams.sys().setCllx(Cllx.sjplsc.name()); } }else { List nList = new ArrayList<>(); JSONObject no; for (JSONObject o:list.toJavaList(JSONObject.class)){ no = yobj.clone(); JsonUtil.mergeJSONObject(no,o); nList.add(no); } myParams.sys().setEditTableData(nList); myParams.remove(KEY_YOBJ); //转为批量保存 if(Cllx.insert.name().equals(cllx)||Cllx.update.name().equals(cllx) ||Cllx.save.name().equals(cllx)){ //一般保存转为批量保存 myParams.sys().setCllx(Cllx.plbc.name()); } } }else if(f.getZdywlb().contains("glcz")){ //关联操作 Object val = yobj.get(e.getKey()); yobj.remove(e.getKey()); MyParams glcs = new MyParams(f.getKzxxObj().getJSONObject("glcs")); if(isBlank(glcs)){ throw new MyException("关联操作参数不能为空:"+e.getKey()); } if(val instanceof List){ if("MyFile".equals(f.getKjlx())){ //文件控件,表示通过文件批量上传的数据 glcs.sys().setFiles((List) val); cllx = getCllx(glcs); //转为批量保存 if(Cllx.insert.name().equals(cllx)||Cllx.update.name().equals(cllx) ||Cllx.save.name().equals(cllx)){ //一般保存转为数据批量上传 glcs.sys().setCllx(Cllx.sjplsc.name()); } }else { glcs.sys().setEditTableData((List) val); } }else { glcs.put(KEY_YOBJ,val); } myParams.sys().getCstcl().put(f.getZdmc(),glcs); } } } /** * 转换规则 * @param myParams 相关参数 */ public void zhgz(MyParams myParams) { JSONObject zhgz = myParams.getJSONObject(KEY_ZHGZ); if (zhgz==null) { //没有配置转换信息 return; } //取出验证规则 String cllx = getCllx(myParams); for (String key : zhgz.keySet()) { JSONObject gzObj = zhgz.getJSONObject(key); Object val = myParams.get("$." + key); Object newVal = TransRule.ruleTrans(val,myParams, gzObj, cllx); if((isBlank(val)&&isBlank(newVal))){ //原始值为空,转换后也为空则跳过 continue; } //转换数据 myParams.set("$." + key,newVal); } } /** * 验证规则 * @param myParams 相关参数 */ public void yzgz(MyParams myParams) { //取出验证规则 JSONObject yzgz = myParams.getJSONObject(KEY_YZGZ); if (myParams.get(KEY_USER) == null||yzgz==null) { //没有用户信息默认为系统内部调用,不进行验证,或没有配置验证信息 return; } String cllx = getCllx(myParams); for (String key : yzgz.keySet()) { JSONObject gzObj = yzgz.getJSONObject(key); try { Object val = myParams.get("$." + key); Object newVal = VerifyRule.ruleVerify(myParams.get("$." + key), myParams, gzObj, cllx); if((isBlank(val)&&isBlank(newVal))){ //原始值为空,转换后也为空则跳过 continue; } //转换数据 myParams.set("$." + key,newVal); } catch (VerifyRuleException e) { throw new MyException(e.getMessage(), HttpStatus.PRECONDITION_FAILED.value(), key); } } } /** * 采用base64的方式上传 */ public Result upload(MyParams myParams) throws Exception { SysSjglFile file = myParams.yobj(SysSjglFile.class); if(StringUtil.isBlank(file.getWjnr())){ throw new MyException("没有获取到上传文件内容"); } if(!yxdwjlx.contains(file.getWjlx())){ throw new MyException("上传的文件类型不支持:"+file.getWjlx()); } if(StringUtil.isEmpty(file.getYwdm())){ file.setYwdm("dxsjsc"); } if(StringUtil.isEmpty(file.getWjlb())){ file.setWjlb(getSjdx().getDxdm()); } byte[] byteArr = Base64.getDecoder().decode(file.getWjnr()); //去重码ywdm+wjlb+MD5 file.setQcm(file.getYwdm() + file.getWjlb() + FileUtil.getFileMD5(byteArr)); //如果表中存在此去重码则把这个文件删除 MyLambdaQuery fileMyLambdaQuery = db(DEFAULT).lambdaQuery(SysSjglFile.class,myParams.user()); SysSjglFile f = fileMyLambdaQuery.andEq(SysSjglFile::getQcm,file.getQcm()).singleSimple(); if (f!=null) { log.info(f.getWjm() + "文件已经存在"+f.getId()); return success("该文件已经存在", f.toQd()); } IFile ifile = file.toIFile(); ifile.save(new ByteArrayInputStream(byteArr)); //保存文件记录 file.setWjdx(byteArr.length); file.setSclj(ifile.getAbsolutePath()); fileMyLambdaQuery.insertSelective(file); //避免文件内容打印到日志和返回前端 file.setWjnr(null); log.debug(file.getWjm() + "文件上传成功"); return success("文件上传成功", file.toQd()); } /** * 只取对外有用的,系统基础信息 * @return 系统基础信息 */ public Result xtjcxx(MyParams myParams){ MyParams jcxx = new MyParams(); jcxx.put(KEY_USER,myParams.user().toQd()); JsonUtil.copy(jcxx, myParams, $_SYS_TOKEN); JsonUtil.copy(jcxx, myParams, $_SYS_CLIENT_IP); //设置在线用户数 jcxx.set("$.sys.zxyhs", XtxxWebSocket.getOnlineCount()); return success("基础信息获取成功", jcxx); } /** * 只取对外有用的,对象基础信息 * @return 对象基础信息 */ public Result dxjcxx(MyParams myParams){ //只取对外有用的,对象基础信息 JSONObject jcxx = new JSONObject(); jcxx.put(KEY_SJDX, myParams.get(KEY_SJDX)); jcxx.put(KEY_FIELDS, myParams.get(KEY_FIELDS)); jcxx.put(KEY_OBJ, myParams.get(KEY_OBJ)); JsonUtil.copy(jcxx, myParams, "$.cllxkz"); JsonUtil.copy(jcxx, myParams, "$.sys.sjdxkz"); JsonUtil.copy(jcxx, myParams, "$.sys.fields"); JsonUtil.copy(jcxx, myParams, "$.sys.cdlj"); JsonUtil.copy(jcxx, myParams, $_SYS_AUTHCODE); return success("对象基础信息获取成功", jcxx); } public Result getdata(MyParams myParams) { //创建个对象,用于在模板中可以设置一些数据作为结果传给前端 JSONObject resultData = new JSONObject(); myParams.sql().setResultData(resultData); //先调用一次查询语句,获取默认查询条件 LjqManager.getSql(myParams,Cllx.select.name()); String[] arr = (String[]) getSql(myParams).getData(); resultData.put("list", db(arr[0]).find(arr[1], myParams)); return success("操作成功", resultData); } public Result plcl(MyParams myParams) { //先调用一次查询语句,获取默认查询条件 LjqManager.getSql(myParams,Cllx.select.name()); String[] arr = LjqManager.getSql(myParams); final int update = db(arr[0]).update(arr[1], myParams); return success("操作成功:"+update, update); } /** * 导出当前页数据 */ public Result dcdqysj(MyParams myParams) { return dcsj(myParams); } public Result dcsj(MyParams myParams) { //导出数据 myParams.set("$.page.totalRequired", Boolean.FALSE); myParams.set("$.page.listRequired", Boolean.TRUE); PageInfo page = (PageInfo) LjqManager.select(myParams).getData(); String fileName = getSjdx().getDxmc()+"-" + DateUtil.getGabDate(); try { dcsjYcl(myParams,page.getList(),Cllx.dcsj.name()); return resultExcelFile(myParams, myParams.other().getDcsjycl().getHeader(), myParams.other().getDcsjycl().getData(), fileName); } catch (Exception e) { throw new MyException("导出数据失败,请查看系统日志分析原因",e); } } public Result getfile(MyParams myParams) { String[] arr; try { arr = (String[]) LjqManager.getSql(myParams); List rl = db(arr[0]).find(arr[1], myParams); if (rl.size() == 0) { throw new MyException("未找到文件数据"); } JSONObject fo = rl.get(0); SysSjglFile file = fo.toJavaObject(SysSjglFile.class); String sjxs = fo.getString("sjxs"); byte[] byteArr = null; if ("bdwjjl".equals(sjxs)) { byteArr = Utils.readByteArray(new FileInputStream(fo.getString("data"))); } else if ("blob".equals(sjxs)) { byteArr = fo.getBytes("data"); } if(myParams.containsKey("$.sys.xzms")){ file.setXzms(myParams.getIntValue("$.sys.xzms")); } return resultFile(byteArr, file); } catch (Exception e) { log.error("获取文件失败:" + myParams, e); throw new MyException("获取文件失败,请查看系统日志分析原因:" + e.getMessage()); } } /** * 下载文件 * @param myParams 相关参数 * @return 处理结果 */ public Result download(MyParams myParams) { MyParams fileJcxx = LjqManager.jcxxByDxdm("SYS_SJGL_FILE",myParams.user()); fileJcxx.set("$.page.totalRequired", Boolean.FALSE); fileJcxx.put(KEY_YOBJ,myParams.get(KEY_YOBJ)); fileJcxx.yobj(SysSjglFile.class).setYxx(Ljpd.TURE.getCode()+""); JsonUtil.copy(fileJcxx,myParams,$_SYS_IDS); PageInfo page = (PageInfo) LjqManager.select(fileJcxx).getData(); if (page.getList().size() == 0) { throw new MyException("没有找到该文件"); } else if (page.getList().size() > 1) { throw new MyException("不能找到唯一的文件记录"); } SysSjglFile file = page.getList().get(0).toJavaObject(SysSjglFile.class); return resultFile(file.getFileBytes(), file); } public Result sjplsc(MyParams myParams) { JSONArray files = myParams.getJSONArray("$.sys.files"); if(isBlank(files)){ throw new MyException("没有获取到文件,请确认文件正确上传"); } Result r = success(""); int count = 0; int insert = 0; int update = 0; int ignore = 0; int repeat = 0; List succFiles = new ArrayList<>(); SysSjglFile file = null; try { for(int i=0;i0){ r.setMsg(StringUtil.join(succFiles,",")); Result r1 = sjplcljg(count, insert, update, ignore, repeat); r.addMsg(r1.getMsg()); r.setData(r1.getData()); } return r; } /** * 批量数据转换验证 * @param myParams 参数体 * @return 验证转换结果 */ public Result plsjzhyz(MyParams myParams) { JSONArray editTableData = myParams.getJSONArray($_SYS_EDITTABLEDATA); if(isBlank(editTableData)){ return success("没有提供批量转换验证的数据"); } //重复数据量 List list = editTableData.toJavaList(JSONObject.class); //处理后的数据列表,用于后续批量插入更新 List dataList; if (Db.isSupported(getSjdx().getDxztlx()) || SjztLx.es.name().equals(getSjdx().getDxztlx())) { //数据库场景才进行查重操作 dataList = new ArrayList<>(); List qcList = new ArrayList<>(); String qczd = null; //先查询重复数据 for (JSONObject j : list){ myParams.put(KEY_YOBJ, j); //根据输入参数进行重复查询 JSONObject qcObj = putObj(myParams,true).getData(JSONObject.class); if (isBlank(qcObj)) { //没有去重的直接加入待处理列表 dataList.add(j); }else { //设置去重字段 qczd = qcObj.keySet().toArray()[0].toString(); //去重字段值 qcList.add(qcObj.values().toArray()[0]); } } //基于去重字段的数据MAP Map qczdMap = Db.listToMap(list, qczd); if(!isBlank(qcList)){ myParams.sql().setQczd(qczd); //不进行总量查询 myParams.page().setTotalRequired(Boolean.FALSE); myParams.page().setPageSize(list.size()*2); myParams.put(KEY_YOBJ, new JSONObject()); JSONObject yobj; //按20000分批次查询,避免sql太长 List> qcList1 = CollectionUtils.partition(qcList, 20000); Map qczdList = (Map) fieldsCache.get(getSjdx().getId()+ QCZD_LIST); for(List ql:qcList1){ //设置根据去重字段查询数据的条件,按1000分组,oracle对in的数量有限制 myParams.sql().setQcList(CollectionUtils.partition(ql, 1000)); List sList = select(myParams).getPageList(JSONObject.class); for(JSONObject o:sList){ //移除查询到的数据 yobj = qczdMap.get(o.getString(qczd)); if(yobj==null){ //查询到多条时会出现 continue; } qczdMap.remove(o.getString(qczd)); //把查询出来的主键设置到原输入参数中,便于配置了去重字段的场景基于主键进行更新 setYobjByObj(yobj, qczdList, o); //设置已找到记录 yobj.put("my-yzdjl",true); yobj.put("my-obj",o); dataList.add(yobj); } } } //将没查询到追加到待处理集合中 dataList.addAll(qczdMap.values()); }else { dataList = list; } List errorList = new ArrayList<>(); Map fieldMap = (Map) myParams .get(KEY_FIELDS); JSONObject zhgz = myParams.getJSONObject(KEY_ZHGZ); JSONObject yzgz = myParams.getJSONObject(KEY_YZGZ); Object val; String cllx; JSONObject ruleObj; Object newVal; boolean sjyz = !(myParams.sys().getNbdy()||(UserManager.hasAuth(myParams.user(),"QTQX_SJTB") &&!TypeUtils.castToBoolean(valByDef(myParams.sys().getSjyz(),1)))); for (int i=0;i e : fieldMap.entrySet()) { val = yobj.get(e.getKey()); //转换规则 ruleObj = zhgz.getJSONObject("yobj."+ e.getKey()); if(ruleObj!=null){ //转换数据 newVal = TransRule.ruleTrans(val,myParams, ruleObj, cllx); if((!isBlank(val)||!isBlank(newVal))){ yobj.put(e.getKey(),newVal); } } if(!sjyz){ //不验证跳过 continue; } ruleObj = yzgz.getJSONObject("yobj." + e.getKey()); if(ruleObj!=null){ try { newVal = VerifyRule.ruleVerify(val, myParams,ruleObj,cllx); if((!isBlank(val)||!isBlank(newVal))){ yobj.put(e.getKey(), newVal); } } catch (VerifyRuleException e1) { SysLogSjsccw sysLogSjsccw = new SysLogSjsccw(yobj.getString("mySswj"),val + "", e.getValue().getZdmc(), (i+1) + "", getSjdx().getId(), (e.getValue().getPx() + 1) + "", e1.getMessage(), myParams.sys().getQqid()); errorList.add(sysLogSjsccw); } } } } myParams.set($_SYS_EDITTABLEDATA,dataList); //设置重复数量 myParams.set("$.sys.cfsjl",editTableData.size()-dataList.size()); Result r; if (errorList.size() > 0) { //设置错误信息相关参数 MyParams sjsccwParams = LjqManager.jcxxByDxdm("SYS_LOG_SJSCCW",myParams.user()); //设置为批量保存模式 sjsccwParams.sys().setCllx(Cllx.plbc.name()); //存入数据库 sjsccwParams.set($_SYS_EDITTABLEDATA, errorList); ThreadPool.use().run(()->{ //采用独立现场去执行错误数据入库,避免主业务事务影响 Result r1 = LjqManager.data(sjsccwParams,Cllx.plbc.name()); if (!r1.isStatus()) { log.error("错误数据入库失败"+r1); } }); r = failed("校验出了" + errorList.size() + "个错误,请按错误列表依次修改后再重新上传",errorList.size()); r.setCode(XtZtm.SJPLSCJYBTG.getCode()); }else { r = success("转换验证成功",dataList); } return r; } /** * 删除数据 * @return 操作结果 */ public Result delete(MyParams myParams) { return LjqManager.data(myParams,Cllx.plsc.name()); } public Result plsc(MyParams myParams) { if (Db.isSupported(getSjdx().getDxztlx())) { //数据库场景 return plscDb(myParams); } else if (SjztLx.es.name().equals(getSjdx().getDxztlx())) { return plscEs(myParams); } else { return plscFile(myParams); } } private Result plscEs(MyParams myParams) { String zjzd = getSjdx().getZddmZjzd(); if(isBlank(zjzd)){ throw new MyException("主键字段没有配置,不能进行批量删除"); } String yxxzd = getSjdx().getYxxzd(); boolean wlsc = myParams.getBooleanValue("$.sys.wlsc"); AtomicInteger wlscsl = new AtomicInteger(); AtomicInteger ljscsl = new AtomicInteger(); Result r = success(""); //设置回调参数体 myParams.set("$.sys.hdcst", (HdInterface) (list, hdjs) -> { if (isBlank(list)) { if (isBlank(r.getMsg())) { r.setMsg("数据列表为空,没有需要处理的数据"); } return r; } MyParams param = JsonUtil.clone(myParams); List ids = new ArrayList<>(); List editTableData = new ArrayList<>(); list.forEach(i -> { if (StringUtil.isNotBlank(yxxzd) && (wlsc || UserManager.hasAuth(param.user(), "QTQX_SYS"))) { if ("0".equals(i.getString(yxxzd))) { ids.add(i.getString(zjzd)); wlscsl.incrementAndGet(); } else { i.set(yxxzd, "0"); editTableData.add(i); ljscsl.incrementAndGet(); } } else if (isBlank(yxxzd)) { ids.add(i.getString(zjzd)); wlscsl.incrementAndGet(); } else { i.set(yxxzd, "0"); editTableData.add(i); ljscsl.incrementAndGet(); } param.set($_SYS_IDS, ids); param.set($_SYS_EDITTABLEDATA, editTableData); }); if (ids.size() != 0) { Result wlsc1 = ES.use(getSjdx().getDxzt()).plsc(param); } if (editTableData.size() != 0) { Map map = new HashMap<>(); map.put("updateList", editTableData); Result ljsc = ES.use(getSjdx().getDxzt()).update(param, map); JSONArray updateIds = ljsc.getJSONArray("updateIds"); } r.setMsg("物理删除记录数:" + wlscsl + "," + "逻辑删除记录数:" + ljscsl); return r; }); Result res = select(myParams); if(!res.isStatus()){ return res; } return r; } /** * @return 核查结果,正确:true,错误:false */ public Result inspect(MyParams myParams) { //不进行列表查询 myParams.set("$.page.listRequired",false); Result r = LjqManager.select(myParams); if(!r.isStatus()){ return r; } return success("核查成功",((PageInfo)r.getData()).getTotalRow()>0); } @MyTransactional public Result select(MyParams myParams) { Result r; if (Db.isSupported(getSjdx().getDxztlx())) { //数据库场景 r = selectDb(myParams); } else if(SjztLx.es.name().equals(getSjdx().getDxztlx())){ r = selectEs(myParams); }else { r = selectFile(myParams); } return r; } @MyTransactional public Result insert(MyParams myParams) throws MyException { myParams.sys().setYzdjl(false); return LjqManager.save(myParams); } @MyTransactional public Result update(MyParams myParams) throws MyException{ myParams.sys().setYzdjl(true); return LjqManager.save(myParams); } /** * 保存数据 * @return 操作结果 */ @MyTransactional public Result save(MyParams myParams) { Result res = success("新增成功"); if(myParams.sys().getYzdjl()){ res.setMsg("更新成功"); myParams.sys().setCllx(Cllx.update.name()); }else{ myParams.sys().setCllx(Cllx.insert.name()); } Result r; if (Db.isSupported(getSjdx().getDxztlx())) { //数据库场景 r = saveDb(myParams); } else if (SjztLx.es.name().equals(getSjdx().getDxztlx())) { //ES场景 r = saveEs(myParams); } else { r = saveFile(myParams); } if(!r.isStatus()){ throw r.newMyException(); } if(valByDef(myParams.sys().getBatch(),false)){ //批量操作时直接返回 return r; } JSONObject data = new JSONObject(); //设置操作记录数 data.put("czjls",r.getData()); //保存成功,返回主键信息 data.put(getSjdx().getZjzd(),myParams.get("$.yobj." + getSjdx().getZddmZjzd())); //返回处理类型,针对自动判断处理类型时,告知前端时进行了插入还是更新 data.put(SjsjField.cllx.name(), myParams.sys().getCllx()); if(!isBlank(myParams.getJSONObject($_SYS_CSTCL))){ //参数体处理的 JSONObject cstcl = myParams.getJSONObject($_SYS_CSTCL); for(String key:cstcl.keySet()){ MyParams nParams = new MyParams(cstcl.getJSONObject(key)); MyParams nJcxx = LjqManager.jcxxByParams(nParams,myParams.user(), false); r = LjqManager.data(nJcxx,nParams.sys().getCllx()); if(!r.isStatus()){ throw r.newMyException(); } data.put(key,r.getData()); res.addMsg(key+":"+r.getMsg()); } } res.setData(data); return res; } /** * 批量保存 * @param myParams 相关参数 * @return 操作结果 */ @MyTransactional public Result plbc(MyParams myParams){ Result r = plsjzhyz(myParams); if(!r.isStatus()){ //验证不通过 throw r.newMyException(); } JSONArray editTableData = myParams.getJSONArray($_SYS_EDITTABLEDATA); JSONObject[] list; if(isBlank(editTableData)){ //也谈不上错误吧。。 return success("没有提供批量保存的数据"); }else { list = editTableData.toJavaList(JSONObject.class).toArray(new JSONObject[]{}); } if(myParams.sys().getBatch()==null){ myParams.sys().setBatch(true); } if (Db.isSupported(getSjdx().getDxztlx())) { //数据库场景 r = plbcDb(myParams,list); } else if (SjztLx.es.name().equals(getSjdx().getDxztlx())) { r = plbcEs(myParams,list); } else { r = plbcFile(myParams,list); } if(!r.isStatus()){ //异常场景抛出异常,便于事务回滚 throw r.newMyException(); } return r; } private Result plbcEs(MyParams myParams, JSONObject[] list) { log.trace("开始进行ES批量保存"); String sjzt = getSjdx().getDxzt(); //新增数据列表 List insertlist = new ArrayList<>(); //修改数据列表 List updateList = new ArrayList<>(); AtomicInteger insert = new AtomicInteger(); AtomicInteger update = new AtomicInteger(); AtomicInteger ignore = new AtomicInteger(); for (JSONObject j : list){ myParams.set($_SYS_YZDJL, valByDef(j.remove("my-yzdjl"), false)); if (myParams.getBooleanValue($_SYS_YZDJL) && myParams.getBooleanValue("$.sys.bzxgx")) { ignore.incrementAndGet(); } else if (!myParams.getBooleanValue($_SYS_YZDJL) && myParams.getBooleanValue("$.sys.bzxxz")) { ignore.incrementAndGet(); } else { myParams.put("obj", j.remove("my-obj")); if (myParams.getBooleanValue($_SYS_YZDJL)) { updateList.add(j); update.incrementAndGet(); } else { insertlist.add(j); insert.incrementAndGet(); } } } Map map = new HashMap<>(); map.put("insertList", insertlist); map.put("updateList", updateList); //保存数据 Result res = ES.use(sjzt).update(myParams, map); if (!res.isStatus()) { throw res.newMyException(); } // PageInfo page = res.getData(PageInfo.class); // JSONArray insertIds = (JSONArray) page.get("insertIds"); // JSONArray updateIds = (JSONArray) page.get("updateIds"); return sjplcljg(list.length, insert.get(), update.get(), ignore.get(), myParams.getIntValue("$.sys.cfsjl")); } public Result getSql(MyParams myParams) { String cllx = myParams.sql().getCllx(); if(isBlank(cllx)){ cllx = myParams.sys().getCllx(); }else { myParams.sql().setCllx(null); } SysSjglSjdx sjdx1 = myParams.getObject(KEY_SJDX, SysSjglSjdx.class); String sql; if(Cllx.select.name().equals(cllx)&&!isBlank(myParams.znjh().getSql())){ //查询场景,存在外部直接传入的sql则优先使用,但要避免一般用户传入造成风险 sql = myParams.znjh().getSql(); String[] arr = Db.parseDictExp(sql, sjdx1.getDxzt()); if(StringUtil.isNotBlank(myParams.page().getOrderBy())){ arr[1] += " order by "+myParams.page().getOrderBy(); } sql = arr[1]+";ds="+arr[0]; myParams.sql().setDefaultSql(sql); }else { //清除之前的默认sql myParams.sql().setDefaultSql(null); //设置from String dxgs = StringUtil.fastNotNull(sjdx1.getDxgs(),sjdx1.getSjztObj().getDxgs()); myParams.sql().setFrom((isBlank(dxgs) ? "" : dxgs + ".") + sjdx1.getJtdx()); //先获取该处理类型对应的数据库的默认sql Db.getZdSqlTmpl(myParams,"DEFAULT."+cllx,sjdx1.getDxztlx()); //处理父对象代码的场景 if(StringUtil.isNotBlank(myParams.sys().getFsjdxdm())&& !myParams.sys().getFsjdxdm().equalsIgnoreCase(sjdx1.getDxdm())){ Db.getZdSqlTmpl(myParams,myParams.sys().getFsjdxdm()+"." +cllx,sjdx1.getDxztlx()); } //获取该对象的专有sql sql = Db.getZdSqlTmpl(myParams,sjdx1.getDxdm() + "." + cllx,sjdx1.getDxztlx()); if(isBlank(sql)){ //模板都不存在哎 throw new MyException(Msg.msg("ljq.default.mypzgsql", cllx), sjdx1); } } log.trace("获取sql,{}.{}:{}",sjdx1.getDxdm(),cllx,sql); return success("获取sql成功",Db.parseDictExp(sql, sjdx1.getDxzt())); } /** * 导出模板 * @param myParams 相关参数 * @return 处理结果 */ public Result dcmb(MyParams myParams) { //导出数据 String fileName = getSjdx().getDxmc()+"-数据上传模板-" + DateUtil.getGabDate(); if (StringUtil.isNotBlank(myParams.sys().getDcwjm())) { fileName = myParams.sys().getDcwjm(); } try { List> header = new ArrayList<>(); List h; List> data = new ArrayList<>(); List r = new ArrayList<>(); data.add(r); List zdList = new ArrayList<>(); Map fields = (Map) myParams.get(KEY_FIELDS); for (Map.Entry f : fields.entrySet()) { SysSjglSjzd field = f.getValue(); if (valByDef(TypeUtils.castToBoolean(field.getMbzs()),false)) { h = new ArrayList<>(); String btmc = field.getZdmc(); if(valByDef(myParams.getBoolean("$.sys.zddm"),true)){ //是否包含字段代码,默认为是 btmc += "[" + f.getKey() + "]"; } zdList.add(f.getKey()); h.add(btmc); header.add(h); if(valByDef(TypeUtils.castToBoolean(field.getBjbt()),false)){ //必填 field.setDcbtbjs(IndexedColors.YELLOW.name()); } r.add(VerifyRule.rulejx(field, field.getKzxxObj().getJSONObject("$.yzgz."+Cllx.insert.name()))); } } //显示的字段 myParams.other().setDcsjycl(Dcsjycl.builder().zdlist(zdList).build()); return resultExcelFile(myParams,header, data, fileName); } catch (Exception e) { log.error("导出数据失败", e); throw new MyException("导出数据失败,请查看系统日志分析原因:" + e.getMessage()); } } /** * websocket客户端注册事件 */ public Result wsmddzc(MyParams myParams){ WebSocketKhdxxVo wsk = myParams.sys().getWskhdxx(); log.info("{}客户端注册:{}", StringUtil.requireNonNull(myParams.user(), "注册WS的用户不能为空").getYhxm(),wsk); SysPtglXtxx xx = SysPtglXtxx.builder().xxnr(getSjdx().getDxmc() + ":消息监听注册成功") .mdddl(wsk.getMdddl()).mddxl(wsk.getMddxl()).tshh(wsk.getToken()).build(); XtxxWebSocket.sendMsg(xx,myParams.user()); return success("收到注册消息"); } /** * websocket客户端取消事件 */ public Result wsmddqx(MyParams myParams){ WebSocketKhdxxVo wsk = myParams.sys().getWskhdxx(); log.info("{}客户端取消:{}", StringUtil.requireNonNull(myParams.user(), "取消注册WS的用户不能为空").getYhxm(),wsk); return success("收到取消消息"); } /** * 穿透app调用,相当于一个代理整合,便于拆分整合应用,如hadoop相关可以单独拆分一个应用,再代理整合一起调用 * @param myParams 参数 * @return 结果 */ public Result ctapp(MyParams myParams) { String ctapp = myParams.sys().getCtapp(); log.trace("开始进行穿透调用:{}",ctapp); //组装请求参数,拿出原始请求 MyParams ysParams = myParams.other().getYsParams(); String url = UserManager.doDesEncryptUrl(StringUtil.fastNotNull(myParams.sys().getCturl(), Conf.getUtilConfig().getZnjh().getUrl(),"/default"),ctapp,myParams.user().getYhdm()); ysParams.sys().setXzms(Xzms.BASE64OBJ.getCode()); //穿透调用时移除加密机制。 ysParams.sys().setPublicKey(null); // if(!isBlank(myParams.getString($_SYS_CLIENT_IP))){ // //ip加密,接收方才认,避免入侵 // ysParams.set($_SYS_CLIENT_IP,StringUtil.encodeing(myParams.getString($_SYS_CLIENT_IP),"sm4ecb",)) // } HttpUtil.HttpUtilBuilder hb = HttpUtil.builder(); if(!isBlank(myParams.sys().getTimeout())){ //设置超时参数 hb.cssc(myParams.sys().getTimeout()); } boolean sfyb = hdffToHdcst(ysParams,myParams); Result r = Result.parse(hb.build().josnByJson(url, ysParams.toJSONString())); return ybjgcl(myParams, r,sfyb); } /** * 统一回调方法 */ public Result tyhd(MyParams myParams) { String hdqqid = myParams.getString("$.sys.hdqqid"); if(isBlank(hdqqid)){ throw new MyException("没有提供回调请求id,无法确定对应哪一次请求"); } int i = 0; while (i<10&&!defaultCache.containsKey(hdqqid)){ //避免回调回来时,主请求还未返回 try { Thread.sleep(1000); } catch (InterruptedException e) { log.warn("等待异常"); } i++; } if(!defaultCache.containsKey(hdqqid)){ throw new MyException("没有对应等待回调的请求"); } HdInterface hdff = (HdInterface) defaultCache.get(hdqqid); Result result = null; try { result = Result.parse(myParams.sys().getContext()+""); result.addMsg("回调方返回结果"); Object r = myParams.get($_SYS_EDITTABLEDATA); List list; if(isBlank(r)){ return success("回调数据为空直接返回"); } list = myParams.getJSONArray($_SYS_EDITTABLEDATA).toJavaList(JSONObject.class); return hdff.run(list,myParams.sys().getHdjs(),result); }finally { if(myParams.sys().getHdjs()){ //回调结束,请求方法结束等待 Lock lock = (Lock) defaultCache.get("lock_"+hdqqid); Condition cond = (Condition) defaultCache.get("cond_"+hdqqid); defaultCache.put("result_"+hdqqid,result); //唤醒等待 lock.lock(); cond.signal(); lock.unlock(); } } } /** * 穿透调用,可以实现将请求生成文件,传到其他地方调用后结果返回 * @param myParams 参数 * @return 结果 */ public Result ctdy(MyParams myParams) { //穿透调用 String ctdyKey = "ctdy" + myParams.sys().getCtdy(); SysZnjhCtdy ctdy = defaultCache.getObject(ctdyKey, SysZnjhCtdy.class); if(ctdy==null){ ctdy = db(DEFAULT).lambdaQuery(SysZnjhCtdy.class) .andEq(SysZnjhCtdy::getTsjd,Conf.getAppdm()) .andEq(SysZnjhCtdy::getDm, myParams.sys().getCtdy()) .singleSimple(); //缓存一下,避免每次查询 if(ctdy==null){ ctdy = new SysZnjhCtdy(); } defaultCache.put(ctdyKey,ctdy); } if (isBlank(ctdy.getDm())) { throw new MyException("没有找到穿透调用配置:"+ myParams.getString("$.sys.ctdy")); } //组装请求参数,拿出原始请求 MyParams ysParams = myParams.other().getYsParams(); //设置来源交换节点,便于请求方法找传回结果的穿透 ysParams.znjh().setMbjd(Conf.getAppdm()); //设置请求用户 ysParams.znjh().setUser(myParams.user().getYhdm()); boolean sfyb = hdffToHdcst(ysParams,myParams); //生成穿透文件 BasicSjzt tszt = BasicSjzt.useSjzt(ctdy.getTsjhObj().getSrzt()); IFile tswj = new BdwjFile(FileUtil.getFilePath(ctdy.getTsjhObj().getSrml(), ctdy.getTsml(),"/ctdy"),myParams.sys().getQqid()+".json",tszt); try { log.debug("开始穿透调用:{}",tswj.getAbsolutePath()); tszt.save(new ByteArrayInputStream(ysParams.toString().getBytes(StandardCharsets.UTF_8)),tswj); } catch (Exception e) { throw new MyException("保存穿透调用请求文件失败",e); } if(!valByDef(myParams.sys().getCtdyjg(),true)){ //是否要穿透调用结果 return success(ctdy.getMc()+">穿透调用完成,该穿透调用不需要穿透调用结果"); } if(isBlank(ctdy.getJsjh())){ log.debug("没有配置接收穿透结果的交换:{}",ctdy.getMc()); return success(ctdy.getMc()+">穿透调用完成,没有配置接收穿透结果的交换"); } //采用锁等待返回结果,超时时长配置 Lock lock = new ReentrantLock(); try { lock.lock(); Condition cond = lock.newCondition(); BasicFile.ctdyMap.put(IFile.RESULT+tswj.getName(),lock); BasicFile.ctdyCondMap.put(IFile.RESULT+tswj.getName(),cond); if(cond.await(StringUtil.fastNotNull(myParams.sys().getTimeout(), Conf.getUtilConfig().getZnjh().getCtdydd(),120000), TimeUnit.MILLISECONDS)){ //结果返回 Result r = BasicFile.ctjgMap.get(IFile.RESULT + tswj.getName()); if(r == null){ return failed(ctdy.getMc()+">没有获取到穿透调用的结果"); } r.addMsg(ctdy.getMc()+">穿透调用完成"); return ybjgcl(myParams, r,sfyb); }else { Result r = failed(ctdy.getMc()+">穿透调用超时:"+tswj.getName()); r.setCode(XtZtm.CTDYCS.getCode()); return r; } } catch (InterruptedException e) { throw new MyException(ctdy.getMc() + ">穿透调用被中断:" + tswj.getName()+"->"+e.getMessage(),e); }finally { lock.unlock(); BasicFile.ctjgMap.remove(IFile.RESULT + tswj.getName()); BasicFile.ctdyMap.remove(IFile.RESULT+tswj.getName()); BasicFile.ctdyCondMap.remove(IFile.RESULT+tswj.getName()); } } /** * 结果发送到前端 * @param myParams 相关参数 */ public void sendResult(MyParams myParams){ Result r = myParams.yobj(Result.class); HttpServletResponse response = LjqManager.getHttpServletResponse(); //将请求id返回给前端 r.setQqid(myParams.sys().getQqid()); //非虚拟对象时才记录日志 writeCzrz(myParams, r); //根据返回类型向前端推送数据 if (XtZtm.DZCLJG.getCode() ==r.getCode()||response==null) { //前面自行处理,不统一处理,或响应对象为空 log.trace("不统一处理返回信息:{}",r); } else if (HttpURLConnection.HTTP_MOVED_TEMP ==r.getCode()) {//重定向 response.setStatus(r.getCode()); try{ response.sendRedirect(r.getData()+""); }catch (Exception e){ log.error("重定向失败:"+r,e); WebUtil.sendJson(response, failed("重定向失败:"+r)); } } else if (MediaType.APPLICATION_OCTET_STREAM_VALUE.equals(r.getDateType())) { //文件下载场景 SysSjglFile file = r.getData(SysSjglFile.class); if(file==null){ //下载文件,没文件信息 r.addMsg("下载文件没有获取到文件信息"); throw r.newMyException(); } byte[] bytes; if(StringUtil.isNotBlank(file.getBytes())){ //提供的是二进制数据 bytes = file.getBytes(); file.setBytes(null); }else if(StringUtil.isNotBlank(file.getWjnr())){ //提供的是base64数据 bytes = Base64.getDecoder().decode(file.getWjnr()); file.setWjnr(null); }else{ throw new MyException("没获取到要下载的数据"); } //base64 String base64; //优先取前端传入的下载模式 int xzms = valByDef(myParams.sys().getXzms(), file.getXzms()); file.setXzms(xzms); switch (Xzms.getByCode(xzms)){ case AWJLXXZ: case EJZ: WebUtil.sendBytes(response, bytes, file); break; case BASE64: base64 = Base64.getEncoder().encodeToString(bytes); WebUtil.sendText(response,base64); break; case BASE64OBJ: //转为base64后作为data以json对象返回 base64 = Base64.getEncoder().encodeToString(bytes); file.setWjnr(base64); //修改下载模式为按文件类型下载,便于后续再次进入时直接进行下载,针对代理下载文件场景 file.setXzms(Xzms.AWJLXXZ.getCode()); r.setData(file); WebUtil.sendJson(response,r); break; default: throw new MyException("不支持的下载模式:"+file.getXzms()); } } else { //默认JSON response.setStatus(r.getCode()); if(r.getCode()>510){ response.setStatus(HttpURLConnection.HTTP_BAD_REQUEST); } if(StringUtil.isNotBlank(myParams.sys().getPublicKey())){ //配置了公钥,则采用该公钥对数据进行加密 WebUtil.sendText(response,StringUtil.encodeing(r.toString(),Jmfs.sm2, null,myParams.sys().getPublicKey())); }else { WebUtil.sendJson(response, r); } } } /** * 获取用户信息 * @param myParams 参数对象 * @return 用户信息 */ public Result getUser(MyParams myParams) { return success("获取用户成功",UserManager.getUser(myParams)); } /** * 权限过滤
* @param myParams 参数集 * @throws QxException 没有权限将抛出异常 * @author jingma */ protected void auth(MyParams myParams) throws QxException { if(hasAuth(myParams,getCllx(myParams))){ //没有用户信息或有权限 return; } QxException e = new QxException("没有操作权限"); e.setData(myParams.sys().getAuthCode()+"_"+getCllx(myParams)); throw e; } /** * 是否有权限 */ protected boolean hasAuth(MyParams myParams,String cllx){ return UserManager.hasAuth(myParams,cllx); } /** * 保存数据-数据库
* @param myParams 相关参数 * @return 处理结果 * @author jingma */ protected Result saveDb(MyParams myParams) { String[] arr = (String[]) getSql(myParams).getData(); if(valByDef(myParams.sys().getBatch(),false)){ SQLManager sm = sqlManager(arr[0]); SqlId sqlId = sm.getSqlIdFactory().buildTemplate(arr[1]); SQLSource source = sm.getSqlLoader().queryAutoSQL(sqlId); if (source == null) { source = new SQLSource(sqlId, arr[1]); source.setSqlType(SQLType.UPDATE); sm.getSqlLoader().addSQL(sqlId, source); } ExecuteContext executeContext = ExecuteContext.instance(sm).initSQLSource(source); SQLExecutor script = sm.getDbStyle().buildExecutor(executeContext); script.beforeExecute(null,myParams,true); return success("数据库保存进行批量操作,此处只返回sql和参数信息,不执行sql",script.run(myParams)); } try { return success("数据库保存成功", db(arr[0]).update(arr[1], myParams)); }catch (Throwable t){ throw new MyException("保存失败",t); } } private Result saveEs(MyParams myParams) { log.trace("开始进行ES新增"); JSONArray arr = new JSONArray(); JSONObject yobj = myParams.getJSONObject(KEY_YOBJ); yobj.put("my-yzdjl", myParams.getString($_SYS_YZDJL)); arr.add(yobj); myParams.set($_SYS_EDITTABLEDATA, arr); return plbc(myParams); } /** * 保存数据-本地文件 */ protected Result saveFile(MyParams myParams) { return plbcFile(myParams,new JSONObject[]{myParams.getJSONObject(KEY_YOBJ)}); } /** * 批量保存数据到本地文件,不考虑内容,原样保存 */ protected Result plbcFile(MyParams myParams, JSONObject[] list) { dcsjYcl(myParams,Arrays.asList(list), Cllx.insert.name()); if(isBlank(myParams.getString("$.sys.fileType"))){ //若外部没有要求文件格式,则采用对象类型 myParams.set("$.sys.fileType",getSjdx().getDxlx()); } Result r = resultExcelFile(myParams, myParams.other().getDcsjycl().getHeader(), myParams.other().getDcsjycl().getData(), getSjdx().getJtdx()+"_"+System.currentTimeMillis()); SysSjglFile jo = r.getData(SysSjglFile.class); try { return new Result(BasicSjzt.useSjzt(getSjdx().getDxzt()).save( new ByteArrayInputStream(jo.getBytes()), new BdwjFile(getSjdx().getDxgs(),jo.getWjm())),"完成批量保存"); } catch (Exception e) { throw new MyException("批量保存文件异常",e); } } protected Result plbcDb(MyParams myParams, JSONObject[] list) { log.trace("开始进行数据库批量保存:"+list.length); BeanProcessor bp = getSqlManager().getDefaultBeanProcessors(); ExecuteContext ec = ExecuteContext.instance(getSqlManager()); ec.target = JSONObject.class; //批量更新 if(myParams.sys().getBatch()) { return getSqlManager().executeOnConnection(new OnConnection() { public Result call(Connection conn) throws SQLException { log.trace("存在的数据已查询完成,开始进行批量保存"); //获取事务提交量 int swtjl = myParams.getIntValue("$.sys.swtjl"); //总共多少条记录 int count = 0; //插入多少记录 int insert = 0; //更新多少记录 int update = 0; //忽略多少记录 int ignore = 0; Map pm = new HashMap<>(); PreparedStatement p; for (JSONObject j : list) { count++; //取消原来的处理类型,由保存方法自动判断 myParams.sys().setCllx(""); myParams.put(KEY_YOBJ, j); try { myParams.sys().setYzdjl(TypeUtils.castToBoolean(valByDef(j.remove("my-yzdjl"),false))); if(myParams.sys().getYzdjl()&&myParams.getBooleanValue("$.sys.bzxgx")){ ignore++; continue; }else if(!myParams.getBooleanValue($_SYS_YZDJL)&&myParams.getBooleanValue("$.sys.bzxxz")){ ignore++; continue; } myParams.put(KEY_OBJ,j.remove("my-obj")); SQLResult sr = save(myParams).getData(SQLResult.class); p = pm.get(sr.jdbcSql); if(p==null){ p = conn.prepareStatement(sr.jdbcSql); pm.put(sr.jdbcSql,p); } bp.setPreparedStatementPara(ec,p,sr.jdbcPara); p.addBatch(); }catch (MyException e){ throw new MyException(e.getMessage()+",第" + (count + 1) + "行",e.getCode(),e.getData()); } if(myParams.getBooleanValue($_SYS_YZDJL)){ update++; }else{ insert++; } if (count % swtjl == 0) { log.trace("开始执行批量入库提交"); for(Map.Entry e:pm.entrySet()){ e.getValue().executeBatch(); e.getValue().close(); } pm.clear(); log.info(getSjdx().getDxmc()+"批量保存已处理数据:"+count); } } log.trace("开始执行批量入库最后提交"); for(Map.Entry e:pm.entrySet()){ e.getValue().executeBatch(); e.getValue().close(); } pm.clear(); //重复量 return sjplcljg(list.length, insert, update, ignore, myParams.getIntValue("$.sys.cfsjl")); } }); }else { //插入多少记录 int insert = 0; //更新多少记录 int update = 0; //忽略多少记录 int ignore = 0; //非批量处理 for (JSONObject j : list) { //取消原来的处理类型,由保存方法自动判断 myParams.put(KEY_YOBJ, j); myParams.set($_SYS_YZDJL, valByDef(j.remove("my-yzdjl"), false)); if(myParams.getBooleanValue($_SYS_YZDJL)&&myParams.getBooleanValue("$.sys.bzxgx")){ ignore++; continue; }else if(!myParams.getBooleanValue($_SYS_YZDJL)&&myParams.getBooleanValue("$.sys.bzxxz")){ ignore++; continue; } myParams.put(KEY_OBJ, j.remove("my-obj")); Result r; if(myParams.getBooleanValue($_SYS_YZDJL)){ r = update(myParams); update++; }else{ r = insert(myParams); insert++; } if(!r.isStatus()){ throw r.newMyException(); } } //重复量 return sjplcljg(list.length, insert, update, ignore, myParams.getIntValue("$.sys.cfsjl")); } } @NotNull protected Result selectDb(MyParams myParams) { log.trace("开始进行数据库查询"); //获取分页对象 PageInfo page = myParams.getObject(KEY_PAGE,PageInfo.class); //获取sql String[] arr = LjqManager.getSql(myParams, Cllx.select.name()); String sql; if (StringUtil.isNotBlank(getSjdx().getSqlmb())) { //对象上设置了查询sql模板 sql = TmplUtil.buildStrSql(getSjdx().getSqlmb(), myParams).trim(); if (sql.startsWith("error:")) { throw new MyException(sql.substring("error:".length())); } arr = Db.parseDictExp(sql, arr[0]); } //排序信息在sql模板中处理 page.setOrderBy(""); log.trace("查询数据库及语句:{},{}",arr[0],arr[1]); String[] sqlArr = arr[1].split(";"); for (int i =0;i list = new ArrayList<>(); PageInfo finalPage = page; SQLManager sm = sqlManager(arr[0]); SqlId sqlId = sm.getSqlIdFactory().buildTemplate(arr[1]); SQLSource source = sm.getSqlLoader().queryAutoSQL(sqlId); if (source == null) { source = new SQLSource(sqlId, arr[1]); source.setSqlType(SQLType.SELECT); sm.getSqlLoader().addSQL(sqlId, source); } ExecuteContext executeContext = ExecuteContext.instance(sm).initSQLSource(source); SQLExecutor script = sm.getDbStyle().buildExecutor(executeContext); script.beforeExecute(null,myParams,false); SQLResult sr = script.run(myParams); log.debug("数据库查询sql:{},{}",sr.jdbcSql,JSON.toJSONString(sr.jdbcPara)); BeanProcessor bp = getSqlManager().getDefaultBeanProcessors(); ExecuteContext ec = ExecuteContext.instance(getSqlManager()); ec.target = JSONObject.class; sm.executeOnConnection(new OnConnection() { public Object call(Connection conn) throws SQLException { PreparedStatement p = conn.prepareStatement(sr.jdbcSql); bp.setPreparedStatementPara(ec,p,sr.jdbcPara); ResultSet rs = p.executeQuery(); ResultSetMetaData meta = rs.getMetaData(); JSONObject row; while (rs.next()){ row = new JSONObject(); for(int i = 1;i<=meta.getColumnCount();i++){ //优先获取别名 row.put(meta.getColumnLabel(i).toLowerCase(),rs.getString(i)); } if(list.size()==0){ log.debug("数据库查询数据样例:{}",row); } num.getAndIncrement(); //处理每一行数据 selectClRow(myParams,row); list.add(row); if(list.size() == finalPage.getPageSize()){ r.addMsg(hdff.run(list,false).getMsg()); //处理完成,清空 list.clear(); } } return null; } }); // page.setList(list); page.setTotalRow(num.get()); r.setData(page); r.addMsg("流式读取数据完成,数据已采用回调机制处理完成:"+num); //最后再次处理 r.addMsg(hdff.run(list,true,r).getMsg()); return r; }catch (Throwable t){ //处理异常结束回调 hdff.run(null,true,failed("流式读取数据失败:"+t.getMessage())); throw new MyException("流式读取数据失败",t); } } } protected Result selectEs(MyParams myParams) { log.trace("开始进行ES查询"); JSONObject r = new JSONObject(); SysSjglSjdx sjdx = myParams.getObject(KEY_SJDX, SysSjglSjdx.class); final PageInfo page = (PageInfo) myParams.getObject("page", PageInfo.class); String[] arr = LjqManager.getSql(myParams,Cllx.select.name()); if (StringUtil.isNotBlank(getSjdx().getSqlmb())) { String sql = TmplUtil.buildStrSql(getSjdx().getSqlmb(), myParams).trim(); if (sql.startsWith("error:")) { throw new MyException(sql.substring("error:".length())); } arr = Db.parseDictExp(sql, arr[0]); } PageInfo res; if (myParams.get("$.sys.hdcst") != null) { final HdInterface hdff = this.getHdff(myParams); int pageNumber = 1; String cursor = ""; List columns; while (true) { page.setPageNumber(pageNumber); try { res = ES.use(getSjdx().getDxzt()).queryPage(page, arr[1], myParams); //分页查询会返回游标,第二次循环直接使用上一次循环返回的游标 if (!isBlank(res.get("cursor"))) { cursor = res.get("cursor").toString(); } columns = (List) res.get("columns"); myParams.set("$.sys.cursor", cursor); myParams.set("$.sys.columns", columns); List list = res.getList(); if (list.size() == 0) { hdff.run(list, true); break; } else { hdff.run(list, false); if (isBlank(cursor) && pageNumber == 1) { break; } pageNumber++; } } catch (Throwable t) { hdff.run(null,true,failed("流式读取数据失败:"+t.getMessage())); throw new MyException("查询异常:" + t.getMessage(), t); } } } else { res = ES.use(getSjdx().getDxzt()).queryPage(page, arr[1], myParams); // 字典翻译 Iterator var5 = res.getList().iterator(); while (var5.hasNext()) { JSONObject row = (JSONObject) var5.next(); this.selectClRow(myParams, row); } //查询完后去掉结果对象中临时存储的游标与字段 r = JSONObject.parseObject(JSON.toJSONString(res)); r.set("tails", "{}"); } return success("请求成功", r.toJavaObject(PageInfo.class)); } /** * 获取查询回调方法 */ protected HdInterface getHdff(MyParams myParams) { HdInterface hdff; if(myParams.get($_SYS_HDCST) instanceof HdInterface){ hdff = (HdInterface) myParams.get($_SYS_HDCST); }else { MyParams hdcst = new MyParams(myParams.getJSONObject($_SYS_HDCST)); //设置回调请求id hdcst.sys().setHdqqid(myParams.sys().getQqid()); MyParams jcxx = LjqManager.jcxxByParams(JsonUtil.clone(hdcst),myParams.user()); //设置下载模式,处理文件传输场景 jcxx.sys().setXzms(Xzms.BASE64OBJ.getCode()); hdff = new HdInterface() { public Result run(List list, boolean hdjs) { return run(list,hdjs,success("成功获取数据")); } public Result run(List list, boolean hdjs,Result r) { jcxx.sys().setEditTableData(list); jcxx.other().getYsParams().sys().setEditTableData(list); //告知请求方法,是否回调结束 jcxx.sys().setHdjs(hdjs); jcxx.other().getYsParams().sys().setHdjs(hdjs); //设置调消息 jcxx.sys().setContext(r); jcxx.other().getYsParams().sys().setContext(r); Result result = LjqManager.data(jcxx,jcxx.sys().getCllx()); if (result.getCode() == HttpURLConnection.HTTP_OK) { //正常状态 log.info("查询回调完成:"+result); }else if(result.getCode() == XtZtm.CTDYCS.getCode()){ //穿透调用超时 log.info("穿透调用超时按正常处理,不再重复推送:"+result); }else { throw result.newMyException(); } return result; } }; } return hdff; } /** * 查询-处理查询出的每一行数据 */ protected void selectClRow(MyParams myParams,JSONObject row) { //树形结构时,将是否有子节点的标志转为boolean形 Map fields = (Map) myParams.get(KEY_FIELDS); String hasChild = myParams.getString("$.cllxkz['select'].tree.hasChild"); String checkField = myParams.getString("$.cllxkz['select'].checkboxConfig.checkFieldOld"); for(String zddm: fields.keySet()){ if(StringUtil.isBlank(row.getString(zddm))){ //字段值为空时跳过 continue; } ZdKjlx kjlx = ZdKjlx.getByCode(fields.get(zddm).getKjlx()); if(kjlx==null){ continue; } //对结果进行字典翻译,字典或者级联控件 switch (kjlx){ case Select: case Radio: case ElCascader: case Checkbox: row.put(zddm,row.getString(zddm)); row.put(zddm+"Mc",DictManager.zdMcByMoreDm(fields.get(zddm).getZdzdlb(), row.getString(zddm))); //字典对象一起返回前端,为便于前端获取附加信息 // row.put(zddm+"_zdobj",DictManager.zdObjByMoreDm(fields.getString("$."+zddm+".zdzdlb"),row.getString(zddm))); break; case Switch: row.put(zddm,row.getString(zddm)); row.put(zddm+"Mc",DictManager.zdMcByDm(Zdlb.SYS_COMMON_LJPD.name(), row.getString(zddm))); } } if(hasChild !=null){ row.put(hasChild, row.getBoolean(hasChild)); } if(checkField !=null){ row.put(checkField +"_boolean", row.getBoolean(checkField)); } } /** * 查询数据-本地文件 */ protected Result selectFile(MyParams myParams) { myParams.sys().setCllx("selectFile"); List ilist = BasicSjzt.useSjzt(getSjdx().getDxzt()).listFiles(getSjdx()); PageInfo page = myParams.getObject(KEY_PAGE,PageInfo.class); Result r; if(myParams.get($_SYS_HDCST)==null){ if(page.getPageNumber()>ilist.size()){ return failed("页大小超出文件数量"); } IFile file = ilist.get((int) page.getPageNumber()-1); //采用流式处理,避免全部读取到内存 SjdxExcelReader er = new SjdxExcelReader(getSjdx(), myParams, file.toSjglFile()); r = er.disposeExcel(); if (!r.isStatus()) { return r; } //一个文件的数据 if(er.getResult().size()>page.getPageSize()){ page.setList(er.getResult().toJavaList(JSONObject.class).subList(0,page.getPageSize())); }else { page.setList(er.getResult().toJavaList(JSONObject.class)); } //一个文件一页 page.setTotalRow((long) page.getPageSize() *ilist.size()); //分页查询 for(JSONObject row : page.getList()){ selectClRow(myParams,row); } return success("文件查询成功",page); }else { //有回调参数体,采用流式读取 HdInterface hdff = getHdff(myParams); boolean scywj = myParams.getBooleanValue("$.sys.scywj"); int num = 0; int i=0; for (IFile file : ilist) { i++; //采用流式处理,避免全部读取到内存 SjdxExcelReader er = new SjdxExcelReader(getSjdx(), myParams, file.toSjglFile()); r = er.disposeExcel(); if (!r.isStatus()) { return r; } num += er.getResult().size(); //最后再次处理 hdff.run(er.getResult().toJavaList(JSONObject.class),i>=ilist.size()); //处理完成后删除 if(scywj){ try { file.delete(); } catch (Exception e) { throw new MyException("删除源文件失败",e); } } } return success("流式读取数据完成,数据已采用回调机制处理完成:"+num); } } /** * 批量删除-数据库 */ @NotNull protected Result plscDb(MyParams myParams) { Result r; // 先调用一次查询语句,获取默认查询条件 LjqManager.getSql(myParams,Cllx.select.name()); boolean wlsc = myParams.getBooleanValue("$.sys.wlsc"); r = success(""); if (StringUtil.isNotBlank(getSjdx().getYxxzd()) && (wlsc||UserManager.hasAuth(myParams.user(), SysAuth.QTQX_SYS.name()))) { //存在有效性字段,且允许物理删除或有最高权限 r = wlscByYxx(myParams); } String[] arr = LjqManager.getSql(myParams,Cllx.plsc.name()); //后续继续进行逻辑删除操作 int scs = db(arr[0]).update(arr[1], myParams); if (isBlank(getSjdx().getYxxzd())||isBlank(r.getMsg())) { r.addMsg("处理记录数:" + scs); } else { r.addMsg("逻辑删除记录数:" + scs); } return r; } /** * 批量删除-文件 */ protected Result plscFile(MyParams myParams) { BasicSjzt sjzt = BasicSjzt.useSjzt(getSjdx().getDxzt()); List ilist = BasicSjzt.useSjzt(getSjdx().getDxzt()).listFiles(getSjdx()); try { for(IFile f:ilist){ sjzt.delete(f); } return success("删除文件数:"+ilist.size()); }catch (Exception e){ log.error("文件删除失败",e); throw new MyException("删除文件失败:"+e.getMessage(),e); } } /** * 导出数据预处理,处理结果在系统参数myParams中。
* 表头:$_OTHEROBJ_DCSJYCL_HEADER、数据:$_OTHEROBJ_DCSJYCL_DATA * @param myParams 系统参数 * @param list 要导出的数据 * @param cllx 处理类型 */ protected void dcsjYcl(MyParams myParams, List list, String cllx){ //导出排除字段列表 Set dcpczdlb = isBlank(myParams.sys().getDcpczdlb())?new HashSet<>() :new HashSet<>(myParams.sys().getDcpczdlb()); //导出字段列表 List dczdlb = isBlank(myParams.sys().getDczdlb())?new ArrayList<>() :myParams.sys().getDczdlb(); Map fields = (Map) myParams.get(KEY_FIELDS); if(isBlank(dczdlb)){ for (Map.Entry f : fields.entrySet()) { SysSjglSjzd field = f.getValue(); ZdKjlx kjlx = ZdKjlx.getByCode(field.getKjlx()); if (valByDef(field.getKzxxObj().getBoolean("$.cllxkz."+cllx+".show"),false) && !dcpczdlb.contains(f.getValue().getZdmc()) && (kjlx==null||(!kjlx.equals(ZdKjlx.Password) && !kjlx.equals(ZdKjlx.Buttons) && !kjlx.equals(ZdKjlx.MyGroup) && !kjlx.equals(ZdKjlx.MySelectGrid)))) { dczdlb.add(f.getKey()); } } } List> header = new ArrayList<>(); List h; for(String dczd : dczdlb){ h = new ArrayList<>(); //详情展示且前端没有要求不导出且控件类型不是密码的字段才导出 h.add(fields.get(dczd).getZdmc()); header.add(h); } //增加行高 boolean zjhg = false; List> data = new ArrayList<>(); List rows; for (Object r2 : list) { JSONObject o; if(r2 instanceof JSONObject){ o = (JSONObject) r2; }else if(r2 instanceof BasicBean){ o = ((BasicBean) r2).toJSONObject(); }else { throw new MyException("不支持导出的数据类型:"+r2.getClass().getName()); } rows = new ArrayList<>(); data.add(rows); for (String f : dczdlb) { SysSjglSjzd field = fields.get(f); String val = o.getString(f); ZdKjlx kjlx = ZdKjlx.getByCode(field.getKjlx()); if(kjlx!=null){ switch (kjlx){ case Switch: fields.get(f).setZdzdlb(Zdlb.SYS_COMMON_LJPD.name()); case Select: case Checkbox: case Radio: case ElCascader: rows.add(DictManager.zdMcByMoreDm(fields.get(f).getZdzdlb(), val)); break; case ElDatePicker: //这个格式可定制 String fmt = valByDef(field.getKzxxObj().getString("$.kjkz.zsgs"),DateUtil.DATE_FORMATTER_L); String v = DateUtil.doFormatDate(val, fmt); if (StringUtil.isBlank(v)) { v = val; } rows.add(v); break; case MyImage: //图片 rows.add(ImageConverterKey.builder().lj(val).build()); //有图片增加行高 zjhg = true; break; default: //EXCEL限制单个大小 if (StringUtil.isNotBlank(val)) { val = val.length() > 32767 ? val.substring(0, 32767) : val; } rows.add(val); } }else { //EXCEL限制单个大小 if (StringUtil.isNotBlank(val)) { val = val.length() > 32767 ? val.substring(0, 32767) : val; } rows.add(val); } } } Dcsjycl dcsjycl = new Dcsjycl(); myParams.other().setDcsjycl(dcsjycl); dcsjycl.setHeader(header); dcsjycl.setData(data); //显示的字段 dcsjycl.setZdlist(dczdlb); //显示的字段 dcsjycl.setZjhg(zjhg); } /** * 基于有效性的物理删除
* @param myParams 相关参数 * @return 处理结果 * @author jingma */ protected Result wlscByYxx(MyParams myParams) { //有有效性字段 String[] arr = LjqManager.getSql(myParams, Cllx.wlplsc.name()); //先执行物理删除,将本次删除中,已经为无效的进行物理删除 int scs = db(arr[0]).update(arr[1], myParams); return success("物理删除数:" + scs); } /** * 设置obj
* @param myParams 参数 * @param batch 是否批量处理,批量处理则值返回条件,不进行数据库查询 * @author jingma */ protected Result putObj(MyParams myParams,boolean batch) { myParams.set($_SYS_YZDJL, Boolean.FALSE); JSONObject yobj = myParams.getJSONObject(KEY_YOBJ); if(isBlank(yobj)){ return success("没有表单数据"); } JSONObject qcObj = new JSONObject(); Map qcList = (Map) fieldsCache.get(getSjdx().getId()+ QCZD_LIST); if(StringUtil.requireNonNull(qcList,"去重字段列表为空,奇葩").size()==0){ return success("没有去重字段"); }else if(!isBlank(getSjdx().getZjzd())&&StringUtil.isNotBlank(yobj.get(getSjdx().getZjzd()))){ //存在主键,只认主键 qcObj.put(getSjdx().getZddmZjzd(),yobj.getString(getSjdx().getZddmZjzd())); }else if(qcList.size()==1){ //一个去重字段 SysSjglSjzd f = (SysSjglSjzd) qcList.values().toArray()[0]; if (f!=null&&StringUtil.isNotBlank(yobj.getString(f.getZddm()))) { //该去重字段不为空 qcObj.put(f.getZddm(),yobj.getString(f.getZddm())); } }else if(StringUtil.isNotBlank(getSjdx().getQczd())){ //多个去重字段,且设置了去重字段 StringBuilder key = new StringBuilder(); for(SysSjglSjzd f : qcList.values()){ //将去重字段的值拼接 key.append(yobj.getString(f.getZddm())).append("_"); } //对去重字段进行md5编码 qcObj.put(getSjdx().getZddmQczd(), MD5Util.encode(key.toString())); //对原对象进行去重字段值补充,便于后续入库 yobj.put(getSjdx().getZddmQczd(), MD5Util.encode(key.toString())); }else{ throw new MyException("配置了具体的多个去重字段,但没有在数据对象中配置存储去重字段md5值的“去重字段”:"+qcList.size()); } if (qcObj.size()>0) { if(batch){ //批量处理,此处不执行 return success("批量处理",qcObj); } //存在去重字段 //不进行总量查询 myParams.set("$.page.totalRequired", Boolean.FALSE); //设置根据去重字段查询数据的条件 myParams.put(KEY_YOBJ,qcObj); Result r; try{ r = select(myParams); if(r.isStatus()){ PageInfo page = r.getData(PageInfo.class); if (page.getList().size() == 1) { //标记能找到要修改的对象,没找到可能是不存在,也可能是没有权限,避免修改无权限记录 myParams.set($_SYS_YZDJL, Boolean.TRUE); JSONObject obj = page.getList().get(0); myParams.put(KEY_OBJ, obj); setYobjByObj(yobj, qcList, obj); if(Cllx.insert.name().equals(getCllx(myParams))){ //新增的数据通过去重字段查询到值,表示重复数据,改为更新 myParams.sys().setCllx(Cllx.update.name()); } } } }catch (MyException e){ log.trace("根据去重信息读取数据失败",e); } //还原原来的输入参数 myParams.put(KEY_YOBJ,yobj); } return success("完成"); } /** * 基于从库中读取的记录信息设置外部输入的表单 * @param yobj 外部输入的表单 * @param qczdMap 去重字段 * @param obj 库中读取的记录 */ protected void setYobjByObj(JSONObject yobj, Map qczdMap, JSONObject obj) { if(!isBlank(getSjdx().getZjzd())&&StringUtil.isBlank(yobj.getString(getSjdx().getZjzd()))){ yobj.put(getSjdx().getZddmZjzd(), obj.getString(getSjdx().getZddmZjzd())); } if(StringUtil.isNotBlank(getSjdx().getQczd())&& qczdMap.size()>1){ //多个去重字段,且设置了去重字段 StringBuilder key = new StringBuilder(); for(SysSjglSjzd f : qczdMap.values()){ //将去重字段的值拼接,优先取前端传入的值,不存在则取库中的值 key.append(StringUtil.fastNotNull(yobj.getString(f.getZddm()), obj.getString(f.getZddm()),NULL_STR)).append("_"); } //对原对象进行去重字段值补充,便于后续入库 yobj.put(getSjdx().getZddmQczd(), MD5Util.encode(key.toString())); } } /** * 获取数据字段
* * @author jingma */ protected synchronized void getFields(MyParams myParams, SysQxYhxx user) { //基于对象和用户等级缓存对象字段 String cacheKey = getSjdx().getId(); if (user != null) { cacheKey = getSjdx().getId() + user.getYhdj(); } Object obj = fieldsCache.get(cacheKey); Map fields; if (obj != null && !myParams.sys().getClearCache()) { //没有缓存且没有要求清除缓存 fields = (Map) obj; }else{ fields = new LinkedHashMap<>(); String[] r = LjqManager.getSql(myParams, Cllx.getFields.name()); List zdList = sqlManager(r[0]).execute(r[1],SysSjglSjzd.class, myParams); if(isBlank(zdList)){ throw new MyException("该数据对象没有配置字段:"+myParams.sjdx().getDxdm()); } for(SysSjglSjzd zd:zdList){ fields.put(zd.getZddm(),zd); } fieldsInit(fields, myParams); if(myParams.containsKey(KEY_FIELDS)){ //如果系统配置的有默认字段则合并,具体字段配置优先 Map sfields = myParams.fields(); sfields.forEach((s, o) -> { if(isBlank(o.getZddm())){ //配置的公共字段自动补充一些默认信息 o.setZddm(s); } if(isBlank(o.getZdywlb())){ //默认业务类别 o.setZdywlb(ZdYwlb.XNZD.getCode()); } }); JSONObject sf = new JSONObject(); sf.putAll(sfields); JsonUtil.mergeJSONObject(sf,fields); //根据排序字段进行排序 List list = new ArrayList(sf.values()); list.sort(Comparator.comparingInt(o -> (((SysSjglSjzd)o).getPx()))); fields = new LinkedHashMap<>(); for(Object o: list){ SysSjglSjzd f = (SysSjglSjzd) o; fields.put(f.getZddm(), f); } } List qcList = new ArrayList<>(); for(SysSjglSjzd f: fields.values()){ if(f.getQcbh()>0){ //去重字段 qcList.add(f); } } if(qcList.size()>0){ //对去重字段按去重编号排序 qcList.sort(Comparator.comparingInt(SysSjglSjzd::getQcbh)); }else if(!isBlank(getSjdx().getQczd())){ //有去重字段,此场景为只有一个非主键字段去重 if(!fields.containsKey(getSjdx().getZddmQczd())){ throw new MyException("去重字段配置错误,该字段不存在:"+getSjdx().getZddmQczd()); } qcList.add(fields.get(getSjdx().getZddmQczd())); }else if(!isBlank(getSjdx().getZjzd())){ if(!fields.containsKey(getSjdx().getZddmZjzd())){ throw new MyException("主键字段配置错误,该字段不存在:"+getSjdx().getZddmZjzd()); } //当没有配置去重字段时,直接采用主键作为去重字段 qcList.add(fields.get(getSjdx().getZddmZjzd())); } //设置缓存 fieldsCache.put(cacheKey, fields); fieldsCache.put(getSjdx().getId()+ QCZD_LIST, Db.listToMap(qcList,"zddm")); } fields.forEach((zddm,field)->{ //将整个字段的验证规则设置到系统验证规则中,因为内部会对规则数据进行修改 JSONObject gz = field.getKzxxObj().getJSONObject("yzgz"); if(gz != null){ myParams.set("$.yzgz['yobj." + zddm + "']",JsonUtil.mergeJSONObjects( myParams.getJSONObject("$.yzgz['yobj." + zddm + "']"),gz)); } gz = field.getKzxxObj().getJSONObject("zhgz"); if(gz != null){ myParams.set("$.zhgz['yobj." + zddm + "']",JsonUtil.mergeJSONObjects( myParams.getJSONObject("$.zhgz['yobj." + zddm + "']"),gz)); } }); myParams.put(KEY_FIELDS, fields); myParams.put(KEY_QCFIELDS,fieldsCache.get(getSjdx().getId()+ QCZD_LIST)); } /** * 根据字段配置进行验证规则、转换规则、处理类型等初始化
* @param fields 字段列表 * @param myParams 相关参数 * @author jingma */ protected void fieldsInit(Map fields, MyParams myParams) { for (SysSjglSjzd field : fields.values()) { JSONObject kzxx = field.getKzxxObj(); //初始化验证规则 fieldYzgzInit(field, kzxx,myParams); //初始化转换规则 fieldZhgzInit(field, kzxx,myParams); //处理类型扩展 fieldCllxInit(field, kzxx); } } /** * 字段处理类型初始化,设置各处理类型是否展示、默认值等 * @param field 字段 * @param kzxx 扩展信息 */ protected void fieldCllxInit(SysSjglSjzd field, JSONObject kzxx) { JSONObject cllxkz = kzxx.getJSONObject("cllxkz"); if(cllxkz==null){ cllxkz = new JSONObject(); kzxx.put("cllxkz",cllxkz); } //insert:新增页面 JSONObject lxkz = getKjkzByCllx(field); lxkz.put("show",valByDef(TypeUtils.castToBoolean(field.getXzzs()),false)); lxkz.put("readonly",false); lxkz.put("default",field.getXzmrz()); mergeConfigByCllx(cllxkz, lxkz, Cllx.insert.name()); //update:编辑 lxkz = getKjkzByCllx(field); lxkz.put("show",valByDef(TypeUtils.castToBoolean(field.getBjzs()),false)); lxkz.put("readonly",false); mergeConfigByCllx(cllxkz, lxkz, Cllx.update.name()); //dxjcxx:对象基础信息,对应详情页面 lxkz = getKjkzByCllx(field); lxkz.put("show",valByDef(TypeUtils.castToBoolean(field.getXqzs()),false)); mergeConfigByCllx(cllxkz, lxkz, Cllx.dxjcxx.name()); //导出字段配置,默认与详情字段一致 lxkz = getKjkzByCllx(field); lxkz.put("show",valByDef(TypeUtils.castToBoolean(field.getXqzs()),false)); mergeConfigByCllx(cllxkz, lxkz, Cllx.dcsj.name()); //dcmb:导出模板 lxkz = getKjkzByCllx(field); lxkz.put("show",valByDef(TypeUtils.castToBoolean(field.getMbzs()),false)); mergeConfigByCllx(cllxkz, lxkz, Cllx.dcmb.name()); //select:查询页面对应的表单 lxkz = getKjkzByCllx(field); lxkz.put("folding",!valByDef(TypeUtils.castToBoolean(field.getLbzs()),false)); lxkz.put("readonly",false); mergeConfigByCllx(cllxkz, lxkz, Cllx.select.name()); //other } /** * 根据处理类型配置控件扩展 * @param field 字段信息 * @return 通用扩展 */ protected JSONObject getKjkzByCllx(SysSjglSjzd field) { JSONObject lxkz = new JSONObject(); lxkz.put("zdkd",field.getZdkd()); //默认不禁用 lxkz.put("disabled",!valByDef(TypeUtils.castToBoolean(field.getYxbj()),true)); //默认只读 lxkz.put("readonly",true); //默认都不展示,只有查询列表控件主动设置为展示 lxkz.put("show",false); return lxkz; } /** * 合并配置-基于处理类型 * @param pzjh 配置集合 * @param lxkz 处理类型扩展 * @param cllx 处理类型 */ protected void mergeConfigByCllx(JSONObject pzjh, JSONObject lxkz, String cllx) { if (pzjh.containsKey(cllx)) { //用户配置了,用户配置的与系统默认的进行合并,用户配置的优先 JsonUtil.mergeJSONObjects(lxkz, pzjh.getJSONObject(cllx)); } pzjh.put(cllx, lxkz); } /** * 字段转换规则初始化,转换的实现前端就不实现了,后台统一转换 * @param field 字段 * @param kzxx 扩展信息 */ protected void fieldZhgzInit(SysSjglSjzd field, JSONObject kzxx, MyParams myParams) { //默认转换规则 JSONObject zhgz = new JSONObject(); //清空前后空格 zhgz.put("qdqhkg",new JSONObject()); if("CLOB".equals(field.getZdlx())){ zhgz.put("clob",new JSONObject()); }else if("BLOB".equals(field.getZdlx())){ zhgz.put("blob",new JSONObject()); } JSONObject kzhgz = kzxx.getJSONObject(KEY_ZHGZ); if(kzhgz == null){ kzhgz = new JSONObject(); } mergeConfigByCllx(kzhgz,zhgz,Cllx.select.name()); zhgz = JsonUtil.clone(zhgz); mergeConfigByCllx(kzhgz,zhgz,Cllx.update.name()); //开始处理新增规则 zhgz = new JSONObject(); //设置默认继承更新的规则 zhgz.put("extends", new String[]{Cllx.update.name()}); //设置最新地新增验证验证规则 mergeConfigByCllx(kzhgz,zhgz,Cllx.insert.name()); //处理验证规则中的继承,后续验证更方便 for(String cllx:kzhgz.keySet()){ mergeRule(myParams,kzhgz,cllx); } kzxx.put(KEY_ZHGZ,kzhgz); } /** * 字段验证规则初始化 * @param field 字段 * @param kzxx 扩展信息 * @param myParams 相关参数 */ protected void fieldYzgzInit(SysSjglSjzd field, JSONObject kzxx, MyParams myParams) { //默认验证规则 JSONObject yzgz = new JSONObject(true); //查询验证规则 JSONObject selectYzgz = new JSONObject(true); JSONObject gz; //必填规则 if (valByDef(TypeUtils.castToBoolean(field.getBjbt()),false)) { yzgz.put("notBlank", new JSONObject()); } //设置信息描述,作为提示的主体 yzgz.put("xxms", field.getZdmc()); //设置信息描述,作为提示的主体 selectYzgz.put("xxms", field.getZdmc()); //根据控件类型生成规则 ZdKjlx kjlx = ZdKjlx.getByCode(field.getKjlx()); if(kjlx!=null){ switch (kjlx){ case Switch: field.setZdzdlb(Zdlb.SYS_COMMON_LJPD.name()); case Select: case Radio: case Checkbox: case ElCascader: gz = new JSONObject(); gz.put(VerifyRule.VALUE, field.getZdzdlb()); boolean zszdx = !valByDef(TypeUtils.castToBoolean(field.getZdfy()),false); //字典分页,说明字典量较大,不直接展示字典项 gz.put("zszdx", zszdx); boolean zddx = valByDef(TypeUtils.castToBoolean(field.getZddx()),false); if(ZdKjlx.Checkbox.equals(kjlx)){ zddx = true; } //字典多选 gz.put("zddx", zddx); yzgz.put("zd", gz); break; case Number: yzgz.put("number", new JSONObject()); break; case ElDatePicker: gz = new JSONObject(); //设置默认值,特殊情况可在字段扩展信息中自主扩展 gz.put(VerifyRule.VALUE, DateUtil.DATE_FORMATTER14); yzgz.put("date", gz); gz = new JSONObject(); selectYzgz.put("dateRange", gz); break; } } //根据字段业务类型设置规则 if (isBlank(field.getZdywlb())) { //为空则忽略 } else if (field.getZdywlb().contains("sfzh")) { yzgz.put("sfzh", new JSONObject()); } else if (field.getZdywlb().contains("sjh")) { //手机号 gz = new JSONObject(); gz.put(VerifyRule.VALUE, "^([0-9]{11}|,)*$"); gz.put(VerifyRule.TS, "只能填写11位手机号,多个电话用英文逗号"); yzgz.put("zzbds", gz); } else if (field.getZdywlb().contains("yx")) { //邮箱 yzgz.put("email", new JSONObject()); } //根据字段类型设置规则 if ("NUMBER".equals(field.getZdlx())) { yzgz.put("number", new JSONObject()); } //根据字段库中的长度设置长度规则。 if(valByDef(field.getZdcd(),0l)>0){ gz = new JSONObject(); gz.put("max", field.getZdcd()); gz.put("min", 0); yzgz.put("length", gz); } JSONObject kyzgz = kzxx.getJSONObject(KEY_YZGZ); if(kyzgz == null){ kyzgz = new JSONObject(); } //验证规则,新增可以通过继承更新验证规则使用该规则 mergeConfigByCllx(kyzgz, yzgz, Cllx.update.name()); //开始处理新增验证规则 yzgz = new JSONObject(true); //必填规则 if (valByDef(TypeUtils.castToBoolean(field.getBjbt()),false)) { yzgz.put("notNull", new JSONObject()); } //设置默认继承更新的验证规则 yzgz.put("extends", new String[]{Cllx.update.name()}); mergeConfigByCllx(kyzgz, yzgz, Cllx.insert.name()); if(valByDef(TypeUtils.castToBoolean(field.getCxbt()),false)){ //处理查询必填 selectYzgz.put("notNull",new JSONObject()); } mergeConfigByCllx(kyzgz, selectYzgz, Cllx.select.name()); //处理验证规则中的继承,后续验证更方便 for(String cllx:kyzgz.keySet()){ mergeRule(myParams,kyzgz,cllx); } kzxx.put(KEY_YZGZ,kyzgz); } /** * 合并验证规则 * @param myParams 系统参数 * @param rootRule 所有规则 * @param cllx 处理类型 */ protected void mergeRule(MyParams myParams, JSONObject rootRule, String cllx){ JSONObject yzgz = rootRule.getJSONObject(cllx); if(yzgz==null){ //该处理类型没有设置验证规则 return; } Object et = yzgz.remove("extends"); if (et != null) { //合并继承的规则 JSONObject newObj = new JSONObject(true); for (String eCllx : (String[]) et) { JsonUtil.mergeJSONObject(newObj, rootRule.getJSONObject(eCllx)); } JsonUtil.mergeJSONObject(newObj,yzgz); rootRule.put(cllx,newObj); } } /** * 初始化操作日志记录
* @param myParams 参数 * @param user 用户 * @author jingma */ protected void initCzrz(MyParams myParams, SysQxYhxx user) { if (valByDef(myParams.sys().getNbdy(),false)) { //为系统内部调用 return; } SysLogFwzr czrz = new SysLogFwzr(); myParams.put(KEY_CZRZ, czrz); czrz.setId(myParams.sys().getQqid()); czrz.setCjsj(DateUtil.getGabDate()); czrz.setCzip(myParams.sys().getClientIp()); czrz.setUrl(myParams.sys().getAuthCode()); czrz.setToken(user.getToken()); czrz.setCzlx(myParams.sys().getCllx()); czrz.setDdjd(Conf.getAppdm()); if(!isBlank(czrz.getUrl())){ String[] urlArr = czrz.getUrl().split("_"); StringBuilder qxm = new StringBuilder(urlArr[0]); StringBuilder qxlj = new StringBuilder(); JSONObject zdobj; zdobj = DictManager.zdObjByDm("SYS_QX_QXXX_DM",qxm.toString()); if(zdobj!=null){ qxlj.append(zdobj.getString("mc")).append("》"); } for (int i = 1; i xtqtzd = getXtqtzd(); czrz.setSjdx(getSjdx().getId()); if (StringUtil.isNotBlank(getSjdx().getZjzd()) && StringUtil.isNotBlank(yobj.getString(getSjdx().getZddmZjzd()))) { //设置了主键 czrz.setSjjl(yobj.remove(getSjdx().getZddmZjzd()).toString()); } JSONObject csObj = new JSONObject(); Map fields = (Map) myParams.get(KEY_FIELDS); if(fields==null){ fields = new HashMap<>(); } csObj.put("表单参数",cscl(yobj, fields, xtqtzd)); int length = csObj.toString().getBytes(StandardCharsets.UTF_8).length; //原始输入 MyParams yssr = JsonUtil.clone(myParams.other().getYsParams()); yssr.sys().setUserInfo(null); //移除单独显示的信息 Arrays.asList(KEY_YOBJ,KEY_SJDX,$_SYS_IDS,$_SYS_EDITTABLEDATA,$_SYS_TOKEN, $_SYS_AUTHCODE,$_SYS_CLIENT_IP,$_SYS_CLLX).forEach(yssr::remove); csObj.put("系统参数",yssr); if(csObj.toString().getBytes(StandardCharsets.UTF_8).length>4000){ csObj.put("系统参数",StringUtil.substrByByte(yssr,3950-length) .replace("\\","").replace("\"","'")); } length = csObj.toString().getBytes(StandardCharsets.UTF_8).length; if(!isBlank(myParams.get($_SYS_IDS))&&length<3950){ csObj.put("批量操作主键",myParams.get($_SYS_IDS)); if(csObj.toString().getBytes(StandardCharsets.UTF_8).length>4000){ csObj.put("批量操作主键",StringUtil.substrByByte(myParams.getString($_SYS_IDS),3950-length) .replace("\\","").replace("\"","'")); } }else if(!isBlank(myParams.get($_SYS_EDITTABLEDATA))&&length<3950){ csObj.put("批量操作表单",myParams.get($_SYS_EDITTABLEDATA)); if(csObj.toString().getBytes(StandardCharsets.UTF_8).length>4000){ csObj.put("批量操作表单",StringUtil.substrByByte(myParams.getString($_SYS_EDITTABLEDATA),3950-length) .replace("\\","").replace("\"","'")); } } czrz.setXgcs(csObj.toString()); } } protected JSONObject cscl(JSONObject yobj, Map fields, Map xtqtzd) { JSONObject csObj = new JSONObject(); for (Map.Entry e : yobj.entrySet()) { if (StringUtil.isBlank(e.getValue())) { continue; } String key = e.getKey(); String val = yobj.getString(key); SysSjglSjzd f = fields.get(key); if (f == null) { //获取系统其他字段信息 f = xtqtzd.get(key); } if (f != null) { key = f.getZdmc(); ZdKjlx kjlx = ZdKjlx.getByCode(f.getKjlx()); if(kjlx!=null){ switch (kjlx){ case Switch: f.setZdzdlb(Zdlb.SYS_COMMON_LJPD.name()); case Radio: case Checkbox: case Select: case ElCascader: try { val = DictManager.zdMcByMoreDm(f.getZdzdlb(), val); }catch (Exception e1){ throw new DictException(e1.getMessage()+",对应字段:"+f); } break; case ElDatePicker: //排除时间范围的场景 if(!val.startsWith("[")){ val = DateUtil.doFormatDate(DateUtil.parseDate(val), DateUtil.DATE_FORMATTER_L); if (val == null) { val = e.getValue().toString(); } } break; case Password: val = "日志不记录密码"; break; } } } if (val.length() > 300) { log.trace("操作参数超长:" + key + "->>" + val); csObj.put(key, val.substring(0, 300) + "[超长截取]"); } else { csObj.put(key, val); } } return csObj; } /** * 写操作日志 * @param myParams 相关参数 * @param r 待返回前端的操作结果 */ protected void writeCzrz(MyParams myParams, Result r) { SysLogFwzr czrz = myParams.getObject(KEY_CZRZ, SysLogFwzr.class); if(czrz!=null){ czrz.setFhjg(r.isStatus()?Ljpd.TURE.getCode():Ljpd.FALSE.getCode()); czrz.setFhdm(r.getCode()+""); czrz.setFhxx(StringUtil.substrByByte(r.getMsg(),4000)); czrz.setFhnr(StringUtil.substrByByte(r.getData(),4000).replace("\\","").replace("\"","'")); //设置请求耗时 long kssj = myParams.sys().getQqkssj(); czrz.setQqhs(System.currentTimeMillis()-kssj); SysQxYhxx user = myParams.user(); db(DEFAULT).lambdaQuery(SysLogFwzr.class,user).insertSelective(czrz); czrz.setId(null); assert user != null; SysPtglXtxx xtxx = SysPtglXtxx.builder().xxnr(czrz.toString()) .mdddl("SYS_QX_YHXX").mddxl(user.getId()).build(); XtxxWebSocket.sendMsg(xtxx,user); if(!r.isStatus()){ xtxx = SysPtglXtxx.builder().xxnr(czrz.toString()) .mdddl("SYS_LOG_HTRZ").build(); XtxxWebSocket.sendMsg(xtxx,user); } } } /** * 获取系统其他字段
* @return 系统其他字段 * @author jingma */ protected Map getXtqtzd() { JSONObject xtqtzdParams = LjqManager.jcxxByDxdm("SYS_COMMON_XTQTZD"); return (Map) xtqtzdParams.get(KEY_FIELDS); } /** * 生成Excel结果文件 * @param myParams 相关参数 * @param header 表头 * @param data 数据 * @param fileName 文件名 * @return 输出为excle的结果 */ protected Result resultExcelFile(MyParams myParams, List> header, List> data, String fileName) { JSONObject sjdxkz = getSjdx().tailsToJSONObject(); ByteArrayOutputStream os = new ByteArrayOutputStream(); byte[] bytes = new byte[0]; AbstractColumnWidthStyleStrategy lmcw = new MyLongestMatchColumnWidthStyleStrategy(); //获取文件类型 ExcelTypeEnum ete = null; SysSjglFile file1 = new SysSjglFile(); if (myParams.sys().getDcwjm() != null) { fileName = myParams.sys().getDcwjm(); } // myParams.set("$.sys.fileType","txt"); try { ete = ExcelTypeEnum.valueOf(StringUtil.fastNotNull(myParams.sys().getFileType(), ExcelTypeEnum.XLSX.name()).toUpperCase()); }catch (IllegalArgumentException e){ //easyExcel不能处理 if ("txt".equals(myParams.sys().getFileType())) {//文本场景 if (!fileName.contains(".")) { fileName += ".txt"; } file1.setWjlx("txt"); //分隔符 String fgf = valByDef(sjdxkz.getString("fgf"), ","); //文本限定符 String wbxdf = valByDef(sjdxkz.getString("wbxdf"),"\""); //编码方式 String bmfs = valByDef(sjdxkz.getString("bmfs"), "utf8"); StringBuilder context = new StringBuilder(); for (List h : header) { context.append(fgf).append(wbxdf).append(h.get(0)).append(wbxdf); } context.append("\n"); for (List h : data) { context.append(wbxdf).append(StringUtil.join(h, wbxdf + fgf + wbxdf)).append(wbxdf).append("\n"); } try { bytes = context.substring(fgf.length()).getBytes(bmfs); } catch (UnsupportedEncodingException ex) { throw new MyException("生成文本文件时,编码转换失败:" + ex.getMessage(), ex); } } else { throw new MyException("暂不支持的文件类型" + myParams.sys().getFileType()); } } if(ete != null){ if(!fileName.contains(".")){ fileName += ete.getValue(); } file1.setWjlx(ete.name().toLowerCase()); List zdlist = myParams.other().getDcsjycl().getZdlist(); Map cssMap = new HashMap<>(); final CellStyle[] cssStr = new CellStyle[1]; Map fields = myParams.fields(); try { ExcelWriterSheetBuilder ee = EasyExcel.write(os).head(header).autoTrim(true).excelType(ete) //自动列宽,不合适可以自己重写 .registerWriteHandler(lmcw).sheet("Sheet1") .registerWriteHandler(new SheetWriteHandler() { public void afterSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) { cssStr[0] = writeWorkbookHolder.getWorkbook().createCellStyle(); DataFormat format = writeWorkbookHolder.getWorkbook().createDataFormat(); //使导出的Excel格式默认为字符串 cssStr[0].setDataFormat(format.getFormat("@")); //自动换行 // cssStr[0].setWrapText(true); for (int i = 0; i < header.size(); i++) { writeSheetHolder.getSheet().setDefaultColumnStyle(i, cssStr[0]); } // 区间设置 第一列第一行和第二行的数据。由于第一行是头,所以第一、二行的数据实际上是第二三行 //此处需要循环context.writeContext.writeWorkbookHolder.head进行筛选是否新增下拉框 //* firstRow 开始行号(下标0开始) //* lastRow 结束行号,最大65535 //* firstCol 区域中第一个单元格的列号 (下标0开始) //* lastCol 区域中最后一个单元格的列号 CellRangeAddressList cellRangeAddressList; DataValidationConstraint constraint; DataValidation dataValidation; DataValidationHelper helper = writeSheetHolder.getSheet().getDataValidationHelper(); for (int i = 0; i < zdlist.size(); i++) { String zddm = zdlist.get(i); SysSjglSjzd f = fields.get(zddm); if (!isBlank(f.getExcelZdlb())) { cellRangeAddressList = new CellRangeAddressList(1, 65535, i, i); constraint = helper.createExplicitListConstraint(f.getExcelZdlb().toArray(new String[0])); dataValidation = helper.createValidation(constraint, cellRangeAddressList); writeSheetHolder.getSheet().addValidationData(dataValidation); } } } public void beforeSheetCreate(SheetWriteHandlerContext context) { context.getWriteSheetHolder().getConverterMap().put(ConverterKeyBuild.buildKey( ImageConverterKey.class), new ImageConverter()); } }).registerWriteHandler(new CellWriteHandler() { public void afterCellDispose(CellWriteHandlerContext context) { String zddm = zdlist.get(context.getColumnIndex()); SysSjglSjzd f = fields.get(zddm); if (context.getHead() && f.getDcbtbjs() != null) { //是表头且设置了表头颜色 WriteCellStyle css = context.getFirstCellData().getOrCreateStyle(); css.setFillPatternType(FillPatternType.SOLID_FOREGROUND); css.setFillForegroundColor(IndexedColors.valueOf(f.getDcbtbjs()).getIndex()); } else { // String ys = IndexedColors.WHITE.name(); String ys = null; if (f.getDcmrbjs() != null) { ys = f.getDcmrbjs(); } if (f.getDcdzbjs().get(context.getRowIndex().toString()) != null) { ys = f.getDcdzbjs().get(context.getRowIndex().toString()).toString(); } //要设置颜色 if (ys != null) { //该对象缓存起来,创建超过6w会报错 CellStyle css = cssMap.get(ys); if (css == null) { css = context.getWriteWorkbookHolder().getWorkbook().createCellStyle(); css.setFillPattern(FillPatternType.SOLID_FOREGROUND); //设置为字符串格式 DataFormat format = context.getWriteWorkbookHolder().getWorkbook().createDataFormat(); css.setDataFormat(format.getFormat("@")); css.setFillForegroundColor(IndexedColors.valueOf(ys).getIndex()); cssMap.put(ys, css); } context.getCell().setCellStyle(css); } else { //设置为字符串格式 context.getCell().setCellStyle(cssStr[0]); } } } }); if(myParams.other().getDcsjycl().getZjhg()){ //增加行高 ee.registerWriteHandler(new SimpleRowHeightStyleStrategy(null, (short) 100)); } ee.doWrite(data); }catch (Throwable t){ throw new MyException("生成Excel异常,header:"+JSON.toJSONString(header)+",data:"+JSON.toJSONString(data),t); } if(ete.equals(ExcelTypeEnum.CSV)){ try { //csv格式转为GBK编码 bytes = os.toString().getBytes("GBK"); }catch (Exception e){ throw new MyException("csv文件编码转换失败:"+e.getMessage(),e); } }else { bytes = os.toByteArray(); } } file1.setWjm(fileName); return resultFile(bytes, file1); } /** * @param byteArr 字节流 * @param file 文件描述 * @return 输出为文件的结果 */ protected Result resultFile(byte[] byteArr, SysSjglFile file) { file.setBytes(byteArr); Result r = success("生成文件结果对象成功", file); r.setDateType(MediaType.APPLICATION_OCTET_STREAM_VALUE); return r; } /** * @see LjqInterface#init() */ public void init() { log.debug("拦截器初始化:" + this.getClass().getSimpleName()); } /** * 异步结果处理 */ private Result ybjgcl(MyParams myParams, Result r,boolean sfyb) { if(myParams.get($_SYS_HDCST)==null||sfyb||!r.isStatus()){ //没有回调,或本身就是异步参数体方式 return r; } String hdqqid = r.getQqid(); //设置请求的回调方法等待回调 defaultCache.put(hdqqid, myParams.get($_SYS_HDCST)); //采用锁等待返回结果,超时时长配置 Lock lock = new ReentrantLock(); try { lock.lock(); Condition cond = lock.newCondition(); defaultCache.put("lock_"+hdqqid,lock); defaultCache.put("cond_"+hdqqid,cond); if (!cond.await(StringUtil.fastNotNull(myParams.sys().getTimeout(), Conf.getUtilConfig().getZnjh().getCtdydd(), 60000000),TimeUnit.MILLISECONDS)) { r = failed("等待回调超时"); r.setCode(XtZtm.CTDYCS.getCode()); } if(!isBlank(defaultCache.get("result_"+hdqqid))){ //取回调结束时的结果 r = defaultCache.getObject("result_"+hdqqid,Result.class); if(!r.isStatus()){ throw r.newMyException(); } } return r; } catch (InterruptedException e) { return failed("等待回调被中断"); }finally { lock.unlock(); defaultCache.remove(hdqqid); defaultCache.remove("lock_"+hdqqid); defaultCache.remove("cond_"+hdqqid); defaultCache.remove("result_"+hdqqid); } } /** * 回调方法转换为回调参数体 * @return 是否需要单独开启线程进行处理,而直接返回结果,是否异步 */ private boolean hdffToHdcst(MyParams ysParams,MyParams myParams) { if(myParams.get($_SYS_HDCST)==null){ //没有回调机制,正常单线程执行 return false; } if(myParams.get($_SYS_HDCST) instanceof Map){ //回调参数体场景,采用开线程异步方式 return true; } //存在回调参数体,且回调参数体是回调方法,此场景不开线程 MyParams hdcst = new MyParams(); hdcst.sys().setCllx(Cllx.tyhd.name()); hdcst.sjdx().setDxdm(getSjdx().getDxdm()); //设置穿透app,默认设置,不需要穿透也没关系 hdcst.sys().setCtapp(Conf.getAppdm()); JsonUtil.copy(hdcst,myParams,$_SYS_TIMEOUT); ysParams.sys().setHdcst(hdcst); return false; } /** * 数据批量处理结果 */ protected Result sjplcljg(int count, int insert, int update, int ignore, int repeat) { JSONObject re = new JSONObject(); re.put("count",count); re.put("insert",insert); re.put("update",update); re.put("ignore",ignore); re.put("repeat",repeat); return success("正常处理共计"+count+"条记录,其中新增"+insert+"条,更新"+update+"条,忽略"+ignore+"条,重复"+repeat+"条",re); } }