diff --git a/src/main/java/com/ycwl/basic/controller/mobile/AppGoodsController.java b/src/main/java/com/ycwl/basic/controller/mobile/AppGoodsController.java
index a25f9ce..2de7738 100644
--- a/src/main/java/com/ycwl/basic/controller/mobile/AppGoodsController.java
+++ b/src/main/java/com/ycwl/basic/controller/mobile/AppGoodsController.java
@@ -1,6 +1,8 @@
 package com.ycwl.basic.controller.mobile;
 
+import com.ycwl.basic.annotation.IgnoreToken;
 import com.ycwl.basic.constant.BaseContextHandler;
+import com.ycwl.basic.exception.CheckTokenException;
 import com.ycwl.basic.model.jwt.JwtInfo;
 import com.ycwl.basic.model.mobile.goods.*;
 import com.ycwl.basic.service.mobile.GoodsService;
@@ -45,9 +47,14 @@ public class AppGoodsController {
 
     @ApiOperation("成片vlog商品详情")
     @GetMapping("/getVideoGoodsDetail/{videoId}")
+    @IgnoreToken
     public ApiResponse<VideoGoodsDetailVO> videoGoodsDetail(@PathVariable("videoId") Long videoId) {
-        JwtInfo worker = JwtTokenUtil.getWorker();
-        return goodsService.videoGoodsDetail(worker.getUserId(), videoId);
+        try {
+            JwtInfo worker = JwtTokenUtil.getWorker();
+            return goodsService.videoGoodsDetail(worker.getUserId(), videoId);
+        } catch (CheckTokenException e) {
+            return goodsService.videoGoodsDetail(null, videoId);
+        }
     }
 
     @GetMapping("/sourceGoods/{sourceId}")
diff --git a/src/main/java/com/ycwl/basic/controller/mobile/AppMemberController.java b/src/main/java/com/ycwl/basic/controller/mobile/AppMemberController.java
index 0ad4c1a..e006d09 100644
--- a/src/main/java/com/ycwl/basic/controller/mobile/AppMemberController.java
+++ b/src/main/java/com/ycwl/basic/controller/mobile/AppMemberController.java
@@ -33,10 +33,10 @@ public class AppMemberController {
      * @throws Exception
      */
     @ApiOperation("登录")
-    @PostMapping("/login")
+    @PostMapping("/{scenicId}/login")
     @IgnoreToken
-    public ApiResponse<?> login(@RequestBody WeChatUserInfoDTO userInfoDTO) throws Exception {
-        return memberService.login(userInfoDTO.getCode(), userInfoDTO);
+    public ApiResponse<?> login(@PathVariable("scenicId") Long scenicId ,@RequestBody WeChatUserInfoDTO userInfoDTO) throws Exception {
+        return memberService.login(scenicId, userInfoDTO.getCode(), userInfoDTO);
     }
 
     /**
diff --git a/src/main/java/com/ycwl/basic/mapper/MpConfigMapper.java b/src/main/java/com/ycwl/basic/mapper/MpConfigMapper.java
new file mode 100644
index 0000000..57013ca
--- /dev/null
+++ b/src/main/java/com/ycwl/basic/mapper/MpConfigMapper.java
@@ -0,0 +1,9 @@
+package com.ycwl.basic.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.ycwl.basic.model.pc.mp.MpConfigEntity;
+import org.apache.ibatis.annotations.Mapper;
+
+@Mapper
+public interface MpConfigMapper extends BaseMapper<MpConfigEntity> {
+}
diff --git a/src/main/java/com/ycwl/basic/mapper/MpNotifyConfigMapper.java b/src/main/java/com/ycwl/basic/mapper/MpNotifyConfigMapper.java
new file mode 100644
index 0000000..c19fdcf
--- /dev/null
+++ b/src/main/java/com/ycwl/basic/mapper/MpNotifyConfigMapper.java
@@ -0,0 +1,12 @@
+package com.ycwl.basic.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.ycwl.basic.model.pc.mp.MpNotifyConfigEntity;
+import org.apache.ibatis.annotations.Mapper;
+
+import java.util.List;
+
+@Mapper
+public interface MpNotifyConfigMapper extends BaseMapper<MpNotifyConfigEntity> {
+    List<MpNotifyConfigEntity> listByMpId(Integer mpId);
+}
diff --git a/src/main/java/com/ycwl/basic/mapper/VideoMapper.java b/src/main/java/com/ycwl/basic/mapper/VideoMapper.java
index 15e364b..0d91dfa 100644
--- a/src/main/java/com/ycwl/basic/mapper/VideoMapper.java
+++ b/src/main/java/com/ycwl/basic/mapper/VideoMapper.java
@@ -34,6 +34,8 @@ public interface VideoMapper {
 
     List<MemberVideoEntity> userFaceTemplateVideo(Long userId, Long faceId, Long templateId);
 
+    MemberVideoEntity queryRelationByMemberTask(Long userId, Long taskId);
+    List<MemberVideoEntity> listRelationByTask(Long taskId);
     List<MemberVideoEntity> listRelationByFace(Long userId, Long faceId);
     List<MemberVideoEntity> listRelationByFaceAndTemplate(Long userId, Long faceId, Long templateId);
 
diff --git a/src/main/java/com/ycwl/basic/model/mobile/goods/VideoGoodsDetailVO.java b/src/main/java/com/ycwl/basic/model/mobile/goods/VideoGoodsDetailVO.java
index b2e7f76..e49b662 100644
--- a/src/main/java/com/ycwl/basic/model/mobile/goods/VideoGoodsDetailVO.java
+++ b/src/main/java/com/ycwl/basic/model/mobile/goods/VideoGoodsDetailVO.java
@@ -39,6 +39,8 @@ public class VideoGoodsDetailVO {
     private String videoUrl;
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
     private Date createTime;
+    @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
+    private Date shotTime;
     @ApiModelProperty("价格")
     private String price;
     private String slashPrice;
@@ -47,4 +49,5 @@ public class VideoGoodsDetailVO {
     @ApiModelProperty("镜头数")
     private Integer lensNum;
     private Long faceId;
+    private boolean share = false;
 }
diff --git a/src/main/java/com/ycwl/basic/model/pc/member/entity/MemberEntity.java b/src/main/java/com/ycwl/basic/model/pc/member/entity/MemberEntity.java
index 1c1d600..4b9bb45 100644
--- a/src/main/java/com/ycwl/basic/model/pc/member/entity/MemberEntity.java
+++ b/src/main/java/com/ycwl/basic/model/pc/member/entity/MemberEntity.java
@@ -15,6 +15,7 @@ import java.util.Date;
 public class MemberEntity {
     @TableId
     private Long id;
+    private Long scenicId;
     /**
      * 微信openId
      */
diff --git a/src/main/java/com/ycwl/basic/model/pc/member/req/MemberReqQuery.java b/src/main/java/com/ycwl/basic/model/pc/member/req/MemberReqQuery.java
index 02efdde..ff632ce 100644
--- a/src/main/java/com/ycwl/basic/model/pc/member/req/MemberReqQuery.java
+++ b/src/main/java/com/ycwl/basic/model/pc/member/req/MemberReqQuery.java
@@ -16,6 +16,7 @@ import java.util.Date;
 @Data
 @ApiModel("查询用户列表请求参数")
 public class MemberReqQuery extends BaseQueryParameterReq {
+    private Long scenicId;
     /**
      * 微信openId
      */
diff --git a/src/main/java/com/ycwl/basic/model/pc/member/resp/MemberRespVO.java b/src/main/java/com/ycwl/basic/model/pc/member/resp/MemberRespVO.java
index 49c0134..3cff0d4 100644
--- a/src/main/java/com/ycwl/basic/model/pc/member/resp/MemberRespVO.java
+++ b/src/main/java/com/ycwl/basic/model/pc/member/resp/MemberRespVO.java
@@ -15,6 +15,7 @@ import java.util.Date;
 @ApiModel("查询用户信息响应参数")
 public class MemberRespVO {
     private Long id;
+    private Long scenicId;
     /**
      * 微信openId
      */
diff --git a/src/main/java/com/ycwl/basic/model/pc/mp/MpConfigEntity.java b/src/main/java/com/ycwl/basic/model/pc/mp/MpConfigEntity.java
new file mode 100644
index 0000000..8335d36
--- /dev/null
+++ b/src/main/java/com/ycwl/basic/model/pc/mp/MpConfigEntity.java
@@ -0,0 +1,24 @@
+package com.ycwl.basic.model.pc.mp;
+
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+
+import java.util.Map;
+
+@TableName("mp_config")
+@Data
+public class MpConfigEntity {
+    private Integer id;
+    private String name;
+    private String appId;
+    private String appSecret;
+    private String state;
+
+    public Map<String, String> toMap() {
+        Map<String, String> map = new java.util.HashMap<>();
+        map.put("appId", this.getAppId());
+        map.put("appSecret", this.getAppSecret());
+        map.put("state", this.getState());
+        return map;
+    }
+}
diff --git a/src/main/java/com/ycwl/basic/model/pc/mp/MpNotifyConfigEntity.java b/src/main/java/com/ycwl/basic/model/pc/mp/MpNotifyConfigEntity.java
new file mode 100644
index 0000000..c725bdb
--- /dev/null
+++ b/src/main/java/com/ycwl/basic/model/pc/mp/MpNotifyConfigEntity.java
@@ -0,0 +1,13 @@
+package com.ycwl.basic.model.pc.mp;
+
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+
+@TableName("mp_notify_config")
+@Data
+public class MpNotifyConfigEntity {
+    private Integer id;
+    private Integer mpId;
+    private String templateId;
+    private Integer type;
+}
diff --git a/src/main/java/com/ycwl/basic/model/pc/mp/ScenicMpNotifyVO.java b/src/main/java/com/ycwl/basic/model/pc/mp/ScenicMpNotifyVO.java
new file mode 100644
index 0000000..d1af411
--- /dev/null
+++ b/src/main/java/com/ycwl/basic/model/pc/mp/ScenicMpNotifyVO.java
@@ -0,0 +1,13 @@
+package com.ycwl.basic.model.pc.mp;
+
+import lombok.Data;
+
+@Data
+public class ScenicMpNotifyVO {
+    private Long scenicId;
+    private Integer mpId;
+    private String appId;
+    private String appSecret;
+    private String appState;
+    private String videoGeneratedTemplateId;
+}
diff --git a/src/main/java/com/ycwl/basic/model/pc/scenic/entity/ScenicEntity.java b/src/main/java/com/ycwl/basic/model/pc/scenic/entity/ScenicEntity.java
index 8c44e8d..15fdf07 100644
--- a/src/main/java/com/ycwl/basic/model/pc/scenic/entity/ScenicEntity.java
+++ b/src/main/java/com/ycwl/basic/model/pc/scenic/entity/ScenicEntity.java
@@ -22,6 +22,7 @@ public class ScenicEntity {
      * 景区名称
      */
     private String name;
+    private Integer mpId;
     /**
      * 景区介绍
      */
diff --git a/src/main/java/com/ycwl/basic/repository/ScenicRepository.java b/src/main/java/com/ycwl/basic/repository/ScenicRepository.java
index c9e1455..5b2d1f5 100644
--- a/src/main/java/com/ycwl/basic/repository/ScenicRepository.java
+++ b/src/main/java/com/ycwl/basic/repository/ScenicRepository.java
@@ -1,22 +1,35 @@
 package com.ycwl.basic.repository;
 
 import com.alibaba.fastjson.JSONObject;
+import com.ycwl.basic.mapper.MpConfigMapper;
+import com.ycwl.basic.mapper.MpNotifyConfigMapper;
 import com.ycwl.basic.mapper.ScenicMapper;
+import com.ycwl.basic.model.pc.mp.MpConfigEntity;
+import com.ycwl.basic.model.pc.mp.MpNotifyConfigEntity;
+import com.ycwl.basic.model.pc.mp.ScenicMpNotifyVO;
 import com.ycwl.basic.model.pc.scenic.entity.ScenicConfigEntity;
 import com.ycwl.basic.model.pc.scenic.entity.ScenicEntity;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.data.redis.core.RedisTemplate;
 import org.springframework.stereotype.Component;
 
+import java.util.List;
+
 @Component
 public class ScenicRepository {
     @Autowired
     private ScenicMapper scenicMapper;
     @Autowired
+    private MpConfigMapper mpConfigMapper;
+    @Autowired
     private RedisTemplate<String, String> redisTemplate;
 
     public static final String SCENIC_CACHE_KEY = "scenic:%s";
     public static final String SCENIC_CONFIG_CACHE_KEY = "scenic:%s:config";
+    public static final String SCENIC_MP_CACHE_KEY = "scenic:%s:mp";
+    public static final String SCENIC_MP_NOTIFY_CACHE_KEY = "scenic:%s:mpNotify";
+    @Autowired
+    private MpNotifyConfigMapper mpNotifyConfigMapper;
 
     public ScenicEntity getScenic(Long id) {
         if (redisTemplate.hasKey(String.format(SCENIC_CACHE_KEY, id))) {
@@ -40,8 +53,51 @@ public class ScenicRepository {
         return scenicConfig;
     }
 
+    public MpConfigEntity getScenicMpConfig(Long scenicId) {
+        if (redisTemplate.hasKey(String.format(SCENIC_MP_CACHE_KEY, scenicId))) {
+            return JSONObject.parseObject(redisTemplate.opsForValue().get(String.format(SCENIC_MP_CACHE_KEY, scenicId)), MpConfigEntity.class);
+        }
+        ScenicEntity scenic = getScenic(scenicId);
+        MpConfigEntity mpConfigEntity = mpConfigMapper.selectById(scenic.getMpId());
+        if (mpConfigEntity != null) {
+            redisTemplate.opsForValue().set(String.format(SCENIC_MP_CACHE_KEY, scenicId), JSONObject.toJSONString(mpConfigEntity));
+        }
+        return mpConfigEntity;
+    }
+
+    public ScenicMpNotifyVO getScenicMpNotifyConfig(Long scenicId) {
+        if (redisTemplate.hasKey(String.format(SCENIC_MP_NOTIFY_CACHE_KEY, scenicId))) {
+            return JSONObject.parseObject(redisTemplate.opsForValue().get(String.format(SCENIC_MP_NOTIFY_CACHE_KEY, scenicId)), ScenicMpNotifyVO.class);
+        }
+        MpConfigEntity mpConfig = getScenicMpConfig(scenicId);
+        ScenicMpNotifyVO mpNotifyConfig = new ScenicMpNotifyVO();
+        mpNotifyConfig.setAppId(mpConfig.getAppId());
+        mpNotifyConfig.setAppSecret(mpConfig.getAppSecret());
+        mpNotifyConfig.setMpId(mpConfig.getId());
+        mpNotifyConfig.setAppState(mpConfig.getState());
+        List<MpNotifyConfigEntity> mpNotifyConfigList = mpNotifyConfigMapper.listByMpId(mpConfig.getId());
+        mpNotifyConfigList.forEach(item -> {
+            switch (item.getType()) {
+                case 0:
+                    mpNotifyConfig.setVideoGeneratedTemplateId(item.getTemplateId());
+                    break;
+            }
+        });
+        redisTemplate.opsForValue().set(String.format(SCENIC_MP_NOTIFY_CACHE_KEY, scenicId), JSONObject.toJSONString(mpNotifyConfig));
+        return mpNotifyConfig;
+    }
+
+    public String getVideoGeneratedTemplateId(Long scenicId) {
+        ScenicMpNotifyVO scenicMpNotifyConfig = getScenicMpNotifyConfig(scenicId);
+        if (scenicMpNotifyConfig != null) {
+            return scenicMpNotifyConfig.getVideoGeneratedTemplateId();
+        }
+        return null;
+    }
+
     public void clearCache(Long scenicId) {
         redisTemplate.delete(String.format(SCENIC_CACHE_KEY, scenicId));
         redisTemplate.delete(String.format(SCENIC_CONFIG_CACHE_KEY, scenicId));
     }
+
 }
diff --git a/src/main/java/com/ycwl/basic/service/impl/mobile/AppMemberServiceImpl.java b/src/main/java/com/ycwl/basic/service/impl/mobile/AppMemberServiceImpl.java
index d84bd71..aaed88e 100644
--- a/src/main/java/com/ycwl/basic/service/impl/mobile/AppMemberServiceImpl.java
+++ b/src/main/java/com/ycwl/basic/service/impl/mobile/AppMemberServiceImpl.java
@@ -16,6 +16,8 @@ import com.ycwl.basic.model.mobile.weChat.DTO.WeChatUserInfoUpdateDTO;
 import com.ycwl.basic.model.pc.member.entity.MemberEntity;
 import com.ycwl.basic.model.pc.member.req.MemberReqQuery;
 import com.ycwl.basic.model.pc.member.resp.MemberRespVO;
+import com.ycwl.basic.model.pc.mp.MpConfigEntity;
+import com.ycwl.basic.repository.ScenicRepository;
 import com.ycwl.basic.service.HttpService;
 import com.ycwl.basic.service.mobile.AppMemberService;
 import com.ycwl.basic.utils.ApiResponse;
@@ -50,13 +52,17 @@ public class AppMemberServiceImpl implements AppMemberService {
     @Autowired
     private JwtTokenUtil jwtTokenUtil;
 
+    @Autowired
+    private ScenicRepository scenicRepository;
+
     @Override
-    public Map<String, Object> getOpenId(String code) {
+    public Map<String, Object> getOpenId(Long scenicId, String code) {
         Map<String, String> paramMap = new HashMap<>(NumberConstant.FOUR);
-        paramMap.put("appid", config.getMiniProgramAppId());
-        paramMap.put("secret", config.getMiniProgramSecret());
+        MpConfigEntity scenicMpConfig = scenicRepository.getScenicMpConfig(scenicId);
+        paramMap.put("appid", scenicMpConfig.getAppId());
+        paramMap.put("secret", scenicMpConfig.getAppSecret());
         paramMap.put("js_code", code);
-        paramMap.put("grant_type", config.getGrandType());
+        paramMap.put("grant_type", "authorization_code");
         try {
             String response = httpService.doHttpsPost(WeiXinConstant.GET_OPEN_ID, paramMap, "UTF-8");
             if (StringUtils.isBlank(response)) {
@@ -72,8 +78,8 @@ public class AppMemberServiceImpl implements AppMemberService {
 
 
     @Override
-    public ApiResponse login(String code, WeChatUserInfoDTO userInfoDTO) throws Exception {
-        Map<String, Object> weixinResponse = this.getOpenId(code);
+    public ApiResponse login(Long scenicId, String code, WeChatUserInfoDTO userInfoDTO) throws Exception {
+        Map<String, Object> weixinResponse = this.getOpenId(scenicId, code);
         if (CollectionUtils.isEmpty(weixinResponse)) {
             throw new AppException(BizCodeEnum.SERVER_INTERNAL_ERROR);
         }
@@ -100,6 +106,7 @@ public class AppMemberServiceImpl implements AppMemberService {
             MemberEntity memberEntity = new MemberEntity();
             BeanCopierUtils.copyProperties(userInfoDTO, memberEntity);
             memberEntity.setId(SnowFlakeUtil.getLongId());
+            memberEntity.setScenicId(scenicId);
             memberEntity.setOpenId(openId.toString());
             memberMapper.add(memberEntity);
             BeanCopierUtils.copyProperties(memberEntity, memberRespVO);
diff --git a/src/main/java/com/ycwl/basic/service/impl/mobile/AppScenicServiceImpl.java b/src/main/java/com/ycwl/basic/service/impl/mobile/AppScenicServiceImpl.java
index 24e894f..dbd95b6 100644
--- a/src/main/java/com/ycwl/basic/service/impl/mobile/AppScenicServiceImpl.java
+++ b/src/main/java/com/ycwl/basic/service/impl/mobile/AppScenicServiceImpl.java
@@ -3,11 +3,13 @@ package com.ycwl.basic.service.impl.mobile;
 import cn.hutool.core.bean.BeanUtil;
 import com.github.pagehelper.PageHelper;
 import com.github.pagehelper.PageInfo;
+import com.ycwl.basic.biz.OrderBiz;
 import com.ycwl.basic.constant.BaseContextHandler;
 import com.ycwl.basic.constant.NumberConstant;
 import com.ycwl.basic.mapper.*;
 import com.ycwl.basic.model.jwt.JwtInfo;
 import com.ycwl.basic.model.mobile.index.TopStateResp;
+import com.ycwl.basic.model.mobile.order.IsBuyRespVO;
 import com.ycwl.basic.model.mobile.scenic.ScenicAppVO;
 import com.ycwl.basic.model.mobile.scenic.ScenicDeviceCountVO;
 import com.ycwl.basic.model.mobile.scenic.ScenicIndexVO;
@@ -67,6 +69,8 @@ public class AppScenicServiceImpl implements AppScenicService {
     private BigDecimal faceScore;
     @Autowired
     private TemplateRepository templateRepository;
+    @Autowired
+    private OrderBiz orderBiz;
 
     @Override
     public ApiResponse<PageInfo<ScenicAppVO>> pageQuery(ScenicReqQuery scenicReqQuery) {
@@ -125,12 +129,18 @@ public class AppScenicServiceImpl implements AppScenicService {
             Integer type = sourceRespVO.getType();
             if(type==1){
                 contentPageVO.setName("原片集");
-            }else {
+            } else {
                 contentPageVO.setName("照片集");
             }
+            IsBuyRespVO isBuyRespVO = orderBiz.isBuy(worker.getUserId(), faceRespVO.getScenicId(), type, faceId);
+            contentPageVO.setSourceType(isBuyRespVO.getGoodsType());
+            contentPageVO.setContentId(isBuyRespVO.getGoodsId());
+            if (isBuyRespVO.isBuy()) {
+                contentPageVO.setIsBuy(1);
+            } else {
+                contentPageVO.setIsBuy(0);
+            }
             contentPageVO.setContentType(2);
-            contentPageVO.setSourceType(type);
-            contentPageVO.setIsBuy(sourceRespVO.getIsBuy());
             contentList.add(contentPageVO);
         });
 
@@ -174,12 +184,18 @@ public class AppScenicServiceImpl implements AppScenicService {
             Integer type = sourceRespVO.getType();
             if(type==1){
                 contentPageVO.setName("原片集");
-            }else {
+            } else {
                 contentPageVO.setName("照片集");
             }
+            IsBuyRespVO isBuyRespVO = orderBiz.isBuy(userId, faceRespVO.getScenicId(), type, faceId);
+            contentPageVO.setSourceType(isBuyRespVO.getGoodsType());
+            contentPageVO.setContentId(isBuyRespVO.getGoodsId());
+            if (isBuyRespVO.isBuy()) {
+                contentPageVO.setIsBuy(1);
+            } else {
+                contentPageVO.setIsBuy(0);
+            }
             contentPageVO.setContentType(2);
-            contentPageVO.setSourceType(type);
-            contentPageVO.setIsBuy(sourceRespVO.getIsBuy());
             contentList.add(contentPageVO);
         });
 
diff --git a/src/main/java/com/ycwl/basic/service/impl/mobile/GoodsServiceImpl.java b/src/main/java/com/ycwl/basic/service/impl/mobile/GoodsServiceImpl.java
index e8c8c10..491753c 100644
--- a/src/main/java/com/ycwl/basic/service/impl/mobile/GoodsServiceImpl.java
+++ b/src/main/java/com/ycwl/basic/service/impl/mobile/GoodsServiceImpl.java
@@ -1,6 +1,7 @@
 package com.ycwl.basic.service.impl.mobile;
 
 import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
 import com.ycwl.basic.constant.BaseContextHandler;
 import com.ycwl.basic.mapper.*;
@@ -15,8 +16,11 @@ import com.ycwl.basic.model.pc.video.entity.MemberVideoEntity;
 import com.ycwl.basic.model.pc.video.req.VideoReqQuery;
 import com.ycwl.basic.model.pc.video.resp.VideoRespVO;
 import com.ycwl.basic.repository.VideoTaskRepository;
+import com.ycwl.basic.service.impl.pc.TaskServiceImpl;
+import com.ycwl.basic.service.impl.task.TaskTaskServiceImpl;
 import com.ycwl.basic.service.mobile.GoodsService;
 import com.ycwl.basic.repository.TemplateRepository;
+import com.ycwl.basic.service.task.TaskService;
 import com.ycwl.basic.utils.ApiResponse;
 import com.ycwl.basic.utils.DateUtils;
 import org.apache.commons.lang3.StringUtils;
@@ -27,6 +31,7 @@ import java.math.BigDecimal;
 import java.math.RoundingMode;
 import java.text.DecimalFormat;
 import java.util.ArrayList;
+import java.util.Date;
 import java.util.List;
 import java.util.Optional;
 import java.util.stream.Collectors;
@@ -42,16 +47,14 @@ public class GoodsServiceImpl implements GoodsService {
      private SourceMapper sourceMapper;
      @Autowired
      private ScenicMapper scenicMapper;
-     @Autowired
-     private TaskMapper taskMapper;
-     @Autowired
-     private DeviceMapper deviceMapper;
     @Autowired
     private FaceMapper faceMapper;
      @Autowired
      private TemplateRepository templateRepository;
     @Autowired
     private VideoTaskRepository videoTaskRepository;
+    @Autowired
+    private TaskService taskTaskService;
 
     public ApiResponse<List<GoodsPageVO>> goodsList(GoodsReqQuery query) {
          //查询原素材
@@ -194,10 +197,6 @@ public class GoodsServiceImpl implements GoodsService {
 
     @Override
     public ApiResponse<VideoGoodsDetailVO> videoGoodsDetail(Long userId, Long videoId) {
-        MemberVideoEntity entity = videoMapper.queryUserVideo(userId, videoId);
-        if (entity == null) {
-            return ApiResponse.fail("该视频不属于您");
-        }
         VideoGoodsDetailVO goodsDetailVO = new VideoGoodsDetailVO();
         VideoRespVO videoRespVO = videoMapper.getById(videoId);
         if(videoRespVO==null){
@@ -211,7 +210,12 @@ public class GoodsServiceImpl implements GoodsService {
         goodsDetailVO.setVideoUrl(videoRespVO.getVideoUrl());
         goodsDetailVO.setTemplateCoverUrl(videoRespVO.getTemplateCoverUrl());
         goodsDetailVO.setCreateTime(videoRespVO.getCreateTime());
-        if (entity.getIsBuy() == 1) {
+        MemberVideoEntity entity = videoMapper.queryUserVideo(userId, videoId);
+        if (entity == null) {
+            goodsDetailVO.setIsBuy(0);
+            goodsDetailVO.setShare(true);
+            goodsDetailVO.setPrice("未登录");
+        } else if (entity.getIsBuy() == 1) {
             goodsDetailVO.setIsBuy(1);
         } else {
             goodsDetailVO.setIsBuy(0);
@@ -222,16 +226,19 @@ public class GoodsServiceImpl implements GoodsService {
             goodsDetailVO.setPrice(templatePrice==null?"":df.format(templatePrice.setScale(2, RoundingMode.HALF_UP)));
             goodsDetailVO.setSlashPrice(slashPrice==null?null:df.format(slashPrice.setScale(2, RoundingMode.HALF_UP)));
         }
-        TaskRespVO taskRespVO = taskMapper.getById(videoRespVO.getTaskId());
-        JSONObject paramJson = JSON.parseObject(taskRespVO.getTaskParams());
+        TaskEntity task = videoTaskRepository.getTaskById(videoRespVO.getTaskId());
+        JSONObject paramJson = JSON.parseObject(task.getTaskParams());
         long deviceCount;
+        goodsDetailVO.setShotTime(taskTaskService.getTaskShotDate(task.getId()));
         if (paramJson == null) {
             deviceCount = 1;
         } else {
             deviceCount = paramJson.keySet().stream().filter(StringUtils::isNumeric).count();
         }
         goodsDetailVO.setLensNum((int) deviceCount);
-        goodsDetailVO.setFaceId(entity.getFaceId());
+        if (entity != null) {
+            goodsDetailVO.setFaceId(entity.getFaceId());
+        }
         return ApiResponse.success(goodsDetailVO);
     }
 
@@ -286,6 +293,7 @@ public class GoodsServiceImpl implements GoodsService {
         List<MemberVideoEntity> taskList = videoMapper.listRelationByFaceAndTemplate(userId, faceId, templateId);
         VideoTaskStatusVO response = new VideoTaskStatusVO();
         response.setFaceId(faceId);
+        response.setTemplateId(templateId);
         if (taskList.isEmpty()) {
             response.setStatus(0);
             return ApiResponse.success(response);
diff --git a/src/main/java/com/ycwl/basic/service/impl/pc/FaceServiceImpl.java b/src/main/java/com/ycwl/basic/service/impl/pc/FaceServiceImpl.java
index d15f065..612a7f3 100644
--- a/src/main/java/com/ycwl/basic/service/impl/pc/FaceServiceImpl.java
+++ b/src/main/java/com/ycwl/basic/service/impl/pc/FaceServiceImpl.java
@@ -14,7 +14,6 @@ import com.ycwl.basic.model.mobile.statistic.req.StatisticsRecordAddReq;
 import com.ycwl.basic.model.pc.face.entity.FaceEntity;
 import com.ycwl.basic.model.pc.face.req.FaceReqQuery;
 import com.ycwl.basic.model.pc.face.resp.FaceRespVO;
-import com.ycwl.basic.model.pc.faceSample.resp.FaceSampleRespVO;
 import com.ycwl.basic.model.pc.source.entity.MemberSourceEntity;
 import com.ycwl.basic.model.pc.source.entity.SourceEntity;
 import com.ycwl.basic.model.task.resp.SearchFaceRespVo;
@@ -56,7 +55,7 @@ public class FaceServiceImpl implements FaceService {
 
     @Value("${face.score}")
     private float faceScore;
-    private float strictScore = 90F;
+    private final float strictScore = 0.90F;
     @Autowired
     private TaskService taskTaskService;
     @Autowired
@@ -181,8 +180,6 @@ public class FaceServiceImpl implements FaceService {
         faceEntity.setMemberId(userId);
         faceEntity.setFaceUrl(faceUrl);
         List<Long> sampleListIds = scenicDbSearchResult.getSampleListIds();
-        // 匹配原片:照片
-        List<SourceEntity> sourceEntities = sourceMapper.listBySampleIds(sampleListIds);
         if (faceEntity.getId()==null) {
             //新增人脸
             faceEntity.setId(newFaceId);
@@ -191,6 +188,11 @@ public class FaceServiceImpl implements FaceService {
             //2、更新人脸
             faceMapper.update(faceEntity);
         }
+        if (sampleListIds == null) {
+            return ApiResponse.fail("请先游玩后再来获取视频吧");
+        }
+        // 匹配原片:照片
+        List<SourceEntity> sourceEntities = sourceMapper.listBySampleIds(sampleListIds);
         List<MemberSourceEntity> memberSourceEntityList = sourceEntities.stream().map(sourceEntity -> {
             MemberSourceEntity memberSourceEntity = new MemberSourceEntity();
             memberSourceEntity.setScenicId(scenicId);
@@ -204,7 +206,7 @@ public class FaceServiceImpl implements FaceService {
         sourceMapper.addRelations(memberSourceEntityList);
         VideoPieceGetter.Task task = new VideoPieceGetter.Task();
         task.faceId = faceEntity.getId();
-        task.faceSampleId = sampleListIds;
+        task.faceSampleIds = sampleListIds;
         task.memberId = userId;
         VideoPieceGetter.addTask(task);
         taskTaskService.autoCreateTaskByFaceId(faceEntity.getId());
diff --git a/src/main/java/com/ycwl/basic/service/impl/pc/ScenicServiceImpl.java b/src/main/java/com/ycwl/basic/service/impl/pc/ScenicServiceImpl.java
index e7711f3..d7faa52 100644
--- a/src/main/java/com/ycwl/basic/service/impl/pc/ScenicServiceImpl.java
+++ b/src/main/java/com/ycwl/basic/service/impl/pc/ScenicServiceImpl.java
@@ -1,13 +1,7 @@
 package com.ycwl.basic.service.impl.pc;
 
-import com.aliyuncs.DefaultAcsClient;
-import com.aliyuncs.IAcsClient;
-import com.aliyuncs.exceptions.ClientException;
-import com.aliyuncs.facebody.model.v20191230.CreateFaceDbRequest;
-import com.aliyuncs.profile.DefaultProfile;
 import com.github.pagehelper.PageHelper;
 import com.github.pagehelper.PageInfo;
-import com.ycwl.basic.config.FaceDetectConfig;
 import com.ycwl.basic.mapper.ScenicAccountMapper;
 import com.ycwl.basic.mapper.ScenicMapper;
 import com.ycwl.basic.model.pc.scenic.entity.ScenicAccountEntity;
@@ -15,6 +9,7 @@ import com.ycwl.basic.model.pc.scenic.entity.ScenicConfigEntity;
 import com.ycwl.basic.model.pc.scenic.req.ScenicAddOrUpdateReq;
 import com.ycwl.basic.model.pc.scenic.req.ScenicReqQuery;
 import com.ycwl.basic.model.pc.scenic.resp.ScenicRespVO;
+import com.ycwl.basic.repository.ScenicRepository;
 import com.ycwl.basic.service.pc.ScenicService;
 import com.ycwl.basic.service.task.TaskFaceService;
 import com.ycwl.basic.utils.ApiResponse;
@@ -39,9 +34,9 @@ public class ScenicServiceImpl implements ScenicService {
     @Autowired
     private ScenicAccountMapper scenicAccountMapper;
     @Autowired
-    private FaceDetectConfig faceDetectConfig;
-    @Autowired
     private TaskFaceService taskFaceService;
+    @Autowired
+    private ScenicRepository scenicRepository;
 
     @Override
     public ApiResponse<PageInfo<ScenicRespVO>> pageQuery(ScenicReqQuery scenicReqQuery) {
@@ -96,6 +91,7 @@ public class ScenicServiceImpl implements ScenicService {
             scenicMapper.deleteConfigByScenicId(id);
             scenicAccountMapper.deleteByScenicId(id);
             taskFaceService.deleteFaceDB(id.toString());
+            scenicRepository.clearCache(id);
             return ApiResponse.success(true);
         }else {
             return ApiResponse.fail("景区删除失败");
@@ -129,6 +125,7 @@ public class ScenicServiceImpl implements ScenicService {
         }
         int i = scenicMapper.update(scenicUpdateReq);
         if (i > 0) {
+            scenicRepository.clearCache(scenicUpdateReq.getId());
             taskFaceService.assureFaceDB(scenicUpdateReq.getId().toString());
             return ApiResponse.success(true);
         }else {
@@ -141,6 +138,7 @@ public class ScenicServiceImpl implements ScenicService {
     public ApiResponse<Boolean> updateStatus(Long id) {
         int i = scenicMapper.updateStatus(id);
         if (i > 0) {
+            scenicRepository.clearCache(id);
             taskFaceService.assureFaceDB(id.toString());
             return ApiResponse.success(true);
         }else {
@@ -152,6 +150,7 @@ public class ScenicServiceImpl implements ScenicService {
     public ApiResponse<Boolean> addConfig(ScenicConfigEntity scenicConfig) {
         int i = scenicMapper.addConfig(scenicConfig);
         if (i > 0) {
+            scenicRepository.clearCache(scenicConfig.getScenicId());
             taskFaceService.assureFaceDB(scenicConfig.getScenicId().toString());
             return ApiResponse.success(true);
         }else {
@@ -163,6 +162,7 @@ public class ScenicServiceImpl implements ScenicService {
     public ApiResponse<Boolean> updateConfigById(ScenicConfigEntity scenicConfig) {
         int i = scenicMapper.updateConfigById(scenicConfig);
         if (i > 0) {
+            scenicRepository.clearCache(scenicConfig.getScenicId());
             taskFaceService.assureFaceDB(scenicConfig.getScenicId().toString());
             return ApiResponse.success(true);
         }else {
@@ -172,27 +172,16 @@ public class ScenicServiceImpl implements ScenicService {
 
     @Override
     public ScenicConfigEntity getConfig(Long id) {
-        ScenicConfigEntity config = scenicMapper.getConfig(id);
-        if (config == null) {
-            config = new ScenicConfigEntity();
-            config.setId(SnowFlakeUtil.getLongId());
-            config.setScenicId(id);
-            config.setIsDefault(1);
-            scenicMapper.addConfig(config);
-        }
-        return config;
+        return scenicRepository.getScenicConfig(id);
     }
 
     @Override
     public void saveConfig(Long configId, ScenicConfigEntity config) {
         config.setId(configId);
+        if (config.getScenicId() == null) {
+            throw new RuntimeException("景区ID不能为空");
+        }
         scenicMapper.updateConfigById(config);
-    }
-
-    private IAcsClient getClient() {
-        DefaultProfile profile = DefaultProfile.getProfile(
-                faceDetectConfig.getRegion(),faceDetectConfig.getAccessKeyId(), faceDetectConfig.getAccessKeySecret());
-        IAcsClient client = new DefaultAcsClient(profile);
-        return client;
+        scenicRepository.clearCache(config.getScenicId());
     }
 }
diff --git a/src/main/java/com/ycwl/basic/service/impl/pc/TaskServiceImpl.java b/src/main/java/com/ycwl/basic/service/impl/pc/TaskServiceImpl.java
index 9364634..dda32cc 100644
--- a/src/main/java/com/ycwl/basic/service/impl/pc/TaskServiceImpl.java
+++ b/src/main/java/com/ycwl/basic/service/impl/pc/TaskServiceImpl.java
@@ -6,6 +6,7 @@ import com.ycwl.basic.mapper.TaskMapper;
 import com.ycwl.basic.model.pc.task.entity.TaskEntity;
 import com.ycwl.basic.model.pc.task.req.TaskReqQuery;
 import com.ycwl.basic.model.pc.task.resp.TaskRespVO;
+import com.ycwl.basic.repository.VideoTaskRepository;
 import com.ycwl.basic.service.pc.TaskService;
 import com.ycwl.basic.utils.ApiResponse;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -22,6 +23,8 @@ public class TaskServiceImpl implements TaskService {
 
     @Autowired
     private TaskMapper taskMapper;
+    @Autowired
+    private VideoTaskRepository videoTaskRepository;
 
     @Override
     public ApiResponse<PageInfo<TaskRespVO>> pageQuery(TaskReqQuery taskReqQuery) {
@@ -44,6 +47,7 @@ public class TaskServiceImpl implements TaskService {
     @Override
     public ApiResponse<Boolean> deleteById(Long id) {
         int i = taskMapper.deleteById(id);
+        videoTaskRepository.clearTaskCache(id);
         if (i > 0) {
             return ApiResponse.success(true);
         }else {
@@ -54,6 +58,7 @@ public class TaskServiceImpl implements TaskService {
     @Override
     public ApiResponse<Boolean> update(TaskEntity task) {
         int i = taskMapper.update(task);
+        videoTaskRepository.clearTaskCache(task.getId());
         if (i > 0) {
             return ApiResponse.success(true);
         }else {
@@ -64,6 +69,7 @@ public class TaskServiceImpl implements TaskService {
     @Override
     public ApiResponse<Boolean> updateStatus(Long id, Integer status) {
         int i = taskMapper.updateStatus(id, status);
+        videoTaskRepository.clearTaskCache(id);
         if (i > 0) {
             return ApiResponse.success(true);
         }else {
diff --git a/src/main/java/com/ycwl/basic/service/impl/task/TaskFaceServiceImpl.java b/src/main/java/com/ycwl/basic/service/impl/task/TaskFaceServiceImpl.java
index 6309efe..cced975 100644
--- a/src/main/java/com/ycwl/basic/service/impl/task/TaskFaceServiceImpl.java
+++ b/src/main/java/com/ycwl/basic/service/impl/task/TaskFaceServiceImpl.java
@@ -108,7 +108,7 @@ public class TaskFaceServiceImpl implements TaskFaceService {
         request.setDbName(dbName);
         request.setImageUrl(faceUrl);
         request.setLimit(100);
-        request.setQualityScoreThreshold(80F);
+        request.setQualityScoreThreshold(60f);
         FaceDetectLog log = FaceDetectLog.quickCreate("预留字段", request);
         try {
             SearchFaceResponse response = client.getAcsResponse(request);
diff --git a/src/main/java/com/ycwl/basic/service/impl/task/TaskTaskServiceImpl.java b/src/main/java/com/ycwl/basic/service/impl/task/TaskTaskServiceImpl.java
index 6732cc3..bce6cff 100644
--- a/src/main/java/com/ycwl/basic/service/impl/task/TaskTaskServiceImpl.java
+++ b/src/main/java/com/ycwl/basic/service/impl/task/TaskTaskServiceImpl.java
@@ -1,10 +1,14 @@
 package com.ycwl.basic.service.impl.task;
 
+import cn.hutool.core.date.DateUtil;
 import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
 import com.ycwl.basic.biz.OrderBiz;
 import com.ycwl.basic.constant.TaskConstant;
 import com.ycwl.basic.mapper.FaceMapper;
 import com.ycwl.basic.mapper.FaceSampleMapper;
+import com.ycwl.basic.mapper.MemberMapper;
 import com.ycwl.basic.mapper.RenderWorkerMapper;
 import com.ycwl.basic.mapper.SourceMapper;
 import com.ycwl.basic.mapper.TaskMapper;
@@ -13,7 +17,10 @@ import com.ycwl.basic.mapper.VideoMapper;
 import com.ycwl.basic.model.mobile.order.PriceObj;
 import com.ycwl.basic.model.pc.face.resp.FaceRespVO;
 import com.ycwl.basic.model.pc.faceSample.resp.FaceSampleRespVO;
+import com.ycwl.basic.model.pc.member.resp.MemberRespVO;
+import com.ycwl.basic.model.pc.mp.MpConfigEntity;
 import com.ycwl.basic.model.pc.renderWorker.entity.RenderWorkerEntity;
+import com.ycwl.basic.model.pc.scenic.entity.ScenicEntity;
 import com.ycwl.basic.model.pc.source.entity.SourceEntity;
 import com.ycwl.basic.model.pc.source.resp.SourceRespVO;
 import com.ycwl.basic.model.pc.task.entity.TaskEntity;
@@ -27,6 +34,11 @@ import com.ycwl.basic.model.task.req.ClientStatusReqVo;
 import com.ycwl.basic.model.task.req.TaskReqVo;
 import com.ycwl.basic.model.task.req.WorkerAuthReqVo;
 import com.ycwl.basic.model.task.resp.TaskSyncRespVo;
+import com.ycwl.basic.notify.NotifyFactory;
+import com.ycwl.basic.notify.adapters.INotifyAdapter;
+import com.ycwl.basic.notify.entity.NotifyContent;
+import com.ycwl.basic.notify.enums.NotifyType;
+import com.ycwl.basic.repository.ScenicRepository;
 import com.ycwl.basic.repository.VideoTaskRepository;
 import com.ycwl.basic.service.task.TaskService;
 import com.ycwl.basic.storage.StorageFactory;
@@ -35,6 +47,7 @@ import com.ycwl.basic.task.VideoPieceGetter;
 import com.ycwl.basic.repository.TemplateRepository;
 import com.ycwl.basic.utils.SnowFlakeUtil;
 import lombok.NonNull;
+import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.data.redis.core.RedisTemplate;
@@ -44,12 +57,15 @@ import java.math.BigDecimal;
 import java.math.RoundingMode;
 import java.util.Arrays;
 import java.util.Date;
+import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
+import java.util.Optional;
 import java.util.concurrent.TimeUnit;
 import java.util.stream.Collectors;
 
+@Slf4j
 @Service
 public class TaskTaskServiceImpl implements TaskService {
     @Autowired
@@ -74,6 +90,10 @@ public class TaskTaskServiceImpl implements TaskService {
     private VideoTaskRepository videoTaskRepository;
     @Autowired
     private OrderBiz orderBiz;
+    @Autowired
+    private MemberMapper memberMapper;
+    @Autowired
+    private ScenicRepository scenicRepository;
 
     private RenderWorkerEntity getWorker(@NonNull WorkerAuthReqVo req) {
         String accessKey = req.getAccessKey();
@@ -207,10 +227,6 @@ public class TaskTaskServiceImpl implements TaskService {
         if (templateList == null || templateList.isEmpty()) {
             return;
         }
-        TaskEntity faceAutomaticTask = taskMapper.getFaceAutomaticTask(faceId);
-        if (faceAutomaticTask != null) {
-            return;
-        }
         createTaskByFaceIdAndTempalteId(faceId, templateList.get(0).getId(), 1);
     }
     @Override
@@ -235,13 +251,31 @@ public class TaskTaskServiceImpl implements TaskService {
             taskReqQuery.setFaceId(faceId);
             taskReqQuery.setTemplateId(templateId);
             List<TaskRespVO> list = taskMapper.list(taskReqQuery);
-            if (!list.isEmpty()) {
-                return;
-            }
+            list.parallelStream().forEach(task -> {
+                MemberVideoEntity memberVideo = videoMapper.queryRelationByMemberTask(faceRespVO.getMemberId(), task.getId());
+                if (memberVideo == null) {
+                    memberVideo = new MemberVideoEntity();
+                    memberVideo.setMemberId(faceRespVO.getMemberId());
+                    memberVideo.setScenicId(task.getScenicId());
+                    memberVideo.setFaceId(faceId);
+                    memberVideo.setTemplateId(task.getTemplateId());
+                    memberVideo.setIsBuy(0);
+                    memberVideo.setTaskId(task.getId());
+                    VideoEntity video = videoMapper.findByTaskId(task.getId());
+                    if (video != null) {
+                        memberVideo.setVideoId(video.getId());
+                    }
+                    videoMapper.addRelation(memberVideo);
+                    new Thread(() -> {
+                        sendVideoGeneratedServiceNotification(list.get(0).getId(), faceRespVO.getMemberId());
+                    }).start();
+                }
+            });
+            return;
         }
         VideoPieceGetter.Task task = new VideoPieceGetter.Task();
         task.faceId = faceId;
-        task.faceSampleId = faceSampleIds;
+        task.faceSampleIds = faceSampleIds;
         task.memberId = faceRespVO.getMemberId();
         task.callback = () -> {
             boolean canGenerate = templateRepository.determineTemplateCanGenerate(templateId, faceId);
@@ -284,6 +318,10 @@ public class TaskTaskServiceImpl implements TaskService {
                         memberVideoEntity.setIsBuy(1);
                     }
                     memberVideoEntity.setVideoId(video.getId());
+                    // 已经生成了
+                    new Thread(() -> {
+                        sendVideoGeneratedServiceNotification(list.get(0).getId(), faceRespVO.getMemberId());
+                    }).start();
                 }
             }
             videoMapper.addRelation(memberVideoEntity);
@@ -328,6 +366,9 @@ public class TaskTaskServiceImpl implements TaskService {
             isBuy = 1;
         }
         videoMapper.updateRelationWhenTaskSuccess(taskId, video.getId(), isBuy);
+        new Thread(() -> {
+            sendVideoGeneratedServiceNotification(taskId);
+        }).start();
     }
 
     @Override
@@ -368,4 +409,83 @@ public class TaskTaskServiceImpl implements TaskService {
         }
         return adapter.getUrlForUpload(filename);
     }
+
+    public void sendVideoGeneratedServiceNotification(Long taskId) {
+        List<MemberVideoEntity> memberVideo = videoMapper.listRelationByTask(taskId);
+        memberVideo.forEach(item -> {
+            sendVideoGeneratedServiceNotification(taskId, item.getMemberId());
+        });
+    }
+
+    @Override
+    public Date getTaskShotDate(Long taskId) {
+        TaskRespVO taskRespVO = taskMapper.getById(taskId);
+        if (taskRespVO == null) {
+            return null;
+        }
+        Date shotTime = taskRespVO.getCreateTime();
+        JSONObject paramJson = JSON.parseObject(taskRespVO.getTaskParams());
+        if (paramJson != null) {
+            Optional<String> any = paramJson.keySet().stream().filter(StringUtils::isNumeric).findAny();
+            if (any.isPresent()) {
+                JSONArray jsonArray = paramJson.getJSONArray(any.get());
+                if (!jsonArray.isEmpty()) {
+                    JSONObject jsonObject = jsonArray.getJSONObject(0);
+                    if (jsonObject.containsKey("createTime")) {
+                        shotTime = new Date(jsonObject.getLong("createTime"));
+                    }
+                }
+            }
+        }
+        return shotTime;
+    }
+
+    @Override
+    public void sendVideoGeneratedServiceNotification(Long taskId, Long memberId) {
+        MemberVideoEntity item = videoMapper.queryRelationByMemberTask(memberId, taskId);
+        MemberRespVO member = memberMapper.getById(memberId);
+        String openId = member.getOpenId();
+        MpConfigEntity scenicMp = scenicRepository.getScenicMpConfig(member.getScenicId());
+        if (StringUtils.isNotBlank(openId) && scenicMp != null) {
+            String templateId = scenicRepository.getVideoGeneratedTemplateId(item.getScenicId());
+            if (StringUtils.isBlank(templateId)) {
+                log.warn("未配置视频生成通知模板");
+                return;
+            }
+            ScenicEntity scenic = scenicRepository.getScenic(item.getScenicId());
+            String title = "您在【" + scenic.getName() + "】的影像";
+            String page = "pages/videoSynthesis/buy?scenicId=" + item.getScenicId() + "&faceId=" + item.getFaceId() + "&id=" + item.getVideoId();
+            /**
+             * 景点 {{thing5.DATA}}
+             * 视频名称 {{thing1.DATA}}
+             * 游玩时间 {{time2.DATA}}
+             * 生成时间 {{time4.DATA}}
+             * 备注 {{thing3.DATA}}
+             */
+            Map<String, Object> params = new HashMap<>();
+            Map<String, Object> dataParam = new HashMap<>();
+            Map<String, String> scenicMap = new HashMap<>();
+            scenicMap.put("value", scenic.getName());
+            dataParam.put("thing5", scenicMap);
+            Map<String, String> videoMap = new HashMap<>();
+            TemplateRespVO template = templateRepository.getTemplate(item.getTemplateId());
+            videoMap.put("value", template.getName());
+            dataParam.put("thing1", videoMap);
+            Map<String, String> timeMap = new HashMap<>();
+            timeMap.put("value", DateUtil.format(getTaskShotDate(taskId), "yyyy-MM-dd"));
+            dataParam.put("time2", timeMap);
+            Map<String, String> timeMap2 = new HashMap<>();
+            timeMap2.put("value", DateUtil.format(new Date(), "yyyy-MM-dd HH:mm"));
+            dataParam.put("time4", timeMap2);
+            Map<String, String> remarkMap = new HashMap<>();
+            remarkMap.put("value", "您的游玩Vlog已经等候多时,快来看看吧");
+            dataParam.put("thing3", remarkMap);
+            params.put("data", dataParam);
+            params.put("page", page);
+            params.put("template_id", templateId);
+            log.info("视频生成通知模板参数:{},用户ID:{}", params, openId);
+            INotifyAdapter adapter = NotifyFactory.get(NotifyType.WX_MP_SRV, scenicMp.toMap());
+            adapter.sendTo(new NotifyContent(title, page, params), openId);
+        }
+    }
 }
diff --git a/src/main/java/com/ycwl/basic/service/mobile/AppMemberService.java b/src/main/java/com/ycwl/basic/service/mobile/AppMemberService.java
index 4b468e4..8836f22 100644
--- a/src/main/java/com/ycwl/basic/service/mobile/AppMemberService.java
+++ b/src/main/java/com/ycwl/basic/service/mobile/AppMemberService.java
@@ -17,16 +17,17 @@ public interface AppMemberService {
      *
      * @return Map
      */
-    Map<String, Object> getOpenId(String code);
+    Map<String, Object> getOpenId(Long scenicId, String code);
 
     /**
      * 登录
      *
+     * @param scenicId
      * @param code        前端授权码
      * @param userInfoDTO 实体信息
      * @return
      */
-    ApiResponse login(String code, WeChatUserInfoDTO userInfoDTO) throws Exception;
+    ApiResponse login(Long scenicId, String code, WeChatUserInfoDTO userInfoDTO) throws Exception;
 
     /**
      * 获取用户信息
diff --git a/src/main/java/com/ycwl/basic/service/task/TaskService.java b/src/main/java/com/ycwl/basic/service/task/TaskService.java
index b07c234..46d1faf 100644
--- a/src/main/java/com/ycwl/basic/service/task/TaskService.java
+++ b/src/main/java/com/ycwl/basic/service/task/TaskService.java
@@ -5,6 +5,8 @@ import com.ycwl.basic.model.task.req.TaskReqVo;
 import com.ycwl.basic.model.task.req.WorkerAuthReqVo;
 import com.ycwl.basic.model.task.resp.TaskSyncRespVo;
 
+import java.util.Date;
+
 public interface TaskService {
     TaskSyncRespVo handleSyncTask(TaskReqVo req);
     void createRenderTask(Long scenicId, Long templateId, Long faceId);
@@ -24,4 +26,8 @@ public interface TaskService {
     void taskStart(Long taskId, WorkerAuthReqVo req);
 
     void autoCreateTaskByFaceId(Long id);
+
+    Date getTaskShotDate(Long taskId);
+
+    void sendVideoGeneratedServiceNotification(Long taskId, Long memberId);
 }
diff --git a/src/main/java/com/ycwl/basic/task/VideoPieceGetter.java b/src/main/java/com/ycwl/basic/task/VideoPieceGetter.java
index 91551b0..7b11cb3 100644
--- a/src/main/java/com/ycwl/basic/task/VideoPieceGetter.java
+++ b/src/main/java/com/ycwl/basic/task/VideoPieceGetter.java
@@ -14,7 +14,6 @@ import com.ycwl.basic.model.pc.source.entity.MemberSourceEntity;
 import com.ycwl.basic.model.pc.source.entity.SourceEntity;
 import com.ycwl.basic.storage.StorageFactory;
 import com.ycwl.basic.storage.adapters.IStorageAdapter;
-import com.ycwl.basic.storage.enums.StorageType;
 import com.ycwl.basic.utils.SnowFlakeUtil;
 import lombok.Data;
 import lombok.extern.slf4j.Slf4j;
@@ -25,8 +24,6 @@ import org.springframework.stereotype.Component;
 
 import java.io.BufferedReader;
 import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
@@ -55,7 +52,7 @@ public class VideoPieceGetter {
     @Data
     public static class Task {
         public String type = "normal";
-        public List<Long> faceSampleId;
+        public List<Long> faceSampleIds;
         public Callback callback;
         public Long memberId;
         public Long faceId;
@@ -86,7 +83,7 @@ public class VideoPieceGetter {
         }
         log.info("poll task: {}", task);
         if (task.getType().equalsIgnoreCase("normal")) {
-            task.getFaceSampleId().parallelStream().forEach(faceSampleId -> {
+            task.getFaceSampleIds().parallelStream().forEach(faceSampleId -> {
                 FaceSampleRespVO faceSample = faceSampleMapper.getById(faceSampleId);
                 DeviceEntity device = deviceRepository.getDevice(faceSample.getDeviceId());
                 DeviceConfigEntity config = deviceRepository.getDeviceConfig(faceSample.getDeviceId());
diff --git a/src/main/resources/application-prod.yml b/src/main/resources/application-prod.yml
index 835b6f7..ad4c1a9 100644
--- a/src/main/resources/application-prod.yml
+++ b/src/main/resources/application-prod.yml
@@ -115,7 +115,7 @@ YfkdFNxtYLdVAwuylMoV3fKI
 
 # 人脸合格得分
 face:
-  score: 80
+  score: 75
 
 # 存储
 storage:
diff --git a/src/main/resources/mapper/MemberMapper.xml b/src/main/resources/mapper/MemberMapper.xml
index b998655..25dd2e6 100644
--- a/src/main/resources/mapper/MemberMapper.xml
+++ b/src/main/resources/mapper/MemberMapper.xml
@@ -2,9 +2,9 @@
 <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
 <mapper namespace="com.ycwl.basic.mapper.MemberMapper">
     <insert id="add">
-        insert into member(id, openid,avatar_url, nickname, real_name, promo_code, broker_id, agreement, phone, country, province,
+        insert into member(id, scenic_id, openid,avatar_url, nickname, real_name, promo_code, broker_id, agreement, phone, country, province,
                            city)
-        values (#{id}, #{openId},  #{avatarUrl},#{nickname}, #{realName}, #{promoCode}, #{brokerId}, #{agreement}, #{phone},
+        values (#{id}, #{scenicId}, #{openId},  #{avatarUrl},#{nickname}, #{realName}, #{promoCode}, #{brokerId}, #{agreement}, #{phone},
                 #{country}, #{province}, #{city})
     </insert>
     <insert id="addScenicServiceNoticeStatus">
@@ -14,6 +14,9 @@
     <update id="update">
         update member
         <set>
+            <if test="scenicId!= null">
+                scenicId = #{scenicId},
+            </if>
             <if test="openId!= null and openId!= ''">
                 openid = #{openId},
             </if>
@@ -67,7 +70,7 @@
         where id = #{id}
     </delete>
     <select id="list" resultType="com.ycwl.basic.model.pc.member.resp.MemberRespVO">
-        select id, openid,avatar_url, nickname, real_name, promo_code, broker_id, agreement, phone, country, province, city,
+        select id, scenic_id, openid,avatar_url, nickname, real_name, promo_code, broker_id, agreement, phone, country, province, city,
         (select count(1) from `order` where `order`.member_id = member.id) as order_count,
         create_date
         from member
@@ -75,6 +78,9 @@
             <if test="openId!= null and openId!= ''">
                 and openid like concat('%',#{openId},'%')
             </if>
+            <if test="scenicId!= null">
+                and scenic_id = #{scenicId}
+            </if>
             <if test="nickname!= null and nickname!= ''">
                 and nickname like concat('%',#{nickname},'%')
             </if>
@@ -106,6 +112,7 @@
     </select>
     <select id="getById" resultType="com.ycwl.basic.model.pc.member.resp.MemberRespVO">
         select id,
+               scenic_id,
                openid,
                avatar_url,
                nickname,
diff --git a/src/main/resources/mapper/MpNotifyConfigMapper.xml b/src/main/resources/mapper/MpNotifyConfigMapper.xml
new file mode 100644
index 0000000..33df7ba
--- /dev/null
+++ b/src/main/resources/mapper/MpNotifyConfigMapper.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
+<mapper namespace="com.ycwl.basic.mapper.MpNotifyConfigMapper">
+    <select id="listByMpId" resultType="com.ycwl.basic.model.pc.mp.MpNotifyConfigEntity">
+        select *
+        from mp_notify_config
+        where mp_id = #{mpId}
+    </select>
+</mapper>
\ No newline at end of file
diff --git a/src/main/resources/mapper/SourceMapper.xml b/src/main/resources/mapper/SourceMapper.xml
index 70b7033..2afc28d 100644
--- a/src/main/resources/mapper/SourceMapper.xml
+++ b/src/main/resources/mapper/SourceMapper.xml
@@ -73,16 +73,14 @@
         where so.id = #{id}
     </select>
     <select id="listGroupByType" resultType="com.ycwl.basic.model.pc.source.resp.SourceRespVO">
-        select so.id, ms.scenic_id,sc.name scenicName, sc.longitude ,sc.latitude,so.type,so.is_buy
+        select ms.type, ms.is_buy
         from member_source ms
-        left join source so on ms.source_id = so.id
-        left join scenic sc on sc.id = so.scenic_id
         <where>
-            <if test="scenicId!= null">and so.scenic_id = #{scenicId} </if>
+            <if test="scenicId!= null">and ms.scenic_id = #{scenicId} </if>
             <if test="memberId!= null">and ms.member_id = #{memberId} </if>
             <if test="isBuy!=null">and ms.is_buy = #{isBuy}</if>
         </where>
-        group by so.type
+        group by ms.type
     </select>
     <select id="countByMemberId" resultType="java.lang.Integer">
         select count(1) from member_source where  member_id = #{userId}
diff --git a/src/main/resources/mapper/VideoMapper.xml b/src/main/resources/mapper/VideoMapper.xml
index 144f366..d9e7840 100644
--- a/src/main/resources/mapper/VideoMapper.xml
+++ b/src/main/resources/mapper/VideoMapper.xml
@@ -115,6 +115,11 @@
         from member_video mv
         where mv.member_id = #{userId} and mv.face_id = #{faceId}
     </select>
+    <select id="listRelationByTask" resultType="com.ycwl.basic.model.pc.video.entity.MemberVideoEntity">
+        select mv.*
+        from member_video mv
+        where mv.task_id = #{taskId}
+    </select>
     <select id="listRelationByFaceAndTemplate" resultType="com.ycwl.basic.model.pc.video.entity.MemberVideoEntity">
         select mv.*
         from member_video mv
@@ -132,4 +137,10 @@
         where member_id = #{userId} and video_id = #{videoId}
         limit 1
     </select>
+    <select id="queryRelationByMemberTask" resultType="com.ycwl.basic.model.pc.video.entity.MemberVideoEntity">
+        select *
+        from member_video
+        where member_id = #{userId} and task_id = #{taskId}
+        limit 1
+    </select>
 </mapper>
\ No newline at end of file