ZoneInfoService.java 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404
  1. package com.lqkj.link.module.zone.service;
  2. import com.alibaba.fastjson2.JSON;
  3. import com.alibaba.fastjson2.JSONObject;
  4. import com.lqkj.link.module.authority.domain.UserInfo;
  5. import com.lqkj.link.module.authority.repository.UserInfoRepository;
  6. import com.lqkj.link.module.bulletin.domain.NoticeInfo;
  7. import com.lqkj.link.module.bulletin.repository.NoticeInfoRepository;
  8. import com.lqkj.link.module.zone.domain.*;
  9. import com.lqkj.link.module.zone.repository.*;
  10. import com.lqkj.link.util.Unzipper;
  11. import org.apache.commons.lang3.StringUtils;
  12. import org.apache.commons.lang3.SystemUtils;
  13. import org.aspectj.weaver.ast.Var;
  14. import org.checkerframework.checker.units.qual.A;
  15. import org.locationtech.jts.geom.Coordinate;
  16. import org.locationtech.jts.geom.GeometryFactory;
  17. import org.springframework.beans.BeanUtils;
  18. import org.springframework.beans.factory.annotation.Autowired;
  19. import org.springframework.data.domain.Page;
  20. import org.springframework.data.domain.PageImpl;
  21. import org.springframework.data.domain.PageRequest;
  22. import org.springframework.data.domain.Pageable;
  23. import org.springframework.stereotype.Service;
  24. import org.springframework.transaction.annotation.Transactional;
  25. import java.io.File;
  26. import java.nio.file.Files;
  27. import java.nio.file.Paths;
  28. import java.util.*;
  29. import java.util.stream.Collectors;
  30. @Service
  31. public class ZoneInfoService {
  32. private final ZoneInfoRepository zoneInfoRepository;
  33. private final UserInfoRepository userInfoRepository;
  34. private final GeomInfoRepository geomInfoRepository;
  35. private final ModelInfoRepository modelInfoRepository;
  36. @Autowired
  37. private LikesInfoRepository likesInfoRepository;
  38. @Autowired
  39. private NoticeInfoRepository noticeInfoRepository;
  40. @Autowired
  41. private ShareInfoRepository shareInfoRepository;
  42. public ZoneInfoService(ZoneInfoRepository zoneInfoRepository, UserInfoRepository userInfoRepository,
  43. GeomInfoRepository geomInfoRepository, ModelInfoRepository modelInfoRepository) {
  44. this.zoneInfoRepository = zoneInfoRepository;
  45. this.userInfoRepository = userInfoRepository;
  46. this.geomInfoRepository = geomInfoRepository;
  47. this.modelInfoRepository = modelInfoRepository;
  48. }
  49. public Page<ZoneInfo> pageQueryTemplate(String zoneName, Integer page, Integer pageSize) {
  50. Pageable pageable = PageRequest.of(page, pageSize);
  51. return zoneInfoRepository.pageQueryTemplate(zoneName, pageable);
  52. }
  53. @Transactional
  54. public Map<String, Object> saveTemplate(ZoneInfo zoneInfo) {
  55. Map<String, Object> result = new HashMap<>();
  56. if ((zoneInfo.getZoneId() != null && zoneInfoRepository.hasSameTemplateNameWithoutOne(zoneInfo.getZoneName(), zoneInfo.getZoneId()))
  57. || (zoneInfo.getZoneId() == null && zoneInfoRepository.hasSameTemplateName(zoneInfo.getZoneName()))) {
  58. result.put("msg", "模板名称不能重复!");
  59. return result;
  60. }
  61. zoneInfo.setUpdateTime(new Date());
  62. if (zoneInfo.getZoneId() == null) {
  63. zoneInfo.setShareCount(0);
  64. zoneInfo.setViewCount(0);
  65. zoneInfo.setTemplateUse(0);
  66. }
  67. ZoneInfo zoneInfo1 = zoneInfoRepository.save(zoneInfo);
  68. try {
  69. if (StringUtils.isNotBlank(zoneInfo.getTemplateFilePath())) {
  70. // 清除元素与模型
  71. geomInfoRepository.deleteAllByZoneId(zoneInfo1.getZoneId());
  72. modelInfoRepository.deleteAllByTemplateIds(Collections.singletonList(zoneInfo1.getZoneId()));
  73. // 解压压缩文件
  74. // 文件目录格式:
  75. // --geom.json
  76. // --models
  77. // ----model1.fbx 模型1文件
  78. // ----model2.fbx 模型2文件
  79. // ----model1.json 模型1材质
  80. // ----model2.json 模型2材质
  81. //
  82. // geom.json文件总json格式:
  83. // {
  84. // "init": {
  85. // "rotation": {
  86. // "x": 0,
  87. // "y": 0,
  88. // "z": 0,
  89. // "w": 0
  90. // },
  91. // "translation": {
  92. // "x": 0,
  93. // "y": 0,
  94. // "z": 0
  95. // },
  96. // "scale3D": {
  97. // "x": 0,
  98. // "y": 0,
  99. // "z": 0
  100. // }
  101. // },
  102. // "models": [
  103. // {
  104. // "modelPath": "model1.fbx",
  105. // "location": [
  106. // {
  107. // "rotation": {
  108. // "x": 0,
  109. // "y": 0,
  110. // "z": 0,
  111. // "w": 0
  112. // },
  113. // "translation": {
  114. // "x": 0,
  115. // "y": 0,
  116. // "z": 0
  117. // },
  118. // "scale3D": {
  119. // "x": 0,
  120. // "y": 0,
  121. // "z": 0
  122. // }
  123. // }
  124. // ]
  125. // }
  126. // ]
  127. // }
  128. Unzipper.unZipFiles(new File("." + zoneInfo.getTemplateFilePath()), "./upload/template/" + zoneInfo1.getZoneId() + "/");
  129. String geomJsonString = Files.readString(Paths.get("./upload/template/" + zoneInfo1.getZoneId() + "/geom.json"));
  130. TemplateGeom templateGeom = JSON.parseObject(geomJsonString, TemplateGeom.class);
  131. zoneInfo1.setInitLocation(templateGeom.getInit());
  132. zoneInfoRepository.save(zoneInfo1);
  133. List<TemplateInfo> templateInfoList = templateGeom.getModels();
  134. String modelFolderPath = "./upload/template/" + zoneInfo1.getZoneId() + "/models";
  135. File modelFolder = new File(modelFolderPath);
  136. List<ModelInfo> list = new ArrayList<>();
  137. File[] models = modelFolder.listFiles();
  138. assert models != null;
  139. for (File model : models) {
  140. if (model.isFile()) {
  141. String modelFileName = model.getName();
  142. if (modelFileName.endsWith(".fbx")) {
  143. String modelPath = "/upload/template/" + zoneInfo1.getZoneId() + "/models/";
  144. if (modelFileName.matches(".*[\u4e00-\u9fa5]+.*")) {
  145. // 如果包含中文,重命名
  146. String newFileName =UUID.randomUUID() + ".fbx";
  147. modelPath += newFileName;
  148. boolean rename = model.renameTo(new File("." + modelPath));
  149. System.out.println(rename);
  150. // 材质文件也需要重命名
  151. File oldMaterialFile = new File("." + "/upload/template/" + zoneInfo1.getZoneId() + "/models/" + modelFileName.replace(".fbx", ".json"));
  152. if (oldMaterialFile.exists()) {
  153. File newMaterialFile = new File("." + "/upload/template/" + zoneInfo1.getZoneId() + "/models/" + newFileName.replace(".fbx", ".json"));
  154. rename = oldMaterialFile.renameTo(newMaterialFile);
  155. System.out.println(rename);
  156. }
  157. } else {
  158. modelPath += modelFileName;
  159. }
  160. list.add(new ModelInfo(null, null, modelFileName.substring(0, modelFileName.lastIndexOf(".")).toLowerCase(),
  161. null, null, null, modelPath,
  162. zoneInfo1.getThumbnail(), null, zoneInfo1.getZoneId()));
  163. }
  164. }
  165. }
  166. List<ModelInfo> modelInfoList = modelInfoRepository.saveAll(list);
  167. Map<String, ModelInfo> modelPathIdMap = modelInfoList
  168. .stream()
  169. .collect(Collectors.toMap(ModelInfo::getModelName, ModelInfo -> ModelInfo));
  170. List<GeomInfo> geomInfoList = new ArrayList<>();
  171. GeometryFactory geometryFactory = new GeometryFactory();
  172. int j = 1;
  173. for (TemplateInfo templateInfo : templateInfoList) {
  174. String modelName = templateInfo.getModelPath().substring(0, templateInfo.getModelPath().lastIndexOf(".")).toLowerCase();
  175. ModelInfo modelInfo = modelPathIdMap.get(modelName);
  176. for (int i = 0; i < templateInfo.getLocation().size(); i++) {
  177. JSONObject trans = templateInfo.getLocation().get(i);
  178. GeomInfo geomInfo = new GeomInfo();
  179. geomInfo.setGeomId(zoneInfo1.getZoneId() + "_" + j);
  180. geomInfo.setModelId(modelInfo.getModelId());
  181. geomInfo.setGeomName(modelInfo.getModelName());
  182. geomInfo.setZoneId(zoneInfo1.getZoneId());
  183. geomInfo.setLocking(false);
  184. geomInfo.setTrans(trans);
  185. JSONObject pointObject = trans.getJSONObject("translation");
  186. geomInfo.setGeom(geometryFactory.createPoint(new Coordinate(
  187. Double.parseDouble(pointObject.get("x").toString()),
  188. Double.parseDouble(pointObject.get("y").toString()),
  189. Double.parseDouble(pointObject.get("z").toString()))));
  190. j++;
  191. geomInfoList.add(geomInfo);
  192. }
  193. }
  194. geomInfoRepository.saveAll(geomInfoList);
  195. }
  196. } catch (Exception e) {
  197. modelInfoRepository.deleteAllByTemplateIds(Collections.singletonList(zoneInfo1.getZoneId()));
  198. zoneInfoRepository.delete(zoneInfo1);
  199. result.put("msg", "模板压缩文件解压失败!");
  200. return result;
  201. }
  202. result.put("zone", zoneInfo1);
  203. return result;
  204. }
  205. @Transactional
  206. public void deleteTemplate(List<Integer> zoneIds) {
  207. zoneInfoRepository.deleteAllByIdInBatch(zoneIds);
  208. modelInfoRepository.deleteAllByTemplateIds(zoneIds);
  209. }
  210. public List<String> autoCompleteMyWork(String userCode, String keyword) {
  211. return zoneInfoRepository
  212. .autoCompleteMyWork(userCode, keyword)
  213. .stream()
  214. .map(v -> (String) v.get("name"))
  215. .toList();
  216. }
  217. public List<String> autoCompleteResource(String keyword, Integer searchType) {
  218. return zoneInfoRepository
  219. .autoCompleteResource(keyword, searchType)
  220. .stream()
  221. .map(v -> (String) v.get("name"))
  222. .toList();
  223. }
  224. public List<String> autoCompleteAudit(String keyword, Integer searchType) {
  225. return zoneInfoRepository
  226. .autoCompleteAudit(keyword, searchType)
  227. .stream()
  228. .map(v -> (String) v.get("name"))
  229. .toList();
  230. }
  231. public Page<ZoneInfo> myWork(String userCode, String name, Integer page, Integer pageSize) {
  232. Pageable pageable = PageRequest.of(page, pageSize);
  233. return zoneInfoRepository.pageQueryMyWork(userCode, name, pageable);
  234. }
  235. public Page<Map<String, Object>> resourceCenter(String name, Integer searchType, Integer page, Integer pageSize, Integer orderType, String userCode) {
  236. Pageable pageable = PageRequest.of(page, pageSize);
  237. Page<Map<String, Object>> maps = zoneInfoRepository.pageQueryResourceCenter(name, searchType, pageable, orderType);
  238. List<Map<String, Object>> result = new ArrayList<>();
  239. maps.getContent().forEach(map -> {
  240. Integer zoneId = (Integer) map.get("zoneId");
  241. UserInfo userInfo = userInfoRepository.findByUserCode(userCode);
  242. boolean isLiked = likesInfoRepository.isLiked(zoneId, userInfo.getUserId());
  243. HashMap<String, Object> zoneInfo = new HashMap<>(map);
  244. if (isLiked) {
  245. zoneInfo.put("isLiked", true);
  246. } else {
  247. zoneInfo.put("isLiked", false);
  248. }
  249. result.add(zoneInfo);
  250. });
  251. return new PageImpl<>(result, PageRequest.of(page, pageSize), maps.getTotalElements());
  252. }
  253. public Page<Map<String, Object>> auditCenter(String name, Integer searchType, Integer page, Integer pageSize) {
  254. Pageable pageable = PageRequest.of(page, pageSize);
  255. return zoneInfoRepository.auditCenter(name, searchType, pageable);
  256. }
  257. @Transactional
  258. public String share(Integer zoneId, String userCode, String shareUserCode) {
  259. UserInfo shareUserInfo = userInfoRepository.findByUserCode(shareUserCode);
  260. if (Objects.isNull(shareUserInfo)) throw new RuntimeException("分享用户不存在!请核验手机号");
  261. String shareCode = UUID.randomUUID().toString();
  262. zoneInfoRepository.share(zoneId, userCode, shareCode, shareUserInfo.getUserId());
  263. UserInfo userInfo = userInfoRepository.findByUserCode(userCode);
  264. NoticeInfo noticeInfo = new NoticeInfo();
  265. noticeInfo.setUserId(shareUserInfo.getUserId());
  266. noticeInfo.setType(4);
  267. noticeInfo.setContent(userInfo.getUserCode().replaceAll("(\\d{3})\\d{4}(\\d{4})", "$1****$2") + "邀请你参加作品协作,与他(她)共建场景。");
  268. noticeInfo.setHasView(true);
  269. noticeInfo.setCreateTime(new Date());
  270. noticeInfo.setZoneId(zoneId);
  271. noticeInfoRepository.save(noticeInfo);
  272. return shareCode;
  273. }
  274. @Transactional
  275. public void view(Integer zoneId, String userCode) {
  276. zoneInfoRepository.view(zoneId, userCode);
  277. }
  278. @Transactional
  279. public String rename(Integer zoneId, String newName, String userCode) {
  280. if (zoneInfoRepository.hasSameNameWithUser(newName, userCode, zoneId)) {
  281. return "不能与已有作品重名!";
  282. }
  283. zoneInfoRepository.rename(newName, zoneId);
  284. return null;
  285. }
  286. public String deleteWork(Integer zoneId, String userCode) {
  287. if(!zoneInfoRepository.existsById(zoneId)){
  288. return "该作品不存在!";
  289. }
  290. if (!zoneInfoRepository.isAuthor(zoneId, userCode)) {
  291. return "您不是该作品的作者!";
  292. }
  293. if (!zoneInfoRepository.canBeDeleteWithAuthStatus(zoneId)) {
  294. return "不能删除正在审核的作品!";
  295. }
  296. zoneInfoRepository.deleteById(zoneId);
  297. return null;
  298. }
  299. @Transactional
  300. public Map<String, Object> create(String name, Integer templateId, String userCode) {
  301. Map<String, Object> result = new HashMap<>();
  302. UserInfo userInfo = userInfoRepository.findByUserCode(userCode);
  303. if (zoneInfoRepository.existsByZoneNameAndUserId(name, userInfo.getUserId())) {
  304. result.put("msg", "不能与已有作品重名!");
  305. return result;
  306. }
  307. ZoneInfo template = null;
  308. if (templateId != null) {
  309. template = zoneInfoRepository.findById(templateId).get();
  310. }
  311. ZoneInfo zoneInfo = new ZoneInfo(null, userInfo.getUserId(), name, template == null ? null : template.getInitLocation(),
  312. template == null ? null : template.getThumbnail(), 0, new Date(), 0, 0,
  313. null, null, 0, 0);
  314. ZoneInfo newInfo = zoneInfoRepository.save(zoneInfo);
  315. if (templateId != null) {
  316. GeometryFactory geometryFactory = new GeometryFactory();
  317. if (geomInfoRepository.hasGeom(templateId)) {
  318. List<GeomInfo> geomInfoList = geomInfoRepository.findAllByZoneId(templateId);
  319. List<GeomInfo> list = new ArrayList<>();
  320. for (GeomInfo geomInfo : geomInfoList) {
  321. String geomId = geomInfo.getGeomId();
  322. String newId = newInfo.getZoneId() + "_" + geomId.split("_")[1];
  323. GeomInfo newGeom = JSON.parseObject(JSON.toJSONString(geomInfo), GeomInfo.class);
  324. newGeom.setGeomId(newId);
  325. newGeom.setZoneId(newInfo.getZoneId());
  326. newGeom.setTrans(geomInfo.getLocation());
  327. JSONObject pointObject = geomInfo.getLocation().getJSONObject("translation");
  328. newGeom.setGeom(geometryFactory.createPoint(new Coordinate(
  329. Double.parseDouble(pointObject.get("x").toString()),
  330. Double.parseDouble(pointObject.get("y").toString()),
  331. Double.parseDouble(pointObject.get("z").toString()))));
  332. newGeom.setLocking(false);
  333. list.add(newGeom);
  334. }
  335. geomInfoRepository.saveAll(list);
  336. }
  337. // 模板使用次数+1
  338. zoneInfoRepository.addTemplateUse(templateId);
  339. }
  340. result.put("zone", newInfo);
  341. return result;
  342. }
  343. public void saveThumbnail(Integer zoneId, String thumbnailPath) {
  344. ZoneInfo zoneInfo = zoneInfoRepository.findById(zoneId).get();
  345. zoneInfo.setThumbnail(thumbnailPath);
  346. zoneInfo.setUpdateTime(new Date());
  347. zoneInfoRepository.save(zoneInfo);
  348. }
  349. public JSONObject readTrans(Integer zoneId) {
  350. return zoneInfoRepository.findById(zoneId).get().getInitLocation();
  351. }
  352. /**
  353. * 检查分享状态
  354. * @param zoneId
  355. * @param userId
  356. * @return
  357. */
  358. public boolean checkShareStatus(Integer zoneId, Integer userId) {
  359. List<ShareInfo> shareInfos = shareInfoRepository.findByZoneIdAndSharedUserId(zoneId, userId);
  360. if (shareInfos.size() < 1) return false;
  361. ShareInfo shareInfo = shareInfos.get(0);
  362. return (shareInfo.getShareTime().getTime() + (shareInfo.getCanUse() * 1000 * 60 * 60)) > System.currentTimeMillis();
  363. }
  364. }