小程式頁面目錄:
index 首頁
userRegist 使用者注冊頁面
userLogin 使用者登入頁面
chooseBgm 選擇背景音樂頁面
resource 圖檔存放目錄
1.使用者注冊實作
1.1 注冊頁面
regist.wxml
<view>
<view class="login-icon">
<image class="login-img" src="../resource/images/dsp.jpg"></image>
</view>
<view class="login-from">
<form bindsubmit='doRegist'>
<!--賬号-->
<view class="inputView">
<image class="nameImage" src="../resource/images/username.png"></image>
<label class="loginLabel">賬号</label>
<input name="username" class="inputText" placeholder="請輸入賬号"/>
</view>
<view class="line"></view>
<!--密碼-->
<view class="inputView">
<image class="keyImage" src="../resource/images/password.png"></image>
<label class="loginLabel">密碼</label>
<input name="password" class="inputText" password="true" placeholder="請輸入密碼"/>
</view>
<!--按鈕-->
<view>
<button class="loginBtn" type="primary" form-type='submit'>注冊</button>
</view>
<view>
<button class="goLoginBtn" type="warn" bindtap="goLoginPage">傳回登入</button>
</view>
</form>
</view>
</view>
1.2 注冊接口
@ApiOperation(value="使用者注冊", notes="使用者注冊的接口")
@PostMapping("/regist")
public IMoocJSONResult regist(@RequestBody Users user) throws Exception {
// 1. 判斷使用者名和密碼必須不為空
if (StringUtils.isBlank(user.getUsername()) || StringUtils.isBlank(user.getPassword())) {
return IMoocJSONResult.errorMsg("使用者名和密碼不能為空");
}
// 2. 判斷使用者名是否存在
boolean usernameIsExist = userService.queryUsernameIsExist(user.getUsername());
// 3. 儲存使用者,注冊資訊
if (!usernameIsExist) {
user.setNickname(user.getUsername());
user.setPassword(MD5Utils.getMD5Str(user.getPassword()));
user.setFansCounts(0);
user.setReceiveLikeCounts(0);
user.setFollowCounts(0);
userService.saveUser(user);
} else {
return IMoocJSONResult.errorMsg("使用者名已經存在,請換一個再試");
}
user.setPassword("");
UsersVO userVO = setUserRedisSessionToken(user);
return IMoocJSONResult.ok(userVO);
}
public UsersVO setUserRedisSessionToken(Users userModel) {
String uniqueToken = UUID.randomUUID().toString();
redis.set(USER_REDIS_SESSION + ":" + userModel.getId(), uniqueToken, 1000 * 60 * 30);
UsersVO userVO = new UsersVO();
BeanUtils.copyProperties(userModel, userVO);
userVO.setUserToken(uniqueToken);
return userVO;
}
1.3.互動
點選注冊按鈕,送出表單,<form bindsubmit='doRegist'>,
js執行doRegist方法,使用e.detail.value擷取表單對象,進而擷取使用者名和密碼,驗證使用者名和密碼的長度是否為0,為0表示為空,驗證通過後,展示一個彈框請等待,使用wx.request請求背景注冊接口,如果背景傳回code為200時,wx.hideLoading();去掉彈框,并彈出使用者注冊成功,app.setGlobalUserInfo(res.data.data);将使用者資訊存儲到全局對象app中,使用 wx.redirectTo跳轉到我的頁面
doRegist: function(e) {
var me = this;
var formObject = e.detail.value;
var username = formObject.username;
var password = formObject.password;
// 簡單驗證
if (username.length == 0 || password.length == 0) {
wx.showToast({
title: '使用者名或密碼不能為空',
icon: 'none',
duration: 3000
})
} else {
var serverUrl = app.serverUrl;
wx.showLoading({
title: '請等待...',
});
wx.request({
url: serverUrl + '/regist',
method: "POST",
data: {
username: username,
password: password
},
header: {
'content-type': 'application/json' // 預設值
},
success: function(res) {
console.log(res.data);
wx.hideLoading();
var status = res.data.status;
if (status == 200) {
wx.showToast({
title: "使用者注冊成功~!!!",
icon: 'none',
duration: 3000
}),
// app.userInfo = res.data.data;
// fixme 修改原有的全局對象為本地緩存
app.setGlobalUserInfo(res.data.data);
// 頁面跳轉
wx.redirectTo({
url: '../mine/mine',
})
} else if (status == 500) {
wx.showToast({
title: res.data.msg,
icon: 'none',
duration: 3000
})
}
}
})
}
},
點選傳回登入按鈕,觸發事件bindtap="goLoginPage"
goLoginPage:function() {
wx.navigateTo({
url: '../userLogin/login',
})
}
使用wx.navigateTo跳轉到登入頁面
2.使用者登入實作
2.1 登入頁面
login.wxml
<view>
<view class="login-icon">
<image class="login-img" src="../resource/images/dsp.jpg"></image>
</view>
<view class="login-from">
<form bindsubmit='doLogin'>
<!--賬号-->
<view class="inputView">
<image class="nameImage" src="../resource/images/username.png"></image>
<label class="loginLabel">賬号</label>
<input name="username" value='imooc' class="inputText" placeholder="請輸入賬号" />
</view>
<view class="line"></view>
<!--密碼-->
<view class="inputView">
<image class="keyImage" src="../resource/images/password.png"></image>
<label class="loginLabel">密碼</label>
<input name="password" value='imooc' class="inputText" password="true" placeholder="請輸入密碼" />
</view>
<!--按鈕-->
<view>
<button class="loginBtn" type="primary" form-type='submit'>登入</button>
</view>
<view>
<button class="goRegistBtn" type="warn" bindtap="goRegistPage">沒有賬号?點選注冊</button>
</view>
</form>
</view>
</view>
2.2 登入接口
@ApiOperation(value="使用者登入", notes="使用者登入的接口")
@PostMapping("/login")
public IMoocJSONResult login(@RequestBody Users user) throws Exception {
String username = user.getUsername();
String password = user.getPassword();
// Thread.sleep(3000);
// 1. 判斷使用者名和密碼必須不為空
if (StringUtils.isBlank(username) || StringUtils.isBlank(password)) {
return IMoocJSONResult.ok("使用者名或密碼不能為空...");
}
// 2. 判斷使用者是否存在
Users userResult = userService.queryUserForLogin(username,
MD5Utils.getMD5Str(user.getPassword()));
// 3. 傳回
if (userResult != null) {
userResult.setPassword("");
UsersVO userVO = setUserRedisSessionToken(userResult);
return IMoocJSONResult.ok(userVO);
} else {
return IMoocJSONResult.errorMsg("使用者名或密碼不正确, 請重試...");
}
}
2.3 互動
進入登入頁面,加載onLoad()方法
onLoad: function (params) {
var me = this;
var redirectUrl = params.redirectUrl;
// debugger;
if (redirectUrl != null && redirectUrl != undefined && redirectUrl != '') {
redirectUrl = redirectUrl.replace(/#/g, "?");
redirectUrl = redirectUrl.replace(/@/g, "=");
me.redirectUrl = redirectUrl;
}
},
點選登入按鈕,送出表單<form bindsubmit='doLogin'>
先使用e.detail.value擷取表單對象,進行擷取使用者名和密碼,對其驗證是否為空,彈出請等待框,使用wx.request請求背景登入接口,在success回調方法中去掉彈框,如果傳回的code為200則彈出登入成功,将使用者對象設定到全局對象app中,跳轉到我的頁面
// 登入
doLogin: function (e) {
var me = this;
var formObject = e.detail.value;
var username = formObject.username;
var password = formObject.password;
// 簡單驗證
if (username.length == 0 || password.length == 0) {
wx.showToast({
title: '使用者名或密碼不能為空',
icon: 'none',
duration: 3000
})
} else {
var serverUrl = app.serverUrl;
wx.showLoading({
title: '請等待...',
});
// 調用後端
wx.request({
url: serverUrl + '/login',
method: "POST",
data: {
username: username,
password: password
},
header: {
'content-type': 'application/json' // 預設值
},
success: function (res) {
console.log(res.data);
wx.hideLoading();
if (res.data.status == 200) {
// 登入成功跳轉
wx.showToast({
title: '登入成功',
icon: 'success',
duration: 2000
});
// app.userInfo = res.data.data;
// fixme 修改原有的全局對象為本地緩存
app.setGlobalUserInfo(res.data.data);
// 頁面跳轉
var redirectUrl = me.redirectUrl;
if (redirectUrl != null && redirectUrl != undefined && redirectUrl != '') {
wx.redirectTo({
url: redirectUrl,
})
} else {
wx.redirectTo({
url: '../mine/mine',
})
}
} else if (res.data.status == 500) {
// 失敗彈出框
wx.showToast({
title: res.data.msg,
icon: 'none',
duration: 3000
})
}
}
})
}
},
點選 沒有賬号?點選注冊 觸發事件
bindtap="goRegistPage"
goRegistPage:function() {
wx.redirectTo({
url: '../userRegist/regist',
})
}
跳轉到注冊頁面
3.上傳頭像實作
3.1 上傳代碼
mine.wxml
<block wx:if="{{isMe}}">
<image src="{{faceUrl}}" class="face" bindtap='changeFace'></image>
</block>
isMe字段定義在js裡面,辨別是否是目前登入使用者,這裡分為2中情況:
1)登入的使用者
2)從視訊詳情裡面的釋出者點選進去,跳轉到我的頁面,該頁面隻能檢視自己的頭像
頁面加載函數的邏輯:
根據params.publisherId判斷是否是目前登入使用者,為空就是目前登入使用者,不為空就是視訊釋出者使用者,設定使用者id,調用查詢使用者資訊接口,擷取使用者資訊
onLoad: function (params) {
var me = this;
// var user = app.userInfo;
// fixme 修改原有的全局對象為本地緩存
var user = app.getGlobalUserInfo();
var userId = user.id;
var publisherId = params.publisherId;
if (publisherId != null && publisherId != '' && publisherId != undefined) {
userId = publisherId;
me.setData({
isMe: false,
publisherId: publisherId,
serverUrl: app.serverUrl
})
}
me.setData({
userId: userId
})
wx.showLoading({
title: '請等待...',
});
var serverUrl = app.serverUrl;
// 調用後端
wx.request({
url: serverUrl + '/user/query?userId=' + userId + "&fanId=" + user.id,
method: "POST",
header: {
'content-type': 'application/json', // 預設值
'headerUserId': user.id,
'headerUserToken': user.userToken
},
success: function (res) {
console.log(res.data);
wx.hideLoading();
if (res.data.status == 200) {
var userInfo = res.data.data;
var faceUrl = "../resource/images/noneface.png";
if (userInfo.faceImage != null && userInfo.faceImage != '' && userInfo.faceImage != undefined) {
faceUrl = serverUrl + userInfo.faceImage;
}
me.setData({
faceUrl: faceUrl,
fansCounts: userInfo.fansCounts,
followCounts: userInfo.followCounts,
receiveLikeCounts: userInfo.receiveLikeCounts,
nickname: userInfo.nickname,
isFollow: userInfo.follow
});
} else if (res.data.status == 502) {
wx.showToast({
title: res.data.msg,
duration: 3000,
icon: "none",
success: function () {
wx.redirectTo({
url: '../userLogin/login',
})
}
})
}
}
})
me.getMyVideoList(1);
},
changeFace()事件,使用wx.chooseImage傳回上傳後的檔案路徑,wx.uploadFile調用上傳頭像接口
changeFace: function () {
var me = this;
wx.chooseImage({
count: 1,
sizeType: ['compressed'],
sourceType: ['album'],
success: function (res) {
var tempFilePaths = res.tempFilePaths;
console.log(tempFilePaths);
wx.showLoading({
title: '上傳中...',
})
var serverUrl = app.serverUrl;
// fixme 修改原有的全局對象為本地緩存
var userInfo = app.getGlobalUserInfo();
wx.uploadFile({
url: serverUrl + '/user/uploadFace?userId=' + userInfo.id, //app.userInfo.id,
filePath: tempFilePaths[0],
name: 'file',
header: {
'content-type': 'application/json', // 預設值
'headerUserId': userInfo.id,
'headerUserToken': userInfo.userToken
},
success: function (res) {
var data = JSON.parse(res.data);
console.log(data);
wx.hideLoading();
if (data.status == 200) {
wx.showToast({
title: '上傳成功!~~',
icon: "success"
});
var imageUrl = data.data;
me.setData({
faceUrl: serverUrl + imageUrl
});
} else if (data.status == 500) {
wx.showToast({
title: data.msg
});
} else if (res.data.status == 502) {
wx.showToast({
title: res.data.msg,
duration: 2000,
icon: "none",
success: function () {
wx.redirectTo({
url: '../userLogin/login',
})
}
});
}
}
})
}
})
},
3.2 上傳頭像接口
@ApiOperation(value="使用者上傳頭像", notes="使用者上傳頭像的接口")
@ApiImplicitParam(name="userId", value="使用者id", required=true,
dataType="String", paramType="query")
@PostMapping("/uploadFace")
public IMoocJSONResult uploadFace(String userId,
@RequestParam("file") MultipartFile[] files) throws Exception {
if (StringUtils.isBlank(userId)) {
return IMoocJSONResult.errorMsg("使用者id不能為空...");
}
// 檔案儲存的命名空間
String fileSpace = "C:/imooc_videos_dev";
// 儲存到資料庫中的相對路徑
String uploadPathDB = "/" + userId + "/face";
FileOutputStream fileOutputStream = null;
InputStream inputStream = null;
try {
if (files != null && files.length > 0) {
String fileName = files[0].getOriginalFilename();
if (StringUtils.isNotBlank(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 {
return IMoocJSONResult.errorMsg("上傳出錯...");
}
} catch (Exception e) {
e.printStackTrace();
return 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);
}
4.上傳作品功能
4.1 上傳作品代碼
<button size='mini' class='primary' bindtap='uploadVideo'> 上傳作品</button>
uploadVideo事件,wx.chooseVideo打開選擇視訊控件,選擇好視訊後,打開選擇背景音頻頁面并攜帶相關參數
uploadVideo: function () {
// fixme 視訊上傳複用
// videoUtil.uploadVideo();
// 以下是原來的代碼,不删除,便于參照
var me = this;
wx.chooseVideo({
sourceType: ['album'],
success: function (res) {
console.log(res);
var duration = res.duration;
var tmpHeight = res.height;
var tmpWidth = res.width;
var tmpVideoUrl = res.tempFilePath;
var tmpCoverUrl = res.thumbTempFilePath;//圖檔臨時目錄
if (duration > 11) {
wx.showToast({
title: '視訊長度不能超過10秒...',
icon: "none",
duration: 2500
})
} else if (duration < 1) {
wx.showToast({
title: '視訊長度太短,請上傳超過1秒的視訊...',
icon: "none",
duration: 2500
})
} else {
// 打開選擇bgm的頁面
wx.navigateTo({
url: '../chooseBgm/chooseBgm?duration=' + duration
+ "&tmpHeight=" + tmpHeight
+ "&tmpWidth=" + tmpWidth
+ "&tmpVideoUrl=" + tmpVideoUrl
+ "&tmpCoverUrl=" + tmpCoverUrl
,
})
}
}
})
},
4.2 bgm頁面
<view>
<form bindsubmit='upload'>
<radio-group name="bgmId">
<block wx:for="{{bgmList}}">
<view class='container'>
<audio name="{{item.name}}" author="{{item.author}}" src="{{serverUrl}}{{item.path}}" style='width:300px' id="myAudio" controls loop></audio>
<radio style='margin-top:20px;' value='{{item.id}}'></radio>
</view>
</block>
</radio-group>
<view class="inputView">
<label class="loginLabel">視訊描述:</label>
<input name="desc" class="inputText" placeholder="說點什麼吧" />
</view>
<!-- 送出 -->
<button class="submitBtn" type="primary" form-type='submit'>上傳視訊</button>
<button class="gobackBtn" type="warn" form-type='reset'>重置</button>
</form>
</view>
頁面加載函數,onLoad(),使用wx.request請求背景背景音頻清單接口展示在頁面
onLoad: function (params) {
var me = this;
console.log(params);
me.setData({
videoParams: params
});
wx.showLoading({
title: '請等待...',
});
var serverUrl = app.serverUrl;
var user = app.getGlobalUserInfo();
debugger;
// 調用後端
wx.request({
url: serverUrl + '/bgm/list',
method: "POST",
header: {
'content-type': 'application/json', // 預設值
'headerUserId': user.id,
'headerUserToken': user.userToken
},
success: function (res) {
console.log(res.data);
wx.hideLoading();
if (res.data.status == 200) {
var bgmList = res.data.data;
me.setData({
bgmList: bgmList,
serverUrl: serverUrl
});
} else if (res.data.status == 502) {
wx.showToast({
title: res.data.msg,
duration: 2000,
icon: "none",
success: function () {
wx.redirectTo({
url: '../userLogin/login',
})
}
});
}
}
})
},
4.3 互動
<form bindsubmit='upload'>,使用 wx.uploadFile調用背景上傳視訊接口
upload: function(e) {
var me = this;
var bgmId = e.detail.value.bgmId;
var desc = e.detail.value.desc;
console.log("bgmId:" + bgmId);
console.log("desc:" + desc);
var duration = me.data.videoParams.duration;
var tmpHeight = me.data.videoParams.tmpHeight;
var tmpWidth = me.data.videoParams.tmpWidth;
var tmpVideoUrl = me.data.videoParams.tmpVideoUrl;
var tmpCoverUrl = me.data.videoParams.tmpCoverUrl;
// 上傳短視訊
wx.showLoading({
title: '上傳中...',
})
var serverUrl = app.serverUrl;
// fixme 修改原有的全局對象為本地緩存
var userInfo = app.getGlobalUserInfo();
wx.uploadFile({
url: serverUrl + '/video/upload',
formData: {
userId: userInfo.id, // fixme 原來的 app.userInfo.id
bgmId: bgmId,
desc: desc,
videoSeconds: duration,
videoHeight: tmpHeight,
videoWidth: tmpWidth
},
filePath: tmpVideoUrl,
name: 'file',
header: {
'content-type': 'application/json', // 預設值
'headerUserId': userInfo.id,
'headerUserToken': userInfo.userToken
},
success: function (res) {
var data = JSON.parse(res.data);
wx.hideLoading();
if (data.status == 200) {
wx.showToast({
title: '上傳成功!~~',
icon: "success"
});
// 上傳成功後跳回之前的頁面
wx.navigateBack({
delta: 1
})
} else if (res.data.status == 502) {
wx.showToast({
title: res.data.msg,
duration: 2000,
icon: "none"
});
wx.redirectTo({
url: '../userLogin/login',
})
} else {
wx.showToast({
title: '上傳失敗!~~',
icon: "success"
});
}
}
})
}
4.4 上傳視訊接口
@ApiOperation(value="上傳視訊", notes="上傳視訊的接口")
@ApiImplicitParams({
@ApiImplicitParam(name="userId", value="使用者id", required=true,
dataType="String", paramType="form"),
@ApiImplicitParam(name="bgmId", value="背景音樂id", required=false,
dataType="String", paramType="form"),
@ApiImplicitParam(name="videoSeconds", value="背景音樂播放長度", required=true,
dataType="String", paramType="form"),
@ApiImplicitParam(name="videoWidth", value="視訊寬度", required=true,
dataType="String", paramType="form"),
@ApiImplicitParam(name="videoHeight", value="視訊高度", required=true,
dataType="String", paramType="form"),
@ApiImplicitParam(name="desc", value="視訊描述", required=false,
dataType="String", paramType="form")
})
@PostMapping(value="/upload", headers="content-type=multipart/form-data")
public IMoocJSONResult upload(String userId,
String bgmId, double videoSeconds,
int videoWidth, int videoHeight,
String desc,
@ApiParam(value="短視訊", required=true)
MultipartFile file) throws Exception {
if (StringUtils.isBlank(userId)) {
return IMoocJSONResult.errorMsg("使用者id不能為空...");
}
// 檔案儲存的命名空間
// String fileSpace = "C:/imooc_videos_dev";
// 儲存到資料庫中的相對路徑
String uploadPathDB = "/" + userId + "/video";
String coverPathDB = "/" + userId + "/video";
FileOutputStream fileOutputStream = null;
InputStream inputStream = null;
// 檔案上傳的最終儲存路徑
String finalVideoPath = "";
try {
if (file != null) {
String fileName = file.getOriginalFilename();
// abc.mp4
String arrayFilenameItem[] = fileName.split("\\.");
String fileNamePrefix = "";
for (int i = 0 ; i < arrayFilenameItem.length-1 ; i ++) {
fileNamePrefix += arrayFilenameItem[i];
}
// fix bug: 解決小程式端OK,PC端不OK的bug,原因:PC端和小程式端對臨時視訊的命名不同
// String fileNamePrefix = fileName.split("\\.")[0];
if (StringUtils.isNotBlank(fileName)) {
finalVideoPath = FILE_SPACE + uploadPathDB + "/" + fileName;
// 設定資料庫儲存的路徑
uploadPathDB += ("/" + fileName);
coverPathDB = coverPathDB + "/" + fileNamePrefix + ".jpg";
File outFile = new File(finalVideoPath);
if (outFile.getParentFile() != null || !outFile.getParentFile().isDirectory()) {
// 建立父檔案夾
outFile.getParentFile().mkdirs();
}
fileOutputStream = new FileOutputStream(outFile);
inputStream = file.getInputStream();
IOUtils.copy(inputStream, fileOutputStream);
}
} else {
return IMoocJSONResult.errorMsg("上傳出錯...");
}
} catch (Exception e) {
e.printStackTrace();
return IMoocJSONResult.errorMsg("上傳出錯...");
} finally {
if (fileOutputStream != null) {
fileOutputStream.flush();
fileOutputStream.close();
}
}
// 判斷bgmId是否為空,如果不為空,
// 那就查詢bgm的資訊,并且合并視訊,生産新的視訊
if (StringUtils.isNotBlank(bgmId)) {
Bgm bgm = bgmService.queryBgmById(bgmId);
String mp3InputPath = FILE_SPACE + bgm.getPath();
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);
}
System.out.println("uploadPathDB=" + uploadPathDB);
System.out.println("finalVideoPath=" + finalVideoPath);
// 對視訊進行截圖
FetchVideoCover videoInfo = new FetchVideoCover(FFMPEG_EXE);
videoInfo.getCover(finalVideoPath, FILE_SPACE + coverPathDB);
// 儲存視訊資訊到資料庫
Videos video = new Videos();
video.setAudioId(bgmId);
video.setUserId(userId);
video.setVideoSeconds((float)videoSeconds);
video.setVideoHeight(videoHeight);
video.setVideoWidth(videoWidth);
video.setVideoDesc(desc);
video.setVideoPath(uploadPathDB);
video.setCoverPath(coverPathDB);
video.setStatus(VideoStatusEnum.SUCCESS.value);
video.setCreateTime(new Date());
String videoId = videoService.saveVideo(video);
return IMoocJSONResult.ok(videoId);
}
5.關注作品功能
5.1 關注代碼
<block wx:if="{{!isFollow}}">
<button size='mini' type='primary' class='follow' data-followType='1' bindtap='followMe'>關注我</button>
</block>
followMe()事件,e.currentTarget.dataset.followtype擷取data-followType的值,根據類型判斷是關注或取消關注,調用對應的接口
followMe: function (e) {
var me = this;
var user = app.getGlobalUserInfo();
var userId = user.id;
var publisherId = me.data.publisherId;
var followType = e.currentTarget.dataset.followtype;
// 1:關注 0:取消關注
var url = '';
if (followType == '1') {
url = '/user/beyourfans?userId=' + publisherId + '&fanId=' + userId;
} else {
url = '/user/dontbeyourfans?userId=' + publisherId + '&fanId=' + userId;
}
wx.showLoading();
wx.request({
url: app.serverUrl + url,
method: 'POST',
header: {
'content-type': 'application/json', // 預設值
'headerUserId': user.id,
'headerUserToken': user.userToken
},
success: function () {
wx.hideLoading();
if (followType == '1') {
me.setData({
isFollow: true,
fansCounts: ++me.data.fansCounts
})
} else {
me.setData({
isFollow: false,
fansCounts: --me.data.fansCounts
})
}
}
})
},
5.2 關注接口
@PostMapping("/beyourfans")
public IMoocJSONResult beyourfans(String userId, String fanId) throws Exception {
if (StringUtils.isBlank(userId) || StringUtils.isBlank(fanId)) {
return IMoocJSONResult.errorMsg("");
}
userService.saveUserFanRelation(userId, fanId);
return IMoocJSONResult.ok("關注成功...");
}
@PostMapping("/dontbeyourfans")
public IMoocJSONResult dontbeyourfans(String userId, String fanId) throws Exception {
if (StringUtils.isBlank(userId) || StringUtils.isBlank(fanId)) {
return IMoocJSONResult.errorMsg("");
}
userService.deleteUserFanRelation(userId, fanId);
return IMoocJSONResult.ok("取消關注成功...");
}
6.首頁視訊展示功能
6.1 首頁頁面
<view wx:for="{{videoList}}" class="item-container">
//封面圖
<view style='width:{{screenWidth}}px;height:210px;' class='back-img'>
<image src="{{serverUrl}}{{item.coverPath}}" style='width:{{screenWidth}}px;height:210px;' mode="aspectFit" bindtap='showVideoInfo' data-arrindex='{{index}}'></image>
</view>
<view class="desc">
<view class="faceName">
<image class='myface' src="{{serverUrl}}{{item.faceImage}}"></image>
<view class="nickname">{{item.nickname}}</view>
</view>
</view>
</view>
6.2 擷取視訊清單接口
/**
*
* @Description: 分頁和搜尋查詢視訊清單
* isSaveRecord:1 - 需要儲存
* 0 - 不需要儲存 ,或者為空的時候
*/
@PostMapping(value="/showAll")
public IMoocJSONResult showAll(@RequestBody Videos video, Integer isSaveRecord,
Integer page, Integer pageSize) throws Exception {
if (page == null) {
page = 1;
}
if (pageSize == null) {
pageSize = PAGE_SIZE;
}
PagedResult result = videoService.getAllVideos(video, isSaveRecord, page, pageSize);
return IMoocJSONResult.ok(result);
}
6.3 互動
頁面加載的時候調用背景擷取視訊清單接口,onPullDownRefresh為下拉重新整理觸底監聽事件,onReachBottom是頁面上拉觸底事件的函數
onLoad: function (params) {
var me = this;
var screenWidth = wx.getSystemInfoSync().screenWidth;
me.setData({
screenWidth: screenWidth,
});
var searchContent = params.search;
var isSaveRecord = params.isSaveRecord;
if (isSaveRecord == null || isSaveRecord == '' || isSaveRecord == undefined) {
isSaveRecord = 0;
}
me.setData({
searchContent: searchContent
});
// 擷取目前的分頁數
var page = me.data.page;
me.getAllVideoList(page, isSaveRecord);
},
getAllVideoList: function (page, isSaveRecord) {
var me = this;
var serverUrl = app.serverUrl;
wx.showLoading({
title: '請等待,加載中...',
});
var searchContent = me.data.searchContent;
wx.request({
url: serverUrl + '/video/showAll?page=' + page + "&isSaveRecord=" + isSaveRecord,
method: "POST",
data: {
videoDesc: searchContent
},
success: function (res) {
wx.hideLoading();
wx.hideNavigationBarLoading();
wx.stopPullDownRefresh();
console.log(res.data);
// 判斷目前頁page是否是第一頁,如果是第一頁,那麼設定videoList為空
if (page === 1) {
me.setData({
videoList: []
});
}
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
});
}
})
},
onPullDownRefresh: function() {
//在目前頁面顯示導覽列加載動畫
wx.showNavigationBarLoading();
this.getAllVideoList(1, 0);
},
//上拉重新整理
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);
},
showVideoInfo: function(e) {
var me = this;
var videoList = me.data.videoList;
var arrindex = e.target.dataset.arrindex;
var videoInfo = JSON.stringify(videoList[arrindex]);
wx.redirectTo({
url: '../videoinfo/videoinfo?videoInfo=' + videoInfo
})
}
7.視訊搜尋功能
7.1 搜尋頁面
wxSearchView.wxml
<view class="weui-search-bar">
<view class="weui-search-bar__form">
<view class="weui-search-bar__box">
<icon class="weui-icon-search_in-box" type="search" size="14"></icon>
<input type="text" class="weui-search-bar__input" placeholder="請輸入查詢内容" value="{{wxSearchData.value}}" bindinput="wxSearchInput" bindconfirm="wxSearchConfirm" />
<view class="weui-icon-clear" wx:if="{{wxSearchData.value.length > 0}}" bindtap="wxSearchClear">
<icon type="clear" size="14"></icon>
</view>
</view>
</view>
<view class="weui-search-bar__cancel-btn" bindtap="wxSearchConfirm">
<text wx:if="{{wxSearchData.value.length>0}}" data-key='search'>搜尋</text>
<text wx:else data-key='back'>首頁</text>
</view>
</view>
<view class="wxSearch" style="'block';height:{{wxSearchData.view.seachHeight}}px;top:{{wxSearchData.view.barHeight}}px;">
<view class="wxSearchInner">
<!-- 搜尋提示部分 -->
<view class="wxSearchMindKey">
<view class="wxSearchMindKeyList">
<block wx:for="{{wxSearchData.tipKeys}}">
<view class="wxSearchMindKeyItem" bindtap="wxSearchKeyTap" data-key="{{item}}">{{item}}</view>
</block>
</view>
</view>
<view wx:if="{{wxSearchData.his[0]}}" class="wxSearchHistory" style="display:{{wxSearchData.value.length>0 ? 'none':'block'}}">
<view class="wxSearchHistoryItem">
<text class="wxSearchHistoryItemTitle">搜尋記錄</text>
<!--text class="wxSearchHistoryItemDel" bindtap="wxSearchDeleteAll">删除</text-->
<icon type="clear" bindtap="wxSearchDeleteAll" size="18" />
</view>
<view class="wxSearchKeyList">
<block wx:for="{{wxSearchData.his}}">
<view class="wxSearchKeyItem" bindtap="wxSearchKeyTap" data-key="{{item}}">{{item}}</view>
</block>
</view>
</view>
<view class="wxSearchKey" style="display:{{wxSearchData.value.length>0 ? 'none':'block'}}">
<text wx:if="{{wxSearchData.hotKeys[0]}}" class="wxSearchTitle">搜尋熱點</text>
<view class="wxSearchKeyList">
<block wx:for="{{wxSearchData.hotKeys}}">
<view class="wxSearchKeyItem" bindtap="wxSearchKeyTap" data-key="{{item}}">{{item}}</view>
</block>
</view>
</view>
</view>
</view>
7.2 互動
// 1 導入js檔案
var WxSearch = require('../../wxSearchView/wxSearchView.js');
const app = getApp()
Page({
data: {
},
onLoad: function () {
// 2 搜尋欄初始化
var that = this;
// 查詢熱搜詞
var serverUrl = app.serverUrl;
wx.request({
url: serverUrl + '/video/hot',
method: "POST",
success: function(res) {
console.log(res);
var hotList = res.data.data;
WxSearch.init(
that, // 本頁面一個引用
hotList,
// ['熱門視訊', '推薦視訊', "java", "小程式", 'zookeeper', 'springboot'], // 熱點搜尋推薦,[]表示不使用
hotList,// 搜尋比對,[]表示不使用
that.mySearchFunction, // 提供一個搜尋回調函數
that.myGobackFunction //提供一個傳回回調函數
);
}
})
},
// 3 轉發函數,固定部分,直接拷貝即可
wxSearchInput: WxSearch.wxSearchInput, // 輸入變化時的操作
wxSearchKeyTap: WxSearch.wxSearchKeyTap, // 點選提示或者關鍵字、曆史記錄時的操作
wxSearchDeleteAll: WxSearch.wxSearchDeleteAll, // 删除所有的曆史記錄
wxSearchConfirm: WxSearch.wxSearchConfirm, // 搜尋函數
wxSearchClear: WxSearch.wxSearchClear, // 清空函數
// 4 搜尋回調函數
mySearchFunction: function (value) {
// do your job here
// 示例:跳轉
wx.redirectTo({
url: '../index/index?isSaveRecord=1&search=' + value
})
},
// 5 傳回回調函數
myGobackFunction: function () {
// do your job here
// 示例:傳回
wx.redirectTo({
url: '../index/index'
})
}
})
8.收藏功能
1.頁面代碼
videoinfo.wxml
<!-- 喜歡收藏按鈕 -->
<block wx:if="{{userLikeVideo}}">
<cover-image class="size-me" src='../resource/images/like.png' style='margin-top:30rpx;' bindtap='likeVideoOrNot'></cover-image>
</block>
<block wx:else>
<cover-image class="size-me" src='../resource/images/unlike.png' style='margin-top:30rpx;' bindtap='likeVideoOrNot'></cover-image>
</block>
2.互動
觸發likeVideoOrNot事件,通過me.data.userLikeVideo來判斷是收藏還是取消收藏
likeVideoOrNot: function () {
var me = this;
var videoInfo = me.data.videoInfo;
var user = app.getGlobalUserInfo();
if (user == null || user == undefined || user == '') {
wx.navigateTo({
url: '../userLogin/login',
})
} else {
var userLikeVideo = me.data.userLikeVideo;
var url = '/video/userLike?userId=' + user.id + '&videoId=' + videoInfo.id + '&videoCreaterId=' + videoInfo.userId;
if (userLikeVideo) {
url = '/video/userUnLike?userId=' + user.id + '&videoId=' + videoInfo.id + '&videoCreaterId=' + videoInfo.userId;
}
var serverUrl = app.serverUrl;
wx.showLoading({
title: '...',
})
wx.request({
url: serverUrl + url,
method: 'POST',
header: {
'content-type': 'application/json', // 預設值
'headerUserId': user.id,
'headerUserToken': user.userToken
},
success:function(res) {
wx.hideLoading();
me.setData({
userLikeVideo: !userLikeVideo
});
}
})
}
},
3.收藏和取消收藏接口
@PostMapping(value="/userLike")
public IMoocJSONResult userLike(String userId, String videoId, String videoCreaterId)
throws Exception {
videoService.userLikeVideo(userId, videoId, videoCreaterId);
return IMoocJSONResult.ok();
}
@PostMapping(value="/userUnLike")
public IMoocJSONResult userUnLike(String userId, String videoId, String videoCreaterId) throws Exception {
videoService.userUnLikeVideo(userId, videoId, videoCreaterId);
return IMoocJSONResult.ok();
}
8.評論功能
1.頁面代碼
videoinfo.wxml
<!-- 評論按鈕 -->
<cover-image class="size-me" src='../resource/images/comments.png' style='margin-top:30rpx;' bindtap='leaveComment'></cover-image>
<view>
<view class="saySthView">
<input name="commentContent" class="saySth" placeholder="{{placeholder}}" confirm-type="send" bindconfirm="saveComment" focus='{{commentFocus}}' value='{{contentValue}}'
data-replyFatherCommentId='{{replyFatherCommentId}}'
data-replyToUserId='{{replyToUserId}}'
/>
</view>
<block wx:for="{{commentsList}}">
<view class='comments-all' bindtap='replyFocus'
data-fatherCommentId='{{item.id}}'
data-toUserId='{{item.fromUserId}}'
data-toNickname='{{item.nickname}}'
>
<view class='container-comments'>
<image class="face-comments" src='{{serverUrl}}{{item.faceImage}}' ></image>
<view class='nickname-comments'>
<label class='nickname-lbl'>@{{item.nickname}}</label>
于
<label class='date-lbl'>{{item.timeAgoStr}}</label>
<!-- 留言: -->
<block wx:if="{{item.toNickname != null}}">
回複
<label class='nickname-lbl'>@{{item.toNickname}}</label>
</block>
<block wx:else>
留言:
</block>
</view>
</view>
<view class='comments-content'>{{item.comment}}</view>
</view>
</block>
</view
2.互動
點選評論按鈕,觸發leaveComment事件,将commentFocus值設定為true
leaveComment: function() {
this.setData({
commentFocus: true
});
},
replyFocus: function(e) {
var fatherCommentId = e.currentTarget.dataset.fathercommentid;
var toUserId = e.currentTarget.dataset.touserid;
var toNickname = e.currentTarget.dataset.tonickname;
this.setData({
placeholder: "回複 " + toNickname,
replyFatherCommentId: fatherCommentId,
replyToUserId: toUserId,
commentFocus: true
});
},
saveComment:function(e) {
var me = this;
var content = e.detail.value;
// 擷取評論回複的fatherCommentId和toUserId
var fatherCommentId = e.currentTarget.dataset.replyfathercommentid;
var toUserId = e.currentTarget.dataset.replytouserid;
var user = app.getGlobalUserInfo();
var videoInfo = JSON.stringify(me.data.videoInfo);
var realUrl = '../videoinfo/videoinfo#videoInfo@' + videoInfo;
if (user == null || user == undefined || user == '') {
wx.navigateTo({
url: '../userLogin/login?redirectUrl=' + realUrl,
})
} else {
wx.showLoading({
title: '請稍後...',
})
wx.request({
url: app.serverUrl + '/video/saveComment?fatherCommentId=' + fatherCommentId + "&toUserId=" + toUserId,
method: 'POST',
header: {
'content-type': 'application/json', // 預設值
'headerUserId': user.id,
'headerUserToken': user.userToken
},
data: {
fromUserId: user.id,
videoId: me.data.videoInfo.id,
comment: content
},
success: function(res) {
console.log(res.data)
wx.hideLoading();
me.setData({
contentValue: "",
commentsList: []
});
me.getCommentsList(1);
}
})
}
},
// commentsPage: 1,
// commentsTotalPage: 1,
// commentsList: []
getCommentsList: function(page) {
var me = this;
var videoId = me.data.videoInfo.id;
wx.request({
url: app.serverUrl + '/video/getVideoComments?videoId=' + videoId + "&page=" + page + "&pageSize=5",
method: "POST",
success: function(res) {
console.log(res.data);
var commentsList = res.data.data.rows;
var newCommentsList = me.data.commentsList;
me.setData({
commentsList: newCommentsList.concat(commentsList),
commentsPage: page,
commentsTotalPage: res.data.data.total
});
}
})
},