CutModelServiceImpl.java 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283
  1. package com.fdkankan.scene.service.impl;
  2. import cn.hutool.core.collection.CollUtil;
  3. import cn.hutool.core.io.FileUtil;
  4. import cn.hutool.core.util.StrUtil;
  5. import com.alibaba.fastjson.JSON;
  6. import com.alibaba.fastjson.JSONArray;
  7. import com.alibaba.fastjson.JSONObject;
  8. import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
  9. import com.fdkankan.common.constant.CommonStatus;
  10. import com.fdkankan.common.constant.ErrorCode;
  11. import com.fdkankan.common.constant.FileBizType;
  12. import com.fdkankan.common.exception.BusinessException;
  13. import com.fdkankan.common.util.FileUtils;
  14. import com.fdkankan.fyun.face.FYunFileServiceInterface;
  15. import com.fdkankan.model.constants.ConstantFilePath;
  16. import com.fdkankan.model.constants.UploadFilePath;
  17. import com.fdkankan.redis.constant.RedisKey;
  18. import com.fdkankan.redis.constant.RedisLockKey;
  19. import com.fdkankan.redis.util.RedisLockUtil;
  20. import com.fdkankan.redis.util.RedisUtil;
  21. import com.fdkankan.scene.bean.TagBean;
  22. import com.fdkankan.scene.entity.SceneEditInfoExt;
  23. import com.fdkankan.scene.entity.ScenePlus;
  24. import com.fdkankan.scene.entity.ScenePlusExt;
  25. import com.fdkankan.scene.service.*;
  26. import com.fdkankan.scene.vo.BaseJsonArrayParamVO;
  27. import com.fdkankan.scene.vo.BaseSceneParamVO;
  28. import com.fdkankan.scene.vo.DeleteFileParamVO;
  29. import com.fdkankan.scene.vo.DeleteSidListParamVO;
  30. import com.fdkankan.web.response.ResultData;
  31. import com.google.j2objc.annotations.AutoreleasePool;
  32. import org.springframework.beans.factory.annotation.Autowired;
  33. import org.springframework.stereotype.Service;
  34. import java.io.IOException;
  35. import java.util.*;
  36. import java.util.stream.Collectors;
  37. @Service
  38. public class CutModelServiceImpl implements ICutModelService {
  39. private final String CUT_MODEL_JSON_NAME = "cutModel.json";
  40. @Autowired
  41. private IScenePlusService scenePlusService;
  42. @Autowired
  43. private IScenePlusExtService scenePlusExtService;
  44. @Autowired
  45. private ISceneEditInfoExtService sceneEditInfoExtService;
  46. @Autowired
  47. private ISceneEditInfoService sceneEditInfoService;
  48. @Autowired
  49. private RedisUtil redisUtil;
  50. @Autowired
  51. private RedisLockUtil redisLockUtil;
  52. @Autowired
  53. private FYunFileServiceInterface fYunFileService;
  54. @Autowired
  55. private ISceneUploadService sceneUploadService;
  56. @Override
  57. public ResultData saveCutModel(BaseJsonArrayParamVO param) throws Exception {
  58. ScenePlus scenePlus = scenePlusService.getScenePlusByNum(param.getNum());
  59. this.addOrUpdate(param.getNum(), param.getData());
  60. //保存数据库
  61. SceneEditInfoExt sceneEditInfoExt = sceneEditInfoExtService.getByScenePlusId(scenePlus.getId());
  62. this.updateDb(param.getNum(), scenePlus.getId());
  63. // this.updateById(sceneEditInfoExt);
  64. sceneEditInfoService.upgradeVersionById(sceneEditInfoExt.getEditInfoId());
  65. return ResultData.ok();
  66. }
  67. @Override
  68. public List<JSONObject> listCutModel(BaseSceneParamVO param) throws Exception {
  69. List<JSONObject> tags = new ArrayList<>();
  70. ScenePlus scenePlus = scenePlusService.getScenePlusByNum(param.getNum());
  71. SceneEditInfoExt sceneEditInfoExt = sceneEditInfoExtService.getByScenePlusId(scenePlus.getId());
  72. this.syncFileToRedis(param.getNum());
  73. //获取裁剪模型数据
  74. String key = String.format(RedisKey.SCENE_CUT_MODEL, param.getNum());
  75. List<String> list = redisUtil.hgetValues(key);
  76. if(CollUtil.isNotEmpty(list)){
  77. List<TagBean> sortList = list.stream().map(str -> {
  78. JSONObject jsonObject = JSON.parseObject(str);
  79. TagBean tagBean = new TagBean();
  80. tagBean.setCreateTime(jsonObject.getLong("createTime"));
  81. jsonObject.remove("createTime");
  82. tagBean.setTag(jsonObject);
  83. return tagBean;
  84. }).collect(Collectors.toList());
  85. sortList.sort(Comparator.comparingLong(TagBean::getCreateTime).reversed());
  86. tags = sortList.stream().map(item -> item.getTag()).collect(Collectors.toList());
  87. }
  88. return tags;
  89. }
  90. @Override
  91. public ResultData deleteCutModel(DeleteSidListParamVO param) throws Exception {
  92. ScenePlus scenePlus = scenePlusService.getScenePlusByNum(param.getNum());
  93. ScenePlusExt scenePlusExt = scenePlusExtService.getScenePlusExtByPlusId(scenePlus.getId());
  94. String bucket = scenePlusExt.getYunFileBucket();
  95. List<String> deleteSidList = param.getSidList();
  96. this.syncFileToRedis(param.getNum());
  97. //处理删除状态数据
  98. List<String> deleteList = this.deleteCutModel(param.getNum(), deleteSidList, bucket);
  99. //写入本地文件,作为备份
  100. this.writeFile(param.getNum());
  101. //删除oss文件
  102. List<String> deleteFileList = new ArrayList<>();
  103. deleteList.stream().forEach(str -> {
  104. JSONObject parse = JSON.parseObject(str);
  105. String playUrl = parse.getString("playUrl");
  106. if(StrUtil.isNotEmpty(playUrl) && playUrl.length() > 1){
  107. deleteFileList.add(playUrl);
  108. }
  109. String poster = parse.getString("poster");
  110. if(StrUtil.isNotEmpty(poster) && poster.length() > 1){
  111. deleteFileList.add(poster);
  112. }
  113. });
  114. sceneUploadService.delete(
  115. DeleteFileParamVO.builder()
  116. .num(param.getNum())
  117. .fileNames(deleteFileList)
  118. .bizType(FileBizType.CUT_MODEL.code()).build());
  119. //保存数据库
  120. SceneEditInfoExt sceneEditInfoExt = sceneEditInfoExtService.getByScenePlusId(scenePlus.getId());
  121. this.updateDb(param.getNum(), scenePlus.getId());
  122. sceneEditInfoService.upgradeVersionById(sceneEditInfoExt.getEditInfoId());
  123. return ResultData.ok();
  124. }
  125. @Override
  126. public void publicCutModel(String sceneNum, String bucket) throws IOException {
  127. String Key = String.format(RedisKey.SCENE_CUT_MODEL, sceneNum);
  128. String userEditPath = String.format(UploadFilePath.USER_EDIT_PATH, sceneNum) + "cutModel.json";
  129. List<String> list = redisUtil.hgetValues(Key);
  130. if(CollUtil.isEmpty(list)){
  131. fYunFileService.deleteFile(bucket, userEditPath);
  132. return;
  133. }
  134. List<JSONObject> collect = list.stream().map(str -> JSON.parseObject(str)).collect(Collectors.toList());
  135. fYunFileService.uploadFile(bucket, JSON.toJSONString(collect).getBytes(), userEditPath);
  136. }
  137. private List<String> deleteCutModel(String num, List<String> deleteSidList, String bucket) throws Exception {
  138. if(CollUtil.isEmpty(deleteSidList)){
  139. return null;
  140. }
  141. //从redis中加载热点数据
  142. String key = String.format(RedisKey.SCENE_CUT_MODEL, num);
  143. List<String> deletDataList = redisUtil.hMultiGet(key, deleteSidList);
  144. if(CollUtil.isNotEmpty(deletDataList)){
  145. redisUtil.hdel(key, deleteSidList.toArray());
  146. }
  147. return deletDataList;
  148. }
  149. private void updateDb(String num, Long scenePlusId){
  150. //查询缓存是否包含热点数据
  151. String key = String.format(RedisKey.SCENE_CUT_MODEL, num);
  152. Map<String, String> cutModelMap = redisUtil.hmget(key);
  153. boolean hasCutModel= false;
  154. for (Map.Entry<String, String> tagMap : cutModelMap.entrySet()) {
  155. if(StrUtil.isEmpty(tagMap.getValue())){
  156. continue;
  157. }
  158. hasCutModel = true;
  159. break;
  160. }
  161. //更改热点状态
  162. sceneEditInfoExtService.update(
  163. new LambdaUpdateWrapper<SceneEditInfoExt>()
  164. .set(SceneEditInfoExt::getCutModel, hasCutModel ? CommonStatus.YES.code().intValue() : CommonStatus.NO.code().intValue())
  165. .eq(SceneEditInfoExt::getScenePlusId,scenePlusId));
  166. }
  167. private void addOrUpdate(String num, List<JSONObject> data) throws Exception{
  168. Map<String, String> addOrUpdateMap = new HashMap<>();
  169. int i = 0;
  170. for (JSONObject jsonObject : data) {
  171. jsonObject.put("createTime", Calendar.getInstance().getTimeInMillis() + i++);
  172. addOrUpdateMap.put(jsonObject.getString("sid"), JSON.toJSONString(jsonObject));
  173. }
  174. this.syncFileToRedis(num);
  175. //处理新增和修改数据
  176. this.addOrUpdateHandler(num, addOrUpdateMap);
  177. }
  178. private void addOrUpdateHandler(String num, Map<String, String> addOrUpdateMap){
  179. if(CollUtil.isEmpty(addOrUpdateMap))
  180. return;
  181. //批量写入缓存
  182. String key = String.format(RedisKey.SCENE_CUT_MODEL, num);
  183. redisUtil.hmset(key, addOrUpdateMap);
  184. //写入本地文件,作为备份
  185. this.writeFile(num);
  186. }
  187. private void writeFile(String num){
  188. String lockKey = String.format(RedisLockKey.LOCK_CUT_MODEL_SYNC, num);
  189. String lockVal = cn.hutool.core.lang.UUID.randomUUID().toString();
  190. boolean lock = redisLockUtil.lock(lockKey, lockVal, RedisKey.EXPIRE_TIME_1_MINUTE);
  191. if(!lock){
  192. return;
  193. }
  194. try{
  195. String dataKey = String.format(RedisKey.SCENE_CUT_MODEL, num);
  196. String cutModelJsonPath = String.format(ConstantFilePath.SCENE_USER_PATH_V4, num) + CUT_MODEL_JSON_NAME;
  197. if(!redisUtil.hasKey(dataKey)){
  198. FileUtil.del(cutModelJsonPath);
  199. return;
  200. }
  201. Map<String, String> cutModelmap = redisUtil.hmget(dataKey);
  202. List<JSONObject> list = cutModelmap.entrySet().stream().map(entry->JSON.parseObject(entry.getValue())).collect(Collectors.toList());
  203. FileUtil.writeUtf8String(JSON.toJSONString(list), cutModelJsonPath);
  204. }finally {
  205. redisLockUtil.unlockLua(lockKey, lockVal);
  206. }
  207. }
  208. private void syncFileToRedis(String num) throws Exception{
  209. String key = String.format(RedisKey.SCENE_CUT_MODEL, num);
  210. boolean exist = redisUtil.hasKey(key);
  211. if(exist){
  212. return;
  213. }
  214. String lockKey = String.format(RedisLockKey.LOCK_CUT_MODEL_SYNC, num);
  215. String lockVal = cn.hutool.core.lang.UUID.randomUUID().toString();
  216. boolean lock = redisLockUtil.lock(lockKey, lockVal, RedisKey.EXPIRE_TIME_1_MINUTE);
  217. if(!lock){
  218. throw new BusinessException(ErrorCode.SYSTEM_BUSY);
  219. }
  220. try{
  221. exist = redisUtil.hasKey(key);
  222. if(exist){
  223. return;
  224. }
  225. String cutModelFilePath = String.format(ConstantFilePath.SCENE_USER_PATH_V4, num) + CUT_MODEL_JSON_NAME;
  226. String cutModelData = FileUtils.readUtf8String(cutModelFilePath);
  227. if(StrUtil.isEmpty(cutModelData)){
  228. return;
  229. }
  230. JSONArray tagsArr = JSON.parseArray(cutModelData);
  231. if(CollUtil.isEmpty(tagsArr)){
  232. return;
  233. }
  234. Map<String, String> map = new HashMap<>();
  235. for (Object o : tagsArr) {
  236. JSONObject jo = (JSONObject)o;
  237. map.put(jo.getString("sid"), jo.toJSONString());
  238. }
  239. redisUtil.hmset(key, map);
  240. }finally {
  241. redisLockUtil.unlockLua(lockKey, lockVal);
  242. }
  243. }
  244. }