AdmEquipmentController.java 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897
  1. package com.persagy.proxy.object.controller;
  2. import cn.hutool.core.collection.CollUtil;
  3. import cn.hutool.core.collection.CollectionUtil;
  4. import cn.hutool.core.date.DateUtil;
  5. import cn.hutool.core.io.IoUtil;
  6. import cn.hutool.core.map.MapUtil;
  7. import cn.hutool.core.util.IdUtil;
  8. import cn.hutool.core.util.StrUtil;
  9. import cn.hutool.json.JSONUtil;
  10. import cn.hutool.poi.excel.ExcelReader;
  11. import cn.hutool.poi.excel.ExcelUtil;
  12. import cn.hutool.poi.excel.RowUtil;
  13. import cn.hutool.poi.excel.WorkbookUtil;
  14. import cn.hutool.poi.excel.cell.CellUtil;
  15. import cn.hutool.poi.excel.editors.TrimEditor;
  16. import com.alibaba.excel.EasyExcel;
  17. import com.fasterxml.jackson.databind.node.ObjectNode;
  18. import com.persagy.dmp.basic.dto.RequestData;
  19. import com.persagy.dmp.basic.model.QueryCriteria;
  20. import com.persagy.dmp.common.constant.CommonConstant;
  21. import com.persagy.dmp.common.constant.ResponseCode;
  22. import com.persagy.dmp.common.context.AppContext;
  23. import com.persagy.dmp.common.exception.BusinessException;
  24. import com.persagy.dmp.common.model.response.CommonResult;
  25. import com.persagy.dmp.define.client.DigitalObjectInfoFacade;
  26. import com.persagy.dmp.define.entity.ObjectInfoDefine;
  27. import com.persagy.dmp.define.entity.ObjectTypeDefine;
  28. import com.persagy.dmp.digital.client.DigitalObjectFacade;
  29. import com.persagy.dmp.simple.client.DigitalObjectSimpleFacade;
  30. import com.persagy.proxy.adm.constant.AdmCommonConstant;
  31. import com.persagy.proxy.adm.constant.AdmDictCategoryEnum;
  32. import com.persagy.proxy.adm.constant.AdmRelationTypeEnum;
  33. import com.persagy.proxy.adm.request.*;
  34. import com.persagy.proxy.adm.service.IAdmRelationService;
  35. import com.persagy.proxy.adm.utils.AdmContextUtil;
  36. import com.persagy.proxy.adm.utils.AdmExcelUtil;
  37. import com.persagy.proxy.adm.utils.AdmQueryCriteriaHelper;
  38. import com.persagy.proxy.adm.utils.ObjectNameUtil;
  39. import com.persagy.proxy.common.entity.InstanceUrlParam;
  40. import com.persagy.proxy.common.entity.RelationDTO;
  41. import com.persagy.proxy.dictionary.model.AdmDict;
  42. import com.persagy.proxy.dictionary.model.AdmObjectType;
  43. import com.persagy.proxy.dictionary.service.IAdmDictService;
  44. import com.persagy.proxy.object.model.AdmEquipment;
  45. import com.persagy.proxy.object.model.AdmProject;
  46. import com.persagy.proxy.object.model.AdmSystem;
  47. import com.persagy.proxy.object.service.IAdmEquipmentService;
  48. import com.persagy.proxy.object.service.IAdmProjectService;
  49. import com.persagy.proxy.report.model.EquipmentPointExcel;
  50. import com.persagy.proxy.report.service.IRelationReportService;
  51. import lombok.extern.slf4j.Slf4j;
  52. import org.apache.poi.ss.usermodel.*;
  53. import org.apache.poi.xssf.usermodel.XSSFCellStyle;
  54. import org.apache.poi.xssf.usermodel.XSSFColor;
  55. import org.springframework.beans.factory.annotation.Autowired;
  56. import org.springframework.web.bind.annotation.*;
  57. import org.springframework.web.multipart.MultipartFile;
  58. import javax.servlet.http.HttpServletRequest;
  59. import javax.servlet.http.HttpServletResponse;
  60. import java.awt.Color;
  61. import java.io.FileOutputStream;
  62. import java.io.IOException;
  63. import java.net.URLEncoder;
  64. import java.nio.charset.StandardCharsets;
  65. import java.util.List;
  66. import java.util.*;
  67. import java.util.stream.Collectors;
  68. /**
  69. * Adm 楼层 API
  70. * @author lvxy
  71. * @date 2021/8/16
  72. */
  73. @Slf4j
  74. @RestController
  75. @RequestMapping("/object/equip")
  76. public class AdmEquipmentController {
  77. @Autowired
  78. private IAdmEquipmentService service;
  79. @Autowired
  80. private IAdmRelationService relationService;
  81. @Autowired
  82. private IRelationReportService relationReportService;
  83. @Autowired
  84. private IAdmDictService dictService;
  85. @Autowired
  86. private IAdmProjectService projectService;
  87. /**
  88. * 统计
  89. *
  90. * @param request
  91. * @return
  92. * @throws Exception
  93. */
  94. @PostMapping("/count")
  95. public AdmResponse count(@RequestBody AdmQueryCriteria request) throws Exception {
  96. request.setName(AdmEquipment.OBJ_TYPE);
  97. request.setOnlyCount(true);
  98. return service.query(request);
  99. }
  100. /**
  101. * 创建
  102. * @param createRequest
  103. * @return
  104. * @throws Exception
  105. */
  106. @PostMapping("/create")
  107. public AdmCreateResponse create(@RequestBody AdmCreateRequest<AdmEquipment> createRequest) throws Exception {
  108. List<AdmEquipment> vos = CollUtil.newArrayList(createRequest.getContent());
  109. if(CollUtil.isEmpty(vos)){
  110. return AdmCreateResponse.success();
  111. }
  112. // 查询所有设备类型
  113. AdmDict dictCond = AdmDict.builder().type(AdmDictCategoryEnum.EQUIPMENT.getValue()).build();
  114. AdmResponse dictResponse = dictService.queryCategory(AdmContextUtil.toDmpContext(), dictCond, AdmObjectType.class);
  115. List<AdmObjectType> dicts = (List<AdmObjectType>) dictResponse.getContent();
  116. // 转换为Map,key为编码后4位。用于适配旧类型编码
  117. Map<String, AdmObjectType> shortDictMap = new HashMap<>();
  118. Map<String, AdmObjectType> fullDictMap = new HashMap<>();
  119. for(int i = 0,j = CollUtil.size(dicts);i < j;i++) {
  120. AdmObjectType dict = dicts.get(i);
  121. shortDictMap.put(StrUtil.subSufByLength(dict.getCode(), 4), dict);
  122. fullDictMap.put(dict.getCode(), dict);
  123. }
  124. // 设备属性调整
  125. List<AdmEquipment> filterVOs = new ArrayList<>();
  126. for(AdmEquipment equipment:vos) {
  127. // 如果不是Eq开头,则重新生成ID
  128. if(StrUtil.startWith(equipment.getId(), "Eq")) {
  129. equipment.setId("Eq"+ IdUtil.simpleUUID());
  130. }
  131. // 类型编码适配
  132. String classCode = equipment.getClassCode();
  133. // 如果编码为空,或在4位、6位里都不存在,则报错
  134. if(StrUtil.isBlank(classCode) ||
  135. (shortDictMap.get(classCode) == null && fullDictMap.get(classCode) == null)) {
  136. log.error(StrUtil.format("没有找到对象类型【{}】!", equipment.getClassCode()));
  137. continue;
  138. }
  139. filterVOs.add(equipment);
  140. // 如果少于6位,则需要适配新编码
  141. if(classCode.length() < 6) {
  142. AdmObjectType dict = MapUtil.get(shortDictMap, classCode, AdmObjectType.class);
  143. equipment.setClassCode(dict.getCode());
  144. }
  145. // 如果名称为空,则提供默认名称
  146. if (StrUtil.isEmpty(equipment.getName())){
  147. AdmObjectType dict = MapUtil.get(fullDictMap, equipment.getClassCode(), AdmObjectType.class);
  148. String preName = dict == null ? "设备" : dict.getName();
  149. equipment.setName(ObjectNameUtil.objectName(preName + "-"));
  150. }
  151. }
  152. if(CollUtil.isEmpty(filterVOs)){
  153. return AdmCreateResponse.success();
  154. }
  155. filterVOs = service.doInsert(AdmContextUtil.toDmpContext(), AdmEquipment.class, filterVOs);
  156. return AdmCreateResponse.success(filterVOs);
  157. }
  158. /**
  159. * 根据ID删除
  160. * @param vos
  161. * @return
  162. * @throws Exception
  163. */
  164. @PostMapping("/delete")
  165. public AdmResponse delete( @RequestBody List<AdmEquipment> vos) throws Exception {
  166. // 组装上下文条件
  167. service.doDelete(AdmContextUtil.toDmpContext(), vos);
  168. return AdmResponse.success();
  169. }
  170. /**
  171. * 更新
  172. * @param createRequest
  173. * @return
  174. * @throws Exception
  175. */
  176. @PostMapping("/update")
  177. public AdmResponse update(@RequestBody AdmCreateRequest<AdmEquipment> createRequest) throws Exception {
  178. List<AdmEquipment> vos = createRequest.getContent();
  179. if(CollUtil.isEmpty(vos)) {
  180. return AdmResponse.success(vos);
  181. }
  182. for(AdmEquipment vo:vos) {
  183. if(StrUtil.isNotBlank(vo.getFlowBuild())) {
  184. // 处理建筑-楼层信息点
  185. List<String> flows = StrUtil.splitTrim(vo.getFlowBuild(), "-");
  186. for(String flow:flows) {
  187. if(StrUtil.startWith(flow, "Bd")) {
  188. vo.setBuildingId(flow);
  189. } else if(StrUtil.startWith(flow, "fl")) {
  190. vo.setFloorId(flow);
  191. }
  192. }
  193. vo.setFlowBuild(null);
  194. }
  195. // 设置remove信息
  196. Set<String> nullList = CollUtil.newHashSet();
  197. CollUtil.addAll(nullList, vo.getNullList());
  198. if(StrUtil.isBlank(vo.getFloorId())) {
  199. nullList.add("floorId");
  200. }
  201. if(StrUtil.isBlank(vo.getBuildingId())) {
  202. nullList.add("buildingId");
  203. }
  204. vo.setNullList(CollUtil.newArrayList(nullList));
  205. //特殊处理位置信息
  206. Map<String,Object> infos = vo.getInfos();
  207. if(infos == null) {
  208. infos = new HashMap<String, Object>();
  209. vo.setInfos(infos);
  210. }
  211. if(StrUtil.isNotEmpty(vo.getBimLocation())){
  212. infos.put("bimLocation", vo.getBimLocation());
  213. }
  214. }
  215. vos = service.doUpdate(AdmContextUtil.toDmpContext(), AdmEquipment.class, vos);
  216. return AdmResponse.success(vos);
  217. }
  218. /**
  219. * 查询
  220. *
  221. * @param request
  222. * @return
  223. * @throws Exception
  224. */
  225. @PostMapping("/query")
  226. public AdmResponse query(@RequestBody AdmQueryCriteria request) throws Exception {
  227. // 组装上下文条件
  228. request.setName(AdmEquipment.OBJ_TYPE);
  229. if(CollUtil.isEmpty(request.getCascade()) && CollUtil.isNotEmpty(request.getProjection()) && request.getDistinct() != null && request.getDistinct() && request.getProjection().size() == 1 && request.getProjection().get(0).equals("classCode")) {
  230. /** 特殊处理
  231. * distinct: true
  232. * pageNumber: 1
  233. * pageSize: 1000
  234. * projection: ["classCode"]
  235. * 0: "classCode"
  236. */
  237. RequestData requestData = new RequestData();
  238. requestData.setProjection(request.getProjection());
  239. requestData.setObjType(AdmEquipment.OBJ_TYPE);
  240. requestData.setPage(request.getPageNumber().longValue());
  241. requestData.setSize(request.getPageSize().longValue());
  242. CommonResult<List<ObjectNode>> result = DigitalObjectSimpleFacade.queryObjListByConditions(AdmContextUtil.toDmpContext().getGroupCode(), AdmContextUtil.toDmpContext().getProjectId(), AdmContextUtil.toDmpContext().getAppId(), null, requestData);
  243. if (result == null || CollUtil.isEmpty(result.getData())) {
  244. return AdmResponse.success();
  245. }else{
  246. List<AdmEquipment> admEquipments = JSONUtil.toList(result.getData().toString(), AdmEquipment.class);
  247. service.ensureSpecialValues(AdmContextUtil.toDmpContext(), admEquipments);
  248. return AdmResponse.success(admEquipments, request);
  249. }
  250. }else{
  251. return service.query(request);
  252. }
  253. }
  254. /**
  255. * 设备绑定的动态信息点或静态信息点
  256. * @param type 数据类型 static (静态)、iot (动态)
  257. * @return
  258. * @throws Exception
  259. */
  260. @GetMapping("/export")
  261. public void exportInfos(@RequestParam("type") String type, @RequestParam("projectId") String projectId, HttpServletResponse response) throws Exception {
  262. try {
  263. response.setContentType("application/vnd.ms-excel");
  264. String encode = StandardCharsets.UTF_8.name();
  265. response.setCharacterEncoding(encode);
  266. AdmQueryCriteria projectRequest = new AdmQueryCriteria();
  267. projectRequest.setName(AdmProject.OBJ_TYPE);
  268. projectRequest.setFilters("id = '" + projectId + "';");
  269. AdmResponse responsePro = projectService.doQuery(AdmContextUtil.toDmpContext(), projectRequest, AdmProject.class);
  270. if (CollUtil.isEmpty(responsePro.getContent())) {
  271. throw new BusinessException(ResponseCode.A0402.getCode(), ResponseCode.A0402.getDesc());
  272. } else {
  273. AdmProject admProject = (AdmProject) responsePro.getContent().get(0);
  274. // 防止中文乱码
  275. String fileName = admProject.getLocalName() + "设备已交付信息点";
  276. fileName = URLEncoder.encode(fileName, encode);
  277. response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");
  278. List<EquipmentPointExcel> equipmentPointExcels = dealEquipmentPoint(admProject.getGroupCode(),admProject.getId(),type, false, null);
  279. int count = equipmentPointExcels.size();
  280. if(count > 100000){
  281. EasyExcel.write(response.getOutputStream(), EquipmentPointExcel.class).sheet("sheet1").doWrite(equipmentPointExcels.subList(0,100000));
  282. EasyExcel.write(response.getOutputStream(), EquipmentPointExcel.class).sheet("sheet2").doWrite(equipmentPointExcels.subList(100000,count+1));
  283. }else{
  284. EasyExcel.write(response.getOutputStream(), EquipmentPointExcel.class).sheet("sheet1").doWrite(equipmentPointExcels);
  285. }
  286. }
  287. }catch (Exception e){
  288. log.error("设备数据导出异常,获取项目失败",e);
  289. }
  290. }
  291. /**
  292. * 根据建筑 查询设备绑定的动态信息点或静态信息点
  293. * @param type 数据类型 static (静态)、iot (动态)
  294. */
  295. @GetMapping("/export/bulidng")
  296. public void equipInfosTwo(@RequestParam("type") String type, @RequestParam("projectId") String projectId, HttpServletResponse response,@RequestParam("buildingId") String buildingId) {
  297. try {
  298. response.setContentType("application/vnd.ms-excel");
  299. String encode = StandardCharsets.UTF_8.name();
  300. response.setCharacterEncoding(encode);
  301. AdmQueryCriteria projectRequest = new AdmQueryCriteria();
  302. projectRequest.setName(AdmProject.OBJ_TYPE);
  303. projectRequest.setFilters("id = '" + projectId + "';");
  304. AdmResponse responsePro = projectService.doQuery(AdmContextUtil.toDmpContext(), projectRequest, AdmProject.class);
  305. if (CollUtil.isEmpty(responsePro.getContent())) {
  306. throw new BusinessException(ResponseCode.A0402.getCode(), ResponseCode.A0402.getDesc());
  307. } else {
  308. AdmProject admProject = (AdmProject) responsePro.getContent().get(0);
  309. // 防止中文乱码
  310. String fileName = admProject.getLocalName() + "设备已交付信息点";
  311. fileName = URLEncoder.encode(fileName, encode);
  312. response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");
  313. List<EquipmentPointExcel> equipmentPointExcels = dealEquipmentPoint(admProject.getGroupCode(),admProject.getId(),type, true, buildingId);
  314. EasyExcel.write(response.getOutputStream(), EquipmentPointExcel.class).sheet("sheet1").doWrite(equipmentPointExcels);
  315. }
  316. }catch (Exception e){
  317. log.error("设备数据导出异常,获取项目失败",e);
  318. }
  319. }
  320. /**
  321. * 根据项目id查询所有的设备和部件
  322. *
  323. * @param request
  324. * @return
  325. * @throws Exception
  326. */
  327. @GetMapping("/query-equip")
  328. public AdmResponse queryEquip(@RequestBody AdmQueryCriteria request) throws Exception {
  329. //request.setName("equipment");
  330. if(StrUtil.isNotEmpty(request.getFilters())){
  331. request.setFilters(String.join(";",request.getFilters(),"objType in ['equipment','component']"));
  332. }else{
  333. request.setFilters("objType in ['equipment','component']");
  334. }
  335. return service.query(request);
  336. }
  337. /**
  338. * 批量创建设备同时创建资产、创建设备和系统的关系
  339. * @param admEquipment
  340. * @return
  341. * @throws Exception
  342. */
  343. @PostMapping("/creat-equip-pro")
  344. public AdmCreateResponse createExt(@RequestBody AdmCreateRequest<AdmEquipment> admEquipment) throws Exception {
  345. List<AdmEquipment> vos = admEquipment.getContent();
  346. if(CollUtil.isEmpty(vos)){
  347. return AdmCreateResponse.success();
  348. }
  349. // 这里应该要移到实现类里
  350. List<RelationDTO> relationDTOS = new ArrayList<>(16);
  351. for(AdmEquipment vo:vos) {
  352. if (StrUtil.isBlank(vo.getId())){
  353. vo.setId(AdmContextUtil.generateIdStr("Eq",true));
  354. }
  355. if (StrUtil.isEmpty(vo.getName())){
  356. vo.setName(ObjectNameUtil.objectName("设备-"));
  357. }
  358. List<AdmSystem> systems = vo.getLinkSystem();
  359. if(CollUtil.isNotEmpty(systems)){
  360. for(AdmSystem system:systems) {
  361. relationDTOS.add(new RelationDTO(StrUtil.format(CommonConstant.DEFAULT_GRAPH_ID_FORMAT,
  362. AdmRelationTypeEnum.EQ2SY.getGraphCode()), AdmRelationTypeEnum.EQ2SY.getGraphCode(),
  363. AdmRelationTypeEnum.EQ2SY.getRelCode(), null , system.getId(), vo.getId()));
  364. }
  365. }
  366. }
  367. if (CollUtil.isNotEmpty(relationDTOS)){
  368. relationService.doSave(AdmContextUtil.toDmpContext(),relationDTOS);
  369. }
  370. vos = service.doInsert(AdmContextUtil.toDmpContext(), AdmEquipment.class, vos);
  371. return AdmCreateResponse.success(vos);
  372. }
  373. /**
  374. * 设备上传excel识别静态信息点
  375. *
  376. * @param file
  377. * @param request
  378. * @param response
  379. */
  380. @RequestMapping("/import")
  381. public AdmResponse importFile(@RequestParam("file") MultipartFile file, HttpServletRequest request, HttpServletResponse response) {
  382. if (file == null) {
  383. return AdmResponse.failure("未选择文件");
  384. }
  385. String path = AdmCommonConstant.SERVER_ROOT_PATH + AdmExcelUtil.TEMP_UPLOAD_PAHT;
  386. int failurNum = 0;
  387. int successCount = 0;
  388. String failure = null;
  389. String primaryKey = null;
  390. String classCodeCloumn = null;
  391. Workbook workbook = null;
  392. FileOutputStream fileOutputStream = null;
  393. String groupCode = AppContext.getContext().getGroupCode();
  394. String projectId = AppContext.getContext().getProjectId();
  395. try {
  396. byte[] bytes = IoUtil.readBytes(file.getInputStream());
  397. workbook = WorkbookUtil.createBook(IoUtil.toStream(bytes));
  398. Sheet sheet = WorkbookUtil.getOrCreateSheet(workbook, 0);
  399. Row row1 = RowUtil.getOrCreateRow(sheet, 1);
  400. /** 获取识别码 */
  401. Cell markCell = CellUtil.getCell(row1, 0);
  402. if (markCell == null) {
  403. AdmExcelUtil.writeFile2Local(workbook, projectId, path, file.getOriginalFilename());
  404. return AdmExcelUtil.getImportFailResult("未填写识别码", "2", 0, ++failurNum);
  405. }
  406. primaryKey = StrUtil.toString(CellUtil.getCellValue(markCell,true)); // 识别码
  407. if (!AdmCommonConstant.codeColMap.containsKey(primaryKey)) {
  408. AdmExcelUtil.writeFile2Local(workbook, projectId, path, file.getOriginalFilename());
  409. return AdmExcelUtil.getImportFailResult("未找到识别码", "2", 0, ++failurNum);
  410. }
  411. primaryKey = AdmCommonConstant.codeColMap.get(primaryKey);
  412. /** 获取类型 */
  413. Cell cell = CellUtil.getCell(row1,1);
  414. if (cell == null) {
  415. AdmExcelUtil.writeFile2Local(workbook, projectId, path, file.getOriginalFilename());
  416. return AdmExcelUtil.getImportFailResult("未填写设备类型", "2", 0, ++failurNum);
  417. }
  418. classCodeCloumn = cell.getStringCellValue().trim();
  419. if (!"ClassCode".equals(classCodeCloumn)) {
  420. AdmExcelUtil.writeFile2Local(workbook, projectId, path, file.getOriginalFilename());
  421. return AdmExcelUtil.getImportFailResult("缺少设备类型(ClassCode)", "2", 0, ++failurNum);
  422. }
  423. // 写入错误报告对比值颜色
  424. this.wirteReport(workbook, sheet);
  425. // 存取所有的信息点
  426. Map<Integer, String> infoMap = new HashMap<>();
  427. List<Object> row1List = RowUtil.readRow(row1, new TrimEditor());
  428. for (int i = 1; i < row1List.size(); i++) {
  429. infoMap.put(i,StrUtil.toString(row1List.get(i)));
  430. }
  431. boolean isClassCode = "classCode".equals(primaryKey);
  432. ExcelReader excelReader = ExcelUtil.getReader(IoUtil.toStream(bytes), 0);
  433. List<List<Object>> listList = excelReader.read();
  434. // 1.存储设备类型code
  435. Set<String> classCodes = CollUtil.newHashSet();
  436. // 2.存储primaryKey对应的值
  437. Set<String> primaryMess = CollUtil.newHashSet();
  438. for (int i = 2; i < listList.size(); i++) {
  439. List<Object> objects = listList.get(i);
  440. if (CollUtil.isEmpty(objects)){
  441. continue;
  442. }
  443. if (null==objects.get(0) || StrUtil.isBlank(StrUtil.toString(objects.get(0)))){
  444. this.setColor(workbook, 252, 255, 77,
  445. CellUtil.getOrCreateCell(RowUtil.getOrCreateRow(sheet,i),0));
  446. continue;
  447. }
  448. if (!isClassCode && (null==objects.get(1) || StrUtil.isBlank(StrUtil.toString(objects.get(1))))){
  449. // 第一个cell为空或者非classCode上传并且第二个cell为空
  450. this.setColor(workbook, 252, 255, 77,
  451. CellUtil.getOrCreateCell(RowUtil.getOrCreateRow(sheet,i),0));
  452. continue;
  453. }
  454. if (isClassCode){
  455. classCodes.add(StrUtil.toString(objects.get(0)));
  456. continue;
  457. }
  458. classCodes.add(StrUtil.toString(objects.get(1)));
  459. primaryMess.add(StrUtil.toString(objects.get(0)));
  460. }
  461. if (isClassCode && CollUtil.isEmpty(classCodes)){
  462. // 设备类型code集合为空
  463. String fileName = AdmExcelUtil.writeFile2Local(workbook, projectId, path, file.getOriginalFilename());
  464. return AdmExcelUtil.getImportSuccessResult(fileName, successCount, listList.size());
  465. }
  466. if (!isClassCode && (CollUtil.isEmpty(primaryMess) || CollUtil.isEmpty(classCodes))){
  467. // 设备类型code集合或唯一标识为空
  468. String fileName = AdmExcelUtil.writeFile2Local(workbook, projectId, path, file.getOriginalFilename());
  469. return AdmExcelUtil.getImportSuccessResult(fileName, successCount, listList.size());
  470. }
  471. // 1.根据设备类型code集合查询定义
  472. Map<String,ObjectTypeDefine> defineMap = relationReportService.queryDefineTypeMapByClassCodes(classCodes);
  473. // 2.根据设备类型code集合查询设备类的信息点
  474. Map<String,List<ObjectInfoDefine>> defineInfoMap = relationReportService.queryDefineInfoMapByClassCodes(classCodes);
  475. // 3.根据是否根据设备类型code上传来区分处理
  476. Map<String,List<ObjectNode>> objectDigitalMap = CollUtil.newHashMap();
  477. if (isClassCode){
  478. objectDigitalMap=relationReportService.queryEquipsByClassCodes(classCodes);
  479. }else {
  480. objectDigitalMap=relationReportService.queryEquipsByConditions(primaryKey,primaryMess,classCodes);
  481. }
  482. List<ObjectNode> updateObjs = new ArrayList<>();
  483. ObjectNode equipment = null;
  484. List<ObjectNode> equipmentList = null;
  485. for (int i = 2; i < listList.size(); i++) {
  486. List<Object> objects = listList.get(i);
  487. if (CollUtil.isEmpty(objects)){
  488. continue;
  489. }
  490. if ((null==objects.get(0) || StrUtil.isBlank(StrUtil.toString(objects.get(0))))
  491. || (!isClassCode && (null==objects.get(1) || StrUtil.isBlank(StrUtil.toString(objects.get(1)))))){
  492. failurNum++;
  493. continue;
  494. }
  495. String classCode = isClassCode?StrUtil.toString(objects.get(0)):StrUtil.toString(objects.get(1));
  496. if (!defineMap.containsKey(classCode)){
  497. failurNum++;
  498. this.setColor(workbook, 56, 94, 15, CellUtil.getCell(RowUtil.getOrCreateRow(sheet, i), isClassCode?0:1));
  499. continue;
  500. }
  501. classCode = defineMap.get(classCode).getCode();
  502. equipmentList = isClassCode ? objectDigitalMap.get(classCode)
  503. : objectDigitalMap.get(StrUtil.toString(objects.get(0)) + StrUtil.UNDERLINE + classCode);
  504. if (CollectionUtil.isEmpty(equipmentList)) {
  505. failurNum++;
  506. this.setColor(workbook, 153, 225, 77, CellUtil.getCell(RowUtil.getOrCreateRow(sheet, i), 0));
  507. continue;
  508. }
  509. if (isClassCode) {
  510. equipment = equipmentList.get(0);
  511. } else {
  512. if (equipmentList.size() > 1) {
  513. failurNum++;
  514. this.setColor(workbook, 249, 203, 77, CellUtil.getCell(RowUtil.getOrCreateRow(sheet, i), 1));
  515. continue;
  516. } else {
  517. equipment = equipmentList.get(0);
  518. }
  519. }
  520. boolean changeFlag = true;
  521. for (int j = 2; j < objects.size(); j++) {
  522. // 剩余列数据处理
  523. if (!infoMap.containsKey(j)) {
  524. continue;
  525. }
  526. Cell tempCell = CellUtil.getOrCreateCell(RowUtil.getOrCreateRow(sheet, i), j);
  527. // 如果值为空直接跳过
  528. if (StrUtil.isBlank(StrUtil.toString(CellUtil.getCellValue(tempCell,true)))){
  529. continue;
  530. }
  531. // 获取设备类的信息点
  532. String code = infoMap.get(j);
  533. List<ObjectInfoDefine> funidList = defineInfoMap.getOrDefault(classCode,new ArrayList<>())
  534. .stream().filter(func->code.equals(func.getAliasCode()) && "STATIC".equals(func.getCategory()))
  535. .collect(Collectors.toList());
  536. if (CollectionUtil.isEmpty(funidList)) {
  537. failurNum++;
  538. this.setColor(workbook, 77, 178, 255, tempCell);
  539. changeFlag=false;
  540. continue;
  541. }
  542. ObjectInfoDefine define = funidList.get(0);
  543. if ("STRING".equalsIgnoreCase(define.getDataType())) {
  544. tempCell.setCellType(CellType.STRING);
  545. equipment.put(define.getCode(), tempCell.getStringCellValue().trim());
  546. } else if ("INTEGER".equalsIgnoreCase(define.getDataType())) {
  547. try {
  548. if (!CellType.NUMERIC.equals(tempCell.getCellTypeEnum())
  549. || StrUtil.isBlank(StrUtil.toString(CellUtil.getCellValue(tempCell,true)))) {
  550. failurNum++;
  551. this.setColor(workbook, 155, 227, 255, tempCell);
  552. changeFlag=false;
  553. continue;
  554. }
  555. tempCell.setCellType(CellType.STRING);
  556. equipment.put(define.getCode(), tempCell.getStringCellValue().trim());
  557. } catch (Exception e) {
  558. failurNum++;
  559. this.setColor(workbook, 155, 227, 255, tempCell);
  560. changeFlag=false;
  561. continue;
  562. }
  563. } else if ("ENUM".equalsIgnoreCase(define.getDataType())) {
  564. if (CellType.NUMERIC.equals(tempCell.getCellTypeEnum())
  565. && StrUtil.isNotBlank(StrUtil.toString(CellUtil.getCellValue(tempCell,true)))) {
  566. tempCell.setCellType(CellType.STRING);
  567. equipment.put(define.getCode(), tempCell.getStringCellValue().trim());
  568. } else if (CellType.STRING.equals(tempCell.getCellTypeEnum())
  569. && StrUtil.isNotBlank(StrUtil.toString(CellUtil.getCellValue(tempCell,true)))) {
  570. equipment.put(define.getCode(), tempCell.getStringCellValue().trim());
  571. } else {
  572. failurNum++;
  573. this.setColor(workbook, 155, 227, 255, tempCell);
  574. changeFlag=false;
  575. continue;
  576. }
  577. } else if ("DATETIME".equalsIgnoreCase(define.getDataType())) {
  578. try {
  579. tempCell.setCellType(CellType.STRING);
  580. String trim = tempCell.getStringCellValue().trim();
  581. DateUtil.parseByPatterns(trim, "yyyyMMdd");
  582. equipment.put(define.getCode(), trim);
  583. } catch (Exception e) {
  584. failurNum++;
  585. this.setColor(workbook, 155, 227, 255, tempCell);
  586. changeFlag=false;
  587. continue;
  588. }
  589. } else if ("DOUBLE".equalsIgnoreCase(define.getDataType())) {
  590. try {
  591. tempCell.setCellType(CellType.STRING);
  592. String trim = tempCell.getStringCellValue().trim();
  593. equipment.put(define.getCode(), Double.parseDouble(trim));
  594. } catch (Exception e) {
  595. failurNum++;
  596. this.setColor(workbook, 155, 227, 255, tempCell);
  597. changeFlag=false;
  598. continue;
  599. }
  600. } else if ("BOOLEAN".equalsIgnoreCase(define.getDataType())) {
  601. tempCell.setCellType(CellType.STRING);
  602. String trim = tempCell.getStringCellValue() == null ? null : tempCell.getStringCellValue().trim();
  603. if ("1".equals(trim) || "0".equals(trim)) {
  604. equipment.put(define.getCode(), Double.parseDouble(trim));
  605. } else {
  606. failurNum++;
  607. this.setColor(workbook, 155, 227, 255, tempCell);
  608. changeFlag=false;
  609. continue;
  610. }
  611. } else {
  612. failurNum++;
  613. this.setColor(workbook, 204, 99, 233, tempCell);
  614. changeFlag=false;
  615. continue;
  616. }
  617. }
  618. if (changeFlag){
  619. updateObjs.add(equipment);
  620. }
  621. }
  622. // 5.更新对象数据
  623. if (CollUtil.isNotEmpty(updateObjs)){
  624. successCount=updateObjs.size();
  625. DigitalObjectFacade.update(AppContext.getContext().getGroupCode(),
  626. AppContext.getContext().getProjectId(),
  627. AppContext.getContext().getAppId(),
  628. AppContext.getContext().getAccountId(),
  629. updateObjs);
  630. }
  631. // 设备类型code集合或唯一标识为空
  632. String fileName = AdmExcelUtil.writeFile2Local(workbook, projectId, path, file.getOriginalFilename());
  633. return AdmExcelUtil.getImportSuccessResult(fileName, successCount, failurNum);
  634. } catch (Exception e) {
  635. log.error("台账信息导入失败", e);
  636. failure = e.getMessage();
  637. } finally {
  638. if (fileOutputStream != null) {
  639. try {
  640. fileOutputStream.flush();
  641. fileOutputStream.close();
  642. } catch (IOException e) {}
  643. }
  644. if (workbook != null) {
  645. try {
  646. workbook.close();
  647. } catch (IOException e) {}
  648. }
  649. }
  650. return AdmResponse.failure(failure);
  651. }
  652. /**
  653. * 设置填充色
  654. *
  655. * @param workbook
  656. * @param r
  657. * @param g
  658. * @param b
  659. * @param cell
  660. */
  661. private void setColor(Workbook workbook, int r, int g, int b, Cell cell) {
  662. XSSFCellStyle cellStyle = (XSSFCellStyle) workbook.createCellStyle();
  663. cellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
  664. cellStyle.setFillForegroundColor(new XSSFColor(new Color(r, g, b)));
  665. cell.setCellStyle(cellStyle);
  666. }
  667. /**
  668. * 写入错误报告对比值颜色
  669. *
  670. * @param workbook
  671. * @param sheet
  672. */
  673. private void wirteReport(Workbook workbook, Sheet sheet) {
  674. Row row = sheet.getRow(1);
  675. short column = (short) (row.getLastCellNum() + 2);
  676. Row row4 = sheet.getRow(4);
  677. if (row4 == null) {
  678. row4 = sheet.createRow(4);
  679. }
  680. Cell createCell = row4.createCell(column);
  681. createCell.setCellValue("导入失败,识别码超出范围(本地编码,设备类型)");
  682. createCell = row4.createCell(column + 1);
  683. this.setColor(workbook,233,99,99,createCell);
  684. Row row5 = sheet.getRow(5);
  685. if (row5 == null) {
  686. row5 = sheet.createRow(5);
  687. }
  688. createCell = row5.createCell(column);
  689. createCell.setCellValue("导入失败,识别码为空");
  690. createCell = row5.createCell(column + 1);
  691. this.setColor(workbook,252,147,77,createCell);
  692. Row row6 = sheet.getRow(6);
  693. if (row6 == null) {
  694. row6 = sheet.createRow(6);
  695. }
  696. createCell = row6.createCell(column);
  697. createCell.setCellValue("导入失败,多个实例");
  698. createCell = row6.createCell(column + 1);
  699. this.setColor(workbook,249,203,77,createCell);
  700. Row row7 = sheet.getRow(7);
  701. if (row7 == null) {
  702. row7 = sheet.createRow(7);
  703. }
  704. createCell = row7.createCell(column);
  705. createCell.setCellValue("导入失败,设备不存在");
  706. createCell = row7.createCell(column + 1);
  707. this.setColor(workbook,153,225,77,createCell);
  708. Row row8 = sheet.getRow(8);
  709. if (row8 == null) {
  710. row8 = sheet.createRow(8);
  711. }
  712. createCell = row8.createCell(column);
  713. createCell.setCellValue("导入失败,识别码值为空");
  714. createCell = row8.createCell(column + 1);
  715. this.setColor(workbook,252,255,77,createCell);
  716. Row row9 = sheet.getRow(9);
  717. if (row9 == null) {
  718. row9 = sheet.createRow(9);
  719. }
  720. createCell = row9.createCell(column);
  721. createCell.setCellValue("导入失败,输入类型与字典定义不一致");
  722. createCell = row9.createCell(column + 1);
  723. this.setColor(workbook,155,227,255,createCell);
  724. Row row10 = sheet.getRow(10);
  725. if (row10 == null) {
  726. row10 = sheet.createRow(10);
  727. }
  728. createCell = row10.createCell(column);
  729. createCell.setCellValue("导入失败,未支持的输入类型");
  730. createCell = row10.createCell(column + 1);
  731. this.setColor(workbook,204,99,233,createCell);
  732. Row row11 = sheet.getRow(11);
  733. if (row11 == null) {
  734. row11 = sheet.createRow(11);
  735. }
  736. createCell = row11.createCell(column);
  737. createCell.setCellValue("导入失败,信息点不存在");
  738. createCell = row11.createCell(column + 1);
  739. this.setColor(workbook,77,178,255,createCell);
  740. Row row12 = sheet.getRow(12);
  741. if (row12 == null) {
  742. row12 = sheet.createRow(12);
  743. }
  744. createCell = row12.createCell(column);
  745. createCell.setCellValue("导入失败,设备类型不在字典定义中");
  746. createCell = row12.createCell(column + 1);
  747. this.setColor(workbook,56,94,15,createCell);
  748. }
  749. /**
  750. * 组装需要导出的设备信息点
  751. * @param groupCode
  752. * @param projectId
  753. * @return
  754. */
  755. private List<EquipmentPointExcel> dealEquipmentPoint(String groupCode,String projectId, String type, Boolean withBuilding, String buildingId){
  756. InstanceUrlParam context = AdmContextUtil.toDmpContext();
  757. if(StrUtil.isAllNotEmpty(groupCode,projectId)){
  758. // 结果封装
  759. List<EquipmentPointExcel> excelList = new ArrayList<EquipmentPointExcel>();
  760. /** 统计项目设备类型 */
  761. RequestData requestData = new RequestData();
  762. requestData.setProjectId(projectId);
  763. requestData.setGroupCode(groupCode);
  764. requestData.setObjType(AdmEquipment.OBJ_TYPE);
  765. requestData.setObjTypes(CollUtil.newHashSet(AdmEquipment.OBJ_TYPE));
  766. List<Map<String, Object>> equipTypeList = DigitalObjectSimpleFacade.queryDefineInfoByObjType(groupCode,projectId,null,null,requestData);
  767. /** 统计信息不为空继续 */
  768. if (equipTypeList.size() > 0 ) {
  769. for(int i = 0; i < equipTypeList.size(); i++){
  770. AdmDictQueryCriteria admQueryCriteriaInfo = new AdmDictQueryCriteria();
  771. /** 是否查询静态信息点 */
  772. if (type.equals("static")){
  773. admQueryCriteriaInfo.addFilters("category = 'STATIC'");
  774. } else {
  775. admQueryCriteriaInfo.addFilters("category != 'STATIC'");
  776. }
  777. admQueryCriteriaInfo.addFilters("valid = 1 ");
  778. admQueryCriteriaInfo.addFilters("classCode = '" + equipTypeList.get(i).get("code").toString() + "'");
  779. AdmQueryCriteria admQueryCriteriaEquip = new AdmQueryCriteria();
  780. admQueryCriteriaEquip.addFilters("classCode = '" + equipTypeList.get(i).get("code").toString() + "'");
  781. admQueryCriteriaEquip.addFilters("not infos isnull");
  782. admQueryCriteriaEquip.setName(AdmEquipment.OBJ_TYPE);
  783. if(withBuilding){
  784. if(StrUtil.isNotEmpty(buildingId)){
  785. admQueryCriteriaEquip.addFilters("buildingId = '"+buildingId+"'");
  786. }else{
  787. admQueryCriteriaEquip.addFilters("buildingId isnull");
  788. }
  789. }
  790. AdmResponse eqResponse = service.query(admQueryCriteriaEquip);
  791. List<AdmEquipment> equipmentList = (List<AdmEquipment>) eqResponse.getContent();
  792. if (equipmentList.size() > 0) {
  793. /** 字典信息点 */
  794. //AdmResponse responseDic = dictService.query(context, admQueryCriteriaInfo, AdmDictConstant.CLASS_CODE, AdmObjectInfo.class);
  795. //List<AdmObjectInfo> defFuncIdList = (List<AdmObjectInfo>) responseDic.getContent();
  796. QueryCriteria queryCriteria = AdmQueryCriteriaHelper.toDmpCriteria(admQueryCriteriaInfo);
  797. queryCriteria.setOnlyCount(false);
  798. List<ObjectInfoDefine> defFuncIdList = DigitalObjectInfoFacade.query(AdmContextUtil.toDmpContext().getGroupCode(), AdmContextUtil.toDmpContext().getProjectId(), AdmCommonConstant.APP_ID,null,queryCriteria);
  799. if (defFuncIdList.size() > 0) {
  800. Map mapInfo = new HashMap<String,String>();
  801. Map mapInputType = new HashMap<String,String>();
  802. Map mapInputFirstName = new HashMap<String,String>();
  803. for (ObjectInfoDefine defFuncId : defFuncIdList) {
  804. if(StrUtil.isEmpty(defFuncId.getCode())){
  805. continue;
  806. }
  807. mapInfo.put(defFuncId.getCode(),defFuncId.getName());
  808. if(StrUtil.isNotEmpty(defFuncId.getDataType())){
  809. mapInputType.put(defFuncId.getCode(), defFuncId.getDataType());
  810. }
  811. if(StrUtil.isNotEmpty(defFuncId.getFirstTag())){
  812. mapInputFirstName.put(defFuncId.getCode(),defFuncId.getFirstTag());
  813. }
  814. }
  815. for (AdmEquipment equipment : equipmentList) {
  816. if(CollUtil.isEmpty(equipment.getInfos())){
  817. continue;
  818. }
  819. Map<String, Object> info = equipment.getInfos();
  820. for(String key : info.keySet()){
  821. if(info.get(key) != null && StrUtil.isNotEmpty(info.get(key).toString())){
  822. boolean containsKey = mapInfo.containsKey(key);
  823. if(!containsKey){
  824. continue;
  825. }
  826. /** 处理数据写入文件 */
  827. EquipmentPointExcel excel = new EquipmentPointExcel();
  828. /** id */
  829. excel.setId(equipment.getId());
  830. /** 本地编码 */
  831. excel.setLocalId(equipment.getLocalId());
  832. /** 本地名称 */
  833. excel.setLocalName(equipment.getLocalName());
  834. /** 类型 */
  835. excel.setClassCode(equipment.getClassCode());
  836. /** 类型 */
  837. excel.setClassCodeName(equipTypeList.get(i).get("name").toString());
  838. /** 一级标签 */
  839. boolean containsFirstName = mapInputFirstName.containsKey(key);
  840. if (containsFirstName) {
  841. /** 一级标签 */
  842. excel.setMapInputFirstName(mapInputFirstName.get(key).toString());
  843. }
  844. /** 信息点名 */
  845. excel.setInfoName(mapInfo.get(key).toString());
  846. /** 信息点 */
  847. excel.setInfoCode(key);
  848. boolean containsInputType = mapInputType.containsKey(key);
  849. if (containsInputType) {
  850. /** 输入类型 */
  851. excel.setInputType(mapInputType.get(key).toString());
  852. }
  853. /** 值 */
  854. excel.setInputValue(info.get(key).toString());
  855. excelList.add(excel);
  856. }
  857. }
  858. }
  859. }
  860. }
  861. }
  862. }
  863. return excelList;
  864. }else{
  865. return null;
  866. }
  867. }
  868. }