SpringBoot 仿抖音短視頻小程序開發(二)

1、註冊和登陸功能

clipboard.png

這兩個功能比較簡單,就不詳細記錄了,須要注意的是【密碼】出於安全考慮用了@JsonIgnore,這樣返回的VO的json數據給前端的時候就忽略掉。javascript

public class UsersVO {

    private String id;

    private String username;

    private String userToken;

    @JsonIgnore
    private String password; 
}

2、上傳我的頭像並展現

clipboard.png

1. 微信小程序前端只須要把圖片的臨時路徑傳給後端接口,後臺再保存到本地和數據庫

前端:前端

clipboard.png

後臺接口:java

@PostMapping("/uploadFace")
    public IMoocJSONResult uploadFace(String userId, @RequestParam("file") MultipartFile[] files) throws Exception {
        if(StringUtils.isBlank(userId)){
            return IMoocJSONResult.errorMsg("用戶Id不能爲空");
        }

        //文件保存的命名空間
        String fileSpace = FILE_SPACE;
        //保存到數據庫的相對路徑
        String uploadPathDB = "/" + userId +"/face";
        FileOutputStream fileOutputStream = null;
        InputStream inputStream = null;
        try {
            if(files !=null && files.length>0){
                String fileName = files[0].getOriginalFilename();
                if(StringUtils.isNoneBlank(fileName)){
                    //文件上傳的最終保存路徑
                    String finalFacePath = fileSpace + uploadPathDB + "/" +fileName;
                    //設置數據庫保存的路徑
                    uploadPathDB += ("/" + fileName);
                    File outFile = new File(finalFacePath);
                    if(outFile.getParentFile() !=null || !outFile.getParentFile().isDirectory()){
                        //建立父文件夾
                        outFile.getParentFile().mkdirs();
                    }
                    fileOutputStream = new FileOutputStream(outFile);
                    inputStream = files[0].getInputStream();
                    IOUtils.copy(inputStream,fileOutputStream);
                }
            }else{
                IMoocJSONResult.errorMsg("上傳出錯");
            }
        } catch (IOException e) {
            e.printStackTrace();
            IMoocJSONResult.errorMsg("上傳出錯");
        }finally {
            if(fileOutputStream!=null){
                fileOutputStream.flush();
                fileOutputStream.close();
            }
        }
        Users user = new Users();
        user.setId(userId);
        user.setFaceImage(uploadPathDB);
        userService.updateUserInfo(user);
        return IMoocJSONResult.ok(uploadPathDB);

    }

2. 靜態資源配置,顯示圖片

clipboard.png

3、上傳視頻、選擇BGM(可選)

clipboard.png

clipboard.png

上傳視頻和上傳頭像的實現是差很少的,多了截圖、與BGM合併的操做
//將視頻和BGM合併
        MergeVideoMp3 tool = new MergeVideoMp3(FFMPEG_EXE);
        String videoInputPath = finalVideoPath;
        String videoOutputName = UUID.randomUUID().toString() + ".mp4";
        uploadPathDB = "/" + userId + "/video/" + videoOutputName;
        finalVideoPath = FILE_SPACE + uploadPathDB;
        tool.convertor(videoInputPath,mp3InputPath,videoSeconds,finalVideoPath);
        
        。。。。。
        //對視頻進行截圖
        FetchVideoCover videoCover = new FetchVideoCover(FFMPEG_EXE);
        videoCover.getCover(finalVideoPath, FILE_SPACE + coverPathDB);

3、首頁展現視頻列表,分頁

clipboard.png

========================前端===============================git

clipboard.png

後端分頁查詢 github

PageHelper.startPage(page, pageSize);
        List<VideosVO> list = videosMapper.queryAllVideos(desc, userId);
        PageInfo<VideosVO> pageList = new PageInfo<>(list);
        PagedResult pagedResult = new PagedResult();
        pagedResult.setPage(page);
        pagedResult.setTotal(pageList.getPages());
        pagedResult.setRows(list);
        pagedResult.setRecords(pageList.getTotal());
        return pagedResult;

前端成功回調函數,對視頻列表進行拼接 數據庫

var videoList = res.data.data.rows;
        var newVideoList = me.data.videoList;
        me.setData({
          videoList: newVideoList.concat(videoList),
          page: page,
          totalPage: res.data.data.total,
          serverUrl: serverUrl
        });

上拉刷新,即下一頁 json

onReachBottom: function(){
    var me = this;
    var currentPage = me.data.page;
    var totalPage = me.data.totalPage;

    //判斷當前頁數和總頁數是否相等,若是相等則無需查詢
    if(currentPage == totalPage){
      wx.showToast({
        title: '已經沒有視頻啦!!',
        icon: "none"
      });
      return;
    }
    var page = currentPage + 1;
    me.getAllVideoList(page,0);
  }

下拉刷新回到第一頁 小程序

onPullDownRefresh: function(){
    wx.showNavigationBarLoading(); 
    this.getAllVideoList(1,0);
  },

4、點擊播放視頻

點擊視頻觸發事件,跳轉頁面後端

showVideoInfo: function(e){
    console.log(e);
    var me = this;
    var videoList = me.data.videoList;
    var arrIndex = e.target.dataset.arrindex;
    console.log(arrIndex);
    var videoInfo = JSON.stringify(videoList[arrIndex]);
    wx.redirectTo({
      url: '../videoinfo/videoinfo?videoInfo=' + videoInfo
    })
  }

clipboard.png

clipboard.png

5、點贊和關注視頻

點贊和取消微信小程序

@Override
    @Transactional(propagation = Propagation.REQUIRED)
    public void userLikeVideo(String userId, String videoId, String videoCreaterId) {
        //1. 保存用戶和視頻的喜歡點贊關聯關係表
        String likeId = sid.nextShort();
        UsersLikeVideos ulv = new UsersLikeVideos();
        ulv.setId(likeId);
        ulv.setUserId(userId);
        ulv.setVideoId(videoId);
        usersLikeVideosMapper.insert(ulv);

        //2. 視頻喜歡數量累加
        videosMapper.addVideoLikeCount(videoId);

        //3. 用戶受喜歡數量的累加
        usersMapper.addReceiveLikeCount(userId);
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED)
    public void userUnLikeVideo(String userId, String videoId, String videoCreaterId) {
        //1. 刪除用戶和視頻的喜歡點贊關聯關係表
        UsersLikeVideosExample example = new UsersLikeVideosExample();
        example.createCriteria().andUserIdEqualTo(userId).andVideoIdEqualTo(videoId);
        usersLikeVideosMapper.deleteByExample(example);


        //2. 視頻喜歡數量累減
        videosMapper.reduceVideoLikeCount(videoId);

        //3. 用戶受喜歡數量的累減
        usersMapper.reduceReceiveLikeCount(userId);
    }

關注用戶和取消關注

@Override
    @Transactional(propagation = Propagation.REQUIRED)
    public void saveUserFanRelation(String userId, String fanId) {
        UsersFans userFan = new UsersFans();
        String relId = sid.nextShort();
        userFan.setId(relId);
        userFan.setUserId(userId);
        userFan.setFanId(fanId);
        usersFansMapper.insert(userFan);
        usersMapper.addFansCount(userId);
        usersMapper.addFollersCount(fanId);
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED)
    public void deleteUserFanRelation(String userId, String fanId) {
        UsersFansExample example = new UsersFansExample();
        example.createCriteria().andFanIdEqualTo(fanId).andUserIdEqualTo(userId);
        usersFansMapper.deleteByExample(example);
        usersMapper.reduceFansCount(userId);
        usersMapper.reduceFollersCount(fanId);
    }

6、視頻熱搜關鍵詞

clipboard.png
使用了一個微信小程序搜索框組件https://github.com/mindawei/w...

前端頁面加載事件:

clipboard.png

熱搜詞的查詢語句:

<select id="getHotWords" resultType="string">
    SELECT content FROM search_records GROUP BY content ORDER BY COUNT(content) DESC
  </select>

6、顯示我點過讚的視頻(即收藏)

clipboard.png

<!-- 查詢我喜歡的視頻 -->
  <select id="queryMyLikeVideos" resultMap="BaseResultMap" parameterType="String">
        select v.*,u.face_image as face_image,u.nickname as nickname from videos v
        left join vuser u on v.user_id = u.id
        where
            v.id in (select ulv.video_id from users_like_videos ulv where ulv.user_id = #{userId})
            and v.status = 1
            order by v.create_time desc
  </select>

7、查詢我關注的人發的視頻

clipboard.png

<!-- 查詢我關注的人發的視頻 -->
   <select id="queryMyFollowVideos" resultMap="BaseResultMap" parameterType="String">
        select v.*,u.face_image as face_image,u.nickname as nickname from videos v
        left join vuser u on v.user_id = u.id
        where
            v.user_id in (select uf.user_id from users_fans uf where uf.fan_id = #{userId})
            and v.status = 1
            order by v.create_time desc
    </select>

8、舉報

clipboard.png

clipboard.png

獲取舉報的內容而後發送請求:
clipboard.png

9、評論留言和回覆

clipboard.png

POJO設計:

public class Comments {
    private String id;

    private String fatherCommentId;

    private String toUserId;

    private String videoId;

    private String fromUserId;  //留言者,評論的用戶id

    private Date createTime;

    private String comment; //評論內容
}

點擊某條評論,回覆:

replyFocus:function(e){
    var me = this;
    var fatherCommentId = e.currentTarget.dataset.fathercommentid;
    var toUserId = e.currentTarget.dataset.touserid;
    var toNickname = e.currentTarget.dataset.tonickname;
    me.setData({
      placeholder: "回覆 " + toNickname,
      replyToUserId: toUserId,
      replyFatherCommentId: fatherCommentId,
      commentFocus: true
    });
  },

前端確認留言,保存:
clipboard.png

相關文章
相關標籤/搜索