package com.boman.system.common; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.boman.common.core.utils.collection.CollectionUtils; import com.boman.common.core.utils.obj.ObjectUtils; import com.boman.common.core.web.domain.AjaxResult; import com.boman.common.redis.RedisKey; import com.boman.common.redis.service.RedisService; import com.boman.gen.controller.MyController; import com.boman.gen.domain.GenTable; import com.boman.gen.domain.GenTableColumn; import com.boman.gen.domain.GenTableRelation; import com.boman.gen.service.IGenTableColumnService; import com.boman.system.domain.SysDictData; import com.boman.system.service.*; import com.boman.system.utils.IdUtils; import com.google.common.collect.Lists; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Component; import org.springframework.web.client.RestTemplate; import javax.annotation.Resource; import java.sql.Timestamp; import java.util.*; import java.util.stream.Collectors; import static com.boman.common.core.utils.obj.ObjectUtils.*; import static com.boman.system.common.FormDataConstant.CONDITION; import static com.boman.system.common.FormDataConstant.SHOW_DATA; /** * @author shiqian * @description * @date 2021年03月22日 09:51 **/ @Component public class TableServiceCmdService { @Resource private IBaseDeleteService deleteService; @Resource private IBaseSaveService saveService; @Resource private RedisService redisService; @Resource private IBaseSelectService selectService; @Resource private IBaseSubmitService submitService; @Resource private IBaseUpdateService updateService; @Resource private RestTemplate restTemplate; @Resource private ISysDictTypeService dictTypeService; @Resource private IGenTableColumnService tableColumnService; private static final Logger LOGGER = LoggerFactory.getLogger(TableServiceCmdService.class); private BaseTableDTO packTableDTO(BaseTableSaveDTO baseTableSaveDTO) { BaseTableDTO baseTableDTO = new BaseTableDTO(); baseTableDTO.setFixedData(baseTableSaveDTO.getFixedData()); baseTableDTO.setObjId(baseTableSaveDTO.getObjId()); baseTableDTO.setTable(baseTableSaveDTO.getTable()); return baseTableDTO; } public final AjaxResult objectSave(BaseTableSaveDTO baseTableSaveDTO) { AjaxResult result = AjaxResult.success(); BaseTableDTO baseTableDTO = packTableDTO(baseTableSaveDTO); TableServiceContext context = TableServiceContext.createFrom(baseTableDTO); // 拿到pkName和maxId List columns = context.getTable().getColumns(); String pkName = IdUtils.getPkName(columns); requireNonNull(pkName, "主键名称为空"); // List allColumnNameList = columns.stream() .map(GenTableColumn::getColumnName) .collect(Collectors.toList()); // 新增 if (ObjectUtils.ltZero(baseTableDTO.getObjId())) { Long maxId = IdUtils.getMaxId(baseTableDTO.getTable(), pkName); RowResult rowResult = saveService.insertRow(context.getRealTableName(), pkName, maxId, context.getRows().get(0), allColumnNameList); if (RowResult.checkSuccess(rowResult)) { LOGGER.info("保存成功,封装到数据库的数据为: {}", JSON.toJSONString(rowResult.getData())); } else { LOGGER.error("保存失败,保持的原始数据为: {}", JSON.toJSONString(baseTableSaveDTO)); result = AjaxResult.error(); } }else { JSONObject commitData = context.getRows().get(0).getCommitData(); // 编辑 int effective = updateService.updateByIdList(context, pkName , Collections.singletonList(baseTableDTO.getObjId()), commitData); if (effective > 0) { LOGGER.info("修改成功,封装到数据库的数据为: {}", JSON.toJSONString(context.getRows().get(0).getCommitData())); } else { LOGGER.error("修改失败,前台传来的原始数据为: {}", JSON.toJSONString(context.getRows().get(0).getCommitData())); result = AjaxResult.error(); } } return result; } /** * 功能描述: 通用删除接口 (真的删除) * * @param dto 前台传过来的dto * @return com.boman.common.core.web.domain.AjaxResult */ public AjaxResult objectDelete(BaseTableSaveDTO dto) { requireNonNull(dto.getTable()); Long[] idArr = CollectionUtils.listToArray(dto.getIdList()); requiredNonNull(idArr); // 拿到pkName GenTable genTable = getTableFromRedisByTableName(RedisKey.TABLE_INFO, dto.getTable()); String pkName = IdUtils.getPkName(genTable.getColumns()); List result = Lists.newArrayListWithCapacity(idArr.length); for (Long id : idArr) { RowResult rowResult = deleteService.deleteById(dto.getTable(), pkName, id); result.add(rowResult); LOGGER.info(rowResult.getMessage() + ", id: {}", Arrays.toString(idArr)); } // RowResult rowResult = deleteService.objectDelete(idArr, dto.getTable(), requireNonNull(pkName, "主键名称为空")); return AjaxResult.success(result); } /** * 功能描述: 通用删除接口 (真的删除) * * @param dto 前台传过来的dto * @return com.boman.common.core.web.domain.AjaxResult */ public AjaxResult objectLogicDelete(BaseTableSaveDTO dto) { requireNonNull(dto.getTable()); Long[] idArr = CollectionUtils.listToArray(dto.getIdList()); requiredNonNull(idArr); // 拿到pkName GenTable genTable = getTableFromRedisByTableName(RedisKey.TABLE_INFO, dto.getTable()); String pkName = IdUtils.getPkName(genTable.getColumns()); JSONObject jsonObject = new JSONObject(); jsonObject.put(dto.getLogicDelName(), dto.getLogicDelValue()); RowResult rowResult = deleteService.objectLogicDelete(idArr, dto.getTable(), requireNonNull(pkName, "主键名称为空"), jsonObject); LOGGER.info(rowResult.getMessage() + ", id: {}", Arrays.toString(idArr)); return AjaxResult.success(rowResult); } /** * 功能描述: 获取单表单数据 * * @param dto condition * @return com.boman.common.core.web.domain.AjaxResult */ public AjaxResult queryList(BaseTableSaveDTO dto) { requireNonNull(dto.getTable()); // 拿到每个字段对应的查询类型,=、 like、 >、 < GenTable genTable = getTableFromRedisByTableName(RedisKey.TABLE_INFO, dto.getTable()); JSONObject fixedData = dto.getFixedData(); fixedData = ifNullSetEmpty(fixedData); // 查询条件 JSONObject condition = ifNullSetEmpty(fixedData.getJSONObject(CONDITION)); List columns = genTable.getColumns(); // 封装好以后的查询条件 JSONObject packCondition = ifNullSetEmpty(packColCondition(columns, condition)); // 需要返回到前台的列 JSONArray showData = ifNullSetEmpty(fixedData.getJSONArray(SHOW_DATA)); JSONObject rows = new JSONObject(); int total = selectService.countByCondition(genTable.getTableName(), condition, packCondition); rows.put(FormDataConstant.PAGE_TOTAL, total); if (total <= 0) { rows.put(FormDataConstant.PAGE_ROWS, null); return AjaxResult.success(rows); } List result = selectService.selectByCondition(genTable.getTableName(), condition, packCondition , showData, dto.getOrderBy(), dto.getLimit(), dto.getOffset()); rows.put(FormDataConstant.PAGE_ROWS, result); return AjaxResult.success(rows); } /** * 功能描述: 获取单表单数据 * * @param dto condition * @return com.boman.common.core.web.domain.AjaxResult */ public AjaxResult getObject(BaseTableSaveDTO dto) { requireNonNull(dto.getTable()); // 拿到每个字段对应的查询类型,=、 like、 >、 < // 拿到pkName GenTable genTable = getTableFromRedisByTableName(RedisKey.TABLE_INFO, dto.getTable()); String pkName = IdUtils.getPkName(genTable.getColumns()); JSONObject fixedData = dto.getFixedData(); fixedData = ifNullSetEmpty(fixedData); Long id = fixedData.getLong(FormDataConstant.ID); requireNonNull(id); // 默认查所有字段,不支持自定义 JSONObject jsonObject = selectService.selectById(genTable.getTableName(), pkName, id); return AjaxResult.success(jsonObject); } /** * 功能描述: 封装成查询条件 key: 列名, value:查询条件_查询类别 * eg: [{"config_name":"系统配置_like"}, {"config_name":"_like"}] * * @param columns columns * @return com.alibaba.fastjson.JSONObject */ private JSONObject packColCondition(List columns, JSONObject condition) { requireNonNull(columns); JSONObject result = new JSONObject(columns.size()); for (Map.Entry entry : condition.entrySet()) { String key = entry.getKey(); Object value = entry.getValue(); for (GenTableColumn column : columns) { // long string collection 暂时只作此三种类型判断 if (column.getColumnName().equalsIgnoreCase(key) && ObjectUtils.isNotEmpty(value)) { // columnType 作为判断需不需要转义的一个标准,防止索引失效 result.put(key, Lists.newArrayList(String.valueOf(value), column.getQueryType(), column.getColumnType())); break; } } } return result; } /** * 功能描述: 获取表单查询字段、按钮、表头 * 注意: 都是从redis中拿的,如果数据库和redis不一致,则需刷新一下redis * 刷新的入口为 {@link MyController#loadTable(com.boman.gen.domain.GenTable)} *

* eg:{ * "table": "sys_config", * } * * @param condition condition * @return com.boman.common.core.web.domain.AjaxResult */ public AjaxResult getTableQuery(BaseTableSaveDTO condition) { GenTable genTable = getTableFromRedisByTableName(RedisKey.TABLE_INFO, condition.getTable()); List columns = genTable.getColumns(); JSONObject jsonObject = new JSONObject(); // 查询字段 ArrayList queryList = Lists.newArrayListWithCapacity(16); for (GenTableColumn column : columns) { if (GenTableColumn.IS_QUERY.equalsIgnoreCase(column.getIsQuery())) { String dictType = column.getDictType(); if (ObjectUtils.isNotEmpty(dictType)) { List sysDictData1 = dictTypeService.selectDictDataByType(dictType); column.setSysDictData(coverSysDictDataToJSONObject(sysDictData1)); } queryList.add(column); } } jsonObject.put(FormDataConstant.QUERY_LIST, queryList); // genTable.getMenuRole() 暂时数据库没有数据, jsonObject.put(FormDataConstant.BUTTON_LIST, genTable.getMenuRole()); // 表头 List tableHeadList = columns.stream() .filter(genTableColumn -> GenTableColumn.IS_LIST.equals(genTableColumn.getIsList())) .collect(Collectors.toList()); jsonObject.put(FormDataConstant.TABLE_HEAD_LIST, tableHeadList); return AjaxResult.success(jsonObject); } /** * 功能描述: 获取表单子表 * * @param condition condition * @return com.boman.common.core.web.domain.AjaxResult */ public AjaxResult objectTab(BaseTableSaveDTO condition) { GenTable genTable = getTableFromRedisByTableName(RedisKey.RELATION, condition.getTable()); List childTableList = genTable.getRelationList(); // 此表没有关联子表,查啥查 requireNonNull(childTableList); // todo for (GenTable childTable : childTableList) { String childTableName = childTable.getTableName(); Long childTableTableId = childTable.getTableId(); List childColumns = childTable.getColumns(); // column_name = 先根据tableName查到id,再用id到relation中查到relation_child_id, 在用这个值去到tableColumn中查到column_name // select * from childTableName where column_name = objId } return AjaxResult.success(); } public String getChildColumnNameByParentTableName(GenTable parentGenTable, Long childTableTableId){ requireNonNull(parentGenTable.getTableName(), "主表名称为空"); // GenTable primaryTable = redisService.getCacheObject(RedisKey.TABLE_INFO + genTable.getTableName()); Long parentTableId = parentGenTable.getTableId(); List relations = redisService.getCacheObject(RedisKey.RELATION_INFO); relations = relations.stream() .filter(relation -> relation.getRelationParentId().equals(parentTableId)) .collect(Collectors.toList()); for (GenTableRelation relation : relations) { if (relation.getRelationChildId().equals(6L)) { tableColumnService.selectGenTableColumnListByTableId(childTableTableId); // return } } return ""; } /** * 功能描述: 表单提交接口 * * @param condition condition * @param isSubmit 提交true, 反提交false * @return com.boman.common.core.web.domain.AjaxResult */ public AjaxResult objectSubmit(BaseTableSaveDTO condition, boolean isSubmit) { GenTable genTable = getTableFromRedisByTableName(RedisKey.TABLE_INFO, condition.getTable()); List commitData = condition.getCommitData(); requireNonNull(commitData, "啥都不提交, 调什么接口??"); String tableName = requireNonNull(genTable.getTableName()); String pkName = IdUtils.getPkName(genTable.getColumns()); // 先去查出之前的状态 List idList = commitData.stream().map(jsonObject -> jsonObject.getLong(FormDataConstant.ID)) .collect(Collectors.toList()); JSONArray showData = new JSONArray(); showData.add(FormDataConstant.STATUS); showData.add(pkName); List beforeList = selectService.selectByIdList(tableName, pkName, idList, showData); requireNonNull(beforeList); for (JSONObject commitDatum : commitData) { String dbStatus = getStatusFromFormData(commitDatum, beforeList); // 只能是未提交的状态下,才能调用提交 if (isSubmit) { // 只能是未提交的状态下,才能调用提交, 下面是不允许 if (!SubmitConstant.NOT_SUBMIT.equals(dbStatus)) { commitDatum.put(SubmitConstant.SUBMIT_RESULT, SubmitConstant.NOT_ALLOWED); } else { commitDatum.put(SubmitConstant.SUBMIT_USERID, 123); commitDatum.put(SubmitConstant.SUBMIT_TIME, new Timestamp(System.currentTimeMillis())); int effective = submitService.handlerSubmit(tableName, pkName, commitDatum, commitDatum.getLong(FormDataConstant.ID)); if (effective > 0) { commitDatum.put(SubmitConstant.SUBMIT_RESULT, SubmitConstant.SUCCESS); } else { commitDatum.put(SubmitConstant.SUBMIT_RESULT, SubmitConstant.FAIL); } } } else { // 只有在已提交的情况下才能反提交, 下面是不允许 if (!SubmitConstant.SUBMITTED.equals(dbStatus)) { commitDatum.put(SubmitConstant.SUBMIT_RESULT, SubmitConstant.NOT_ALLOWED); } else { commitDatum.put(SubmitConstant.SUBMIT_USERID, 123); commitDatum.put(SubmitConstant.SUBMIT_TIME, new Timestamp(System.currentTimeMillis())); int effective = submitService.handlerSubmit(tableName, pkName, commitDatum, commitDatum.getLong(FormDataConstant.ID)); if (effective > 0) { commitDatum.put(SubmitConstant.SUBMIT_RESULT, SubmitConstant.SUCCESS); } else { commitDatum.put(SubmitConstant.SUBMIT_RESULT, SubmitConstant.FAIL); } } } } return AjaxResult.success(commitData); } private String getStatusFromFormData(JSONObject next, List commitData) { for (JSONObject jsonObject : commitData) { if (jsonObject.getLong(FormDataConstant.ID).equals(next.getLong(FormDataConstant.ID))) { return jsonObject.getString(FormDataConstant.STATUS); } } throw new IllegalArgumentException("不可能没有一个合适的"); } /** * 是否定制 * 判断是否需要转发到定制接口 * @param tableName 表明 * @param result 结果 * @param action 动作 * @return 结果 */ public List isCustomized(String tableName, List result, String action) { requireNonNull(tableName); requireNonNull(action); if (result != null && result.size() > 0){ //获取到服务名称 String triggerName = getTriggerName(tableName, action); requireNonNull(triggerName); //组织请求 acos + RestTemplate return restTemplate.postForObject("http://" + triggerName, result, List.class); } return result; } /** * 判断是什么action * @param tableName 表明 * @param action 动作 * @return */ private String getTriggerName(String tableName, String action){ GenTable genTable = getTableFromRedisByTableName(RedisKey.TABLE_INFO, tableName); requireNonNull(genTable); if (action.equals(TriggerActionConstant.ACTION_CREATE)){ return genTable.getTriggerCreate(); }else if (action.equals(TriggerActionConstant.ACTION_RETRIEVE)){ return genTable.getTriggerRetrieve(); }else if (action.equals(TriggerActionConstant.ACTION_UPDATE)){ return genTable.getTriggerUpdate(); }else if (action.equals(TriggerActionConstant.ACTION_DELETE)){ return genTable.getTriggerDelete(); }else if (action.equals(TriggerActionConstant.ACTION_SUBMIT)){ return genTable.getTriggerSubmit(); } return null; } // todo redis中未找到,要去查数据库,然后再塞进去 private GenTable getTableFromRedisByTableName(String redisKeyPrefix, String tableName) { GenTable genTable = redisService.getCacheObject(redisKeyPrefix + requireNonNull(tableName)); return requireNonNull(genTable, "未找到表对应的信息"); } /** * 功能描述: 反提交接口, 更改的字段类型和字段值都是一致的 * { * "table": "sys_config", * } * * * @param condition condition * @return com.boman.common.core.web.domain.AjaxResult */ public AjaxResult getByTableName(BaseTableSaveDTO condition) { // requiredNonNull(condition.getTable(), "表名为空"); GenTable genTable = getTableFromRedisByTableName(RedisKey.TABLE_INFO, condition.getTable()); List columns = genTable.getColumns(); for (GenTableColumn column : columns) { String dictType = column.getDictType(); if (ObjectUtils.isNotEmpty(dictType)) { List sysDictData1 = dictTypeService.selectDictDataByType(dictType); column.setSysDictData(coverSysDictDataToJSONObject(sysDictData1)); } } return AjaxResult.success(genTable); } public List coverSysDictDataToJSONObject(List sysDictData) { List result = Lists.newArrayListWithCapacity(sysDictData.size()); for (SysDictData data : sysDictData) { JSONObject jsonObject = new JSONObject(); String dictLabel = data.getDictLabel(); String dictValue = data.getDictValue(); jsonObject.put(DictConstant.DICT_LABEL, dictLabel); jsonObject.put(DictConstant.DICT_VALUE, dictValue); result.add(jsonObject); } return result; } }