SpringBoot 仿抖音短视频小程序开发(二)

8次阅读

共计 6229 个字符,预计需要花费 16 分钟才能阅读完成。

一、注册和登录功能

这两个功能比较简单,就不详细记录了,需要注意的是【密码】出于安全考虑用了 @JsonIgnore,这样返回的 VO 的 json 数据给前端的时候就忽略掉。
public class UsersVO {

private String id;

private String username;

private String userToken;

@JsonIgnore
private String password;
}

二、上传个人头像并展示

1. 微信小程序前端只需要把图片的临时路径传给后端接口,后台再保存到本地和数据库
前端:

后台接口:
@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. 静态资源配置,显示图片

三、上传视频、选择 BGM(可选)

上传视频和上传头像的实现是差不多的,多了截图、与 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);
三、首页展示视频列表,分页

======================== 前端 ===============================

后端分页查询
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
});
上拉刷新,即下一页
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);
},
四、点击播放视频
点击视频触发事件,跳转页面
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
})
}

五、点赞和关注视频
点赞和取消
@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);
}
六、视频热搜关键词
使用了一个微信小程序搜索框组件:https://github.com/mindawei/w…
前端页面加载事件:

热搜词的查询语句:
<select id=”getHotWords” resultType=”string”>
SELECT content FROM search_records GROUP BY content ORDER BY COUNT(content) DESC
</select>
六、显示我点过赞的视频(即收藏)

<!– 查询我喜欢的视频 –>
<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>
七、查询我关注的人发的视频

<!– 查询我关注的人发的视频 –>
<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>
八、举报

获取举报的内容然后发送请求:
九、评论留言和回复

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
});
},
前端确认留言,保存:

正文完
 0