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.SecurityUtils; 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.system.mapper.StandardlyMapper; 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 javax.annotation.Resource; import java.sql.Timestamp; import java.util.*; import java.util.stream.Collectors; import static com.boman.common.core.utils.obj.ObjectUtils.requireNonNull; import static com.boman.common.core.utils.obj.ObjectUtils.requiredNonNull; 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; 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) { 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()); 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)); } return AjaxResult.success(rowResult); } /** * 功能描述: 通用删除接口 (真的删除) * * @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()); RowResult rowResult = deleteService.objectDelete(idArr, dto.getTable(), requireNonNull(pkName, "主键名称为空")); LOGGER.info(rowResult.getMessage() + ", id: {}", Arrays.toString(idArr)); return AjaxResult.success(rowResult); } /** * 功能描述: 通用删除接口 (真的删除) * * @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 = ObjectUtils.ifNullSetEmpty(fixedData); // 查询条件 JSONObject condition = ObjectUtils.ifNullSetEmpty(fixedData.getJSONObject(CONDITION)); List columns = genTable.getColumns(); // 封装好以后的查询条件 JSONObject packCondition = ObjectUtils.ifNullSetEmpty(packColCondition(columns, condition)); // 需要返回到前台的列 JSONArray showData = ObjectUtils.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 = ObjectUtils.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, packValue(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())) { 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); } /** * 功能描述: 封装查询条件,在拼sql的时候按照此规则去取值 * {@link StandardlyMapper.SqlProvider#selectByCondition(java.util.Map)} * * @param value 查询的值 * @param queryType queryType * @param columnType columnType * @return java.lang.String */ public String packValue(String value, String queryType, String columnType) { requireNonNull(value); requireNonNull(queryType); return value + "_" + queryType + "_" + columnType; } /** * 功能描述: 获取表单子表 * * @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); for (GenTable childTable : childTableList) { String childTableName = childTable.getTableName(); } return AjaxResult.success(); } /** * 功能描述: 表单提交接口 * * @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("不可能没有一个合适的"); } // todo redis中未找到,要去查数据库,然后再塞进去 private GenTable getTableFromRedisByTableName(String redisKeyPrefix, String tableName){ GenTable genTable = redisService.getCacheObject(redisKeyPrefix + requireNonNull(tableName)); return requireNonNull(genTable); } }