FormCheckUtils.java 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445
  1. package jnpf.base.util;
  2. import cn.hutool.core.util.ObjectUtil;
  3. import jnpf.base.entity.VisualdevEntity;
  4. import jnpf.base.mapper.FlowFormDataMapper;
  5. import jnpf.base.model.CheckFormModel;
  6. import jnpf.base.model.ColumnDataModel;
  7. import jnpf.base.model.OnlineImport.ImportDataModel;
  8. import jnpf.base.model.OnlineImport.ImportFormCheckUniqueModel;
  9. import jnpf.base.model.VisualConst;
  10. import jnpf.base.model.form.FormCheckModel;
  11. import jnpf.constant.JnpfConst;
  12. import jnpf.constant.MsgCode;
  13. import jnpf.database.model.entity.DbLinkEntity;
  14. import jnpf.database.util.ConnUtil;
  15. import jnpf.database.util.DynamicDataSourceUtil;
  16. import jnpf.exception.DataException;
  17. import jnpf.i18n.util.I18nUtil;
  18. import jnpf.model.visualJson.FieLdsModel;
  19. import jnpf.model.visualJson.FormDataModel;
  20. import jnpf.model.visualJson.TableFields;
  21. import jnpf.model.visualJson.TableModel;
  22. import jnpf.model.visualJson.config.ConfigModel;
  23. import jnpf.onlinedev.model.VisualErrInfo;
  24. import jnpf.util.FlowFormConstant;
  25. import jnpf.util.JsonUtil;
  26. import jnpf.util.StringUtil;
  27. import jnpf.util.TableFeildsEnum;
  28. import jnpf.util.visiual.JnpfKeyConsts;
  29. import lombok.Cleanup;
  30. import org.apache.commons.collections4.CollectionUtils;
  31. import org.apache.commons.collections4.MapUtils;
  32. import org.apache.commons.lang3.StringUtils;
  33. import org.mybatis.dynamic.sql.AndOrCriteriaGroup;
  34. import org.mybatis.dynamic.sql.BasicColumn;
  35. import org.mybatis.dynamic.sql.SqlBuilder;
  36. import org.mybatis.dynamic.sql.SqlTable;
  37. import org.mybatis.dynamic.sql.render.RenderingStrategies;
  38. import org.mybatis.dynamic.sql.select.QueryExpressionDSL;
  39. import org.mybatis.dynamic.sql.select.SelectModel;
  40. import org.mybatis.dynamic.sql.select.join.EqualTo;
  41. import org.mybatis.dynamic.sql.select.render.SelectStatementProvider;
  42. import org.springframework.beans.factory.annotation.Autowired;
  43. import org.springframework.stereotype.Component;
  44. import java.sql.Connection;
  45. import java.sql.SQLException;
  46. import java.text.SimpleDateFormat;
  47. import java.util.*;
  48. import java.util.stream.Collectors;
  49. /**
  50. * 验证表单数据
  51. *
  52. * @author JNPF开发平台组
  53. * @version V3.4.2
  54. * @copyright 引迈信息技术有限公司(https://www.jnpfsoft.com)
  55. * @date 2022/5/25
  56. */
  57. @Component
  58. public class FormCheckUtils {
  59. public static final List<String> LINK_ALLOW_KEY = Arrays.asList("alert", "card", "collapse", "collapseItem", "colorPicker", "datePicker", "divider", "editor",
  60. "groupTitle", "iframe", "input", "inputNumber", "link", "location", "rate", "row", "slider", "stepItem", "steps", "switch", "tab", "tabItem", "table", "tableGrid",
  61. "tableGridTd", "tableGridTr", "text", "textarea", "timePicker");
  62. @Autowired
  63. private FlowFormDataUtil flowDataUtil;
  64. @Autowired
  65. private FlowFormDataMapper flowFormDataMapper;
  66. public String checkForm(CheckFormModel checkFormModel) {
  67. List<FieLdsModel> formFieldList = checkFormModel.getFormFieldList();
  68. Map<String, Object> dataMap = checkFormModel.getDataMap();
  69. DbLinkEntity linkEntity = checkFormModel.getLinkEntity();
  70. List<TableModel> tableModelList = checkFormModel.getTableModelList();
  71. VisualdevEntity visualdevEntity = checkFormModel.getVisualdevEntity();
  72. String id = checkFormModel.getId();
  73. Boolean isTransfer = checkFormModel.getIsTransfer();
  74. FormDataModel formData = JsonUtil.getJsonToBean(visualdevEntity.getFormData(), FormDataModel.class);
  75. ColumnDataModel columnDataModel = JsonUtil.getJsonToBean(visualdevEntity.getColumnData(), ColumnDataModel.class);
  76. boolean inlineEdit = columnDataModel != null && columnDataModel.getType() != null && columnDataModel.getType() == 4;
  77. boolean logicalDelete = formData.getLogicalDelete();
  78. List<FieLdsModel> fields = new ArrayList<>();
  79. FormPublicUtils.recursionFieldsExceptChild(fields, formFieldList);
  80. try {
  81. //切换数据源
  82. DynamicDataSourceUtil.switchToDataSource(linkEntity);
  83. @Cleanup Connection conn = ConnUtil.getConnOrDefault(linkEntity);
  84. String dbType = conn.getMetaData().getDatabaseProductName().trim();
  85. //业务主键判断
  86. VisualErrInfo visualErrInfo = this.checkBusinessKey(fields, dataMap, tableModelList, formData, id);
  87. if (ObjectUtil.isNotEmpty(visualErrInfo) && StringUtil.isNotEmpty(visualErrInfo.getErrMsg())) {
  88. return visualErrInfo.getErrMsg();
  89. }
  90. //唯一和非空判断
  91. List<FormCheckModel> formCheckModels = new ArrayList<>();
  92. for (FieLdsModel fieLdsModel : fields) {
  93. ConfigModel config = fieLdsModel.getConfig();
  94. if(checkFormModel.getIsLink() && !LINK_ALLOW_KEY.contains( config.getJnpfKey())){
  95. continue;
  96. }
  97. Object o = dataMap.get(fieLdsModel.getVModel());
  98. if (config.isRequired() && !inlineEdit && !isTransfer) {
  99. if (ObjectUtil.isEmpty(o) || StringUtil.isEmpty(o.toString().trim())) {
  100. return I18nUtil.getMessageStr(config.getLabelI18nCode(), config.getLabel()) + MsgCode.VS015.get();
  101. }
  102. }
  103. if (JnpfKeyConsts.COM_INPUT.equals(config.getJnpfKey()) && config.getUnique()) {
  104. o = ObjectUtil.isEmpty(o) ? null : String.valueOf(o).trim();
  105. dataMap.put(fieLdsModel.getVModel(), o);
  106. String tableName = fieLdsModel.getConfig().getTableName();
  107. //验证唯一
  108. SqlTable sqlTable = SqlTable.of(tableName);
  109. String key = flowDataUtil.getTableKey(conn, tableName);
  110. String vModelThis = fieLdsModel.getVModel();
  111. String foriegKey = "";
  112. String columnName = "";
  113. boolean isMain = true;
  114. TableModel mainTableModel = new TableModel();
  115. TableModel tableModel = new TableModel();
  116. for (TableModel item : tableModelList) {
  117. if (Objects.equals(item.getTypeId(), "1")) {
  118. mainTableModel = item;
  119. }
  120. if (StringUtil.isNotEmpty(fieLdsModel.getConfig().getRelationTable())) {
  121. //子表判断
  122. if (fieLdsModel.getConfig().getRelationTable().equals(item.getTable())) {
  123. tableModel = item;
  124. }
  125. } else {
  126. //主副表判断
  127. if (fieLdsModel.getConfig().getTableName().equals(item.getTable())) {
  128. tableModel = item;
  129. }
  130. }
  131. }
  132. if (tableModel != null) {
  133. String fieldName = vModelThis;
  134. if (!"1".equals(tableModel.getTypeId()) && vModelThis.contains(JnpfConst.SIDE_MARK)){
  135. fieldName = vModelThis.split(JnpfConst.SIDE_MARK)[1];
  136. isMain = false;
  137. foriegKey = tableModel.getTableField();
  138. }
  139. String finalFieldName = fieldName;
  140. TableFields tableFields = tableModel.getFields().stream().filter(t -> t.getField().equals(finalFieldName)).findFirst().orElse(null);
  141. if (tableFields != null) {
  142. columnName = StringUtil.isNotEmpty(tableFields.getField()) ? tableFields.getField() : fieldName;
  143. }
  144. }
  145. List<BasicColumn> selectKey = new ArrayList<>();
  146. selectKey.add(sqlTable.column(columnName));
  147. selectKey.add(sqlTable.column(key));
  148. if (StringUtil.isNotEmpty(foriegKey)) {
  149. String finalForiegKey = foriegKey;
  150. TableFields tableFields = tableModel.getFields().stream().filter(t -> t.getField().equals(finalForiegKey)).findFirst().orElse(null);
  151. if (tableFields != null) {
  152. foriegKey = StringUtil.isNotEmpty(tableFields.getField()) ? tableFields.getField() : finalForiegKey;
  153. }
  154. selectKey.add(sqlTable.column(foriegKey));
  155. }
  156. SqlTable sqlMainTable = SqlTable.of(mainTableModel.getTable());
  157. String taskIdField = TableFeildsEnum.FLOWTASKID.getField();
  158. if (dbType.contains("Oracle") || dbType.contains("DM DBMS")) {
  159. taskIdField = TableFeildsEnum.FLOWTASKID.getField().toUpperCase();
  160. }
  161. if (dataMap.get(FlowFormConstant.FLOWID) != null && StringUtil.isNotEmpty(dataMap.get(FlowFormConstant.FLOWID).toString())) {
  162. selectKey.add(sqlMainTable.column(taskIdField));
  163. }
  164. QueryExpressionDSL<SelectModel>.QueryExpressionWhereBuilder where;
  165. //是否主表
  166. if (isMain) {
  167. where = SqlBuilder
  168. .select(selectKey)
  169. .from(sqlTable)
  170. .where();
  171. } else {
  172. where = SqlBuilder
  173. .select(selectKey)
  174. .from(sqlMainTable)
  175. .leftJoin(sqlTable)
  176. .on(sqlTable.column(tableModel.getTableField()), new EqualTo(sqlMainTable.column(tableModel.getRelationField())))
  177. .where();
  178. }
  179. if (ObjectUtil.isEmpty(o)) {
  180. where.and(sqlTable.column(columnName), SqlBuilder.isNull());
  181. } else {
  182. where.and(sqlTable.column(columnName), SqlBuilder.isEqualTo(o.toString()));
  183. }
  184. if (StringUtils.isNotEmpty(id)) {
  185. TableFields mainKeyModel = mainTableModel.getFields().stream().filter(t ->
  186. Objects.equals(t.getPrimaryKey(), 1) && !t.getField().equalsIgnoreCase(TableFeildsEnum.TENANTID.getField())).findFirst().orElse(null);
  187. Object realId = id;
  188. if (VisualConst.DB_INT_ALL.contains(mainKeyModel.getDataType().toLowerCase())) {
  189. realId = Long.parseLong(id);
  190. }
  191. where.and(sqlTable.column(mainKeyModel.getField()), SqlBuilder.isNotEqualTo(realId));
  192. }
  193. if (logicalDelete) {
  194. where.and(sqlMainTable.column(TableFeildsEnum.DELETEMARK.getField()), SqlBuilder.isNull());
  195. }
  196. //是流程
  197. if (dataMap.get(FlowFormConstant.FLOWID) != null && StringUtil.isNotEmpty(dataMap.get(FlowFormConstant.FLOWID).toString())) {
  198. where.and(sqlMainTable.column(TableFeildsEnum.FLOWID.getField()), SqlBuilder.isEqualTo(dataMap.get(FlowFormConstant.FLOWID)));
  199. } else {
  200. where.and(sqlMainTable.column(TableFeildsEnum.FLOWID.getField()), SqlBuilder.isNull());
  201. }
  202. SelectStatementProvider render = where.build().render(RenderingStrategies.MYBATIS3);
  203. FormCheckModel formCheckModel = new FormCheckModel();
  204. formCheckModel.setLabel(I18nUtil.getMessageStr(fieLdsModel.getConfig().getLabelI18nCode(), fieLdsModel.getConfig().getLabel()));
  205. formCheckModel.setStatementProvider(render);
  206. formCheckModels.add(formCheckModel);
  207. }
  208. }
  209. //主副表数据库判重
  210. for (FormCheckModel formCheckModel : formCheckModels) {
  211. int count = flowFormDataMapper.selectManyMappedRows(formCheckModel.getStatementProvider()).size();
  212. if (count > 0) {
  213. return formCheckModel.getLabel() + MsgCode.EXIST103.get();
  214. }
  215. }
  216. //子表当前表单数据判重
  217. List<FieLdsModel> childFieldList = fields.stream().filter(f -> JnpfKeyConsts.CHILD_TABLE.equals(f.getConfig().getJnpfKey())).collect(Collectors.toList());
  218. for (FieLdsModel fieLdsModel : childFieldList) {
  219. List<Map<String, Object>> childMapList = (List) dataMap.get(fieLdsModel.getVModel());
  220. if (ObjectUtil.isEmpty(childMapList)) continue;
  221. String tableName = I18nUtil.getMessageStr(fieLdsModel.getConfig().getLabelI18nCode(), fieLdsModel.getConfig().getLabel());
  222. for (FieLdsModel childField : fieLdsModel.getConfig().getChildren()) {
  223. ConfigModel config = childField.getConfig();
  224. if(checkFormModel.getIsLink() && !LINK_ALLOW_KEY.contains( config.getJnpfKey())){
  225. continue;
  226. }
  227. //判断为空
  228. if (config.isRequired() && !inlineEdit && !isTransfer) {
  229. for (Map<String, Object> item : childMapList) {
  230. Object o = item.get(childField.getVModel());
  231. if (ObjectUtil.isEmpty(o) || StringUtil.isEmpty(o.toString().trim())) {
  232. return tableName + "-" + I18nUtil.getMessageStr(config.getLabelI18nCode(), config.getLabel()) + MsgCode.VS015.get();
  233. }
  234. }
  235. }
  236. //判断唯一
  237. if (JnpfKeyConsts.COM_INPUT.equals(config.getJnpfKey()) && config.getUnique()) {
  238. List<String> childValues = childMapList.stream().filter(ChildTbMap -> ChildTbMap.get(childField.getVModel()) != null)
  239. .map(ChildTbMap -> String.valueOf(ChildTbMap.get(childField.getVModel())).trim()).collect(Collectors.toList());
  240. if (childValues.size() > 0) {
  241. HashSet<String> child = new HashSet<>(childValues);
  242. if (child.size() != childValues.size()) {
  243. return tableName + "-" + I18nUtil.getMessageStr(config.getLabelI18nCode(), config.getLabel()) + MsgCode.EXIST103.get();
  244. }
  245. }
  246. }
  247. }
  248. }
  249. if (conn != null) {
  250. conn.close();
  251. }
  252. } catch (Exception e) {
  253. e.printStackTrace();
  254. } finally {
  255. DynamicDataSourceUtil.clearSwitchDataSource();
  256. }
  257. return "";
  258. }
  259. public String getCount(Object id, SqlTable sqlTable, TableModel tableModel, DbLinkEntity linkEntity) {
  260. try {
  261. DynamicDataSourceUtil.switchToDataSource(linkEntity);
  262. @Cleanup Connection conn = ConnUtil.getConnOrDefault(linkEntity);
  263. String dbType = conn.getMetaData().getDatabaseProductName().trim();
  264. String key = flowDataUtil.getKey(tableModel, dbType);
  265. String flowTaskId = flowDataUtil.getFlowTaskId(tableModel, dbType);
  266. List<AndOrCriteriaGroup> groupList = new ArrayList<>();
  267. groupList.add(SqlBuilder.or(sqlTable.column(flowTaskId), SqlBuilder.isEqualTo(id.toString())));
  268. SelectStatementProvider countRender = SqlBuilder
  269. .select(sqlTable.column(key))
  270. .from(sqlTable)
  271. .where(sqlTable.column(key), SqlBuilder.isEqualTo(id), groupList)
  272. .build().render(RenderingStrategies.MYBATIS3);
  273. Map<String, Object> map = flowFormDataMapper.selectOneMappedRow(countRender);
  274. if (MapUtils.isNotEmpty(map)) {
  275. if (Objects.nonNull(map.get(key))) {
  276. return map.get(key).toString();
  277. }
  278. }
  279. } catch (DataException e) {
  280. e.printStackTrace();
  281. } catch (SQLException sqlException) {
  282. sqlException.printStackTrace();
  283. } finally {
  284. DynamicDataSourceUtil.clearSwitchDataSource();
  285. }
  286. return null;
  287. }
  288. /**
  289. * 业务主键 判断
  290. *
  291. * @param fields
  292. * @param data
  293. * @param tableList
  294. * @param formData
  295. * @param id
  296. * @return
  297. */
  298. public VisualErrInfo checkBusinessKey(List<FieLdsModel> fields, Map<String, Object> data, List<TableModel> tableList, FormDataModel formData, String id) {
  299. Boolean logicalDelete = formData.getLogicalDelete();
  300. if (formData.isUseBusinessKey()) {
  301. List<String> businessKeyList = Arrays.asList(formData.getBusinessKeyList());
  302. if (CollectionUtils.isEmpty(businessKeyList)) return null;
  303. TableModel mainTable = tableList.stream().filter(t -> t.getTypeId().equals("1")).findFirst().orElse(null);
  304. TableFields mainFields = mainTable.getFields().stream().filter(t -> Objects.equals(t.getPrimaryKey(), 1)
  305. && !t.getField().equalsIgnoreCase(TableFeildsEnum.TENANTID.getField())).findFirst().orElse(null);
  306. SqlTable sqlTable = SqlTable.of(mainTable.getTable());
  307. String mainKey = mainFields.getField();
  308. String taskIdField = TableFeildsEnum.FLOWTASKID.getField();
  309. TableFields taskIdFielde = mainTable.getFields().stream().filter(t -> TableFeildsEnum.FLOWTASKID.getField().equalsIgnoreCase(t.getField())).findFirst().orElse(null);
  310. if (ObjectUtil.isNotEmpty(taskIdFielde)) {
  311. taskIdField = taskIdFielde.getField();
  312. }
  313. List<BasicColumn> selectKey = new ArrayList<>();
  314. selectKey.add(sqlTable.column(mainKey));
  315. if (data.get(FlowFormConstant.FLOWID) != null && StringUtil.isNotEmpty(data.get(FlowFormConstant.FLOWID).toString())) {
  316. selectKey.add(sqlTable.column(taskIdField));
  317. }
  318. QueryExpressionDSL<SelectModel>.QueryExpressionWhereBuilder where = SqlBuilder.select(selectKey).from(sqlTable).where();
  319. for (FieLdsModel fieLdsModel : fields) {
  320. String fieldName = fieLdsModel.getVModel();
  321. Object o = data.get(fieldName);
  322. if (businessKeyList.contains(fieldName)) {
  323. if (ObjectUtil.isEmpty(o)) {
  324. where.and(sqlTable.column(fieldName), SqlBuilder.isNull());
  325. } else {
  326. o = o instanceof List ? JsonUtil.getObjectToString(o) : o;
  327. if (JnpfKeyConsts.DateSelect.contains(fieLdsModel.getConfig().getJnpfKey())) {
  328. try {
  329. o = new Date((Long) o);
  330. } catch (Exception e) {
  331. try {
  332. String format = fieLdsModel.getFormat();
  333. SimpleDateFormat sdf = new SimpleDateFormat(format);
  334. o = sdf.parse(String.valueOf(o));
  335. } catch (Exception ex) {
  336. }
  337. }
  338. }
  339. where.and(sqlTable.column(fieldName), SqlBuilder.isEqualTo(o));
  340. }
  341. }
  342. }
  343. //更新跳过本条数据
  344. if (StringUtils.isNotEmpty(id)) {
  345. Object realId = id;
  346. if (VisualConst.DB_INT_ALL.contains(mainFields.getDataType().toLowerCase())) {
  347. realId = Long.parseLong(id);
  348. }
  349. where.and(sqlTable.column(mainKey), SqlBuilder.isNotEqualTo(realId));
  350. }
  351. //流程数据过滤
  352. if (data.get(FlowFormConstant.FLOWID) != null && StringUtil.isNotEmpty(data.get(FlowFormConstant.FLOWID).toString())) {
  353. where.and(sqlTable.column(TableFeildsEnum.FLOWID.getField()), SqlBuilder.isEqualTo(data.get(FlowFormConstant.FLOWID)));
  354. } else {
  355. where.and(sqlTable.column(TableFeildsEnum.FLOWID.getField()), SqlBuilder.isNull());
  356. }
  357. //逻辑删除
  358. if (logicalDelete) {
  359. where.and(sqlTable.column(TableFeildsEnum.DELETEMARK.getField()), SqlBuilder.isNull());
  360. }
  361. SelectStatementProvider render = where.build().render(RenderingStrategies.MYBATIS3);
  362. List<Map<String, Object>> maps;
  363. try {
  364. maps = flowFormDataMapper.selectManyMappedRows(render);
  365. } catch (Exception e) {
  366. return null;
  367. }
  368. int count = maps.size();
  369. if (count > 0) {
  370. VisualErrInfo visualErrInfo = VisualErrInfo.builder().errMsg(formData.getBusinessKeyTip()).build();
  371. if (ObjectUtil.isNotEmpty(maps.get(0).get(mainKey))) {
  372. visualErrInfo.setId(maps.get(0).get(mainKey).toString());
  373. }
  374. if (ObjectUtil.isNotEmpty(maps.get(0).get(taskIdField))) {
  375. visualErrInfo.setFlowTaskId(maps.get(0).get(taskIdField).toString());
  376. }
  377. return visualErrInfo;
  378. }
  379. }
  380. return null;
  381. }
  382. /**
  383. * 判断excel表内业务主键是否重复
  384. *
  385. * @param formData
  386. * @param resultMap
  387. * @param uniqueModel
  388. * @return
  389. */
  390. public String checkBusinessKeyExcel(FormDataModel formData, Map<String, Object> resultMap, ImportFormCheckUniqueModel uniqueModel) {
  391. List<String> businessKeyList = Arrays.asList(formData.getBusinessKeyList());
  392. List<Map<String, Object>> successList = uniqueModel.getImportDataModel().stream().map(ImportDataModel::getResultData).collect(Collectors.toList());
  393. if (com.baomidou.mybatisplus.core.toolkit.CollectionUtils.isNotEmpty(successList)) {
  394. boolean exists = false;
  395. for (int uniqueIndex = 0; uniqueIndex < successList.size(); uniqueIndex++) {
  396. Map<String, Object> indexMap = successList.get(uniqueIndex);
  397. boolean hasB = false;
  398. for (String fieldsKey : businessKeyList) {
  399. if ((resultMap.get(fieldsKey) == null && indexMap.get(fieldsKey) == null)
  400. || (resultMap.get(fieldsKey) != null && resultMap.get(fieldsKey).equals(indexMap.get(fieldsKey)))) {
  401. hasB = true;
  402. } else {
  403. //有一个没匹配上就跳出循环
  404. hasB = false;
  405. break;
  406. }
  407. }
  408. if (hasB) {
  409. exists = true;
  410. if (uniqueModel.isUpdate()) {
  411. uniqueModel.getImportDataModel().get(uniqueIndex).setResultData(resultMap);
  412. }
  413. break;
  414. }
  415. }
  416. if (exists) {
  417. return formData.getBusinessKeyTip();
  418. }
  419. }
  420. return null;
  421. }
  422. }