Selaa lähdekoodia

[task-4305]操作日志功能优化

gaozl 11 kuukautta sitten
vanhempi
sitoutus
5e7f63269e

+ 10 - 0
ibps-provider-base-root/modules/provider-form-api/src/main/java/com/lc/ibps/form/vo/DataTemplateRequestVo.java

@@ -20,6 +20,16 @@ public class DataTemplateRequestVo {
 	@ApiModelProperty(value = "数据模板json")
 	@NotBlank(message = "{com.lc.ibps.form.data}")
 	private String data;
+	@ApiModelProperty(value = "是否记录操作日志;true/false")
+	private Boolean addLog;
+
+	public Boolean getAddLog() {
+		return addLog;
+	}
+
+	public void setAddLog(Boolean addLog) {
+		this.addLog = addLog;
+	}
 
 	public String getTitle() {
 		return title;

+ 395 - 9
ibps-provider-root/modules/provider-business/src/main/java/com/lc/ibps/aop/IDataTemplateMsgAop.java

@@ -1,25 +1,114 @@
 package com.lc.ibps.aop;
 
 import cn.hutool.core.date.StopWatch;
-import com.lc.ibps.sysdata.dao.UpdateDataTableDao;
+import cn.hutool.core.lang.Assert;
+import cn.hutool.json.JSONArray;
+import cn.hutool.json.JSONUtil;
+import com.alibaba.fastjson.JSONObject;
+import com.lc.ibps.base.bo.constants.BoTableConstants;
+import com.lc.ibps.base.bo.constants.DataSaveMode;
+import com.lc.ibps.base.bo.constants.SaveDatabaseMode;
+import com.lc.ibps.base.bo.exception.BoBaseException;
+import com.lc.ibps.base.bo.handler.PhysicalTableDataHandler;
+import com.lc.ibps.base.bo.model.DataObjectModel;
+import com.lc.ibps.base.bo.model.SqlMapVo;
+import com.lc.ibps.base.bo.persistence.entity.BoAttrColumnPo;
+import com.lc.ibps.base.bo.persistence.entity.BoDefPo;
+import com.lc.ibps.base.bo.persistence.entity.BoTablePo;
+import com.lc.ibps.base.bo.repository.BoAttrColumnRepository;
+import com.lc.ibps.base.bo.repository.BoDefRepository;
+import com.lc.ibps.base.bo.repository.BoInstanceRepository;
+import com.lc.ibps.base.bo.repository.BoTableRepository;
+import com.lc.ibps.base.bo.service.impl.DefaultBoInstanceService;
+import com.lc.ibps.base.core.util.AppUtil;
+import com.lc.ibps.base.core.util.BeanUtils;
+import com.lc.ibps.base.core.util.JacksonUtil;
+import com.lc.ibps.base.core.util.string.StringUtil;
+import com.lc.ibps.base.framework.table.ICommonDao;
+import com.lc.ibps.base.web.context.ContextUtil;
+import com.lc.ibps.form.form.helper.FormDefDataBuilder;
+import com.lc.ibps.form.form.helper.JacksonFormDefDataBuilder;
+import com.lc.ibps.form.form.persistence.entity.FormBoPo;
+import com.lc.ibps.form.form.persistence.entity.FormDefPo;
+import com.lc.ibps.form.form.repository.FormDefRepository;
+import com.lc.ibps.form.vo.DataTemplateRequestVo;
 import com.lc.ibps.untils.LogAopUtil;
+import com.lc.ibps.untils.SqlUtil;
 import org.aspectj.lang.ProceedingJoinPoint;
 import org.aspectj.lang.annotation.Around;
 import org.aspectj.lang.annotation.Aspect;
-import org.springframework.beans.factory.annotation.Autowired;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 import org.springframework.stereotype.Component;
 import org.springframework.web.context.request.RequestContextHolder;
 import org.springframework.web.context.request.ServletRequestAttributes;
 
+import javax.annotation.Resource;
 import javax.servlet.http.HttpServletRequest;
-import java.util.Objects;
+import java.text.SimpleDateFormat;
+import java.util.*;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
 @Aspect
 @Component
 public class IDataTemplateMsgAop {
 
-    @Autowired
-    private UpdateDataTableDao updateDataTableDao;
+    private static final String TABLE_NAME = "t_business_log";
+
+    private static final String REMOVE_METHOD = "removeFormData";
+
+    private static final String SAVE_METHOD = "saveFormDataVo";
+
+    private static final Logger logger = LoggerFactory.getLogger(IDataTemplateMsgAop.class);
+
+    @Resource
+    private ICommonDao commonDao;
+
+    private PhysicalTableDataHandler physicalTableDataHandler;
+
+    private BoInstanceRepository boInstanceRepository;
+
+    private BoTableRepository boTableRepository;
+
+    private BoAttrColumnRepository boAttrColumnRepository;
+
+    @Resource
+    private FormDefRepository formDefRepository;
+
+    @Resource
+    private BoDefRepository boDefRepository;
+
+    @Resource
+    private DefaultBoInstanceService boInstanceService;
+
+    private PhysicalTableDataHandler physicalTableDataHandler() {
+        if(physicalTableDataHandler==null) {
+            physicalTableDataHandler=AppUtil.getBean(PhysicalTableDataHandler.class);
+        }
+        return physicalTableDataHandler;
+    }
+
+    private BoInstanceRepository boInstanceRepository() {
+        if(boInstanceRepository==null) {
+            boInstanceRepository= AppUtil.getBean(BoInstanceRepository.class);
+        }
+        return boInstanceRepository;
+    }
+
+    private BoTableRepository boTableRepository() {
+        if(boTableRepository==null) {
+            boTableRepository=AppUtil.getBean(BoTableRepository.class);
+        }
+        return boTableRepository;
+    }
+
+    private BoAttrColumnRepository boAttrColumnRepository() {
+        if(boAttrColumnRepository==null) {
+            boAttrColumnRepository=AppUtil.getBean(BoAttrColumnRepository.class);
+        }
+        return boAttrColumnRepository;
+    }
 
     //删除表单数据     /ibps/business/v3/data/template/removeFormData
 
@@ -29,17 +118,314 @@ public class IDataTemplateMsgAop {
         StopWatch stopWatch = new StopWatch();
         stopWatch.start();
         Object result = null;
+        String oldData = "";
+        String tableName = "";
+        String tableComment = "";
         try {
+            if (REMOVE_METHOD.equals(point.getSignature().getName())){
+                String params = LogAopUtil.filterParam(point.getArgs());
+                JSONArray jsonArray = JSONUtil.parseArray(params);
+                JSONArray secondArray = jsonArray.getJSONArray(1);
+                String[] ids = secondArray.toArray(new String[0]);
+                String formKey = point.getArgs()[0].toString();
+                FormDefPo formDefPo = formDefRepository.getByFormKey(formKey);
+                FormBoPo formBo = formDefPo.getFormBo();
+                BoDefPo boDefPo = boDefRepository.get(formBo.getBoId());
+                BoTablePo boTable = boTableRepository().getByDefCode(boDefPo.getCode(),boDefPo.getVersion());
+                tableName = boTable.getName();
+                tableComment = boTable.getComment();
+                Map<String, List<Object[]>> sqls = getDelList(boDefPo.getCode(),boDefPo.getVersion(),ids,boTable);
+                oldData = getOldData(sqls);
+            }
+            if (SAVE_METHOD.equals(point.getSignature().getName())){
+                String params = LogAopUtil.filterParam(point.getArgs());
+                cn.hutool.json.JSONObject jsonObject = JSONUtil.parseObj(params);
+                if (BeanUtils.isNotEmpty(jsonObject.getBool("addLog"))){
+                    DataTemplateRequestVo dataTemplateRequestVo = new DataTemplateRequestVo();
+                    dataTemplateRequestVo.setData(jsonObject.getStr("data"));
+                    dataTemplateRequestVo.setAddLog(jsonObject.getBool("addLog"));
+                    dataTemplateRequestVo.setBoCode(jsonObject.getStr("boCode"));
+                    dataTemplateRequestVo.setPk(jsonObject.getStr("pk"));
+                    dataTemplateRequestVo.setVersion(jsonObject.getInt("version"));
+                    dataTemplateRequestVo.setFormKey(jsonObject.getStr("formKey"));
+
+                    String saveType = DataSaveMode.TABLE;
+                    DataObjectModel dataObject = null;
+                    Integer boVersion = 0;
+                    FormDefPo formDefPo = formDefRepository.getByFormKey(dataTemplateRequestVo.getFormKey());
+                    FormBoPo formBo = formDefPo.getFormBo();
+                    BoDefPo boDefPo = boDefRepository.get(formBo.getBoId());
+                    Assert.notNull(boDefPo, "业务对象【{}】不存在!", formBo.getBoId());
+
+                    boVersion = boDefPo.getVersion();
+                    if (StringUtil.isNotEmpty(dataTemplateRequestVo.getPk())) {
+                        dataObject = boInstanceService.getDataObject(saveType, dataTemplateRequestVo.getPk(), dataTemplateRequestVo.getBoCode(), boVersion);
+                    }
+                    // 将前台的BO数据与原有BO数据 融合(前台的BO数据可能只有一部分数据)
+                    if (BeanUtils.isEmpty(dataObject)) {
+                        dataObject = boInstanceService.createDataObject(dataTemplateRequestVo.getBoCode(), boVersion, dataTemplateRequestVo.getData());
+                    } else {
+                        boInstanceService.mergerDataObject(dataObject, dataTemplateRequestVo.getData());
+                    }
+                    dataObject.setCurUserId(ContextUtil.getCurrentUserId());
+                    dataObject.setTenantId(ContextUtil.getCurrentTenantId());
+                    dataObject.setPageVersion(dataTemplateRequestVo.getVersion());
+                    String formData;
+                    boolean isJackson = AppUtil.getProperty("com.lc.ibps.form.build.jackson", Boolean.class, false);
+                    if(isJackson) {
+                        formData = JacksonFormDefDataBuilder.buildFormOptionData(formDefPo, dataTemplateRequestVo.getData());
+                    }
+                    else {
+                        formData = FormDefDataBuilder.buildFormOptionData(formDefPo, dataTemplateRequestVo.getData());
+                    }
+                    dataObject.setFormOptions(formData);
+                    boTableRepository().setForUpdate();
+                    BoTablePo boTable = boTableRepository().getByDefCode(boDefPo.getCode(), boDefPo.getVersion());
+                    tableName = boTable.getName();
+                    tableComment = boTable.getComment();
+                    boTableRepository().removeForUpdate();
+
+                    Map<String, List<Object[]>> sqls = getSaveSql(dataObject,boTable,boDefPo);
+                    oldData = getOldDataBySave(sqls,tableName,jsonObject.getStr("pk"));
+                }
+            }
+
             result = point.proceed();
+
         } catch (Throwable throwable) {
-            updateDataTableDao.insertLog(LogAopUtil.logError(request, point, throwable));
-            throw throwable;
+            Map<String,Object> map = LogAopUtil.logError(request, point, throwable);
+            map.put("table_name" , tableName);
+            map.put("table_comment" , tableComment);
+            map.put("data_" , oldData);
+            String sql = SqlUtil.buildInsertSql(map,TABLE_NAME);
+            try {
+                commonDao.execute(sql);
+            }catch (Exception e){
+                logger.error(e.getMessage());
+            }
+            logger.error(throwable.getMessage(), throwable);
         } finally {
             stopWatch.stop();
         }
-        if ("removeFormData".equals(point.getSignature().getName())){
-            updateDataTableDao.insertLog(LogAopUtil.log( request, point, result, stopWatch));
+        if (REMOVE_METHOD.equals(point.getSignature().getName()) || SAVE_METHOD.equals(point.getSignature().getName())){
+            Map<String,Object> map = LogAopUtil.log(request, point, result, stopWatch);
+            map.put("table_name" , tableName);
+            map.put("table_comment" , tableComment);
+            map.put("data_" , oldData);
+            String sql = SqlUtil.buildInsertSql(map,TABLE_NAME);
+            try {
+                commonDao.execute(sql);
+            }catch (Exception e){
+                logger.error(e.getMessage());
+            }
         }
         return result;
     }
+
+    private Map<String, List<Object[]>> getSaveSql(DataObjectModel dataObject,BoTablePo boTable,BoDefPo boDef) {
+        Map<String, List<Object[]>> sqls = new LinkedHashMap<>(16);
+        try {
+            if (BeanUtils.isEmpty(boTable)) {
+                throw new BoBaseException("业务对象未生成物理表");
+            }
+            Map<String, Object> instDataMap = dataObject.instData2Map();
+            String pkColumn = boTable.getPkColumn();
+            BoAttrColumnPo attrColumnPo = boAttrColumnRepository().getByDefIdTableIdFieldName(boDef.getId(),boTable.getId(), boTable.getPkColumn());
+            if (BeanUtils.isNotEmpty(attrColumnPo)) {
+                pkColumn = attrColumnPo.getAttrCode();
+            }
+            String pkCol = boDef.getCode() + "." + pkColumn;
+            String id = dataObject.getString(pkCol);
+            List<SqlMapVo> sqlMaps = null;
+            // 3 根据boTable(包含子表)生成sql语句
+            String action = SaveDatabaseMode.ADD;
+            Map<String, Object> extAttr = new HashMap<>();
+            //扩展参数
+            extAttr.put(BoTableConstants.EXT_ATTR_TENANT_ID, dataObject.getTenantId());
+            extAttr.put(BoTableConstants.EXT_ATTR_USER_ID, dataObject.getCurUserId());
+            extAttr.put(BoTableConstants.EXT_ATTR_IP, dataObject.getOptIp());
+            extAttr.put(BoTableConstants.EXT_ATTR_VERSION, dataObject.getVersion());
+            extAttr.put(BoTableConstants.EXT_ATTR_DATA_STATUS, dataObject.getDataStatus());
+
+            if (StringUtil.isBlank(id)) {
+                Map<String, Object> map = ((Map<String, Object>) instDataMap.get(boDef.getCode()));
+                if(BeanUtils.isEmpty(map)) {
+                    map = new HashMap<>();
+                }
+                map.put(pkColumn, dataObject.getId());
+            }
+            else {
+                //判断是否id存在
+                boInstanceRepository().setForUpdate();
+                DataObjectModel data = boInstanceRepository().getDataObjectModel(DataSaveMode.TABLE, id,boDef.getCode(), boDef.getVersion());
+                boInstanceRepository().removeForUpdate();
+                String d = data.getData();
+                // 如果外部主动传入数据id,只有第一次是保存,后续操作都是更新
+                if(JacksonUtil.isNotEmpty(d)) {
+                    action = SaveDatabaseMode.UPD;
+                }
+            }
+            physicalTableDataHandler().setMybatisNamedParamter();
+            sqlMaps = physicalTableDataHandler().genSqlMap(boTable, instDataMap, action, extAttr);
+
+            if (BeanUtils.isNotEmpty(sqlMaps)) {
+                for (SqlMapVo sqlMap : sqlMaps) {
+                    List<Object[]> params = sqls.get(sqlMap.getSql());
+                    if(BeanUtils.isEmpty(params)) {
+                        params = sqlMap.getParams();
+                    }else {
+                        params.addAll(sqlMap.getParams());
+                    }
+                    sqls.put(sqlMap.getSql(), params);
+                }
+            }
+        } catch (Exception e) {
+            throw e;
+        }
+        finally {
+            physicalTableDataHandler().removeMybatisNamedParamter();
+        }
+        return sqls;
+    }
+
+
+    private Map<String, List<Object[]>> getDelList(String code, Integer version, String[] ids,BoTablePo boTable) {
+        DataObjectModel dataObject = null;
+        Map<String, Object> instDataMap = null;
+        Map<String, List<Object[]>> sqls = new LinkedHashMap<>(16);
+        try {
+            physicalTableDataHandler().setMybatisNamedParamter();
+            for (String pk : ids) {
+                // 将dataObject中的instData转换为物理表的数据
+                boInstanceRepository().setForUpdate();
+                dataObject = boInstanceRepository().getDataObjectModel(DataSaveMode.TABLE, pk, code, version);
+                boInstanceRepository().removeForUpdate();
+                instDataMap = dataObject.instData2Map();
+                List<SqlMapVo> sqlMaps = physicalTableDataHandler().genSqlMap(boTable, instDataMap, SaveDatabaseMode.DEL, null);
+                if (BeanUtils.isEmpty(sqlMaps)) {
+                    continue;
+                }
+                for (SqlMapVo sqlMap : sqlMaps) {
+                    List<Object[]> params = sqls.get(sqlMap.getSql());
+                    if(BeanUtils.isEmpty(params)) {
+                        params = sqlMap.getParams();
+                    }else {
+                        params.addAll(sqlMap.getParams());
+                    }
+                    sqls.put(sqlMap.getSql(), params);
+                }
+            }
+        }catch (Exception e) {
+            logger.warn(e.getMessage());
+            return null;
+        }finally {
+            physicalTableDataHandler().removeMybatisNamedParamter();
+        }
+        return sqls;
+    }
+
+    public String getOldDataBySave(Map<String, List<Object[]>> sqls,String mainTable,String pk) {
+        JSONArray jsonArray = new JSONArray();
+        if (BeanUtils.isEmpty(sqls)){
+            return "";
+        }
+        Set<Map.Entry<String, List<Object[]>>> entrySet = sqls.entrySet();
+        for(Map.Entry<String, List<Object[]>> entry : entrySet) {
+            boolean aaa = entry.getKey().contains("delete");
+            if (entry.getKey().contains("delete")) {
+                String sql = entry.getKey().replace("delete","select * ");
+                String tableName = extractTableName(entry.getKey());
+                if (BeanUtils.isEmpty(tableName)){
+                    continue;
+                }
+                List<Object[]> param = entry.getValue();
+                for (Object[] obj : param) {
+                    List<Map<String,Object>> list = commonDao.query(sql,obj);
+                    for (Map<String,Object> map : list) {
+                        if (BeanUtils.isEmpty(map)){
+                            continue;
+                        }
+                        JSONObject jsonObject = new JSONObject();
+                        jsonObject.put("table_name" , tableName);
+                        for (Object key : map.keySet()){
+                            jsonObject.put(key.toString(), map.get(key));
+                            if (key.equals("create_time_")){
+                                jsonObject.put("create_time_", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(map.get(key)));
+                            }
+                            if (key.equals("update_time_")){
+                                jsonObject.put("update_time_", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(map.get(key)));
+                            }
+                        }
+                        jsonArray.add(jsonObject);
+                    }
+                }
+            }
+        }
+
+        if (BeanUtils.isNotEmpty(mainTable) && BeanUtils.isNotEmpty(pk)){
+            String sql = "select *from "+mainTable + " where id_ ='"+pk+"'";
+            Map<String,Object> dataMap = commonDao.queryOne(sql);
+            JSONObject jsonObject = new JSONObject();
+            jsonObject.put("table_name" , mainTable);
+            for (Object key : dataMap.keySet()){
+                jsonObject.put(key.toString(), dataMap.get(key));
+                if (key.equals("create_time_")){
+                    jsonObject.put("create_time_", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(dataMap.get(key)));
+                }
+                if (key.equals("update_time_")){
+                    jsonObject.put("update_time_", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(dataMap.get(key)));
+                }
+            }
+            jsonArray.add(jsonObject);
+        }
+
+        return jsonArray.toString();
+    }
+
+    public String getOldData(Map<String, List<Object[]>> sqls) {
+        JSONArray jsonArray = new JSONArray();
+        if (BeanUtils.isEmpty(sqls)){
+            return "";
+        }
+        Set<Map.Entry<String, List<Object[]>>> entrySet = sqls.entrySet();
+        for(Map.Entry<String, List<Object[]>> entry : entrySet) {
+            String tableName = extractTableName(entry.getKey());
+            if (BeanUtils.isEmpty(tableName)){
+                continue;
+            }
+            List<Object[]> param = entry.getValue();
+            for (Object[] obj : param) {
+                String id = (String) obj[0];
+                String sql = "select *from "+tableName + " where id_ ='"+id+"'";
+                Map<String,Object> dataMap = commonDao.queryOne(sql);
+                if (BeanUtils.isEmpty(dataMap)){
+                    continue;
+                }
+                JSONObject jsonObject = new JSONObject();
+                jsonObject.put("table_name" , tableName);
+                for (Object key : dataMap.keySet()){
+                    jsonObject.put(key.toString(), dataMap.get(key));
+                    if (key.equals("create_time_")){
+                        jsonObject.put("create_time_", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(dataMap.get(key)));
+                    }
+                    if (key.equals("update_time_")){
+                        jsonObject.put("update_time_", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(dataMap.get(key)));
+                    }
+                }
+                jsonArray.add(jsonObject);
+            }
+        }
+        return jsonArray.toString();
+    }
+
+    public static String extractTableName(String sql) {
+        // 匹配 delete from 后的表名(不区分大小写,支持模式名如schema.table)
+        String regex = "(?i)delete\\s+from\\s+([a-zA-Z0-9_.]+)";
+        Pattern pattern = Pattern.compile(regex);
+        Matcher matcher = pattern.matcher(sql);
+        if (matcher.find()) {
+            return matcher.group(1).trim(); // 返回第一个捕获组并去除空格
+        }
+        return null;
+    }
 }

+ 1 - 2
ibps-provider-root/modules/provider-business/src/main/java/com/lc/ibps/untils/LogAopUtil.java

@@ -28,12 +28,11 @@ public class LogAopUtil {
 
     public static String filterParam(Object[] pointArgs){
         ObjectMapper objectMapper = new ObjectMapper();
-        String ciphertext = "";
         for (Object pointArg : pointArgs) {
             try {
                 JsonNode jsonNode = objectMapper.readTree(pointArg.toString());
                 if (jsonNode.has("ciphertext") && !jsonNode.get("ciphertext").isNull()) {
-                    ciphertext = jsonNode.get("ciphertext").asText();
+                    String ciphertext = jsonNode.get("ciphertext").asText();
                     pointArgs = new String[]{AESUtil.decrypt(ciphertext)};
                 }
             } catch (Exception e) {}