|
@@ -0,0 +1,282 @@
|
|
|
+package com.fdkankan.scene.service.impl;
|
|
|
+
|
|
|
+import cn.hutool.core.collection.CollUtil;
|
|
|
+import cn.hutool.core.io.FileUtil;
|
|
|
+import cn.hutool.core.util.StrUtil;
|
|
|
+import com.alibaba.fastjson.JSON;
|
|
|
+import com.alibaba.fastjson.JSONArray;
|
|
|
+import com.alibaba.fastjson.JSONObject;
|
|
|
+import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
|
|
+import com.fdkankan.common.constant.CommonStatus;
|
|
|
+import com.fdkankan.common.constant.ErrorCode;
|
|
|
+import com.fdkankan.common.constant.FileBizType;
|
|
|
+import com.fdkankan.common.exception.BusinessException;
|
|
|
+import com.fdkankan.common.util.FileUtils;
|
|
|
+import com.fdkankan.fyun.face.FYunFileServiceInterface;
|
|
|
+import com.fdkankan.model.constants.ConstantFilePath;
|
|
|
+import com.fdkankan.model.constants.UploadFilePath;
|
|
|
+import com.fdkankan.redis.constant.RedisKey;
|
|
|
+import com.fdkankan.redis.constant.RedisLockKey;
|
|
|
+import com.fdkankan.redis.util.RedisLockUtil;
|
|
|
+import com.fdkankan.redis.util.RedisUtil;
|
|
|
+import com.fdkankan.scene.bean.TagBean;
|
|
|
+import com.fdkankan.scene.entity.SceneEditInfoExt;
|
|
|
+import com.fdkankan.scene.entity.ScenePlus;
|
|
|
+import com.fdkankan.scene.entity.ScenePlusExt;
|
|
|
+import com.fdkankan.scene.service.*;
|
|
|
+import com.fdkankan.scene.vo.BaseJsonArrayParamVO;
|
|
|
+import com.fdkankan.scene.vo.BaseSceneParamVO;
|
|
|
+import com.fdkankan.scene.vo.DeleteFileParamVO;
|
|
|
+import com.fdkankan.scene.vo.DeleteSidListParamVO;
|
|
|
+import com.fdkankan.web.response.ResultData;
|
|
|
+import com.google.j2objc.annotations.AutoreleasePool;
|
|
|
+import org.springframework.beans.factory.annotation.Autowired;
|
|
|
+import org.springframework.stereotype.Service;
|
|
|
+
|
|
|
+import java.io.IOException;
|
|
|
+import java.util.*;
|
|
|
+import java.util.stream.Collectors;
|
|
|
+
|
|
|
+@Service
|
|
|
+public class CutModelServiceImpl implements ICutModelService {
|
|
|
+
|
|
|
+ private final String CUT_MODEL_JSON_NAME = "cutModel.json";
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private IScenePlusService scenePlusService;
|
|
|
+ @Autowired
|
|
|
+ private IScenePlusExtService scenePlusExtService;
|
|
|
+ @Autowired
|
|
|
+ private ISceneEditInfoExtService sceneEditInfoExtService;
|
|
|
+ @Autowired
|
|
|
+ private ISceneEditInfoService sceneEditInfoService;
|
|
|
+ @Autowired
|
|
|
+ private RedisUtil redisUtil;
|
|
|
+ @Autowired
|
|
|
+ private RedisLockUtil redisLockUtil;
|
|
|
+ @Autowired
|
|
|
+ private FYunFileServiceInterface fYunFileService;
|
|
|
+ @Autowired
|
|
|
+ private ISceneUploadService sceneUploadService;
|
|
|
+
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public ResultData saveCutModel(BaseJsonArrayParamVO param) throws Exception {
|
|
|
+ ScenePlus scenePlus = scenePlusService.getScenePlusByNum(param.getNum());
|
|
|
+
|
|
|
+ this.addOrUpdate(param.getNum(), param.getData());
|
|
|
+
|
|
|
+ //保存数据库
|
|
|
+ SceneEditInfoExt sceneEditInfoExt = sceneEditInfoExtService.getByScenePlusId(scenePlus.getId());
|
|
|
+ this.updateDb(param.getNum(), scenePlus.getId());
|
|
|
+// this.updateById(sceneEditInfoExt);
|
|
|
+
|
|
|
+ sceneEditInfoService.upgradeVersionById(sceneEditInfoExt.getEditInfoId());
|
|
|
+
|
|
|
+ return ResultData.ok();
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public List<JSONObject> listCutModel(BaseSceneParamVO param) throws Exception {
|
|
|
+
|
|
|
+ List<JSONObject> tags = new ArrayList<>();
|
|
|
+ ScenePlus scenePlus = scenePlusService.getScenePlusByNum(param.getNum());
|
|
|
+ SceneEditInfoExt sceneEditInfoExt = sceneEditInfoExtService.getByScenePlusId(scenePlus.getId());
|
|
|
+
|
|
|
+ this.syncFileToRedis(param.getNum());
|
|
|
+
|
|
|
+ //获取裁剪模型数据
|
|
|
+ String key = String.format(RedisKey.SCENE_CUT_MODEL, param.getNum());
|
|
|
+ List<String> list = redisUtil.hgetValues(key);
|
|
|
+ if(CollUtil.isNotEmpty(list)){
|
|
|
+ List<TagBean> sortList = list.stream().map(str -> {
|
|
|
+ JSONObject jsonObject = JSON.parseObject(str);
|
|
|
+ TagBean tagBean = new TagBean();
|
|
|
+ tagBean.setCreateTime(jsonObject.getLong("createTime"));
|
|
|
+ jsonObject.remove("createTime");
|
|
|
+ tagBean.setTag(jsonObject);
|
|
|
+ return tagBean;
|
|
|
+ }).collect(Collectors.toList());
|
|
|
+ sortList.sort(Comparator.comparingLong(TagBean::getCreateTime).reversed());
|
|
|
+ tags = sortList.stream().map(item -> item.getTag()).collect(Collectors.toList());
|
|
|
+ }
|
|
|
+
|
|
|
+ return tags;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public ResultData deleteCutModel(DeleteSidListParamVO param) throws Exception {
|
|
|
+ ScenePlus scenePlus = scenePlusService.getScenePlusByNum(param.getNum());
|
|
|
+ ScenePlusExt scenePlusExt = scenePlusExtService.getScenePlusExtByPlusId(scenePlus.getId());
|
|
|
+ String bucket = scenePlusExt.getYunFileBucket();
|
|
|
+
|
|
|
+ List<String> deleteSidList = param.getSidList();
|
|
|
+
|
|
|
+ this.syncFileToRedis(param.getNum());
|
|
|
+
|
|
|
+ //处理删除状态数据
|
|
|
+ List<String> deleteList = this.deleteCutModel(param.getNum(), deleteSidList, bucket);
|
|
|
+
|
|
|
+ //写入本地文件,作为备份
|
|
|
+ this.writeFile(param.getNum());
|
|
|
+
|
|
|
+ //删除oss文件
|
|
|
+ List<String> deleteFileList = new ArrayList<>();
|
|
|
+ deleteList.stream().forEach(str -> {
|
|
|
+ JSONObject parse = JSON.parseObject(str);
|
|
|
+ String playUrl = parse.getString("playUrl");
|
|
|
+ if(StrUtil.isNotEmpty(playUrl) && playUrl.length() > 1){
|
|
|
+ deleteFileList.add(playUrl);
|
|
|
+ }
|
|
|
+ String poster = parse.getString("poster");
|
|
|
+ if(StrUtil.isNotEmpty(poster) && poster.length() > 1){
|
|
|
+ deleteFileList.add(poster);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ sceneUploadService.delete(
|
|
|
+ DeleteFileParamVO.builder()
|
|
|
+ .num(param.getNum())
|
|
|
+ .fileNames(deleteFileList)
|
|
|
+ .bizType(FileBizType.CUT_MODEL.code()).build());
|
|
|
+
|
|
|
+ //保存数据库
|
|
|
+ SceneEditInfoExt sceneEditInfoExt = sceneEditInfoExtService.getByScenePlusId(scenePlus.getId());
|
|
|
+ this.updateDb(param.getNum(), scenePlus.getId());
|
|
|
+ sceneEditInfoService.upgradeVersionById(sceneEditInfoExt.getEditInfoId());
|
|
|
+
|
|
|
+ return ResultData.ok();
|
|
|
+ }
|
|
|
+
|
|
|
+ public void publicCutModel(String sceneNum, String bucket) throws IOException {
|
|
|
+ String Key = String.format(RedisKey.SCENE_CUT_MODEL, sceneNum);
|
|
|
+ String userEditPath = String.format(UploadFilePath.USER_EDIT_PATH, sceneNum) + "cutModel.json";
|
|
|
+ List<String> list = redisUtil.hgetValues(Key);
|
|
|
+ if(CollUtil.isEmpty(list)){
|
|
|
+ fYunFileService.deleteFile(bucket, userEditPath);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ List<JSONObject> collect = list.stream().map(str -> JSON.parseObject(str)).collect(Collectors.toList());
|
|
|
+ fYunFileService.uploadFile(bucket, JSON.toJSONString(collect).getBytes(), userEditPath);
|
|
|
+ }
|
|
|
+
|
|
|
+ private List<String> deleteCutModel(String num, List<String> deleteSidList, String bucket) throws Exception {
|
|
|
+ if(CollUtil.isEmpty(deleteSidList)){
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ //从redis中加载热点数据
|
|
|
+ String key = String.format(RedisKey.SCENE_CUT_MODEL, num);
|
|
|
+ List<String> deletDataList = redisUtil.hMultiGet(key, deleteSidList);
|
|
|
+ if(CollUtil.isNotEmpty(deletDataList)){
|
|
|
+ redisUtil.hdel(key, deleteSidList.toArray());
|
|
|
+ }
|
|
|
+ return deletDataList;
|
|
|
+ }
|
|
|
+
|
|
|
+ private void updateDb(String num, Long scenePlusId){
|
|
|
+ //查询缓存是否包含热点数据
|
|
|
+ String key = String.format(RedisKey.SCENE_CUT_MODEL, num);
|
|
|
+ Map<String, String> cutModelMap = redisUtil.hmget(key);
|
|
|
+ boolean hasCutModel= false;
|
|
|
+ for (Map.Entry<String, String> tagMap : cutModelMap.entrySet()) {
|
|
|
+ if(StrUtil.isEmpty(tagMap.getValue())){
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ hasCutModel = true;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ //更改热点状态
|
|
|
+ sceneEditInfoExtService.update(
|
|
|
+ new LambdaUpdateWrapper<SceneEditInfoExt>()
|
|
|
+ .set(SceneEditInfoExt::getCutModel, hasCutModel ? CommonStatus.YES.code().intValue() : CommonStatus.NO.code().intValue())
|
|
|
+ .eq(SceneEditInfoExt::getScenePlusId,scenePlusId));
|
|
|
+ }
|
|
|
+
|
|
|
+ private void addOrUpdate(String num, List<JSONObject> data) throws Exception{
|
|
|
+ Map<String, String> addOrUpdateMap = new HashMap<>();
|
|
|
+ int i = 0;
|
|
|
+ for (JSONObject jsonObject : data) {
|
|
|
+ jsonObject.put("createTime", Calendar.getInstance().getTimeInMillis() + i++);
|
|
|
+ addOrUpdateMap.put(jsonObject.getString("sid"), JSON.toJSONString(jsonObject));
|
|
|
+ }
|
|
|
+
|
|
|
+ this.syncFileToRedis(num);
|
|
|
+
|
|
|
+ //处理新增和修改数据
|
|
|
+ this.addOrUpdateHandler(num, addOrUpdateMap);
|
|
|
+ }
|
|
|
+
|
|
|
+ private void addOrUpdateHandler(String num, Map<String, String> addOrUpdateMap){
|
|
|
+ if(CollUtil.isEmpty(addOrUpdateMap))
|
|
|
+ return;
|
|
|
+
|
|
|
+ //批量写入缓存
|
|
|
+ String key = String.format(RedisKey.SCENE_CUT_MODEL, num);
|
|
|
+ redisUtil.hmset(key, addOrUpdateMap);
|
|
|
+
|
|
|
+ //写入本地文件,作为备份
|
|
|
+ this.writeFile(num);
|
|
|
+ }
|
|
|
+
|
|
|
+ private void writeFile(String num){
|
|
|
+ String lockKey = String.format(RedisLockKey.LOCK_CUT_MODEL_SYNC, num);
|
|
|
+ String lockVal = cn.hutool.core.lang.UUID.randomUUID().toString();
|
|
|
+ boolean lock = redisLockUtil.lock(lockKey, lockVal, RedisKey.EXPIRE_TIME_1_MINUTE);
|
|
|
+ if(!lock){
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ try{
|
|
|
+ String dataKey = String.format(RedisKey.SCENE_CUT_MODEL, num);
|
|
|
+ String cutModelJsonPath = String.format(ConstantFilePath.SCENE_USER_PATH_V4, num) + CUT_MODEL_JSON_NAME;
|
|
|
+ if(!redisUtil.hasKey(dataKey)){
|
|
|
+ FileUtil.del(cutModelJsonPath);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ Map<String, String> cutModelmap = redisUtil.hmget(dataKey);
|
|
|
+ List<JSONObject> list = cutModelmap.entrySet().stream().map(entry->JSON.parseObject(entry.getValue())).collect(Collectors.toList());
|
|
|
+ FileUtil.writeUtf8String(JSON.toJSONString(list), cutModelJsonPath);
|
|
|
+ }finally {
|
|
|
+ redisLockUtil.unlockLua(lockKey, lockVal);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private void syncFileToRedis(String num) throws Exception{
|
|
|
+
|
|
|
+ String key = String.format(RedisKey.SCENE_CUT_MODEL, num);
|
|
|
+ boolean exist = redisUtil.hasKey(key);
|
|
|
+ if(exist){
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ String lockKey = String.format(RedisLockKey.LOCK_CUT_MODEL_SYNC, num);
|
|
|
+ String lockVal = cn.hutool.core.lang.UUID.randomUUID().toString();
|
|
|
+ boolean lock = redisLockUtil.lock(lockKey, lockVal, RedisKey.EXPIRE_TIME_1_MINUTE);
|
|
|
+ if(!lock){
|
|
|
+ throw new BusinessException(ErrorCode.SYSTEM_BUSY);
|
|
|
+ }
|
|
|
+ try{
|
|
|
+ exist = redisUtil.hasKey(key);
|
|
|
+ if(exist){
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ String cutModelFilePath = String.format(ConstantFilePath.SCENE_USER_PATH_V4, num) + CUT_MODEL_JSON_NAME;
|
|
|
+ String cutModelData = FileUtils.readUtf8String(cutModelFilePath);
|
|
|
+ if(StrUtil.isEmpty(cutModelData)){
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ JSONArray tagsArr = JSON.parseArray(cutModelData);
|
|
|
+ if(CollUtil.isEmpty(tagsArr)){
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ Map<String, String> map = new HashMap<>();
|
|
|
+ for (Object o : tagsArr) {
|
|
|
+ JSONObject jo = (JSONObject)o;
|
|
|
+ map.put(jo.getString("sid"), jo.toJSONString());
|
|
|
+ }
|
|
|
+ redisUtil.hmset(key, map);
|
|
|
+ }finally {
|
|
|
+ redisLockUtil.unlockLua(lockKey, lockVal);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+}
|