HouseController.java 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747
  1. package com.fdkanfang.web.backend;
  2. import cn.hutool.core.io.FileUtil;
  3. import com.alibaba.fastjson.JSON;
  4. import com.alibaba.fastjson.JSONObject;
  5. import com.fdkanfang.common.constant.ConstantFilePath;
  6. import com.fdkanfang.common.constant.MsgCode;
  7. import com.fdkanfang.common.constant.TypeCode;
  8. import com.fdkanfang.common.enums.ImageResolutionRate;
  9. import com.fdkanfang.common.enums.ResultCodeEnum;
  10. import com.fdkanfang.common.exception.BaseRuntimeException;
  11. import com.fdkanfang.common.exception.CommonBaseException;
  12. import com.fdkanfang.common.model.PageDto;
  13. import com.fdkanfang.common.util.*;
  14. import com.fdkanfang.domain.backend.*;
  15. import com.fdkanfang.domain.dto.*;
  16. import com.fdkanfang.domain.response.HouseResponse;
  17. import com.fdkanfang.domain.response.UserResponse;
  18. import com.fdkanfang.service.backend.*;
  19. import com.fdkanfang.web.backend.utils.UserUtils;
  20. import com.fdkanfang.web.mq.config.RabbitConfig;
  21. import com.fdkanfang.web.shiro.JWTUtil;
  22. import com.github.pagehelper.PageInfo;
  23. import io.swagger.annotations.*;
  24. import lombok.extern.log4j.Log4j2;
  25. import org.apache.commons.lang3.StringUtils;
  26. import org.apache.shiro.authz.annotation.Logical;
  27. import org.apache.shiro.authz.annotation.RequiresPermissions;
  28. import org.apache.shiro.authz.annotation.RequiresRoles;
  29. import org.springframework.amqp.rabbit.core.RabbitTemplate;
  30. import org.springframework.beans.BeanUtils;
  31. import org.springframework.beans.factory.annotation.Autowired;
  32. import org.springframework.beans.factory.annotation.Value;
  33. import org.springframework.transaction.annotation.Transactional;
  34. import org.springframework.util.CollectionUtils;
  35. import org.springframework.web.bind.annotation.*;
  36. import org.springframework.web.multipart.MultipartFile;
  37. import tk.mybatis.mapper.entity.Condition;
  38. import javax.validation.Valid;
  39. import java.io.File;
  40. import java.io.IOException;
  41. import java.time.LocalDateTime;
  42. import java.util.*;
  43. /**
  44. * Created by owen on 2020/2/18 0018 12:17
  45. */
  46. @Api(tags = "房源管理")
  47. @RestController
  48. @RequestMapping("manage/house")
  49. @Transactional
  50. @Log4j2
  51. public class HouseController extends BaseController {
  52. // 服务器文件保存位置
  53. @Value("${output.file.path}")
  54. private String OUTPATH;
  55. @Value("${server.domain}")
  56. private String domain;
  57. @Autowired
  58. private HouseService2 houseService2;
  59. @Autowired
  60. private ImageService2 imageService2;
  61. @Autowired
  62. private RabbitTemplate rabbitTemplate;
  63. @Autowired
  64. private ISceneProService sceneProService;
  65. @Autowired
  66. private ISceneProEditService sceneProEditService;
  67. @Autowired
  68. private RoleService2 roleService;
  69. @Autowired
  70. private UserUtils userUtils;
  71. @ApiOperation("房源列表")
  72. @PostMapping("list")
  73. public R list(@RequestBody PageDto param){
  74. String token = getToken();
  75. // 获取用户角色
  76. List<String> userRoles = userUtils.getRolesByToken(token);
  77. UserEntity user = userUtils.getUserByToken(token);
  78. Long userId = user.getId();
  79. PageInfo<HouseResponse> page = null;
  80. if (userRoles.contains("admin")) {
  81. page = new PageInfo<>(houseService2.findBySearchKeyForEditOrUploader(param, null, null));
  82. } else if (userRoles.contains("edit")){
  83. if (userRoles.size() == 2) {
  84. log.info("有edit、upload权限");
  85. // 有edit、upload
  86. // page = new PageInfo<>(houseService2.findAllBySearchKey(param, userId, userId));
  87. page = new PageInfo<>(houseService2.findBySearchKeyForEditOrUploader(param, null ,userId));
  88. } else {
  89. // 只有edit
  90. log.info("只有edit权限");
  91. page = new PageInfo<>(houseService2.findBySearchKeyForEditOrUploader(param, userId , null));
  92. }
  93. } else {
  94. page = new PageInfo<>(houseService2.findAllBySearchKey(param, userId, null));
  95. }
  96. return new R(2000, page);
  97. }
  98. /**
  99. * 服务器版本+垂直校验
  100. *
  101. * 使用mq队列
  102. *
  103. * 上传文件,不能使用json传参,只能用表单
  104. *
  105. * 如果图片审核不通过,就直接把这条记录禁用or删除,从新添加一条。
  106. * 修改只能修改房源信息,不能修改图片
  107. *
  108. * 上传的图片必须是以xxx_xxx.jpg 格式命名,xxx_:图片所属的户型
  109. *
  110. *
  111. * 这里要用手写的表单验证验证方式
  112. *
  113. * 提前把垂直校验,模型图片地址写入数据库,需要配合状态来判断算法计算是否完成;
  114. */
  115. @RequiresRoles(value = {"admin", "edit", "upload"}, logical = Logical.OR)
  116. @ApiOperation("新增或修改房源信息 + 垂直校验")
  117. @PostMapping(value = "save", consumes = {"multipart/form-data"})
  118. @Transactional(rollbackFor = Exception.class)
  119. public R save(HouseDto param){
  120. if(StringUtils.isBlank(param.getDistrictName())){
  121. log.error("小区名称不能为空");
  122. return new R(MsgCode.e_COMMON_3001, "小区名称不能为空");
  123. }
  124. if(null == param.getFloor() || !StringUtils.isNoneBlank(param.getUnitType() , param.getArea() , param.getOrientation())){
  125. return new R(MsgCode.e_COMMON_3001, "楼层/户型/面积/朝向不能为空");
  126. }
  127. boolean isNewAdd = false;
  128. HouseEntity house = null;
  129. if (param.getId() == null) {
  130. house = new HouseEntity();
  131. UserEntity user = userUtils.getUserByToken(getToken());
  132. house.setUserId(user.getId());
  133. param.setId(null);
  134. BeanUtils.copyProperties(param, house);
  135. Integer byMaxNum = houseService2.findByMaxNum();
  136. // 用于第一条数据
  137. byMaxNum = (byMaxNum == null)? 10000:byMaxNum;
  138. String sceneCode = getSceneCode();
  139. house.setNum(byMaxNum + 1);
  140. house.setSceneCode(sceneCode);
  141. house.setWebSite(domain+"?m="+sceneCode);
  142. house.setFilePath(OUTPATH + sceneCode);
  143. houseService2.save(house);
  144. SceneProEntity sceneProEntity = new SceneProEntity();
  145. sceneProEntity.setNum(house.getSceneCode());
  146. sceneProService.save(sceneProEntity);
  147. SceneProEditEntity sceneProEditEntity = new SceneProEditEntity();
  148. sceneProEditEntity.setProId(sceneProEntity.getId());
  149. // 默认是1
  150. sceneProEditEntity.setPanoVisi(1);
  151. sceneProEditEntity.setM2dVisi(1);
  152. sceneProEditEntity.setM3dVisi(1);
  153. sceneProEditEntity.setMeasureVisi(1);
  154. sceneProEditService.save(sceneProEditEntity);
  155. isNewAdd = true;
  156. } else {
  157. house = houseService2.findById(param.getId());
  158. if (house == null) {
  159. log.error("房源不存在: {}", param.getId());
  160. return new R(MsgCode.e_COMMON_3002, MsgCode.msg_COMMON_3002);
  161. }
  162. BeanUtils.copyProperties(param, house);
  163. house.setUpdateTime(new Date());
  164. houseService2.update(house);
  165. }
  166. // 处理上传图片
  167. MultipartFile[] files = param.getFiles();
  168. if (files == null || files.length <= 0) {
  169. log.info("文件为空");
  170. return new R(MsgCode.e_COMMON_3100, MsgCode.msg_COMMON_3100);
  171. }
  172. // 只有新增是才保存图片,修改时另外处理
  173. if (isNewAdd) {
  174. //场景码
  175. String sceneCode = house.getSceneCode();
  176. boolean needSendMqMsg = false;
  177. String directoryName = OUTPATH + sceneCode + File.separator + "input_img"+ File.separator;
  178. FileUtil.mkdir(directoryName);
  179. HashMap<String, String> ossVerticalImageHighMap = new HashMap<>();
  180. HashMap<String, String> ossVerticalImageLowMap = new HashMap<>();
  181. String imageHighPath = null;
  182. String imageLowPath = null;
  183. //照片分辨率,以最高的为准
  184. ImageResolutionRate maxResolutionRate = null;
  185. int imageResolutionRateSort = 0;
  186. for (MultipartFile file : files) {
  187. ImageEntity image = new ImageEntity();
  188. String filename = file.getOriginalFilename();
  189. if(StringUtils.isBlank(filename)){
  190. throw new CommonBaseException(ResultCodeEnum.D100 , "文件名不能为空");
  191. }
  192. if(filename.contains(".JPG")){
  193. int index = filename.lastIndexOf(".");
  194. String fileNameWithoutPostfix = filename.substring(0 , index);
  195. filename = fileNameWithoutPostfix + ".jpg";
  196. log.info("照片的格式写成了大写,需要转成小写:{}" , filename);
  197. }
  198. // 检查一下,测试时,可能会没有"_"
  199. if (!filename.contains("_")) {
  200. log.error("filename: {}", filename);
  201. throw new BaseRuntimeException(MsgCode.e_COMMON_3003, "图片命名不符合要求,需要类型+下划线");
  202. }
  203. if (RegexpUtils.isContainChinese(filename)) {
  204. log.error("图片名称不允许中文字符: {}", filename);
  205. throw new BaseRuntimeException(MsgCode.e_COMMON_3003, "图片名称不允许中文字符");
  206. }
  207. // 获取图片房间类型
  208. String imageType = StringUtils.substringBefore(filename, "_");
  209. // 本地图片保存位置: /root/data/kanfang/场景码/input_img/xxxx.jpg
  210. String fileFullPath = directoryName + filename;
  211. imageHighPath = OUTPATH + sceneCode + "/output_img/" + filename;
  212. imageLowPath = OUTPATH + sceneCode + "/output_img_low/" + filename;
  213. // 提前把算法的图片路径存到数据库,但不代表算法运行成功,最后好是要看house的状态;
  214. String ossVerticalHighPath = ConstantFilePath.OSS_IMAGE_PATH+ sceneCode+"/pan/high/"+ filename;
  215. String ossVerticalLowPath = ConstantFilePath.OSS_IMAGE_PATH+ sceneCode+"/pan/low/"+ filename;
  216. image.setVerticalPath(ossVerticalHighPath);
  217. image.setFileName(filename);
  218. // 这个参数给前端用,只要有文件名就可以了
  219. image.setPath(fileFullPath);
  220. image.setLocalPath(fileFullPath);
  221. image.setHouseId(house.getId());
  222. // 默认所有图片都是一楼
  223. image.setFloor(1);
  224. image.setType(imageType);
  225. try {
  226. //将图片保存到本地指定目录filePath eg: /root/data/kanfang/d_9iRDUgn3l/input_img/xxx.jpg
  227. int resolutionRate = FileUtils.downloanAndGetResolutionRate(file.getInputStream(), fileFullPath , false);
  228. maxResolutionRate = ImageResolutionRate.getResolutionRateByRate(resolutionRate);
  229. image.setResolutionRate(null != maxResolutionRate ? maxResolutionRate.name() : "TWO_K");
  230. imageService2.save(image);
  231. // 封装垂直校验后的图片到信息到oss
  232. ossVerticalImageHighMap.put(imageHighPath, ossVerticalHighPath);
  233. ossVerticalImageLowMap.put(imageLowPath, ossVerticalLowPath);
  234. needSendMqMsg = true;
  235. } catch (IOException e) {
  236. needSendMqMsg = false;
  237. log.error("保存照片到本地和持久化image对象出现异常:{}" , e);
  238. }
  239. }
  240. if (needSendMqMsg) {
  241. HashMap<Object, Object> mqMap = new HashMap<>();
  242. mqMap.put("ossImageHigh", ossVerticalImageHighMap);
  243. mqMap.put("ossImageLow", ossVerticalImageLowMap);
  244. mqMap.put("id", house.getId());
  245. mqMap.put("basePath", OUTPATH);
  246. mqMap.put("dataDescribe", "");
  247. log.info("houseId: {}", house.getId());
  248. //发消息到mq
  249. rabbitTemplate.convertAndSend(RabbitConfig.VERTICAL_EXCHANGE, RabbitConfig.VERTICAL_QUEUE_ROUTING, mqMap);
  250. }
  251. }
  252. return new R(MsgCode.SUCCESS_CODE, house);
  253. }
  254. @ApiOperation("预审")
  255. @ResponseBody
  256. @PostMapping(value = "/auditHouse")
  257. @Transactional(rollbackFor = Exception.class)
  258. public Result auditHouse(@RequestBody @ApiParam(name = "用户登录注册实体", value = "传入json格式", required = true) HouseAuditDto houseAuditDto) {
  259. if(StringUtils.isBlank(houseAuditDto.getDesc()) || null == houseAuditDto.getHouseId() || null == houseAuditDto.getResult()){
  260. throw new CommonBaseException(ResultCodeEnum.D3001);
  261. }
  262. HouseEntity houseEntity = houseService2.findById(houseAuditDto.getHouseId());
  263. if(null == houseEntity){
  264. throw new CommonBaseException(ResultCodeEnum.D101 , "房源不存在");
  265. }
  266. if(houseAuditDto.getResult().compareTo(1) != 0 && houseAuditDto.getResult().compareTo(0) != 0){
  267. throw new CommonBaseException(ResultCodeEnum.D101 , "审批结果格式不正确");
  268. }
  269. houseEntity.setAuditResult(houseAuditDto.getResult());
  270. houseEntity.setAuditDesc(houseAuditDto.getDesc());
  271. houseEntity.setUpdateTime(new Date());
  272. int update = houseService2.update(houseEntity);
  273. if(update != 1){
  274. throw new CommonBaseException(ResultCodeEnum.D101 , "更新房源预审信息失败");
  275. }
  276. return Result.success();
  277. }
  278. @ApiOperation("标记不能编辑")
  279. @ResponseBody
  280. @PostMapping(value = "/markFail")
  281. public Result markCannotEditHouse(@RequestBody @ApiParam(name = "用户登录注册实体", value = "传入json格式", required = true) HouseAuditDto houseAuditDto) {
  282. if(StringUtils.isBlank(houseAuditDto.getDesc()) || null == houseAuditDto.getHouseId()){
  283. throw new CommonBaseException(ResultCodeEnum.D3001);
  284. }
  285. HouseEntity houseEntity = houseService2.findById(houseAuditDto.getHouseId());
  286. if(null == houseEntity){
  287. throw new CommonBaseException(ResultCodeEnum.D101 , "房源不存在");
  288. }
  289. houseEntity.setCanNotEdit(0);
  290. houseEntity.setCanNotEditDesc(houseAuditDto.getDesc());
  291. houseEntity.setUpdateTime(new Date());
  292. int update = houseService2.update(houseEntity);
  293. if(update != 1){
  294. throw new CommonBaseException(ResultCodeEnum.D101 , "更新房源无法制作信息失败");
  295. }
  296. return Result.success();
  297. }
  298. /**
  299. *
  300. * @param houseId
  301. * @param floor 可选参数
  302. */
  303. @ApiOperation("查询房源信息")
  304. @GetMapping("detail")
  305. @ApiImplicitParams({
  306. @ApiImplicitParam(name = "houseId", value = "房源id", required = true),
  307. @ApiImplicitParam(name = "floor", value = "楼层", required = false)
  308. })
  309. public R detail(Long houseId, Integer floor){
  310. HouseEntity house = houseService2.findById(houseId);
  311. List<ImageEntity> images = imageService2.findByHouseIdAndFloor(houseId, floor);
  312. if(null != house){
  313. house.setImages(images);
  314. return new R(MsgCode.SUCCESS_CODE, house);
  315. }else{
  316. return new R(MsgCode.ERROR_CODE, "房源不存在");
  317. }
  318. }
  319. @RequiresRoles(value = {"admin", "edit", "upload"}, logical = Logical.OR)
  320. @ApiOperation("删除房源(软删除)")
  321. @GetMapping("removes/{ids}")
  322. public R removes(@PathVariable String ids){
  323. List<String> userRoles = userUtils.getRolesByToken(getToken());
  324. UserEntity user = userUtils.getUserByToken(getToken());
  325. Long loginUserId = user.getId();
  326. String roleKey = null;
  327. // 只有一个权限时
  328. if (userRoles.size() == 1) {
  329. roleKey = (String)userRoles.get(0);
  330. }
  331. String[] split = ids.split(",");
  332. for (String s : split) {
  333. HouseEntity houseEntity = houseService2.findById(Long.valueOf(s));
  334. if (houseEntity == null) {
  335. log.error("房源id有误,没有存在的房源");
  336. return new R(MsgCode.e_COMMON_3002,"没有存在的房源");
  337. }
  338. if ("upload".equals(roleKey)) {
  339. if(null != houseEntity.getAuditResult() && houseEntity.getAuditResult().compareTo(1) == 0){
  340. log.error("只有upload, 房源id!=0,审批通过的房源不能删除");
  341. return new R(MsgCode.e_COMMON_3002,"审批通过的房源不能删除");
  342. }
  343. }
  344. if ("edit".equals(roleKey)) {
  345. log.error("只有edit,没有权限删除房源");
  346. return new R(MsgCode.e_COMMON_3002,"没有权限删除房源");
  347. }
  348. if (!loginUserId.equals(houseEntity.getUserId()) && !userRoles.contains("admin")) {
  349. log.error("userId: {}, loginUserId: {}", houseEntity.getUserId(), loginUserId);
  350. log.error("用户不相等时, edit,upload不能删除他人房源");
  351. return new R(MsgCode.e_COMMON_3002,"没有权限删除房源");
  352. }
  353. houseEntity.setRecStatus("I");
  354. houseEntity.setUpdateTime(new Date());
  355. houseService2.update(houseEntity);
  356. }
  357. return new R(MsgCode.SUCCESS_CODE, MsgCode.msg_SUCCESS);
  358. }
  359. /**
  360. * 更新sceneJson(写到另一个字段), 保留原始sceneJson数据
  361. *
  362. */
  363. @RequiresRoles(value = {"admin", "edit"}, logical = Logical.OR)
  364. @ApiOperation("更新sceneJson")
  365. @PostMapping("update/sceneJson")
  366. public R updateSceneJson(@Valid @RequestBody SceneJsonDto param){
  367. HouseEntity house = houseService2.findById(param.getId());
  368. if (house == null) {
  369. log.error("房源id不存在");
  370. return new R(MsgCode.e_COMMON_3001, "房源id不存在");
  371. }
  372. house.setNewSceneJson(param.getSceneJson());
  373. house.setUpdateTime(new Date());
  374. houseService2.update(house);
  375. return new R(MsgCode.SUCCESS_CODE, MsgCode.msg_SUCCESS);
  376. }
  377. @ApiOperation("获取楼层户型图")
  378. @GetMapping("image/find/floor/{houseId}/{floor}")
  379. public R findImageByFloor(@PathVariable Long houseId, @PathVariable Integer floor){
  380. List<ImageEntity> images = imageService2.findByHouseIdAndFloor(houseId, floor);
  381. return new R(MsgCode.SUCCESS_CODE, images);
  382. }
  383. /**
  384. * 只有管理员才能分配制作人
  385. * 制作人是edit角色
  386. */
  387. @RequiresRoles(value = {"admin"}, logical = Logical.OR)
  388. @ApiOperation("获取制作人")
  389. @GetMapping("getHandler")
  390. public R getHandler(){
  391. // 根据edit权限查询用户
  392. List<UserResponse> usre = roleService.findUserByRoleKey("edit");
  393. return new R(MsgCode.SUCCESS_CODE, usre);
  394. }
  395. @RequiresRoles(value = {"admin"}, logical = Logical.OR)
  396. @ApiOperation("分配制作人")
  397. @GetMapping("setHandler/{houseId}/{userId}")
  398. public R setHandler(@PathVariable Long houseId, @PathVariable Long userId){
  399. // 根据edit权限查询用户
  400. HouseEntity houseEntity = houseService2.findById(houseId);
  401. if (houseEntity == null) {
  402. log.error("房源不存在: {}", houseId);
  403. return new R(MsgCode.e_COMMON_3001, "房源不存在");
  404. }
  405. houseEntity.setHandler(userId);
  406. houseEntity.setUpdateTime(new Date());
  407. houseService2.update(houseEntity);
  408. return new R(MsgCode.SUCCESS_CODE, MsgCode.msg_SUCCESS);
  409. }
  410. @ApiOperation("查询房源图片")
  411. @GetMapping("image/detail/{id}")
  412. public R imageDetail(@PathVariable Long id){
  413. return new R(MsgCode.SUCCESS_CODE, imageService2.findById(id));
  414. }
  415. @RequiresRoles(value = {"admin", "edit"}, logical = Logical.OR)
  416. @ApiOperation("编辑图片信息")
  417. @PostMapping("image/edit")
  418. public R imageEdit(@RequestBody ImageDto param){
  419. ImageEntity image = imageService2.findById(param.getId());
  420. if (image == null){
  421. log.error("图片id不存在: {}" , param.getId());
  422. throw new BaseRuntimeException(MsgCode.e_COMMON_3002, MsgCode.msg_COMMON_3002);
  423. }
  424. BeanUtils.copyProperties(param, image);
  425. image.setUpdateTime(new Date());
  426. imageService2.update(image);
  427. return new R(MsgCode.SUCCESS_CODE, MsgCode.msg_SUCCESS);
  428. }
  429. @RequiresRoles(value = {"admin", "edit"}, logical = Logical.OR)
  430. @ApiOperation("批量编辑图片信息")
  431. @PostMapping("image/edit/all")
  432. public R imageEdit(@RequestBody Map<Long, String> param){
  433. for (Map.Entry<Long, String> a : param.entrySet()) {
  434. ImageEntity image = imageService2.findById(a.getKey());
  435. image.setUpdateTime(new Date());
  436. image.setIssue(a.getValue());
  437. imageService2.update(image);
  438. }
  439. return new R(MsgCode.SUCCESS_CODE, MsgCode.msg_SUCCESS);
  440. }
  441. /**
  442. * 陈世超的算法
  443. * 调用算法计算场景,生产全景图
  444. *
  445. * 图片是用垂直校验后的图片
  446. *
  447. * Content传到后台会生成两个文件:floorplan.json、vision.txt
  448. */
  449. @RequiresRoles(value = {"admin", "edit"}, logical = Logical.OR)
  450. @ApiOperation("生成模型")
  451. @PostMapping("rsa/pano")
  452. @Transactional(rollbackFor = Exception.class)
  453. public R rsaPano(@Valid @RequestBody PanoDto param) throws Exception {
  454. log.info("run rsaPano");
  455. if (param == null) {
  456. log.error("参数为空");
  457. return new R(50001, "error");
  458. }
  459. HouseEntity house = houseService2.findById(param.getHouseId());
  460. if (house == null) {
  461. log.error("房源不存在: {}", param.getHouseId());
  462. return new R(MsgCode.e_COMMON_3002, MsgCode.msg_COMMON_3002);
  463. }
  464. String sceneCode = house.getSceneCode();
  465. boolean flagQ = false;
  466. // data/kanfang/10001/pano
  467. String savePath = OUTPATH + sceneCode + "/" + TypeCode.SCENE_PANO;
  468. // 检查场景码对应的pano文件夹是否存在,存在则删除里面的内容(用户从新编辑场景)
  469. if (FileUtil.isDirectory(savePath)) {
  470. FileUtil.del(savePath);
  471. log.info("删除旧目录重新计算: {}", sceneCode);
  472. }
  473. log.warn("savePath: {}", savePath);
  474. String sourcePath = savePath + "/extras/";
  475. try {
  476. FileUtils.createDir(sourcePath);
  477. /*
  478. /***
  479. * 以下字段为给算法部传递的参数(data.json),用于生成模型和
  480. * 照片,提供前端使用,完整的参数如下:
  481. * {
  482. * "split_type": "SPLIT_V5",
  483. * "skybox_type": "SKYBOX_V5",
  484. * "extras": {
  485. * "has_vision_txt": true,
  486. * "has_floorplan_json": true,
  487. * "has_source_images": true
  488. * }
  489. * }
  490. * */
  491. String content = "";
  492. //生成data.json供算法部使用
  493. JSONObject dataJson = new JSONObject();
  494. dataJson.put("split_type", "SPLIT_V5");
  495. String imageResolution = checkImageResolutionRate(house);
  496. if(ImageResolutionRate.TWO_K.name().equals(imageResolution)){
  497. //2 K 照片
  498. dataJson.put("skybox_type", "SKYBOX_V7");
  499. }else{
  500. //4 k照片
  501. dataJson.put("skybox_type", "SKYBOX_V6");
  502. }
  503. dataJson.put("extras", null);
  504. JSONObject extrasJson = new JSONObject();
  505. extrasJson.put("has_vision_txt" , true);
  506. extrasJson.put("has_floorplan_json" , true);
  507. extrasJson.put("has_source_images" , true);
  508. dataJson.put("extras" , extrasJson);
  509. FileUtils.fileWriter(dataJson.toJSONString(), savePath + "/data.json");
  510. log.warn("dataJson的生成路径: {}", savePath + "/data.json");
  511. // 解析json
  512. JSONObject original = JSON.parseObject(param.getContent());
  513. // 获取modelData, cameraData
  514. String floorPlan = original.getString("floorplan");
  515. String vision = original.getString("vision");
  516. if (floorPlan == null) {
  517. log.error("floorPlan不能为空");
  518. return new R(50002, "floorPlan不能为空");
  519. }
  520. if (vision == null) {
  521. log.error("vision不能为空");
  522. return new R(50002, "vision不能为空");
  523. }
  524. // json写入服务器
  525. FileUtils.fileWriter(floorPlan, sourcePath + "floorplan.json");
  526. FileUtils.fileWriter(vision, sourcePath + "vision.txt");
  527. log.info("floorplan.json生成完成");
  528. log.info("vision.txt生成完成");
  529. // 复制垂直校验图片到指定目录
  530. String verticalImagePath = OUTPATH + sceneCode+"/output_img";
  531. String panoImagePath = sourcePath + "images/";
  532. // srcPath: /data/kanfang/10002/output_img
  533. log.info("srcPath: {}", verticalImagePath);
  534. // target: /data/kanfang/10002/pano/extras/images/
  535. log.info("target: {}", panoImagePath);
  536. FileUtil.copyFilesFromDir(new File(verticalImagePath), new File(panoImagePath), true);
  537. flagQ = true;
  538. } catch (Exception e) {
  539. e.printStackTrace();
  540. log.error("出错了……");
  541. return new R(50002, e.getMessage());
  542. }
  543. if (flagQ) {
  544. HashMap<Object, Object> mqMap = new HashMap<>();
  545. mqMap.put("id", house.getId());
  546. mqMap.put("basePath", savePath);
  547. // 上传floorplan.json到oss, 并命名为floor.json
  548. HashMap<String, String> uploadJson = new HashMap<>();
  549. // osspath : images/images+sceneCode/floor.json
  550. uploadJson.put(sourcePath + "floorplan.json", ConstantFilePath.OSS_FLOOR_PATH+sceneCode+"/floor.json");
  551. AliyunOssUtil.uploadMulFiles(uploadJson);
  552. // savePath:/data/kanfang/房源编号/
  553. // basePath: /data/kanfang/10002/pano
  554. log.info("basePath: {}", savePath);
  555. log.info("houseId: {}", house.getId());
  556. //发消息到mq
  557. rabbitTemplate.convertAndSend(RabbitConfig.PANO_EXCHANGE, RabbitConfig.PANO_QUEUE_ROUTING, mqMap);
  558. // 修改房源状态, 3:模型计算中
  559. house.setStatus(3);
  560. house.setUpdateTime(new Date());
  561. houseService2.update(house);
  562. // 每点击生成模型一次,就修改SceneProEditEntity的部分值
  563. SceneProEntity sceneProEntity = sceneProService.findBySceneNum(house.getSceneCode());
  564. if (sceneProEntity == null) {
  565. log.error("sceneProEntity对象不存在:{}", house.getSceneCode());
  566. return new R(MsgCode.ERROR_CODE, "sceneProEntity对象不存在");
  567. }
  568. SceneProEditEntity proEditEntity = sceneProEditService.findByProId(sceneProEntity.getId());
  569. proEditEntity.setVersion(proEditEntity.getVersion() + 1);
  570. proEditEntity.setFloorEditVer(proEditEntity.getFloorEditVer() + 1);
  571. proEditEntity.setFloorPublishVer(proEditEntity.getFloorPublishVer() + 1);
  572. proEditEntity.setUpdateTime(new Date());
  573. sceneProEditService.update(proEditEntity);
  574. log.info("更新SceneProEditEntity数据完成");
  575. log.info("入队成功");
  576. }
  577. return new R(MsgCode.SUCCESS_CODE, house);
  578. }
  579. private String checkImageResolutionRate(HouseEntity houseEntity){
  580. if(null == houseEntity || null == houseEntity.getId()){
  581. return null;
  582. }
  583. List<ImageEntity> imageEntities = imageService2.findByHouseId(houseEntity.getId());
  584. if(CollectionUtils.isEmpty(imageEntities)){
  585. log.error("房源[{}]下面无照片,默认返回2k的分辨率");
  586. return ImageResolutionRate.TWO_K.name();
  587. }
  588. int sort = 0;
  589. ImageResolutionRate maxResolution = null;
  590. for (ImageEntity imageEntity : imageEntities){
  591. if(StringUtils.isBlank(imageEntity.getResolutionRate())){
  592. log.warn("房源[{}]的照片[{}]没有设置照片分辨率,跳过" , houseEntity.getId() , imageEntity.getId());
  593. break;
  594. }
  595. ImageResolutionRate curResolution = ImageResolutionRate.getResolutionByName(imageEntity.getResolutionRate());
  596. if(null != curResolution){
  597. if(curResolution.getOrder() > sort){
  598. sort = curResolution.getOrder();
  599. maxResolution = curResolution;
  600. }
  601. }
  602. }
  603. log.info("房源[{}]的照片最大的分辨率为:{}" , houseEntity.getId() , null != maxResolution ? maxResolution.name() :"空值");
  604. return null != maxResolution ? maxResolution.name() : ImageResolutionRate.TWO_K.name();
  605. }
  606. /***
  607. * 获取唯一场景码
  608. */
  609. private String getSceneCode(){
  610. String randowString = null;
  611. Condition condition = new Condition(HouseEntity.class);
  612. List<HouseEntity> all = null;
  613. boolean flag = true;
  614. while (flag) {
  615. randowString = RandomUtils.randowString(9);
  616. condition.and().andEqualTo("sceneCode", randowString);
  617. all = houseService2.findAll(condition);
  618. log.info(all.size());
  619. flag = all.size() > 0;
  620. }
  621. log.info("code: {}", randowString);
  622. return "d_" + randowString;
  623. }
  624. }