Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
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);
}
}