TableServiceCmdService.java 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499
  1. package com.boman.system.common;
  2. import com.alibaba.fastjson.JSON;
  3. import com.alibaba.fastjson.JSONArray;
  4. import com.alibaba.fastjson.JSONObject;
  5. import com.boman.common.core.utils.collection.CollectionUtils;
  6. import com.boman.common.core.utils.obj.ObjectUtils;
  7. import com.boman.common.core.web.domain.AjaxResult;
  8. import com.boman.common.redis.RedisKey;
  9. import com.boman.common.redis.service.RedisService;
  10. import com.boman.gen.controller.MyController;
  11. import com.boman.gen.domain.GenTable;
  12. import com.boman.gen.domain.GenTableColumn;
  13. import com.boman.gen.domain.GenTableRelation;
  14. import com.boman.gen.service.IGenTableColumnService;
  15. import com.boman.system.domain.SysDictData;
  16. import com.boman.system.service.*;
  17. import com.boman.system.utils.IdUtils;
  18. import com.google.common.collect.Lists;
  19. import org.slf4j.Logger;
  20. import org.slf4j.LoggerFactory;
  21. import org.springframework.stereotype.Component;
  22. import org.springframework.web.client.RestTemplate;
  23. import javax.annotation.Resource;
  24. import java.sql.Timestamp;
  25. import java.util.*;
  26. import java.util.stream.Collectors;
  27. import static com.boman.common.core.utils.obj.ObjectUtils.*;
  28. import static com.boman.system.common.FormDataConstant.CONDITION;
  29. import static com.boman.system.common.FormDataConstant.SHOW_DATA;
  30. /**
  31. * @author shiqian
  32. * @description
  33. * @date 2021年03月22日 09:51
  34. **/
  35. @Component
  36. public class TableServiceCmdService {
  37. @Resource
  38. private IBaseDeleteService deleteService;
  39. @Resource
  40. private IBaseSaveService saveService;
  41. @Resource
  42. private RedisService redisService;
  43. @Resource
  44. private IBaseSelectService selectService;
  45. @Resource
  46. private IBaseSubmitService submitService;
  47. @Resource
  48. private IBaseUpdateService updateService;
  49. @Resource
  50. private RestTemplate restTemplate;
  51. @Resource
  52. private ISysDictTypeService dictTypeService;
  53. @Resource
  54. private IGenTableColumnService tableColumnService;
  55. private static final Logger LOGGER = LoggerFactory.getLogger(TableServiceCmdService.class);
  56. private BaseTableDTO packTableDTO(BaseTableSaveDTO baseTableSaveDTO) {
  57. BaseTableDTO baseTableDTO = new BaseTableDTO();
  58. baseTableDTO.setFixedData(baseTableSaveDTO.getFixedData());
  59. baseTableDTO.setObjId(baseTableSaveDTO.getObjId());
  60. baseTableDTO.setTable(baseTableSaveDTO.getTable());
  61. return baseTableDTO;
  62. }
  63. public final AjaxResult objectSave(BaseTableSaveDTO baseTableSaveDTO) {
  64. AjaxResult result = AjaxResult.success();
  65. BaseTableDTO baseTableDTO = packTableDTO(baseTableSaveDTO);
  66. TableServiceContext context = TableServiceContext.createFrom(baseTableDTO);
  67. // 拿到pkName和maxId
  68. List<GenTableColumn> columns = context.getTable().getColumns();
  69. String pkName = IdUtils.getPkName(columns);
  70. requireNonNull(pkName, "主键名称为空");
  71. //
  72. List<String> allColumnNameList = columns.stream()
  73. .map(GenTableColumn::getColumnName)
  74. .collect(Collectors.toList());
  75. // 新增
  76. if (ObjectUtils.ltZero(baseTableDTO.getObjId())) {
  77. Long maxId = IdUtils.getMaxId(baseTableDTO.getTable(), pkName);
  78. RowResult rowResult = saveService.insertRow(context.getRealTableName(), pkName, maxId, context.getRows().get(0), allColumnNameList);
  79. if (RowResult.checkSuccess(rowResult)) {
  80. LOGGER.info("保存成功,封装到数据库的数据为: {}", JSON.toJSONString(rowResult.getData()));
  81. } else {
  82. LOGGER.error("保存失败,保持的原始数据为: {}", JSON.toJSONString(baseTableSaveDTO));
  83. result = AjaxResult.error();
  84. }
  85. }else {
  86. JSONObject commitData = context.getRows().get(0).getCommitData();
  87. // 编辑
  88. int effective = updateService.updateByIdList(context, pkName
  89. , Collections.singletonList(baseTableDTO.getObjId()), commitData);
  90. if (effective > 0) {
  91. LOGGER.info("修改成功,封装到数据库的数据为: {}", JSON.toJSONString(context.getRows().get(0).getCommitData()));
  92. } else {
  93. LOGGER.error("修改失败,前台传来的原始数据为: {}", JSON.toJSONString(context.getRows().get(0).getCommitData()));
  94. result = AjaxResult.error();
  95. }
  96. }
  97. return result;
  98. }
  99. /**
  100. * 功能描述: 通用删除接口 (真的删除)
  101. *
  102. * @param dto 前台传过来的dto
  103. * @return com.boman.common.core.web.domain.AjaxResult
  104. */
  105. public AjaxResult objectDelete(BaseTableSaveDTO dto) {
  106. requireNonNull(dto.getTable());
  107. Long[] idArr = CollectionUtils.listToArray(dto.getIdList());
  108. requiredNonNull(idArr);
  109. // 拿到pkName
  110. GenTable genTable = getTableFromRedisByTableName(RedisKey.TABLE_INFO, dto.getTable());
  111. String pkName = IdUtils.getPkName(genTable.getColumns());
  112. List<RowResult> result = Lists.newArrayListWithCapacity(idArr.length);
  113. for (Long id : idArr) {
  114. RowResult rowResult = deleteService.deleteById(dto.getTable(), pkName, id);
  115. result.add(rowResult);
  116. LOGGER.info(rowResult.getMessage() + ", id: {}", Arrays.toString(idArr));
  117. }
  118. // RowResult rowResult = deleteService.objectDelete(idArr, dto.getTable(), requireNonNull(pkName, "主键名称为空"));
  119. return AjaxResult.success(result);
  120. }
  121. /**
  122. * 功能描述: 通用删除接口 (真的删除)
  123. *
  124. * @param dto 前台传过来的dto
  125. * @return com.boman.common.core.web.domain.AjaxResult
  126. */
  127. public AjaxResult objectLogicDelete(BaseTableSaveDTO dto) {
  128. requireNonNull(dto.getTable());
  129. Long[] idArr = CollectionUtils.listToArray(dto.getIdList());
  130. requiredNonNull(idArr);
  131. // 拿到pkName
  132. GenTable genTable = getTableFromRedisByTableName(RedisKey.TABLE_INFO, dto.getTable());
  133. String pkName = IdUtils.getPkName(genTable.getColumns());
  134. JSONObject jsonObject = new JSONObject();
  135. jsonObject.put(dto.getLogicDelName(), dto.getLogicDelValue());
  136. RowResult rowResult = deleteService.objectLogicDelete(idArr, dto.getTable(), requireNonNull(pkName, "主键名称为空"), jsonObject);
  137. LOGGER.info(rowResult.getMessage() + ", id: {}", Arrays.toString(idArr));
  138. return AjaxResult.success(rowResult);
  139. }
  140. /**
  141. * 功能描述: 获取单表单数据
  142. *
  143. * @param dto condition
  144. * @return com.boman.common.core.web.domain.AjaxResult
  145. */
  146. public AjaxResult queryList(BaseTableSaveDTO dto) {
  147. requireNonNull(dto.getTable());
  148. // 拿到每个字段对应的查询类型,=、 like、 >、 <
  149. GenTable genTable = getTableFromRedisByTableName(RedisKey.TABLE_INFO, dto.getTable());
  150. JSONObject fixedData = dto.getFixedData();
  151. fixedData = ifNullSetEmpty(fixedData);
  152. // 查询条件
  153. JSONObject condition = ifNullSetEmpty(fixedData.getJSONObject(CONDITION));
  154. List<GenTableColumn> columns = genTable.getColumns();
  155. // 封装好以后的查询条件
  156. JSONObject packCondition = ifNullSetEmpty(packColCondition(columns, condition));
  157. // 需要返回到前台的列
  158. JSONArray showData = ifNullSetEmpty(fixedData.getJSONArray(SHOW_DATA));
  159. JSONObject rows = new JSONObject();
  160. int total = selectService.countByCondition(genTable.getTableName(), condition, packCondition);
  161. rows.put(FormDataConstant.PAGE_TOTAL, total);
  162. if (total <= 0) {
  163. rows.put(FormDataConstant.PAGE_ROWS, null);
  164. return AjaxResult.success(rows);
  165. }
  166. List<JSONObject> result = selectService.selectByCondition(genTable.getTableName(), condition, packCondition
  167. , showData, dto.getOrderBy(), dto.getLimit(), dto.getOffset());
  168. rows.put(FormDataConstant.PAGE_ROWS, result);
  169. return AjaxResult.success(rows);
  170. }
  171. /**
  172. * 功能描述: 获取单表单数据
  173. *
  174. * @param dto condition
  175. * @return com.boman.common.core.web.domain.AjaxResult
  176. */
  177. public AjaxResult getObject(BaseTableSaveDTO dto) {
  178. requireNonNull(dto.getTable());
  179. // 拿到每个字段对应的查询类型,=、 like、 >、 <
  180. // 拿到pkName
  181. GenTable genTable = getTableFromRedisByTableName(RedisKey.TABLE_INFO, dto.getTable());
  182. String pkName = IdUtils.getPkName(genTable.getColumns());
  183. JSONObject fixedData = dto.getFixedData();
  184. fixedData = ifNullSetEmpty(fixedData);
  185. Long id = fixedData.getLong(FormDataConstant.ID);
  186. requireNonNull(id);
  187. // 默认查所有字段,不支持自定义
  188. JSONObject jsonObject = selectService.selectById(genTable.getTableName(), pkName, id);
  189. return AjaxResult.success(jsonObject);
  190. }
  191. /**
  192. * 功能描述: 封装成查询条件 key: 列名, value:查询条件_查询类别
  193. * eg: [{"config_name":"系统配置_like"}, {"config_name":"_like"}]
  194. *
  195. * @param columns columns
  196. * @return com.alibaba.fastjson.JSONObject
  197. */
  198. private JSONObject packColCondition(List<GenTableColumn> columns, JSONObject condition) {
  199. requireNonNull(columns);
  200. JSONObject result = new JSONObject(columns.size());
  201. for (Map.Entry<String, Object> entry : condition.entrySet()) {
  202. String key = entry.getKey();
  203. Object value = entry.getValue();
  204. for (GenTableColumn column : columns) {
  205. // long string collection 暂时只作此三种类型判断
  206. if (column.getColumnName().equalsIgnoreCase(key) && ObjectUtils.isNotEmpty(value)) {
  207. // columnType 作为判断需不需要转义的一个标准,防止索引失效
  208. result.put(key, Lists.newArrayList(String.valueOf(value), column.getQueryType(), column.getColumnType()));
  209. break;
  210. }
  211. }
  212. }
  213. return result;
  214. }
  215. /**
  216. * 功能描述: 获取表单查询字段、按钮、表头
  217. * 注意: 都是从redis中拿的,如果数据库和redis不一致,则需刷新一下redis
  218. * 刷新的入口为 {@link MyController#loadTable(com.boman.gen.domain.GenTable)}
  219. * <p>
  220. * eg:{
  221. * "table": "sys_config",
  222. * }
  223. *
  224. * @param condition condition
  225. * @return com.boman.common.core.web.domain.AjaxResult
  226. */
  227. public AjaxResult getTableQuery(BaseTableSaveDTO condition) {
  228. GenTable genTable = getTableFromRedisByTableName(RedisKey.TABLE_INFO, condition.getTable());
  229. List<GenTableColumn> columns = genTable.getColumns();
  230. JSONObject jsonObject = new JSONObject();
  231. // 查询字段
  232. ArrayList<GenTableColumn> queryList = Lists.newArrayListWithCapacity(16);
  233. for (GenTableColumn column : columns) {
  234. if (GenTableColumn.IS_QUERY.equalsIgnoreCase(column.getIsQuery())) {
  235. String dictType = column.getDictType();
  236. if (ObjectUtils.isNotEmpty(dictType)) {
  237. List<SysDictData> sysDictData1 = dictTypeService.selectDictDataByType(dictType);
  238. column.setSysDictData(coverSysDictDataToJSONObject(sysDictData1));
  239. }
  240. queryList.add(column);
  241. }
  242. }
  243. jsonObject.put(FormDataConstant.QUERY_LIST, queryList);
  244. // genTable.getMenuRole() 暂时数据库没有数据,
  245. jsonObject.put(FormDataConstant.BUTTON_LIST, genTable.getMenuRole());
  246. // 表头
  247. List<GenTableColumn> tableHeadList = columns.stream()
  248. .filter(genTableColumn -> GenTableColumn.IS_LIST.equals(genTableColumn.getIsList()))
  249. .collect(Collectors.toList());
  250. jsonObject.put(FormDataConstant.TABLE_HEAD_LIST, tableHeadList);
  251. return AjaxResult.success(jsonObject);
  252. }
  253. /**
  254. * 功能描述: 获取表单子表
  255. *
  256. * @param condition condition
  257. * @return com.boman.common.core.web.domain.AjaxResult
  258. */
  259. public AjaxResult objectTab(BaseTableSaveDTO condition) {
  260. GenTable genTable = getTableFromRedisByTableName(RedisKey.RELATION, condition.getTable());
  261. List<GenTable> childTableList = genTable.getRelationList();
  262. // 此表没有关联子表,查啥查
  263. requireNonNull(childTableList);
  264. // todo
  265. for (GenTable childTable : childTableList) {
  266. String childTableName = childTable.getTableName();
  267. Long childTableTableId = childTable.getTableId();
  268. List<GenTableColumn> childColumns = childTable.getColumns();
  269. // column_name = 先根据tableName查到id,再用id到relation中查到relation_child_id, 在用这个值去到tableColumn中查到column_name
  270. // select * from childTableName where column_name = objId
  271. }
  272. return AjaxResult.success();
  273. }
  274. public String getChildColumnNameByParentTableName(GenTable parentGenTable, Long childTableTableId){
  275. requireNonNull(parentGenTable.getTableName(), "主表名称为空");
  276. // GenTable primaryTable = redisService.getCacheObject(RedisKey.TABLE_INFO + genTable.getTableName());
  277. Long parentTableId = parentGenTable.getTableId();
  278. List<GenTableRelation> relations = redisService.getCacheObject(RedisKey.RELATION_INFO);
  279. relations = relations.stream()
  280. .filter(relation -> relation.getRelationParentId().equals(parentTableId))
  281. .collect(Collectors.toList());
  282. for (GenTableRelation relation : relations) {
  283. if (relation.getRelationChildId().equals(6L)) {
  284. tableColumnService.selectGenTableColumnListByTableId(childTableTableId);
  285. // return
  286. }
  287. }
  288. return "";
  289. }
  290. /**
  291. * 功能描述: 表单提交接口
  292. *
  293. * @param condition condition
  294. * @param isSubmit 提交true, 反提交false
  295. * @return com.boman.common.core.web.domain.AjaxResult
  296. */
  297. public AjaxResult objectSubmit(BaseTableSaveDTO condition, boolean isSubmit) {
  298. GenTable genTable = getTableFromRedisByTableName(RedisKey.TABLE_INFO, condition.getTable());
  299. List<JSONObject> commitData = condition.getCommitData();
  300. requireNonNull(commitData, "啥都不提交, 调什么接口??");
  301. String tableName = requireNonNull(genTable.getTableName());
  302. String pkName = IdUtils.getPkName(genTable.getColumns());
  303. // 先去查出之前的状态
  304. List<Long> idList = commitData.stream().map(jsonObject -> jsonObject.getLong(FormDataConstant.ID))
  305. .collect(Collectors.toList());
  306. JSONArray showData = new JSONArray();
  307. showData.add(FormDataConstant.STATUS);
  308. showData.add(pkName);
  309. List<JSONObject> beforeList = selectService.selectByIdList(tableName, pkName, idList, showData);
  310. requireNonNull(beforeList);
  311. for (JSONObject commitDatum : commitData) {
  312. String dbStatus = getStatusFromFormData(commitDatum, beforeList);
  313. // 只能是未提交的状态下,才能调用提交
  314. if (isSubmit) {
  315. // 只能是未提交的状态下,才能调用提交, 下面是不允许
  316. if (!SubmitConstant.NOT_SUBMIT.equals(dbStatus)) {
  317. commitDatum.put(SubmitConstant.SUBMIT_RESULT, SubmitConstant.NOT_ALLOWED);
  318. } else {
  319. commitDatum.put(SubmitConstant.SUBMIT_USERID, 123);
  320. commitDatum.put(SubmitConstant.SUBMIT_TIME, new Timestamp(System.currentTimeMillis()));
  321. int effective = submitService.handlerSubmit(tableName, pkName, commitDatum, commitDatum.getLong(FormDataConstant.ID));
  322. if (effective > 0) {
  323. commitDatum.put(SubmitConstant.SUBMIT_RESULT, SubmitConstant.SUCCESS);
  324. } else {
  325. commitDatum.put(SubmitConstant.SUBMIT_RESULT, SubmitConstant.FAIL);
  326. }
  327. }
  328. } else {
  329. // 只有在已提交的情况下才能反提交, 下面是不允许
  330. if (!SubmitConstant.SUBMITTED.equals(dbStatus)) {
  331. commitDatum.put(SubmitConstant.SUBMIT_RESULT, SubmitConstant.NOT_ALLOWED);
  332. } else {
  333. commitDatum.put(SubmitConstant.SUBMIT_USERID, 123);
  334. commitDatum.put(SubmitConstant.SUBMIT_TIME, new Timestamp(System.currentTimeMillis()));
  335. int effective = submitService.handlerSubmit(tableName, pkName, commitDatum, commitDatum.getLong(FormDataConstant.ID));
  336. if (effective > 0) {
  337. commitDatum.put(SubmitConstant.SUBMIT_RESULT, SubmitConstant.SUCCESS);
  338. } else {
  339. commitDatum.put(SubmitConstant.SUBMIT_RESULT, SubmitConstant.FAIL);
  340. }
  341. }
  342. }
  343. }
  344. return AjaxResult.success(commitData);
  345. }
  346. private String getStatusFromFormData(JSONObject next, List<JSONObject> commitData) {
  347. for (JSONObject jsonObject : commitData) {
  348. if (jsonObject.getLong(FormDataConstant.ID).equals(next.getLong(FormDataConstant.ID))) {
  349. return jsonObject.getString(FormDataConstant.STATUS);
  350. }
  351. }
  352. throw new IllegalArgumentException("不可能没有一个合适的");
  353. }
  354. /**
  355. * 是否定制
  356. * 判断是否需要转发到定制接口
  357. * @param tableName 表明
  358. * @param result 结果
  359. * @param action 动作
  360. * @return 结果
  361. */
  362. public List<JSONObject> isCustomized(String tableName, List<JSONObject> result, String action) {
  363. requireNonNull(tableName);
  364. requireNonNull(action);
  365. if (result != null && result.size() > 0){
  366. //获取到服务名称
  367. String triggerName = getTriggerName(tableName, action);
  368. requireNonNull(triggerName);
  369. //组织请求 acos + RestTemplate
  370. return restTemplate.postForObject("http://" + triggerName, result, List.class);
  371. }
  372. return result;
  373. }
  374. /**
  375. * 判断是什么action
  376. * @param tableName 表明
  377. * @param action 动作
  378. * @return
  379. */
  380. private String getTriggerName(String tableName, String action){
  381. GenTable genTable = getTableFromRedisByTableName(RedisKey.TABLE_INFO, tableName);
  382. requireNonNull(genTable);
  383. if (action.equals(TriggerActionConstant.ACTION_CREATE)){
  384. return genTable.getTriggerCreate();
  385. }else if (action.equals(TriggerActionConstant.ACTION_RETRIEVE)){
  386. return genTable.getTriggerRetrieve();
  387. }else if (action.equals(TriggerActionConstant.ACTION_UPDATE)){
  388. return genTable.getTriggerUpdate();
  389. }else if (action.equals(TriggerActionConstant.ACTION_DELETE)){
  390. return genTable.getTriggerDelete();
  391. }else if (action.equals(TriggerActionConstant.ACTION_SUBMIT)){
  392. return genTable.getTriggerSubmit();
  393. }
  394. return null;
  395. }
  396. // todo redis中未找到,要去查数据库,然后再塞进去
  397. private GenTable getTableFromRedisByTableName(String redisKeyPrefix, String tableName) {
  398. GenTable genTable = redisService.getCacheObject(redisKeyPrefix + requireNonNull(tableName));
  399. return requireNonNull(genTable, "未找到表对应的信息");
  400. }
  401. /**
  402. * 功能描述: 反提交接口, 更改的字段类型和字段值都是一致的
  403. * {
  404. * "table": "sys_config",
  405. * }
  406. *
  407. *
  408. * @param condition condition
  409. * @return com.boman.common.core.web.domain.AjaxResult
  410. */
  411. public AjaxResult getByTableName(BaseTableSaveDTO condition) {
  412. // requiredNonNull(condition.getTable(), "表名为空");
  413. GenTable genTable = getTableFromRedisByTableName(RedisKey.TABLE_INFO, condition.getTable());
  414. List<GenTableColumn> columns = genTable.getColumns();
  415. for (GenTableColumn column : columns) {
  416. String dictType = column.getDictType();
  417. if (ObjectUtils.isNotEmpty(dictType)) {
  418. List<SysDictData> sysDictData1 = dictTypeService.selectDictDataByType(dictType);
  419. column.setSysDictData(coverSysDictDataToJSONObject(sysDictData1));
  420. }
  421. }
  422. return AjaxResult.success(genTable);
  423. }
  424. public List<JSONObject> coverSysDictDataToJSONObject(List<SysDictData> sysDictData) {
  425. List<JSONObject> result = Lists.newArrayListWithCapacity(sysDictData.size());
  426. for (SysDictData data : sysDictData) {
  427. JSONObject jsonObject = new JSONObject();
  428. String dictLabel = data.getDictLabel();
  429. String dictValue = data.getDictValue();
  430. jsonObject.put(DictConstant.DICT_LABEL, dictLabel);
  431. jsonObject.put(DictConstant.DICT_VALUE, dictValue);
  432. result.add(jsonObject);
  433. }
  434. return result;
  435. }
  436. }