HouseController.java 51 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191
  1. package com.fdkanfang.web.backend;
  2. import cn.hutool.core.bean.BeanUtil;
  3. import cn.hutool.core.bean.copier.CopyOptions;
  4. import cn.hutool.core.io.FileUtil;
  5. import com.alibaba.fastjson.JSON;
  6. import com.alibaba.fastjson.JSONObject;
  7. import com.fdkanfang.common.constant.ConstantFilePath;
  8. import com.fdkanfang.common.constant.MsgCode;
  9. import com.fdkanfang.common.constant.TypeCode;
  10. import com.fdkanfang.common.enums.ImageResolutionRate;
  11. import com.fdkanfang.common.enums.ResultCodeEnum;
  12. import com.fdkanfang.common.exception.BaseRuntimeException;
  13. import com.fdkanfang.common.exception.CommonBaseException;
  14. import com.fdkanfang.common.model.PageDto;
  15. import com.fdkanfang.common.util.*;
  16. import com.fdkanfang.domain.backend.*;
  17. import com.fdkanfang.domain.dto.*;
  18. import com.fdkanfang.domain.response.HouseResponse;
  19. import com.fdkanfang.domain.response.UserResponse;
  20. import com.fdkanfang.service.backend.*;
  21. import com.fdkanfang.web.backend.utils.UserUtils;
  22. import com.fdkanfang.web.mq.config.RabbitConfig;
  23. import com.github.pagehelper.PageInfo;
  24. import io.swagger.annotations.*;
  25. import lombok.extern.log4j.Log4j2;
  26. import net.coobird.thumbnailator.Thumbnails;
  27. import org.apache.commons.lang3.StringUtils;
  28. import org.apache.shiro.authz.annotation.Logical;
  29. import org.apache.shiro.authz.annotation.RequiresRoles;
  30. import org.springframework.amqp.rabbit.core.RabbitTemplate;
  31. import org.springframework.beans.BeanUtils;
  32. import org.springframework.beans.factory.annotation.Autowired;
  33. import org.springframework.beans.factory.annotation.Value;
  34. import org.springframework.transaction.annotation.Transactional;
  35. import org.springframework.util.CollectionUtils;
  36. import org.springframework.web.bind.annotation.*;
  37. import org.springframework.web.multipart.commons.CommonsMultipartFile;
  38. import javax.mail.MessagingException;
  39. import javax.validation.Valid;
  40. import java.io.File;
  41. import java.io.IOException;
  42. import java.io.UnsupportedEncodingException;
  43. import java.util.*;
  44. /**
  45. * Created by owen on 2020/2/18 0018 12:17
  46. */
  47. @Api(tags = "房源管理")
  48. @RestController
  49. @RequestMapping("manage/house")
  50. @Transactional
  51. @Log4j2
  52. public class HouseController extends BaseController {
  53. // 服务器文件保存位置
  54. @Value("${output.file.path}")
  55. private String OUTPATH;
  56. @Value("${server.domain}")
  57. private String domain;
  58. @Value("${4dkankan.host}")
  59. private String KankanHost;
  60. @Value("${admin.email.account}")
  61. private String adminEmailAccount;
  62. @Value("${oss.image.file.path}")
  63. private String ossPath;
  64. @Value("${oss.query.url}")
  65. private String ossQueryUrl;
  66. @Autowired
  67. private HouseService2 houseService2;
  68. @Autowired
  69. private ImageService2 imageService2;
  70. @Autowired
  71. private RabbitTemplate rabbitTemplate;
  72. @Autowired
  73. private ISceneProService sceneProService;
  74. @Autowired
  75. private ISceneProEditService sceneProEditService;
  76. @Autowired
  77. private RoleService2 roleService;
  78. @Autowired
  79. private UserUtils userUtils;
  80. @Autowired
  81. private UserService2 userService2;
  82. @Autowired
  83. private OssCheckPointUploadUtil ossCheckPointUploadUtil;
  84. @ApiOperation("房源列表")
  85. @PostMapping("list")
  86. public R list(@RequestBody PageDto param){
  87. String token = getToken();
  88. // 获取用户角色
  89. List<String> userRoles = userUtils.getRolesByToken(token);
  90. UserEntity user = userUtils.getUserByToken(token);
  91. Long userId = user.getId();
  92. PageInfo<HouseResponse> page = null;
  93. if(CollectionUtils.isEmpty(userRoles)){
  94. log.info("用户权限为空,无法获取房源列表");
  95. throw new CommonBaseException(ResultCodeEnum.D101 , "权限不足");
  96. }
  97. if(userRoles.size() == 3){
  98. //管理员获取全部房源列表
  99. page = new PageInfo<>(houseService2.findBySearchKeyForEditOrUploader(param, null, null));
  100. }else if(userRoles.size() == 2){
  101. if(userRoles.contains("edit") && userRoles.contains("upload")){
  102. //同时拥有编辑和上传权限
  103. page = new PageInfo<>(houseService2.findBySearchKeyForEditOrUploader(param, userId ,userId));
  104. }else if(userRoles.contains("edit") && !userRoles.contains("upload")){
  105. //只拥有编辑权限
  106. page = new PageInfo<>(houseService2.findBySearchKeyForEditOrUploader(param, userId ,null));
  107. }else if (!userRoles.contains("edit") && userRoles.contains("upload")){
  108. //只拥有上传权限
  109. page = new PageInfo<>(houseService2.findBySearchKeyForEditOrUploader(param, null ,userId));
  110. }else{
  111. //理论上不存在此分支情况
  112. log.error("上传的权限超出了当前有效权限范围");
  113. throw new CommonBaseException(ResultCodeEnum.D101 , "存在无效权限");
  114. }
  115. }else if(userRoles.size() == 1){
  116. if(userRoles.contains("edit")){
  117. //只拥有编辑权限
  118. page = new PageInfo<>(houseService2.findBySearchKeyForEditOrUploader(param, userId ,null));
  119. }else if (userRoles.contains("upload")){
  120. //只拥有上传权限
  121. page = new PageInfo<>(houseService2.findBySearchKeyForEditOrUploader(param, null ,userId));
  122. }else{
  123. //只有管理用户的权限,理论不应该单独给这种角色
  124. log.warn("用户[{}]只单独给了用户管理权限" ,userId);
  125. throw new CommonBaseException(ResultCodeEnum.D101 , "当前权限不能查看数据");
  126. }
  127. }else{
  128. log.info("用户[{}]的权限超过3个,默认给拉取所有房源");
  129. //默认获取全部
  130. page = new PageInfo<>(houseService2.findBySearchKeyForEditOrUploader(param, null, null));
  131. }
  132. return new R(2000, page);
  133. }
  134. /**
  135. * 服务器版本+垂直校验
  136. *
  137. * 使用mq队列
  138. *
  139. * 上传文件,不能使用json传参,只能用表单
  140. *
  141. * 如果图片审核不通过,就直接把这条记录禁用or删除,从新添加一条。
  142. * 修改只能修改房源信息,不能修改图片
  143. *
  144. * 上传的图片必须是以xxx_xxx.jpg 格式命名,xxx_:图片所属的户型
  145. *
  146. *
  147. * 这里要用手写的表单验证验证方式
  148. *
  149. * 提前把垂直校验,模型图片地址写入数据库,需要配合状态来判断算法计算是否完成;
  150. */
  151. @RequiresRoles(value = {"admin", "edit", "upload"}, logical = Logical.OR)
  152. @ApiOperation("新增或修改房源信息 + 垂直校验")
  153. @PostMapping(value = "save", consumes = {"multipart/form-data"})
  154. @Transactional(rollbackFor = Exception.class)
  155. public R save(HouseDto param){
  156. if(StringUtils.isBlank(param.getDistrictName())){
  157. log.error("小区名称不能为空");
  158. return new R(MsgCode.e_COMMON_3001, "小区名称不能为空");
  159. }
  160. if(null == param.getFloor() || !StringUtils.isNoneBlank(param.getUnitType() , param.getArea() , param.getOrientation())){
  161. return new R(MsgCode.e_COMMON_3001, "楼层/户型/面积/朝向不能为空");
  162. }
  163. List<String> fileNames = param.getFileNames();
  164. if(CollectionUtils.isEmpty(fileNames)){
  165. return new R(MsgCode.e_COMMON_3001, "照片名称列表不能为空");
  166. }
  167. boolean isNewAdd = false;
  168. HouseEntity house = null;
  169. if (null != param.getIsCreate() && param.getIsCreate().compareTo(0) == 0) {
  170. isNewAdd = true;
  171. }
  172. house = updateOrInsertHouse(param);
  173. // 只有新增是才保存图片,修改时另外处理
  174. if (isNewAdd) {
  175. //场景码
  176. String sceneCode = house.getSceneCode();
  177. boolean needSendMqMsg = false;
  178. String directoryName = OUTPATH + sceneCode + File.separator + "input_img"+ File.separator;
  179. FileUtil.mkdir(directoryName);
  180. HashMap<String, String> ossVerticalImageHighMap = new HashMap<>();
  181. HashMap<String, String> ossVerticalImageLowMap = new HashMap<>();
  182. String imageHighPath = null;
  183. String imageLowPath = null;
  184. for (String filename : fileNames) {
  185. JSONObject jsonObject = JSON.parseObject(filename);
  186. if(null == jsonObject){
  187. log.error("转换json对象失败:{}" , filename);
  188. continue;
  189. }
  190. //原始照片在oss的路径
  191. String origin = jsonObject.getString("origin");
  192. String newFileName = jsonObject.getString("name");
  193. if(!StringUtils.isNoneEmpty(origin , newFileName)){
  194. continue;
  195. }
  196. checkAndChangeFileName(newFileName);
  197. //从oss获取照片,然后用新的名字下载到本地
  198. Map<String , Object> ossInfo = getOssBucketInfo(origin);
  199. if(CollectionUtils.isEmpty(ossInfo)){
  200. log.info("oss数据解析失败,跳过");
  201. continue;
  202. }
  203. String bucketName = (String) ossInfo.get("ossBucket");
  204. String ossObjKey = (String) ossInfo.get("ossKey");
  205. if(!StringUtils.isNoneBlank(bucketName , ossObjKey)){
  206. log.info("oss的bucketName数据解析失败,跳过");
  207. continue;
  208. }
  209. String oldImageName = "";
  210. int index = ossObjKey.lastIndexOf("/");
  211. if(index == -1){
  212. log.error("[{}]获取不到改名前的名称" , ossObjKey);
  213. continue;
  214. }
  215. oldImageName = ossObjKey.substring(index + 1);
  216. log.info("照片改名前的名称为:{}" , oldImageName);
  217. //这里改名
  218. String newFilePath = directoryName + newFileName;
  219. String oldFilePath = directoryName + oldImageName;
  220. File oldImageFile = new File(oldFilePath);
  221. File newImageFile = new File(newFilePath);
  222. try {
  223. org.apache.commons.io.FileUtils.copyFile(oldImageFile, newImageFile);
  224. } catch (IOException e) {
  225. log.error("改名操作出现异常,跳过");
  226. e.printStackTrace();
  227. continue;
  228. }
  229. boolean del = FileUtils.deleteFile(oldFilePath);
  230. log.info("删除的文件目录为:{},删除结果为:{}" , oldFilePath , del);
  231. //用于四维看看的
  232. imageHighPath = OUTPATH + sceneCode + "/output_img/" + newFileName;
  233. //用于sketch,sketch的image表需要存储这个路径,给前端使用
  234. imageLowPath = OUTPATH + sceneCode + "/output_img_low/" + newFileName;
  235. // 提前把算法的图片路径存到数据库,但不代表算法运行成功,最后好是要看house的状态;
  236. String ossVerticalHighPath = ConstantFilePath.OSS_IMAGE_PATH+ sceneCode+"/pan/high/"+ newFileName;
  237. String ossVerticalLowPath = ConstantFilePath.OSS_IMAGE_PATH+ sceneCode+"/pan/low/"+ newFileName;
  238. //TODO:这里需要计算分辨率
  239. //照片分辨率
  240. int totalResolutinRate = 0;
  241. try {
  242. totalResolutinRate = getImageResolutinoRate(newImageFile);
  243. } catch (IOException e) {
  244. log.error("计算照片[{}]分辨率出异常" , newFilePath);
  245. e.printStackTrace();
  246. }
  247. ImageResolutionRate maxResolutionRate = ImageResolutionRate.getResolutionRateByRate(totalResolutinRate);
  248. log.info("照片{}的像素为:{}" , newFilePath , totalResolutinRate);
  249. addNewImage(param.getId() , newFileName , newFilePath , ossVerticalLowPath, maxResolutionRate);
  250. // 封装垂直校验后的图片到信息到oss,key为照片在本地的路径,value为照片在oss中的目录路径
  251. //给四维看看的前端加载使用
  252. ossVerticalImageHighMap.put(imageHighPath, ossVerticalHighPath); //四维看看用的,文件太大
  253. //给sketch的前端使用
  254. ossVerticalImageLowMap.put(imageLowPath, ossVerticalLowPath); //sketch用的,文件适中
  255. needSendMqMsg = true;
  256. }
  257. insertScene(param.getImageMaxRate() , house);
  258. if (needSendMqMsg) {
  259. HashMap<Object, Object> mqMap = new HashMap<>();
  260. mqMap.put("ossImageHigh", ossVerticalImageHighMap);
  261. mqMap.put("ossImageLow", ossVerticalImageLowMap);
  262. mqMap.put("id", house.getId());
  263. mqMap.put("basePath", OUTPATH);
  264. mqMap.put("dataDescribe", "");
  265. log.info("houseId: {}", house.getId());
  266. //发消息到mq
  267. rabbitTemplate.convertAndSend(RabbitConfig.VERTICAL_EXCHANGE, RabbitConfig.VERTICAL_QUEUE_ROUTING, mqMap);
  268. }
  269. //新增这里,给管理员发送邮件
  270. String emailContent = "【四维看看 Sketch】温馨提示:用户上传了新的房源,请尽快完成制作。点击立即登录查看:https://sk.4dkankan.com";
  271. String subject = "四维看看sketch通知";
  272. try {
  273. MailUtils.sendHtmlMail(adminEmailAccount,subject,emailContent);
  274. } catch (UnsupportedEncodingException e) {
  275. log.error("发送邮件给管理员出错");
  276. e.printStackTrace();
  277. } catch (MessagingException e) {
  278. log.error("发送邮件给管理员出错");
  279. e.printStackTrace();
  280. }
  281. }
  282. return new R(MsgCode.SUCCESS_CODE, house);
  283. }
  284. public Map<String ,Object> getOssBucketInfo(String ossUrl){
  285. Map<String , Object> result = new HashMap<>();
  286. if(StringUtils.isBlank(ossUrl)){
  287. return result;
  288. }
  289. log.info("oss资源的路径为:{}" , ossUrl);
  290. int bucketStar = ossUrl.indexOf("://");
  291. if(bucketStar == -1){
  292. log.error("oss路径没有://");
  293. return result;
  294. }
  295. bucketStar += 3;
  296. int buckeEnd = ossUrl.indexOf(".");
  297. if(buckeEnd == -1){
  298. log.error("oss路径没有./");
  299. return result;
  300. }
  301. String buckeName = ossUrl.substring(bucketStar , buckeEnd);
  302. log.info("解析的buckeName={}" , buckeName);
  303. int keyStart = ossUrl.indexOf("com/");
  304. if(keyStart == -1){
  305. log.error("oss路径没有com/");
  306. return result;
  307. }
  308. keyStart += 5;
  309. String key = ossUrl.substring(keyStart , ossUrl.length());
  310. log.info("解析出来的oss key={}" , key);
  311. result.put("ossBucket" , buckeName);
  312. result.put("ossKey" , key);
  313. return result;
  314. }
  315. // @RequiresRoles(value = {"admin", "edit", "upload"}, logical = Logical.OR)
  316. @ApiOperation("生成houseId和场景码")
  317. @PostMapping(value = "addPosition")
  318. @Transactional(rollbackFor = Exception.class)
  319. public R addPosition(){
  320. return new R(MsgCode.SUCCESS_CODE, generateHouseIdAndSceneNum());
  321. }
  322. @ApiOperation("从OSS上下载原始照片并生成缩略图")
  323. @PostMapping(value = "uploadImages")
  324. @Transactional(rollbackFor = Exception.class)
  325. @ApiImplicitParams({
  326. @ApiImplicitParam(name = "file", value = "文件", paramType = "query", required = true, dataType = "List"),
  327. @ApiImplicitParam(name = "sceneCode", value = "场景码", paramType = "query", required = true, dataType = "String"),
  328. @ApiImplicitParam(name = "houseId", value = "房间ID", paramType = "query", required = true, dataType = "Long")
  329. })
  330. public Result uploadImages(@RequestParam(name = "sceneCode") String sceneCode,
  331. @RequestParam(name = "ossBucketName") String ossBucketName,
  332. @RequestParam(name = "ossObjectKey") String ossObjectKey){
  333. return Result.success("成功" , genScaleImage(ossBucketName , ossObjectKey , sceneCode));
  334. }
  335. @Transactional(rollbackFor = Exception.class)
  336. public void insertScene(String maxResolutionRate , HouseEntity house){
  337. SceneProEntity sceneProEntity = new SceneProEntity();
  338. SceneProEditEntity sceneProEditEntity = new SceneProEditEntity();
  339. if(ImageResolutionRate.TWO_K.name().equals(maxResolutionRate)){
  340. //2k
  341. sceneProEntity.setSceneScheme(11);
  342. }else{
  343. //4k
  344. sceneProEntity.setSceneScheme(10);
  345. }
  346. sceneProEntity.setNum(house.getSceneCode());
  347. //TODO:不知道为何数据库设置的默认不生效
  348. sceneProEditEntity.setM2dVisi(1);
  349. sceneProEditEntity.setM3dVisi(1);
  350. sceneProEditEntity.setPanoVisi(1);
  351. sceneProEditEntity.setMapVisi(1);
  352. int insertOne = sceneProService.save(sceneProEntity);
  353. if(insertOne != 1){
  354. throw new CommonBaseException(ResultCodeEnum.D101, "新增scenePro记录失败");
  355. }
  356. sceneProEditEntity.setProId(sceneProEntity.getId());
  357. int insertTwo = sceneProEditService.save(sceneProEditEntity);
  358. if(insertTwo != 1){
  359. throw new CommonBaseException(ResultCodeEnum.D101, "新增sceneProEdit记录失败");
  360. }
  361. }
  362. public String genScaleImage(String ossBucketName , String ossObjectKey , String sceneCode){
  363. String scalImageOssUrl = "";
  364. if(!StringUtils.isNoneEmpty(ossBucketName)){
  365. log.error("oss的bucketName 和ossKey不能为空");
  366. return scalImageOssUrl;
  367. }
  368. try {
  369. String fileName = "";
  370. int index = ossObjectKey.lastIndexOf("/");
  371. if(index != -1){
  372. fileName = ossObjectKey.substring(index + 1 , ossObjectKey.length());
  373. }else{
  374. log.error("ossObjectKey[{}]的格式不正确,无法提取文件名" , ossObjectKey);
  375. }
  376. String directoryName = OUTPATH + sceneCode + File.separator + "input_img"+ File.separator;
  377. String localFile = ossCheckPointUploadUtil.downLoadOssFileWithSdk(directoryName , "",
  378. ossBucketName , ossObjectKey);
  379. if(StringUtils.isNotBlank(localFile)){
  380. //生成缩略图,并上传到oss
  381. String scalImageFullPath = directoryName + "scal_" + fileName;
  382. log.info("要转换的照片的路径:{},转换的目标路径:{}" , localFile , scalImageFullPath);
  383. Thumbnails.of(localFile).size(980, 490).toFile(scalImageFullPath);
  384. String imageOssPath = ossPath + "scal_" + fileName;
  385. log.info("生成的照片上传oss的路径:{}" , imageOssPath);
  386. ossCheckPointUploadUtil.upload2(scalImageFullPath, imageOssPath);
  387. scalImageOssUrl = ossQueryUrl + imageOssPath;
  388. //删除缩略图的本地文件
  389. boolean delScalResult = FileUtils.deleteFile(scalImageFullPath);
  390. if(!delScalResult){
  391. log.error("删除本地缩略图[{}]失败" , scalImageFullPath);
  392. }
  393. }
  394. } catch (IOException e) {
  395. log.error("从oss上下载照片到本地出现异常");
  396. e.printStackTrace();
  397. }
  398. return scalImageOssUrl;
  399. }
  400. @Transactional(rollbackFor = Exception.class)
  401. // public ImageResolutionRate addAndGetResolutionRate(MultipartFile file , String filename,String directoryName ,
  402. public Map<String ,Object> addAndGetResolutionRate(CommonsMultipartFile file , String filename,
  403. String directoryName ,
  404. String ossVerticalHighPath ,
  405. Long houseId) throws IOException {
  406. if(null == file || null == houseId){
  407. log.error("房源id或者文件为空,无法生成image记录");
  408. return new HashMap<>();
  409. }
  410. File dir = new File(directoryName);
  411. if(!dir.exists()){
  412. dir.mkdirs();
  413. }
  414. // 本地图片保存位置: /root/data/kanfang/场景码/input_img/xxxx.jpg
  415. String newFileName = generalRandFileName(filename);
  416. log.info("修改后的文件名称为:{}" , newFileName);
  417. String fileFullPath = directoryName + newFileName;
  418. String oldFileFullPath = directoryName + filename;
  419. ossVerticalHighPath = ossVerticalHighPath + newFileName;
  420. ImageEntity image = new ImageEntity();
  421. image.setVerticalPath(ossVerticalHighPath);
  422. image.setFileName(newFileName);
  423. // 这个参数给前端用,只要有文件名就可以了
  424. image.setPath(fileFullPath);
  425. image.setLocalPath(fileFullPath);
  426. image.setHouseId(houseId);
  427. // 默认所有图片都是一楼
  428. image.setFloor(1);
  429. // image.setType(imageType);
  430. //将图片保存到本地指定目录filePath eg: /root/data/kanfang/d_9iRDUgn3l/input_img/xxx.jpg
  431. saveFileToLocal(file , fileFullPath);
  432. boolean delResult = FileUtils.deleteFile(oldFileFullPath);
  433. if(!delResult){
  434. log.error("删除旧文件[{}]失败" , oldFileFullPath);
  435. }
  436. File localFile = new File(fileFullPath);
  437. //生成缩略图,并上传到oss
  438. String scalImageFullPath = directoryName + "scal_" + newFileName;
  439. Thumbnails.of(localFile).size(128 , 256).outputQuality(0.8f).toFile(scalImageFullPath);
  440. String imageOssPath = ossPath + "scal_" + newFileName;
  441. log.info("生成的照片上传oss的路径:{}" , imageOssPath);
  442. ossCheckPointUploadUtil.upload2(scalImageFullPath, imageOssPath);
  443. String imageTotalOssUrl = ossQueryUrl + imageOssPath;
  444. //删除缩略图的本地文件
  445. boolean delScalResult = FileUtils.deleteFile(scalImageFullPath);
  446. if(!delScalResult){
  447. log.error("删除本地缩略图[{}]失败" , scalImageFullPath);
  448. }
  449. //照片分辨率
  450. int totalResolutinRate = getImageResolutinoRate(localFile);
  451. ImageResolutionRate maxResolutionRate = ImageResolutionRate.getResolutionRateByRate(totalResolutinRate);
  452. log.info("照片{}的像素为:{}" , fileFullPath , totalResolutinRate);
  453. image.setResolutionRate(null != maxResolutionRate ? maxResolutionRate.name() : "TWO_K");
  454. int insert = imageService2.save(image);
  455. if(insert != 1){
  456. throw new CommonBaseException(ResultCodeEnum.D101, "新增image记录失败");
  457. }
  458. Map<String , Object> result = new HashMap<>();
  459. result.put("rate" , maxResolutionRate.name());
  460. result.put("fileName" , newFileName);
  461. result.put("ossUrl" , imageTotalOssUrl);
  462. return result;
  463. }
  464. private void addNewImage(long houseId,
  465. String imageFileName , String imageLocalPath ,
  466. String ossVerticalHighPath,
  467. ImageResolutionRate maxResolutionRate){
  468. ImageEntity image = new ImageEntity();
  469. // 获取图片房间类型
  470. String imageType = StringUtils.substringBefore(imageFileName, "_");
  471. image.setType(imageType);
  472. image.setVerticalPath(ossVerticalHighPath);
  473. image.setFileName(imageFileName);
  474. // 这个参数给前端用,只要有文件名就可以了
  475. image.setPath(imageLocalPath);
  476. image.setLocalPath(imageLocalPath);
  477. image.setHouseId(houseId);
  478. // 默认所有图片都是一楼
  479. image.setFloor(1);
  480. image.setResolutionRate(null != maxResolutionRate ? maxResolutionRate.name() : "TWO_K");
  481. int insert = imageService2.save(image);
  482. if(insert != 1){
  483. throw new CommonBaseException(ResultCodeEnum.D101, "新增image记录失败");
  484. }
  485. }
  486. private String generalRandFileName(String fileName){
  487. if(StringUtils.isBlank(fileName)){
  488. return "";
  489. }
  490. int index = fileName.lastIndexOf(".");
  491. if(index != -1){
  492. String name = fileName.substring(0 , index);
  493. String form = fileName.substring(index , fileName.length());
  494. log.info("照片存名字部分为:{}" , name);
  495. if(StringUtils.isNotBlank(name)){
  496. Random random = new Random(10);
  497. name += System.currentTimeMillis() + random.nextInt(10);
  498. name += form;
  499. return name;
  500. }
  501. }
  502. return "";
  503. }
  504. private int getImageResolutinoRate(File localFile) throws IOException {
  505. if(null != localFile){
  506. int totalResolutinRate = -1;
  507. SimpleImageInfo simpleImageInfo = new SimpleImageInfo(localFile);
  508. if(null != simpleImageInfo){
  509. if(simpleImageInfo.getWidth() < simpleImageInfo.getHeight()){
  510. totalResolutinRate = simpleImageInfo.getHeight();
  511. }else{
  512. totalResolutinRate = simpleImageInfo.getWidth();
  513. }
  514. }
  515. return totalResolutinRate;
  516. }
  517. return 0;
  518. }
  519. private void saveFileToLocal(CommonsMultipartFile file , String localFullPath) throws IOException {
  520. if(StringUtils.isBlank(localFullPath) || null == file){
  521. return;
  522. }
  523. File newFile = new File(localFullPath);
  524. file.transferTo(newFile);
  525. }
  526. private String checkAndChangeFileName(String filename){
  527. if(StringUtils.isBlank(filename)){
  528. throw new CommonBaseException(ResultCodeEnum.D100 , "文件名不能为空");
  529. }
  530. if(filename.contains(".JPG")){
  531. int index = filename.lastIndexOf(".");
  532. String fileNameWithoutPostfix = filename.substring(0 , index);
  533. filename = fileNameWithoutPostfix + ".jpg";
  534. log.info("照片的格式写成了大写,需要转成小写:{}" , filename);
  535. }
  536. // 检查一下,生成模型的照片名称不能有"-",否则生成模型会出现问题
  537. if (filename.contains("-")) {
  538. log.error("filename: {}", filename);
  539. throw new BaseRuntimeException(MsgCode.e_COMMON_3003, "图片命名不符合要求,不能包含符号-,请使用_");
  540. }
  541. if (RegexpUtils.isContainChinese(filename)) {
  542. log.error("图片名称不允许中文字符: {}", filename);
  543. throw new BaseRuntimeException(MsgCode.e_COMMON_3003, "图片名称不允许中文字符");
  544. }
  545. return filename;
  546. }
  547. private Map<String , Object> generateHouseIdAndSceneNum(){
  548. Map<String ,Object> result = new HashMap<>();
  549. Integer byMaxNum = houseService2.findByMaxNum();
  550. // 用于第一条数据
  551. byMaxNum = (byMaxNum == null)? 10000:byMaxNum;
  552. byMaxNum += 1;
  553. String sceneCode = getSceneCode();
  554. HouseEntity house = new HouseEntity();
  555. UserEntity user = userUtils.getUserByToken(getToken());
  556. house.setUserId(user.getId());
  557. house.setNum(byMaxNum + 1);
  558. house.setSceneCode(sceneCode);
  559. house.setWebSite(domain+"?m="+sceneCode);
  560. house.setFilePath(OUTPATH + sceneCode);
  561. int insert = houseService2.save(house);
  562. if(insert != 1){
  563. log.error("新增房源失败");
  564. return result;
  565. }
  566. HouseEntity dbHouse = houseService2.findBySceneCode(sceneCode);
  567. if(null != dbHouse){
  568. result.put("id" , dbHouse.getId());
  569. result.put("sceneCode" , sceneCode);
  570. }
  571. return result;
  572. }
  573. @Transactional(rollbackFor = Exception.class)
  574. public HouseEntity updateOrInsertHouse(HouseDto param){
  575. if(null == param){
  576. return null;
  577. }
  578. HouseEntity house = null;
  579. if (param.getId() == null) {
  580. house = new HouseEntity();
  581. UserEntity user = userUtils.getUserByToken(getToken());
  582. house.setUserId(user.getId());
  583. param.setId(null);
  584. BeanUtils.copyProperties(param, house);
  585. Integer byMaxNum = houseService2.findByMaxNum();
  586. // 用于第一条数据
  587. byMaxNum = (byMaxNum == null)? 10000:byMaxNum;
  588. String sceneCode = getSceneCode();
  589. house.setNum(byMaxNum + 1);
  590. house.setSceneCode(sceneCode);
  591. house.setWebSite(domain+"?m="+sceneCode);
  592. house.setFilePath(OUTPATH + sceneCode);
  593. houseService2.save(house);
  594. } else {
  595. house = houseService2.findById(param.getId());
  596. if (house == null) {
  597. log.error("房源不存在: {}", param.getId());
  598. throw new CommonBaseException(ResultCodeEnum.D101 , "房源不存在");
  599. }
  600. BeanUtils.copyProperties(param, house);
  601. if(StringUtils.isBlank(house.getSceneCode())){
  602. house.setSceneCode(param.getSceneCode());
  603. }
  604. if(StringUtils.isBlank(house.getWebSite())){
  605. house.setWebSite(domain+"?m=" + param.getSceneCode());
  606. }
  607. if(StringUtils.isBlank(house.getFilePath())){
  608. house.setFilePath(OUTPATH + param.getSceneCode());
  609. }
  610. house.setUpdateTime(new Date());
  611. house.setStatus(0);
  612. houseService2.update(house);
  613. }
  614. return house;
  615. }
  616. @ApiOperation("预审")
  617. @ResponseBody
  618. @PostMapping(value = "/auditHouse")
  619. @Transactional(rollbackFor = Exception.class)
  620. public Result auditHouse(@RequestBody @ApiParam(name = "用户登录注册实体", value = "传入json格式", required = true) HouseAuditDto houseAuditDto) {
  621. if(StringUtils.isBlank(houseAuditDto.getDesc()) || null == houseAuditDto.getHouseId() || null == houseAuditDto.getResult()){
  622. throw new CommonBaseException(ResultCodeEnum.D3001);
  623. }
  624. HouseEntity houseEntity = houseService2.findById(houseAuditDto.getHouseId());
  625. if(null == houseEntity){
  626. throw new CommonBaseException(ResultCodeEnum.D101 , "房源不存在");
  627. }
  628. if(houseAuditDto.getResult().compareTo(1) != 0 && houseAuditDto.getResult().compareTo(0) != 0){
  629. throw new CommonBaseException(ResultCodeEnum.D101 , "审批结果格式不正确");
  630. }
  631. houseEntity.setAuditResult(houseAuditDto.getResult());
  632. houseEntity.setAuditDesc(houseAuditDto.getDesc());
  633. houseEntity.setUpdateTime(new Date());
  634. int update = houseService2.update(houseEntity);
  635. if(update != 1){
  636. throw new CommonBaseException(ResultCodeEnum.D101 , "更新房源预审信息失败");
  637. }
  638. return Result.success();
  639. }
  640. @ApiOperation("标记不能编辑")
  641. @ResponseBody
  642. @PostMapping(value = "/markFail")
  643. public Result markCannotEditHouse(@RequestBody @ApiParam(name = "用户登录注册实体", value = "传入json格式", required = true) HouseAuditDto houseAuditDto) {
  644. if(StringUtils.isBlank(houseAuditDto.getDesc()) || null == houseAuditDto.getHouseId()){
  645. throw new CommonBaseException(ResultCodeEnum.D3001);
  646. }
  647. HouseEntity houseEntity = houseService2.findById(houseAuditDto.getHouseId());
  648. if(null == houseEntity){
  649. throw new CommonBaseException(ResultCodeEnum.D101 , "房源不存在");
  650. }
  651. houseEntity.setCanNotEdit(0);
  652. houseEntity.setCanNotEditDesc(houseAuditDto.getDesc());
  653. houseEntity.setUpdateTime(new Date());
  654. int update = houseService2.update(houseEntity);
  655. if(update != 1){
  656. throw new CommonBaseException(ResultCodeEnum.D101 , "更新房源无法制作信息失败");
  657. }
  658. return Result.success();
  659. }
  660. /**
  661. *
  662. * @param houseId
  663. * @param floor 可选参数
  664. */
  665. @ApiOperation("查询房源信息")
  666. @GetMapping("detail")
  667. @ApiImplicitParams({
  668. @ApiImplicitParam(name = "houseId", value = "房源id", required = true),
  669. @ApiImplicitParam(name = "floor", value = "楼层", required = false)
  670. })
  671. public R detail(Long houseId, Integer floor){
  672. HouseEntity house = houseService2.findById(houseId);
  673. List<ImageEntity> images = imageService2.findByHouseIdAndFloor(houseId, floor);
  674. if(null != house){
  675. house.setImages(images);
  676. HouseResponse houseResponse = new HouseResponse();
  677. BeanUtil.copyProperties(house ,houseResponse , CopyOptions.create().setIgnoreNullValue(true).setIgnoreError(true));
  678. if(null != house.getUserId()){
  679. UserEntity uploader = userService2.findById(house.getUserId());
  680. if(null != uploader){
  681. houseResponse.setUploadName(uploader.getRealName());
  682. }
  683. }
  684. if(null != house.getHandler()){
  685. UserEntity handler = userService2.findById(house.getHandler());
  686. if(null != handler){
  687. houseResponse.setHandlerName(handler.getRealName());
  688. }
  689. }
  690. return new R(MsgCode.SUCCESS_CODE, houseResponse);
  691. }else{
  692. return new R(MsgCode.ERROR_CODE, "房源不存在");
  693. }
  694. }
  695. @RequiresRoles(value = {"admin", "edit", "upload"}, logical = Logical.OR)
  696. @ApiOperation("删除房源(软删除)")
  697. @GetMapping("removes/{ids}")
  698. @Transactional(rollbackFor = Exception.class)
  699. public R removes(@PathVariable String ids){
  700. List<String> userRoles = userUtils.getRolesByToken(getToken());
  701. String roleKey = null;
  702. if (userRoles.size() <= 1) {
  703. // 只有一个权限时
  704. roleKey = (String)userRoles.get(0);
  705. if (!"upload".equals(roleKey)) {
  706. log.warn("只有一个权限的非上传者角色,不能删除房源");
  707. throw new CommonBaseException(ResultCodeEnum.D101 , "权限不足,不能删除房源");
  708. }
  709. }else if(userRoles.size() == 2){
  710. if(userRoles.contains("edit") && userRoles.contains("admin")){
  711. //理论上不会有这种权限组合
  712. log.warn("多于一个权限的角色,只有用户管理和编辑房源权限不能删除房源");
  713. throw new CommonBaseException(ResultCodeEnum.D101 , "权限不足(缺少上传房源权限),不能删除房源");
  714. }
  715. }
  716. String[] split = ids.split(",");
  717. for (String s : split) {
  718. HouseEntity houseEntity = houseService2.findById(Long.valueOf(s));
  719. if (houseEntity == null) {
  720. log.error("房源id有误,没有存在的房源");
  721. return new R(MsgCode.e_COMMON_3002,"没有存在的房源");
  722. }
  723. if(null != houseEntity.getStatus()){
  724. if((houseEntity.getStatus().compareTo(0) == 0) && (null != houseEntity.getStatus() && houseEntity.getStatus().compareTo(1) == 0)){
  725. //预审通过了的,还未垂直校验的,不能删除
  726. log.error("房源垂直校验计算中不能删除");
  727. throw new CommonBaseException(ResultCodeEnum.D101 , "房源垂直校验计算中不能删除");
  728. }
  729. if(houseEntity.getStatus().compareTo(3) == 0){
  730. log.error("房源生成模型计算中不能删除");
  731. throw new CommonBaseException(ResultCodeEnum.D101 , "房源生成模型计算中不能删除");
  732. }
  733. }
  734. houseEntity.setRecStatus("I");
  735. houseEntity.setUpdateTime(new Date());
  736. int update = houseService2.update(houseEntity);
  737. if(update != 1){
  738. log.error( "删除房源失败[{}]" , houseEntity.getId());
  739. throw new CommonBaseException(ResultCodeEnum.D101 , "删除房源失败");
  740. }
  741. }
  742. return new R(MsgCode.SUCCESS_CODE, MsgCode.msg_SUCCESS);
  743. }
  744. /**
  745. * 更新sceneJson(写到另一个字段), 保留原始sceneJson数据
  746. *
  747. */
  748. @RequiresRoles(value = {"admin", "edit"}, logical = Logical.OR)
  749. @ApiOperation("更新sceneJson")
  750. @PostMapping("update/sceneJson")
  751. public R updateSceneJson(@Valid @RequestBody SceneJsonDto param){
  752. HouseEntity house = houseService2.findById(param.getId());
  753. if (house == null) {
  754. log.error("房源id不存在");
  755. return new R(MsgCode.e_COMMON_3001, "房源id不存在");
  756. }
  757. house.setNewSceneJson(param.getSceneJson());
  758. house.setUpdateTime(new Date());
  759. houseService2.update(house);
  760. return new R(MsgCode.SUCCESS_CODE, MsgCode.msg_SUCCESS);
  761. }
  762. @ApiOperation("获取楼层户型图")
  763. @GetMapping("image/find/floor/{houseId}/{floor}")
  764. public R findImageByFloor(@PathVariable Long houseId, @PathVariable Integer floor){
  765. List<ImageEntity> images = imageService2.findByHouseIdAndFloor(houseId, floor);
  766. return new R(MsgCode.SUCCESS_CODE, images);
  767. }
  768. /**
  769. * 只有管理员才能分配制作人
  770. * 制作人是edit角色
  771. */
  772. @RequiresRoles(value = {"admin"}, logical = Logical.OR)
  773. @ApiOperation("获取制作人")
  774. @GetMapping("getHandler")
  775. public R getHandler(){
  776. // 根据edit权限查询用户
  777. List<UserResponse> usre = roleService.findUserByRoleKey("edit");
  778. return new R(MsgCode.SUCCESS_CODE, usre);
  779. }
  780. @RequiresRoles(value = {"admin"}, logical = Logical.OR)
  781. @ApiOperation("分配制作人")
  782. @GetMapping("setHandler/{houseId}/{userId}")
  783. public R setHandler(@PathVariable Long houseId, @PathVariable Long userId){
  784. // 根据edit权限查询用户
  785. HouseEntity houseEntity = houseService2.findById(houseId);
  786. if (houseEntity == null) {
  787. log.error("房源不存在: {}", houseId);
  788. return new R(MsgCode.e_COMMON_3001, "房源不存在");
  789. }
  790. houseEntity.setHandler(userId);
  791. houseEntity.setUpdateTime(new Date());
  792. if(null != houseEntity.getAuditResult() && houseEntity.getAuditResult().compareTo(0) == 0){
  793. //重新分配制作人,前面不通过的审批,需要擦除,TODO:需要添加一个上一状态,用于追踪
  794. houseEntity.setAuditResult(null);
  795. houseEntity.setAuditDesc(null);
  796. houseEntity.setCanNotEdit(1);
  797. houseEntity.setCanNotEditDesc(null);
  798. }
  799. if(null != houseEntity.getCanNotEdit() && houseEntity.getCanNotEdit().compareTo(0) == 0){
  800. //重新分配制作人,前面不通过的审批,需要擦除,TODO:需要添加一个上一状态,用于追踪
  801. houseEntity.setAuditResult(null);
  802. houseEntity.setAuditDesc(null);
  803. houseEntity.setCanNotEdit(1);
  804. houseEntity.setCanNotEditDesc(null);
  805. }
  806. int update = houseService2.updateAll(houseEntity);
  807. if(update != 1){
  808. throw new CommonBaseException(ResultCodeEnum.D101 , "更新房源数据失败");
  809. }
  810. return new R(MsgCode.SUCCESS_CODE, MsgCode.msg_SUCCESS);
  811. }
  812. @ApiOperation("查询房源图片")
  813. @GetMapping("image/detail/{id}")
  814. public R imageDetail(@PathVariable Long id){
  815. return new R(MsgCode.SUCCESS_CODE, imageService2.findById(id));
  816. }
  817. @RequiresRoles(value = {"admin", "edit"}, logical = Logical.OR)
  818. @ApiOperation("编辑图片信息")
  819. @PostMapping("image/edit")
  820. public R imageEdit(@RequestBody ImageDto param){
  821. ImageEntity image = imageService2.findById(param.getId());
  822. if (image == null){
  823. log.error("图片id不存在: {}" , param.getId());
  824. throw new BaseRuntimeException(MsgCode.e_COMMON_3002, MsgCode.msg_COMMON_3002);
  825. }
  826. BeanUtils.copyProperties(param, image);
  827. image.setUpdateTime(new Date());
  828. imageService2.update(image);
  829. return new R(MsgCode.SUCCESS_CODE, MsgCode.msg_SUCCESS);
  830. }
  831. @RequiresRoles(value = {"admin", "edit"}, logical = Logical.OR)
  832. @ApiOperation("批量编辑图片信息")
  833. @PostMapping("image/edit/all")
  834. public R imageEdit(@RequestBody Map<Long, String> param){
  835. for (Map.Entry<Long, String> a : param.entrySet()) {
  836. ImageEntity image = imageService2.findById(a.getKey());
  837. image.setUpdateTime(new Date());
  838. image.setIssue(a.getValue());
  839. imageService2.update(image);
  840. }
  841. return new R(MsgCode.SUCCESS_CODE, MsgCode.msg_SUCCESS);
  842. }
  843. /**
  844. * 陈世超的算法
  845. * 调用算法计算场景,生产全景图
  846. *
  847. * 图片是用垂直校验后的图片
  848. *
  849. * Content传到后台会生成两个文件:floorplan.json、vision.txt
  850. */
  851. @RequiresRoles(value = {"admin", "edit"}, logical = Logical.OR)
  852. @ApiOperation("生成模型")
  853. @PostMapping("rsa/pano")
  854. @Transactional(rollbackFor = Exception.class)
  855. public R rsaPano(@Valid @RequestBody PanoDto param) throws Exception {
  856. log.info("run rsaPano");
  857. if (param == null) {
  858. log.error("参数为空");
  859. return new R(50001, "error");
  860. }
  861. HouseEntity house = houseService2.findById(param.getHouseId());
  862. if (house == null) {
  863. log.error("房源不存在: {}", param.getHouseId());
  864. return new R(MsgCode.e_COMMON_3002, MsgCode.msg_COMMON_3002);
  865. }
  866. String sceneCode = house.getSceneCode();
  867. boolean flagQ = false;
  868. // data/kanfang/10001/pano
  869. String savePath = OUTPATH + sceneCode + "/" + TypeCode.SCENE_PANO;
  870. // 检查场景码对应的pano文件夹是否存在,存在则删除里面的内容(用户从新编辑场景)
  871. if (FileUtil.isDirectory(savePath)) {
  872. FileUtil.del(savePath);
  873. log.info("删除旧目录重新计算: {}", sceneCode);
  874. }
  875. log.warn("savePath: {}", savePath);
  876. String sourcePath = savePath + "/extras/";
  877. String resultSourcePath = savePath + "/results/";
  878. try {
  879. FileUtils.createDir(sourcePath);
  880. FileUtils.createDirIfExistThenDel(resultSourcePath);
  881. /**
  882. * 以下字段为给算法部传递的参数(data.json),用于生成模型和
  883. * 照片,提供前端使用,完整的参数如下:
  884. * {
  885. * "split_type": "SPLIT_V5",
  886. * "skybox_type": "SKYBOX_V5",
  887. * "extras": {
  888. * "has_vision_txt": true,
  889. * "has_floorplan_json": true,
  890. * "has_source_images": true
  891. * }
  892. * }
  893. * */
  894. String content = "";
  895. //生成data.json供算法部使用
  896. JSONObject dataJson = new JSONObject();
  897. dataJson.put("split_type", "SPLIT_V5");
  898. String imageResolution = checkImageResolutionRate(house);
  899. if(ImageResolutionRate.TWO_K.name().equals(imageResolution)){
  900. //2 K 照片
  901. dataJson.put("skybox_type", "SKYBOX_V7");
  902. }else{
  903. //4 k照片
  904. dataJson.put("skybox_type", "SKYBOX_V6");
  905. }
  906. dataJson.put("extras", null);
  907. JSONObject extrasJson = new JSONObject();
  908. extrasJson.put("has_vision_txt" , true);
  909. extrasJson.put("has_floorplan_json" , true);
  910. extrasJson.put("has_source_images" , true);
  911. dataJson.put("extras" , extrasJson);
  912. FileUtils.fileWriter(dataJson.toJSONString(), savePath + "/data.json");
  913. log.warn("dataJson的生成路径: {}", savePath + "/data.json");
  914. // 解析json
  915. JSONObject original = JSON.parseObject(param.getContent());
  916. // 获取modelData, cameraData
  917. String floorPlan = original.getString("floorplan");
  918. String vision = original.getString("vision");
  919. if (floorPlan == null) {
  920. log.error("floorPlan不能为空");
  921. return new R(50002, "floorPlan不能为空");
  922. }
  923. if (vision == null) {
  924. log.error("vision不能为空");
  925. return new R(50002, "vision不能为空");
  926. }
  927. // json写入服务器
  928. FileUtils.fileWriter(floorPlan, sourcePath + "floorplan.json");
  929. FileUtils.fileWriter(vision, sourcePath + "vision.txt");
  930. FileUtils.fileWriter(vision, resultSourcePath + "vision.txt");
  931. log.info("floorplan.json生成完成");
  932. log.info("/extras/vision.txt,/results/vision.txt生成完成");
  933. // 复制垂直校验图片到指定目录
  934. String verticalImagePath = OUTPATH + sceneCode+"/output_img";
  935. String panoImagePath = sourcePath + "images/";
  936. // srcPath: /data/kanfang/10002/output_img
  937. log.info("srcPath: {}", verticalImagePath);
  938. // target: /data/kanfang/10002/pano/extras/images/
  939. log.info("target: {}", panoImagePath);
  940. FileUtil.copyFilesFromDir(new File(verticalImagePath), new File(panoImagePath), true);
  941. flagQ = true;
  942. } catch (Exception e) {
  943. e.printStackTrace();
  944. log.error("出错了……");
  945. return new R(50002, e.getMessage());
  946. }
  947. if (flagQ) {
  948. // 上传floorplan.json到oss, 并命名为floor.json
  949. HashMap<String, String> uploadJson = new HashMap<>();
  950. // osspath : images/images+sceneCode/floor.json
  951. uploadJson.put(sourcePath + "floorplan.json", ConstantFilePath.OSS_FLOOR_PATH+sceneCode+"/floor.json");
  952. AliyunOssUtil.uploadMulFiles(uploadJson);
  953. // savePath:/data/kanfang/房源编号/
  954. // basePath: /data/kanfang/10002/pano
  955. log.info("basePath: {}", savePath);
  956. log.info("houseId: {}", house.getId());
  957. // 每点击生成模型一次,就修改SceneProEditEntity的部分值
  958. SceneProEntity sceneProEntity = sceneProService.findBySceneNum(house.getSceneCode());
  959. if (sceneProEntity == null) {
  960. log.error("sceneProEntity对象不存在:{}", house.getSceneCode());
  961. return new R(MsgCode.ERROR_CODE, "sceneProEntity对象不存在");
  962. }
  963. // 修改房源状态, 3:模型计算中
  964. house.setStatus(3);
  965. house.setUpdateTime(new Date());
  966. int updateHouse = houseService2.update(house);
  967. if(updateHouse != 1){
  968. throw new CommonBaseException(ResultCodeEnum.D101 , "更新房源状态失败");
  969. }
  970. SceneProEditEntity proEditEntity = sceneProEditService.findByProId(sceneProEntity.getId());
  971. proEditEntity.setVersion(proEditEntity.getVersion() + 1);
  972. proEditEntity.setFloorEditVer(proEditEntity.getFloorEditVer() + 1);
  973. proEditEntity.setFloorPublishVer(proEditEntity.getFloorPublishVer() + 1);
  974. proEditEntity.setUpdateTime(new Date());
  975. int updateSceneProEdit = sceneProEditService.update(proEditEntity);
  976. if(updateSceneProEdit != 1){
  977. throw new CommonBaseException(ResultCodeEnum.D101 , "更新sceneProEdit状态失败");
  978. }
  979. log.info("更新SceneProEditEntity数据完成");
  980. //发消息到mq
  981. Map<String, Object> mqMap = formatMqReq(house , sceneProEntity , savePath , RabbitConfig.PANO_CALLBACK_QUEUE);
  982. String mqMapStr = JSON.toJSONString(mqMap);
  983. log.info("发送mq消息给四维看看建模:{}", mqMapStr);
  984. rabbitTemplate.convertAndSend(RabbitConfig.PANO_EXCHANGE, RabbitConfig.PANO_QUEUE_ROUTING, mqMapStr);
  985. log.info("Mq入队成功");
  986. }
  987. return new R(MsgCode.SUCCESS_CODE, house);
  988. }
  989. private Map<String, Object> formatMqReq(HouseEntity house , SceneProEntity sceneProEntity ,
  990. String path, String callbackQueue){
  991. Map<String ,Object> result = new HashMap<>();
  992. if(null == house){
  993. return result;
  994. }
  995. result.put("sceneName" , house.getDistrictName());
  996. result.put("sceneNum" , house.getSceneCode());
  997. result.put("sceneScheme" , sceneProEntity.getSceneScheme());
  998. if(null != house.getUserId()){
  999. UserEntity user = userService2.findById(house.getUserId());
  1000. int kankanUserId = -1;
  1001. if(null != user && null != user.getKankanUserId()){
  1002. kankanUserId = user.getKankanUserId();
  1003. }
  1004. result.put("userId" , kankanUserId);
  1005. }
  1006. result.put("dataSource" , path);
  1007. result.put("callbackQueue" , callbackQueue);
  1008. return result;
  1009. }
  1010. private String checkImageResolutionRate(HouseEntity houseEntity){
  1011. if(null == houseEntity || null == houseEntity.getId()){
  1012. return null;
  1013. }
  1014. List<ImageEntity> imageEntities = imageService2.findByHouseId(houseEntity.getId());
  1015. if(CollectionUtils.isEmpty(imageEntities)){
  1016. log.error("房源[{}]下面无照片,默认返回2k的分辨率");
  1017. return ImageResolutionRate.TWO_K.name();
  1018. }
  1019. int sort = 0;
  1020. ImageResolutionRate maxResolution = null;
  1021. for (ImageEntity imageEntity : imageEntities){
  1022. if(StringUtils.isBlank(imageEntity.getResolutionRate())){
  1023. log.warn("房源[{}]的照片[{}]没有设置照片分辨率,跳过" , houseEntity.getId() , imageEntity.getId());
  1024. break;
  1025. }
  1026. ImageResolutionRate curResolution = ImageResolutionRate.getResolutionByName(imageEntity.getResolutionRate());
  1027. if(null != curResolution){
  1028. if(curResolution.getOrder() > sort){
  1029. sort = curResolution.getOrder();
  1030. maxResolution = curResolution;
  1031. }
  1032. }
  1033. }
  1034. log.info("房源[{}]的照片最大的分辨率为:{}" , houseEntity.getId() , null != maxResolution ? maxResolution.name() :"空值");
  1035. return null != maxResolution ? maxResolution.name() : ImageResolutionRate.TWO_K.name();
  1036. }
  1037. /***
  1038. * 从四维看看获取唯一场景码
  1039. */
  1040. private String getSceneCode(){
  1041. String url = KankanHost + "api/scene/finSkSceneNum";
  1042. String kankanResult = HttpClientUtil.doPost(url);
  1043. //解析返回结果
  1044. JSONObject res = JSONObject.parseObject(kankanResult);
  1045. log.info("四维看看返回登录数据:{}" , null != res ? res.toJSONString() : "返回结果为null");
  1046. Integer code = DataUtils.getInteger(res.get("code"));
  1047. if(null == code || code.compareTo(0) != 0){
  1048. throw new CommonBaseException(ResultCodeEnum.D101 , "从四维看看获取场景码失败");
  1049. }
  1050. String sceneCode = res.getString("msg");
  1051. if(StringUtils.isBlank(sceneCode)){
  1052. throw new CommonBaseException(ResultCodeEnum.D101 , "四维看看返回的场景码为空");
  1053. }
  1054. return sceneCode;
  1055. }
  1056. }