04e82cae53e0182a1b850f7c3f89ac9a486dcc2d.svn-base 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408
  1. package org.jeecg.modules.demo.mock.vxe.controller;
  2. import com.alibaba.fastjson.JSON;
  3. import com.alibaba.fastjson.JSONArray;
  4. import com.alibaba.fastjson.JSONObject;
  5. import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
  6. import com.baomidou.mybatisplus.core.metadata.IPage;
  7. import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
  8. import lombok.extern.slf4j.Slf4j;
  9. import org.apache.commons.io.IOUtils;
  10. import org.apache.commons.lang3.StringUtils;
  11. import org.jeecg.common.api.vo.Result;
  12. import org.jeecg.common.constant.VXESocketConst;
  13. import org.jeecg.common.system.query.MatchTypeEnum;
  14. import org.jeecg.common.system.query.QueryCondition;
  15. import org.jeecg.common.system.query.QueryGenerator;
  16. import org.jeecg.modules.demo.mock.vxe.entity.MockEntity;
  17. import org.jeecg.modules.demo.mock.vxe.websocket.VXESocket;
  18. import org.springframework.web.bind.annotation.*;
  19. import javax.servlet.http.HttpServletRequest;
  20. import java.io.IOException;
  21. import java.io.InputStream;
  22. import java.net.URLDecoder;
  23. import java.util.*;
  24. @RestController
  25. @RequestMapping("/mock/vxe")
  26. @Slf4j
  27. public class VxeMockController {
  28. /**
  29. * 模拟更改状态
  30. *
  31. * @param id
  32. * @param status
  33. * @return
  34. */
  35. @GetMapping("/change1")
  36. public Result mockChange1(@RequestParam("id") String id, @RequestParam("status") String status) {
  37. /* id 为 行的id(rowId),只要获取到rowId,那么只需要调用 VXESocket.sendMessageToAll() 即可 */
  38. // 封装行数据
  39. JSONObject rowData = new JSONObject();
  40. // 这个字段就是要更改的行数据ID
  41. rowData.put("id", id);
  42. // 这个字段就是要更改的列的key和具体的值
  43. rowData.put("status", status);
  44. // 模拟更改数据
  45. this.mockChange(rowData);
  46. return Result.ok();
  47. }
  48. /**
  49. * 模拟更改拖轮状态
  50. *
  51. * @param id
  52. * @param tug_status
  53. * @return
  54. */
  55. @GetMapping("/change2")
  56. public Result mockChange2(@RequestParam("id") String id, @RequestParam("tug_status") String tug_status) {
  57. /* id 为 行的id(rowId),只要获取到rowId,那么只需要调用 VXESocket.sendMessageToAll() 即可 */
  58. // 封装行数据
  59. JSONObject rowData = new JSONObject();
  60. // 这个字段就是要更改的行数据ID
  61. rowData.put("id", id);
  62. // 这个字段就是要更改的列的key和具体的值
  63. JSONObject tugStatus = JSON.parseObject(tug_status);
  64. rowData.put("tug_status", tugStatus);
  65. // 模拟更改数据
  66. this.mockChange(rowData);
  67. return Result.ok();
  68. }
  69. /**
  70. * 模拟更改进度条状态
  71. *
  72. * @param id
  73. * @param progress
  74. * @return
  75. */
  76. @GetMapping("/change3")
  77. public Result mockChange3(@RequestParam("id") String id, @RequestParam("progress") String progress) {
  78. /* id 为 行的id(rowId),只要获取到rowId,那么只需要调用 VXESocket.sendMessageToAll() 即可 */
  79. // 封装行数据
  80. JSONObject rowData = new JSONObject();
  81. // 这个字段就是要更改的行数据ID
  82. rowData.put("id", id);
  83. // 这个字段就是要更改的列的key和具体的值
  84. rowData.put("progress", progress);
  85. // 模拟更改数据
  86. this.mockChange(rowData);
  87. return Result.ok();
  88. }
  89. private void mockChange(JSONObject rowData) {
  90. // 封装socket数据
  91. JSONObject socketData = new JSONObject();
  92. // 这里的 socketKey 必须要和调度计划页面上写的 socketKey 属性保持一致
  93. socketData.put("socketKey", "page-dispatch");
  94. // 这里的 args 必须得是一个数组,下标0是行数据,下标1是caseId,一般不用传
  95. socketData.put("args", new Object[]{rowData, ""});
  96. // 封装消息字符串,这里的
  97. // type 必须是 VXESocketConst.TYPE_UVT
  98. String message = VXESocket.packageMessage(VXESocketConst.TYPE_UVT, socketData);
  99. // 调用 sendMessageToAll 发送给所有在线的用户
  100. VXESocket.sendMessageToAll(message);
  101. }
  102. /**
  103. * 模拟更改【大船待审】状态
  104. *
  105. * @param status
  106. * @return
  107. */
  108. @GetMapping("/change4")
  109. public Result mockChange4(@RequestParam("status") String status) {
  110. // 封装socket数据
  111. JSONObject socketData = new JSONObject();
  112. // 这里的 key 是前端注册时使用的key,必须保持一致
  113. socketData.put("key", "dispatch-dcds-status");
  114. // 这里的 args 必须得是一个数组,每一位都是注册方法的参数,按顺序传递
  115. socketData.put("args", new Object[]{status});
  116. // 封装消息字符串,这里的 type 必须是 VXESocketConst.TYPE_UVT
  117. String message = VXESocket.packageMessage(VXESocketConst.TYPE_CSD, socketData);
  118. // 调用 sendMessageToAll 发送给所有在线的用户
  119. VXESocket.sendMessageToAll(message);
  120. return Result.ok();
  121. }
  122. /**
  123. * 【模拟】即时保存单行数据
  124. *
  125. * @param rowData 行数据,实际使用时可以替换成一个实体类
  126. */
  127. @PostMapping("/immediateSaveRow")
  128. public Result mockImmediateSaveRow(@RequestBody JSONObject rowData) throws Exception {
  129. System.out.println("即时保存.rowData:" + rowData.toJSONString());
  130. // 延时1.5秒,模拟网慢堵塞真实感
  131. Thread.sleep(500);
  132. return Result.ok();
  133. }
  134. /**
  135. * 【模拟】即时保存整个表格的数据
  136. *
  137. * @param tableData 表格数据(实际使用时可以替换成一个List实体类)
  138. */
  139. @PostMapping("/immediateSaveAll")
  140. public Result mockImmediateSaveAll(@RequestBody JSONArray tableData) throws Exception {
  141. // 【注】:
  142. // 1、tableData里包含该页所有的数据
  143. // 2、如果你实现了“即时保存”,那么除了新增的数据,其他的都是已经保存过的了,
  144. // 不需要再进行一次update操作了,所以可以在前端传数据的时候就遍历判断一下,
  145. // 只传新增的数据给后台insert即可,否者将会造成性能上的浪费。
  146. // 3、新增的行是没有id的,通过这一点,就可以判断是否是新增的数据
  147. System.out.println("即时保存.tableData:" + tableData.toJSONString());
  148. // 延时1.5秒,模拟网慢堵塞真实感
  149. Thread.sleep(1000);
  150. return Result.ok();
  151. }
  152. /**
  153. * 获取模拟数据
  154. *
  155. * @param pageNo 页码
  156. * @param pageSize 页大小
  157. * @param parentId 父ID,不传则查询顶级
  158. * @return
  159. */
  160. @GetMapping("/getData")
  161. public Result getMockData(
  162. @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
  163. @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
  164. // 父级id,根据父级id查询子级,如果为空则查询顶级
  165. @RequestParam(name = "parentId", required = false) String parentId
  166. ) {
  167. // 模拟JSON数据路径
  168. String path = "classpath:org/jeecg/modules/demo/mock/vxe/json/dlglong.json";
  169. // 读取JSON数据
  170. JSONArray dataList = readJsonData(path);
  171. if (dataList == null) {
  172. return Result.error("读取数据失败!");
  173. }
  174. IPage<JSONObject> page = this.queryDataPage(dataList, parentId, pageNo, pageSize);
  175. return Result.ok(page);
  176. }
  177. /**
  178. * 获取模拟“调度计划”页面的数据
  179. *
  180. * @param pageNo 页码
  181. * @param pageSize 页大小
  182. * @param parentId 父ID,不传则查询顶级
  183. * @return
  184. */
  185. @GetMapping("/getDdjhData")
  186. public Result getMockDdjhData(
  187. // SpringMVC 会自动将参数注入到实体里
  188. MockEntity mockEntity,
  189. @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
  190. @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
  191. // 父级id,根据父级id查询子级,如果为空则查询顶级
  192. @RequestParam(name = "parentId", required = false) String parentId,
  193. @RequestParam(name = "status", required = false) String status,
  194. // 高级查询条件
  195. @RequestParam(name = "superQueryParams", required = false) String superQueryParams,
  196. // 高级查询模式
  197. @RequestParam(name = "superQueryMatchType", required = false) String superQueryMatchType,
  198. HttpServletRequest request
  199. ) {
  200. // 获取查询条件(前台传递的查询参数)
  201. Map<String, String[]> parameterMap = request.getParameterMap();
  202. // 遍历输出到控制台
  203. System.out.println("\ngetDdjhData - 普通查询条件:");
  204. for (String key : parameterMap.keySet()) {
  205. System.out.println("-- " + key + ": " + JSON.toJSONString(parameterMap.get(key)));
  206. }
  207. // 输出高级查询
  208. try {
  209. System.out.println("\ngetDdjhData - 高级查询条件:");
  210. // 高级查询模式
  211. MatchTypeEnum matchType = MatchTypeEnum.getByValue(superQueryMatchType);
  212. if (matchType == null) {
  213. System.out.println("-- 高级查询模式:不识别(" + superQueryMatchType + ")");
  214. } else {
  215. System.out.println("-- 高级查询模式:" + matchType.getValue());
  216. }
  217. superQueryParams = URLDecoder.decode(superQueryParams, "UTF-8");
  218. List<QueryCondition> conditions = JSON.parseArray(superQueryParams, QueryCondition.class);
  219. if (conditions != null) {
  220. for (QueryCondition condition : conditions) {
  221. System.out.println("-- " + JSON.toJSONString(condition));
  222. }
  223. } else {
  224. System.out.println("-- 没有传递任何高级查询条件");
  225. }
  226. System.out.println();
  227. } catch (Exception e) {
  228. log.error("-- 高级查询操作失败:" + superQueryParams, e);
  229. e.printStackTrace();
  230. }
  231. /* 注:实际使用中不用写上面那种繁琐的代码,这里只是为了直观的输出到控制台里而写的示例,
  232. 使用下面这种写法更简洁方便 */
  233. // 封装成 MyBatisPlus 能识别的 QueryWrapper,可以直接使用这个对象进行SQL筛选条件拼接
  234. // 这个方法也会自动封装高级查询条件,但是高级查询参数名必须是superQueryParams和superQueryMatchType
  235. QueryWrapper<MockEntity> queryWrapper = QueryGenerator.initQueryWrapper(mockEntity, parameterMap);
  236. System.out.println("queryWrapper: " + queryWrapper.getCustomSqlSegment());
  237. // 模拟JSON数据路径
  238. String path = "classpath:org/jeecg/modules/demo/mock/vxe/json/ddjh.json";
  239. if ("8".equals(status)) {
  240. path = "classpath:org/jeecg/modules/demo/mock/vxe/json/ddjh_s8.json";
  241. }
  242. // 读取JSON数据
  243. JSONArray dataList = readJsonData(path);
  244. if (dataList == null) {
  245. return Result.error("读取数据失败!");
  246. }
  247. IPage<JSONObject> page = this.queryDataPage(dataList, parentId, pageNo, pageSize);
  248. // 逐行查询子表数据,用于计算拖轮状态
  249. List<JSONObject> records = page.getRecords();
  250. for (JSONObject record : records) {
  251. Map<String, Integer> tugStatusMap = new HashMap<>();
  252. String id = record.getString("id");
  253. // 查询出主表的拖轮
  254. String tugMain = record.getString("tug");
  255. // 判断是否有值
  256. if (StringUtils.isNotBlank(tugMain)) {
  257. // 拖轮根据分号分割
  258. String[] tugs = tugMain.split(";");
  259. // 查询子表数据
  260. List<JSONObject> subRecords = this.queryDataPage(dataList, id, null, null).getRecords();
  261. // 遍历子表和拖轮数据,找出进行计算反推拖轮状态
  262. for (JSONObject subData : subRecords) {
  263. String subTug = subData.getString("tug");
  264. if (StringUtils.isNotBlank(subTug)) {
  265. for (String tug : tugs) {
  266. if (tug.equals(subTug)) {
  267. // 计算拖轮状态逻辑
  268. int statusCode = 0;
  269. /* 如果有发船时间、作业开始时间、作业结束时间、回船时间,则主表中的拖轮列中的每个拖轮背景色要即时变色 */
  270. // 有发船时间,状态 +1
  271. String departureTime = subData.getString("departure_time");
  272. if (StringUtils.isNotBlank(departureTime)) {
  273. statusCode += 1;
  274. }
  275. // 有作业开始时间,状态 +1
  276. String workBeginTime = subData.getString("work_begin_time");
  277. if (StringUtils.isNotBlank(workBeginTime)) {
  278. statusCode += 1;
  279. }
  280. // 有作业结束时间,状态 +1
  281. String workEndTime = subData.getString("work_end_time");
  282. if (StringUtils.isNotBlank(workEndTime)) {
  283. statusCode += 1;
  284. }
  285. // 有回船时间,状态 +1
  286. String returnTime = subData.getString("return_time");
  287. if (StringUtils.isNotBlank(returnTime)) {
  288. statusCode += 1;
  289. }
  290. // 保存拖轮状态,key是拖轮的值,value是状态,前端根据不同的状态码,显示不同的颜色,这个颜色也可以后台计算完之后返回给前端直接使用
  291. tugStatusMap.put(tug, statusCode);
  292. break;
  293. }
  294. }
  295. }
  296. }
  297. }
  298. // 新加一个字段用于保存拖轮状态,不要直接覆盖原来的,这个字段可以不保存到数据库里
  299. record.put("tug_status", tugStatusMap);
  300. }
  301. page.setRecords(records);
  302. return Result.ok(page);
  303. }
  304. /**
  305. * 模拟查询数据,可以根据父ID查询,可以分页
  306. *
  307. * @param dataList 数据列表
  308. * @param parentId 父ID
  309. * @param pageNo 页码
  310. * @param pageSize 页大小
  311. * @return
  312. */
  313. private IPage<JSONObject> queryDataPage(JSONArray dataList, String parentId, Integer pageNo, Integer pageSize) {
  314. // 根据父级id查询子级
  315. JSONArray dataDB = dataList;
  316. if (StringUtils.isNotBlank(parentId)) {
  317. JSONArray results = new JSONArray();
  318. List<String> parentIds = Arrays.asList(parentId.split(","));
  319. this.queryByParentId(dataDB, parentIds, results);
  320. dataDB = results;
  321. }
  322. // 模拟分页(实际中应用SQL自带的分页)
  323. List<JSONObject> records = new ArrayList<>();
  324. IPage<JSONObject> page;
  325. long beginIndex, endIndex;
  326. // 如果任意一个参数为null,则不分页
  327. if (pageNo == null || pageSize == null) {
  328. page = new Page<>(0, dataDB.size());
  329. beginIndex = 0;
  330. endIndex = dataDB.size();
  331. } else {
  332. page = new Page<>(pageNo, pageSize);
  333. beginIndex = page.offset();
  334. endIndex = page.offset() + page.getSize();
  335. }
  336. for (long i = beginIndex; (i < endIndex && i < dataDB.size()); i++) {
  337. JSONObject data = dataDB.getJSONObject((int) i);
  338. data = JSON.parseObject(data.toJSONString());
  339. // 不返回 children
  340. data.remove("children");
  341. records.add(data);
  342. }
  343. page.setRecords(records);
  344. page.setTotal(dataDB.size());
  345. return page;
  346. }
  347. private void queryByParentId(JSONArray dataList, List<String> parentIds, JSONArray results) {
  348. for (int i = 0; i < dataList.size(); i++) {
  349. JSONObject data = dataList.getJSONObject(i);
  350. JSONArray children = data.getJSONArray("children");
  351. // 找到了该父级
  352. if (parentIds.contains(data.getString("id"))) {
  353. if (children != null) {
  354. // addAll 的目的是将多个子表的数据合并在一起
  355. results.addAll(children);
  356. }
  357. } else {
  358. if (children != null) {
  359. queryByParentId(children, parentIds, results);
  360. }
  361. }
  362. }
  363. results.addAll(new JSONArray());
  364. }
  365. private JSONArray readJsonData(String path) {
  366. try {
  367. InputStream stream = getClass().getClassLoader().getResourceAsStream(path.replace("classpath:", ""));
  368. if (stream != null) {
  369. String json = IOUtils.toString(stream, "UTF-8");
  370. return JSON.parseArray(json);
  371. }
  372. } catch (IOException e) {
  373. log.error(e.getMessage(), e);
  374. }
  375. return null;
  376. }
  377. }