This commit is contained in:
abu 2025-03-28 15:46:11 +08:00
parent 9492c13b08
commit c54a5f1b1f
58 changed files with 9979 additions and 3263 deletions

29
App.vue
View File

@ -225,9 +225,11 @@ export default {
},
};
</script>
<style lang="scss">
@import "uview-ui/index.scss";
<style lang="scss">
/* #ifndef APP-NVUE */
@import "uview-ui/index.scss";
/* #endif */
// ------- x
@ -239,12 +241,13 @@ export default {
height: auto !important;
padding-top: 10rpx;
}
// #endif
/* #ifndef APP-NVUE */
body {
background-color: $bg-color;
}
/* #endif */
/************************ */
.w200 {
@ -259,12 +262,12 @@ body {
transition-duration: 300ms;
}
uni-page-body,
html,
body,
page {
width: 100% !important;
height: 100% !important;
overflow: hidden;
}
// uni-page-body,
// html,
// body,
// page {
// width: 100% !important;
// height: 100% !important;
// overflow: hidden;
// }
</style>

3
androidPrivacy.json Executable file
View File

@ -0,0 +1,3 @@
{
"prompt" : "template"
}

View File

@ -7,7 +7,38 @@ import { http, Method } from "@/utils/request.js";
import api from "@/config/api.js";
/**
* 短视频关注列表
*/
export function vlogDetail(vlogId,userId) {
let data = {
vlogId,
userId
}
return http.request({
url: api.vlog + "/vlog/detail",
method: Method.GET,
needToken: true,
params: data,
});
}
/**
* 短视频关注列表
*/
export function vlogFollowList(page, pageSize,myId) {
let data = {
page,
pageSize,
myId
}
return http.request({
url: api.vlog + "/vlog/followList",
method: Method.GET,
needToken: true,
params: data,
});
}
/**
* 短视频列表-true
@ -52,7 +83,7 @@ export function vlogUnLike({userId,vlogId,vlogerId}) {
}
/**
* 短视频评论
* 短视频评论数量统计
*/
export function vlogComment(vlogId) {
return http.request({
@ -63,10 +94,14 @@ export function vlogComment(vlogId) {
});
}
/**
* 短视频关注博主
*/
export function vlogFollow({myId,vlogerId}) {
export function vlogFollow(myId,vlogerId) {
return http.request({
url: api.vlog + "/fans/follow",
method: Method.POST,
@ -87,85 +122,219 @@ export function vlogTotalLikedCounts(vlogId) {
});
}
/**
* 通过cityCode获取地区代码
* 查询用户信息
*/
export function getAddressCode(cityCode, townName) {
export function vlogUserInfo(userId) {
return http.request({
url: api.common + "/common/region/region",
url: api.vlog + "/userInfo/query",
method: Method.GET,
needToken: true,
params: { cityCode, townName },
params: { userId },
});
}
/**
* 添加收货地址
* @param params 地址参数
* @returns {AxiosPromise}
* 查询我的公开视频
*/
export function addAddress(data) {
export function vlogMyPublicList(page,pageSize,userId) {
return http.request({
url: "/member/address",
url: api.vlog + "/vlog/myPublicList",
method: Method.GET,
needToken: true,
params: { page,pageSize,userId },
});
}
/**
* 查询我的私密视频
*/
export function vlogMyPrivateList(page,pageSize,userId) {
return http.request({
url: api.vlog + "/vlog/myPrivateList",
method: Method.GET,
needToken: true,
params: { page,pageSize,userId },
});
}
/**
* 查询我喜欢的视频
*/
export function vlogMyLikedList(page,pageSize,userId) {
return http.request({
url: api.vlog + "/vlog/myLikedList",
method: Method.GET,
needToken: true,
params: { page,pageSize,userId },
});
}
/**
* 查询我喜欢的视频
*/
export function vlogMeTag(path,page,pageSize,userId) {
return http.request({
url: api.vlog + "/vlog/"+path,
method: Method.GET,
needToken: true,
params: { page,pageSize,userId },
});
}
/**
* 视频评论数量
*/
export function vlogCommentCounts(vlogId) {
return http.request({
url: api.vlog + "/comment/counts",
method: Method.GET,
needToken: true,
params: { vlogId },
});
}
/**
* 视频评论不喜欢
*/
export function vlogCommentUnLike(userId,commentId) {
return http.request({
url: api.vlog + "/comment/unlike",
method: Method.POST,
needToken: true,
header: { "content-type": "application/x-www-form-urlencoded" },
data: data,
params: {userId,commentId}
});
}
/**
* 编辑地址
* @param id 地址ID
* @param params 地址参数
* @returns {AxiosPromise}
* 视频评论喜欢
*/
export function editAddress(params) {
export function vlogCommentLike(userId,commentId) {
return http.request({
url: `/member/address`,
method: Method.PUT,
url: api.vlog + "/comment/like",
method: Method.POST,
needToken: true,
header: { "content-type": "application/x-www-form-urlencoded" },
data: params,
params: {userId,commentId}
});
}
/**
* 删除收货地址
* @param id
* 视频评论删除
*/
export function deleteAddress(id) {
export function vlogCommentDelete(vlogId,commentUserId,commentId) {
return http.request({
url: `/member/address/delById/${id}`,
url: api.vlog + "/comment/delete",
method: Method.DELETE,
needToken: true,
params: {vlogId,commentUserId,commentId}
});
}
/**
* 根据ID获取会员收件地址
* @param id
* 查询视频评论内容
*/
export function getAddressDetail(id) {
export function vlogCommentList(page,pageSize,vlogId,userId) {
return http.request({
url: `/member/address/get/${id}`,
url: api.vlog + "/comment/list",
method: Method.GET,
loading: false,
needToken: true,
params: { page,pageSize,vlogId,userId },
});
}
/**
*
* 发表评论
*/
export function getAddressDefault() {
export function vlogCommentCreate(data) {
return http.request({
url: `/member/address/get/default`,
method: Method.GET,
loading: false,
url: api.vlog + "/comment/create",
method: Method.POST,
needToken: true,
data
});
}
/**
* 将视频转为公开
*/
export function vlogChangeToPublic(userId,vlogId) {
return http.request({
url: api.vlog + "/vlog/changeToPublic",
method: Method.POST,
needToken: true,
params:{userId,vlogId}
});
}
/**
* 将视频转为私密
*/
export function vlogChangeToPrivate(userId,vlogId) {
return http.request({
url: api.vlog + "/vlog/changeToPrivate",
method: Method.POST,
needToken: true,
params:{userId,vlogId}
});
}
/**
* 修改信息
*/
export function vlogModifyUserInfo(data,type) {
return http.request({
url: api.vlog + "/userInfo/modifyUserInfo?type="+type,
method: Method.POST,
needToken: true,
data
});
}
/**
* 取关
*/
export function vlogFansCancel({myId,vlogerId}) {
return http.request({
url: api.vlog + "/fans/cancel",
method: Method.POST,
needToken: true,
params:{myId,vlogerId}
});
}
/**
* 关注
*/
export function vlogFansFollow({myId,vlogerId}) {
return http.request({
url: api.vlog + "/fans/follow",
method: Method.POST,
needToken: true,
params:{myId,vlogerId}
});
}
/**
* 我的粉丝
*/
export function vlogQueryMyFans({myId,page,pageSize}) {
return http.request({
url: api.vlog + "/fans/queryMyFans",
method: Method.GET,
needToken: true,
params:{myId,page,pageSize}
});
}
/**
* 我的关注
*/
export function vlogQueryMyFollows({myId,page,pageSize}) {
return http.request({
url: api.vlog + "/fans/queryMyFollows",
method: Method.GET,
needToken: true,
params:{myId,page,pageSize}
});
}

View File

@ -1,7 +1,8 @@
<template>
<view style="flex: 1">
<!-- <uni-list @change="onchange" :num="playerList.length"> -->
<list ref="list" :pagingEnabled="true" :show-scrollbar="false" @scroll="listScroll" @scrollend="scroll" :scrollable="true">
<list ref="list" :pagingEnabled="true" :show-scrollbar="false" @scroll="listScroll" @scrollend="scroll"
:scrollable="true">
<refresh @pullingdown="onpullingdown" @refresh="onrefresh" :display="refreshing ? 'show' : 'hide'">
<text class="refresh-info-txt"></text>
<loading-indicator></loading-indicator>
@ -10,9 +11,10 @@
:style="{ height: screenHeight + 'px' }">
<!-- <uni-video :src="item.url" :playStatus="playStatus" :screenHeight="screenHeight" v-if="playerCur === index" @play="onplay"></uni-video> -->
<video ref="myVideo" id="myVideo" :object-fit="item.width >= item.height ? 'contain' : 'fill'"
:src="item.url" :controls="false" :enable-progress-gesture="false" :show-progress="true" v-if="playerCur === index" loop
autoplay show-loading="true" :http-cache="true" style="width: 750rpx" :style="{ height: screenHeight + 'px' }"
@click="playOrPause" @play="onplay" @error="onerror" @timeupdate="timeupdate"></video>
:src="item.url" :controls="false" :enable-progress-gesture="false"
v-if="playerCur === index" loop autoplay show-loading="true" :http-cache="true"
style="width: 750rpx" :style="{ height: screenHeight + 'px' }" @click="playOrPause" @play="onplay"
@error="onerror" @timeupdate="timeupdate"></video>
<image :lazy-load="true" :fade-show="false" v-if="!item.play" :src="item.cover"
:mode="item.width >= item.height ? 'aspectFit' : 'scaleToFill'"
style="width: 750rpx; filter: blur(10px)" :style="{ height: screenHeight + 'px' }"></image>
@ -84,20 +86,20 @@
</template>
<script>
import storage from "@/utils/storage.js"; //
import storage from "@/utils/storage.js"; //
import {
graceNumber
} from '@/utils/tools.js'
import api from "@/config/api.js";
import {
vlogList,
vlogLike,
vlogUnLike,
vlogComment,
vlogFollow,
vlogTotalLikedCounts
} from '@/utils/tools.js'
import api from "@/config/api.js";
import {
vlogList,
vlogLike,
vlogUnLike,
vlogComment,
vlogFollow,
vlogTotalLikedCounts
} from "@/api/vlog";
export default {
export default {
props: {
screenHeight: {
default: 0,
@ -116,15 +118,15 @@
},
pagingList: {
default: [],
},
//
pid: {
type: [Number, String],
default: ''
},
parentId: {
type: String,
default: ''
},
//
pid: {
type: [Number, String],
default: ''
},
parentId: {
type: String,
default: ''
}
},
data() {
@ -166,12 +168,11 @@
}
//
this.displayVideoPaging(this.page + 1, true);
this.videoContext = uni.createVideoContext("myVideo",this.$refs.myVideo);
console.log(this.videoContext)
},
onReady() {
},
this.displayVideoPaging(this.page + 1, true);
this.videoContext = uni.createVideoContext("myVideo", this.$refs.myVideo);
console.log(this.videoContext)
},
onReady() {},
watch: {
refreshList(value) {
var me = this;
@ -196,47 +197,46 @@
}
},
},
methods: {
//------------addd
setScrollRef(height) {
if (this.$refs['list'].setSpecialEffects) {
this.$refs['list'].setSpecialEffects({
id: this.parentId,
headerHeight: height
});
}
},
loadData() {
//
this.displayVideoPaging(this.page + 1, true);
},
clear() {
// swiper-list
this.playerList.length = 0;
},
methods: {
//------------addd
setScrollRef(height) {
if (this.$refs['list'].setSpecialEffects) {
this.$refs['list'].setSpecialEffects({
id: this.parentId,
headerHeight: height
});
}
},
loadData() {
//
this.displayVideoPaging(this.page + 1, true);
},
clear() {
// swiper-list
this.playerList.length = 0;
},
//---------------------------------
// 1000100001.3k/6.8w
getGraceNumber(num) {
return graceNumber(num);
},
async freshCommentCounts() {
var me = this;
var currentIndex = me.playerCur;
console.log('currentIndex',currentIndex)
var me = this;
var currentIndex = me.playerCur;
console.log('currentIndex', currentIndex)
var vlog = me.playerList[currentIndex];
var vlogId = vlog.vlogId;
var result = await vlogComment(vlogId)
if (result.data.status == 200) {
me.thisVlogTotalComentCounts = result.data.data;
} else {
me.thisVlogTotalComentCounts = 0;
var result = await vlogComment(vlogId)
if (result.data.status == 200) {
me.thisVlogTotalComentCounts = result.data.data;
} else {
me.thisVlogTotalComentCounts = 0;
}
},
async likeOrDislikeVlog(isLike) {
var me = this;
var myUserInfo = storage.getVlogUserInfo()||null
var userId = myUserInfo.id;
var currentIndex = me.playerCur;
var me = this;
var myUserInfo = storage.getVlogUserInfo() || null
var currentIndex = me.playerCur;
var vlog = me.playerList[currentIndex];
if (isLike == 1) {
// /
@ -244,47 +244,57 @@
uni.navigateTo({
url: "/pages/passport/login",
animationType: "slide-in-bottom",
});
return;
}
var result = await vlogLike({userId,vlogerId:vlog.vlogerId,vlogId:vlog.vlogId})
console.log(result)
if (result.data.status == 200) {
me.reLikePlayList(vlog.vlogId);
me.refreshVlogCounts();
} else {
uni.showToast({
title: result.data.msg,
icon: "none",
duration: 3000,
});
var userId = myUserInfo.id;
var result = await vlogLike({
userId,
vlogerId: vlog.vlogerId,
vlogId: vlog.vlogId
})
console.log(result)
if (result.data.status == 200) {
me.reLikePlayList(vlog.vlogId);
me.refreshVlogCounts();
} else {
uni.showToast({
title: result.data.msg,
icon: "none",
duration: 3000,
});
}
} else if (isLike == 0) {
// /
var myUserInfo = storage.getVlogUserInfo()
var myUserInfo = storage.getVlogUserInfo() || null
if (myUserInfo == null) {
uni.navigateTo({
url: "/pages/passport/login",
animationType: "slide-in-bottom",
});
return;
}
var result = await vlogUnLike({userId,vlogerId:vlog.vlogerId,vlogId:vlog.vlogId})
if (result.data.status == 200) {
me.reDislikePlayList(vlog.vlogId);
me.refreshVlogCounts();
} else {
uni.showToast({
title: result.data.msg,
icon: "none",
duration: 3000,
});
}
}
var userId = myUserInfo.id;
var result = await vlogUnLike({
userId,
vlogerId: vlog.vlogerId,
vlogId: vlog.vlogId
})
if (result.data.status == 200) {
me.reDislikePlayList(vlog.vlogId);
me.refreshVlogCounts();
} else {
uni.showToast({
title: result.data.msg,
icon: "none",
duration: 3000,
});
}
}
},
@ -353,40 +363,39 @@
//
async followMe(vlogerId) {
var me = this;
var myUserInfo = storage.getVlogUserInfo()
var userId = myUserInfo.id;
var myUserInfo = storage.getVlogUserInfo()||null
if (myUserInfo == null) {
uni.navigateTo({
url: "/pages/passport/login",
animationType: "slide-in-bottom",
});
return;
}
var result = await vlogFollow({myId:userId,vlogerId})
if (result.data.status == 200) {
me.reFollowPlayList(vlogerId);
} else {
uni.showToast({
title: result.data.msg,
icon: "none",
duration: 3000,
});
var userId = myUserInfo.id;
var result = await vlogFollow(userId, vlogerId)
if (result.data.status == 200) {
me.reFollowPlayList(vlogerId);
} else {
uni.showToast({
title: result.data.msg,
icon: "none",
duration: 3000,
});
}
},
//
goUserInfoSeeSee(userId) {
uni.setStorageSync("userPageId", userId);
const info = storage.getVlogUserInfo()||null
//
let myUserId = "";
if (info==null) {
myUserId = info.id;
uni.setStorageSync("userPageId", userId);
const info = storage.getVlogUserInfo() || null
if (info == null) {
uni.navigateTo({
url: "/pages/passport/login",
animationType: "slide-in-bottom",
});
return
}
if (myUserId == userId) {
let myUserId = info.id
if (myUserId == userId) {
uni.switchTab({
url: "/pages/me/me",
});
@ -397,10 +406,10 @@
}
},
listScroll(e) {
// console.log(e)
listScroll(e) {
// console.log(e.contentOffset.y)
if (e.contentOffset.y > 0) {
this.$emit("showLoading");
this.$emit("showLoading");
}
},
@ -425,17 +434,26 @@
},
// tab
onpullingdown(e) {},
onrefresh(e) {
this.refreshing = true;
setTimeout(() => {
this.refreshing = false;
this.$emit("hideLoading");
this.refreshText = "↓ Pull To Refresh";
}, 300);
// list
uni.startPullDownRefresh();
onpullingdown(e) {
console.log('下拉中')
},
async onrefresh(e) {
// console.log('')
// this.refreshing = true;
// // list
// uni.startPullDownRefresh();
// await this.displayVideoPaging(1,true)
// uni.stopPullDownRefresh()
// this.refreshing = false;
// this.$emit("hideLoading");
console.log('开始')
this.refreshing = true;
// list
uni.startPullDownRefresh();
await this.displayVideoPaging(1,true)
uni.stopPullDownRefresh()
this.refreshing = false;
this.$emit("hideLoading");
},
onplay: function(e) {
@ -462,22 +480,22 @@
this.playStatus = !playStatus;
},
scroll: function(e) {
scroll: function(e) {
let originalIndex = this.currentIndex;
let isNext = false;
if (e.contentOffset.y < this.contentOffsetY) {
isNext = true;
}
this.contentOffsetY = Number(e.contentOffset.y);
var num = this.playerList.length;
if(num>0){
var ht = Number(e.contentSize.height)
console.log(ht)
this.currentIndex = Math.round(
Math.abs(this.contentOffsetY) / (ht / num)
);
}else{
this.currentIndex=0
var num = this.playerList.length;
if (num > 0) {
var ht = Number(e.contentSize.height)
console.log(ht)
this.currentIndex = Math.round(
Math.abs(this.contentOffsetY) / (ht / num)
);
} else {
this.currentIndex = 0
}
this.onchange(this.currentIndex);
@ -485,7 +503,8 @@
// -3list
if (this.playerList.length - this.currentIndex < 3) {
// pagetotalPage
if (this.page == this.totalPage) {
if (this.page == this.totalPage|| this.totalPage==0) {
this.$emit('hideLoading')
return;
}
this.displayVideoPaging(this.page + 1, false);
@ -494,51 +513,52 @@
// list, list
async displayVideoPaging(page, needClearList) {
//
//
let me = this
let myUserInfo = storage.getVlogUserInfo()
let userId = "";
let userId = "";
if (myUserInfo != null) {
userId = myUserInfo.id;
}
const result = await vlogList(page,10,userId).catch(err=>{
uni.stopPullDownRefresh();
})
uni.stopPullDownRefresh();
console.log(result)
if (result.data.status == 200) {
let vlogList = result.data.data.rows;
//
let totalPage = result.data.data.total;
// me.playerList = vlogList;
if (needClearList) {
me.playerList = [];
}
me.playerList = me.playerList.concat(vlogList);
me.page = page;
me.totalPage = totalPage;
if (needClearList) {
me.setThisVlogInfo();
me.freshCommentCounts();
}
} else {
uni.showToast({
title: result.data.msg,
icon: "none",
duration: 3000,
});
this.userId = userId
}
const result = await vlogList(page, 10, userId).catch(err => {
uni.stopPullDownRefresh();
})
uni.stopPullDownRefresh();
console.log(result)
if (result.data.status == 200) {
let vlogList = result.data.data.rows;
//
let totalPage = result.data.data.total;
// me.playerList = vlogList;
if (needClearList) {
me.playerList = [];
}
me.playerList = me.playerList.concat(vlogList);
me.page = page;
me.totalPage = totalPage;
if (needClearList) {
me.setThisVlogInfo();
me.freshCommentCounts();
}
} else {
uni.showToast({
title: result.data.msg,
icon: "none",
duration: 3000,
});
}
},
doplay: function(time) {
doplay: function(time) {
if (time > 0) {
this.playerList[this.playerCur].play = true;
}
},
onchange: function(index) {
console.log(index)
onchange: function(index) {
console.log(index)
console.log(this.playerCur)
if (index != this.playerCur) {
this.playerList[this.playerCur].play = false;
@ -564,11 +584,11 @@
//
var me = this;
var currentIndex = me.playerCur;
var vlog = me.playerList[currentIndex];
var result = await vlogTotalLikedCounts(vlog.vlogId)
if (result.data.status == 200) {
var counts = result.data.data;
me.reChangeVlogLikedCountsInPlayList(vlog.vlogId, counts);
var vlog = me.playerList[currentIndex];
var result = await vlogTotalLikedCounts(vlog.vlogId)
if (result.data.status == 200) {
var counts = result.data.data;
me.reChangeVlogLikedCountsInPlayList(vlog.vlogId, counts);
}
},
@ -603,7 +623,7 @@
};
</script>
<style>
<style scoped>
.icon {
width: 80rpx;
height: 80rpx;

View File

@ -124,15 +124,31 @@
:isPrivate="thisVlog.isPrivate"></uni-popup-share>
</uni-popup>
</view>
</view>
</template>
<script>
let app = getApp();
import uniPopupComments from "@/uni_modules/uni-popup/components/uni-popup-comments/uni-popup-comments.vue"
import storage from "@/utils/storage.js"; //
import {
graceNumber
} from '@/utils/tools.js'
import api from "@/config/api.js";
import {
vlogDetail,
vlogLike,
vlogUnLike,
vlogComment,
vlogFollow,
vlogTotalLikedCounts
} from "@/api/vlog";
export default {
components: {
uniPopupComments,
},
props: {
screenHeight: {
default: 0,
@ -188,14 +204,14 @@ export default {
if (!this.isIOS) {
this.objectFit = "cover";
}
let myUserInfo = getApp().getUserInfoSession();
if (!app.isStrEmpty(myUserInfo)) {
let myUserInfo = storage.getVlogUserInfo()||null;
if (myUserInfo!=null) {
this.userId = myUserInfo.id;
}
//
this.displayVideoPaging(this.page + 1, true);
let videoContext = uni.createVideoContext("videoDetail");
this.videoContext = videoContext;
// let videoContext = uni.createVideoContext("videoDetail");
// this.videoContext = videoContext;
},
watch: {
refreshList(value) {
@ -259,118 +275,73 @@ export default {
me.playerList = playerList;
},
refreshVlogCounts() {
// ,
let me = this;
let serverUrl = app.globalData.serverUrl;
let currentIndex = me.playerCur;
let vlog = me.playerList[currentIndex];
uni.request({
method: "POST",
url: serverUrl + "/vlog/totalLikedCounts?vlogId=" + vlog.vlogId,
success(result) {
if (result.data.status == 2095) {
let counts = result.data.data;
me.reChangeVlogLikedCountsInPlayList(vlog.vlogId, counts);
} else {
uni.showToast({
title: result.data.msg,
duration: 3000,
icon: "none",
});
}
},
});
async refreshVlogCounts() {
var me = this;
if(me.playerList.length==0){
return
}
var currentIndex = me.playerCur;
var vlog = me.playerList[currentIndex];
var result = await vlogTotalLikedCounts(vlog.vlogId)
if (result.data.status == 200) {
let counts = result.data.data;
me.reChangeVlogLikedCountsInPlayList(vlog.vlogId, counts);
} else {
uni.showToast({
title: result.data.msg,
duration: 3000,
icon: "none",
});
}
},
likeOrDislikeVlog(isLike) {
let me = this;
async likeOrDislikeVlog(isLike) {
var me = this;
var myUserInfo = storage.getVlogUserInfo() || null
var currentIndex = me.playerCur;
var vlog = me.playerList[currentIndex];
if (myUserInfo==null) {
uni.navigateTo({
url: "/pages/passport/login",
animationType: "slide-in-bottom",
});
return;
}
var userId = myUserInfo.id;
if (isLike == 1) {
//
let myUserInfo = getApp().getUserInfoSession();
if (app.isStrEmpty(myUserInfo)) {
uni.navigateTo({
url: "/pages/passport/login",
animationType: "slide-in-bottom",
});
return;
}
let userId = myUserInfo.id;
let serverUrl = app.globalData.serverUrl;
let currentIndex = me.playerCur;
let vlog = me.playerList[currentIndex];
uni.request({
method: "POST",
header: {
headerUserId: userId,
headerUserToken: app.getUserSessionToken(),
},
url:
serverUrl +
"/vlog/like?userId=" +
userId +
"&vlogerId=" +
vlog.vlogerId +
"&vlogId=" +
vlog.vlogId,
success(result) {
if (result.data.status == 2093) {
me.reLikePlayList(vlog.vlogId);
me.refreshVlogCounts();
} else {
uni.showToast({
title: result.data.msg,
icon: "none",
duration: 3000,
});
}
},
});
var result = await vlogLike({
userId,
vlogerId: vlog.vlogerId,
vlogId: vlog.vlogId
})
if (result.data.status == 200) {
me.reLikePlayList(vlog.vlogId);
me.refreshVlogCounts();
} else {
uni.showToast({
title: result.data.msg,
icon: "none",
duration: 3000,
});
}
} else if (isLike == 0) {
let myUserInfo = getApp().getUserInfoSession();
if (app.isStrEmpty(myUserInfo)) {
uni.navigateTo({
url: "/pages/passport/login",
animationType: "slide-in-bottom",
});
return;
}
let userId = myUserInfo.id;
let serverUrl = app.globalData.serverUrl;
let currentIndex = me.playerCur;
let vlog = me.playerList[currentIndex];
uni.request({
method: "POST",
header: {
headerUserId: userId,
headerUserToken: app.getUserSessionToken(),
},
url:
serverUrl +
"/vlog/unlike?userId=" +
userId +
"&vlogerId=" +
vlog.vlogerId +
"&vlogId=" +
vlog.vlogId,
success(result) {
if (result.data.status == 2094) {
me.reDislikePlayList(vlog.vlogId);
me.refreshVlogCounts();
} else {
uni.showToast({
title: result.data.msg,
icon: "none",
duration: 3000,
});
}
},
});
var result = await vlogUnLike({
userId,
vlogerId: vlog.vlogerId,
vlogId: vlog.vlogId
})
if (result.data.status == 200) {
me.reDislikePlayList(vlog.vlogId);
me.refreshVlogCounts();
} else {
uni.showToast({
title: result.data.msg,
icon: "none",
duration: 3000,
});
}
}
},
// list
@ -400,10 +371,10 @@ export default {
me.playerList = playerList;
},
//
followMe(vlogerId) {
async followMe(vlogerId) {
let me = this;
let myUserInfo = getApp().getUserInfoSession();
if (app.isStrEmpty(myUserInfo)) {
let myUserInfo = storage.getVlogUserInfo()||null;
if (myUserInfo==null) {
uni.navigateTo({
url: "/pages/passport/login",
animationType: "slide-in-bottom"
@ -413,34 +384,24 @@ export default {
}
let userId = myUserInfo.id;
let serverUrl = app.globalData.serverUrl;
uni.request({
method: "POST",
header: {
headerUserId: userId,
headerUserToken: app.getUserSessionToken(),
},
url:
serverUrl + "/fans/follow?myId=" + userId + "&vlogerId=" + vlogerId,
success(result) {
if (result.data.status == 208) {
me.reFollowPlayList(vlogerId);
} else {
uni.showToast({
title: result.data.msg,
icon: "none",
duration: 3000,
});
}
},
});
var result = await vlogFollow(userId,vlogerId)
if (result.data.status == 208) {
me.reFollowPlayList(vlogerId);
} else {
uni.showToast({
title: result.data.msg,
icon: "none",
duration: 3000,
});
}
},
goUserInfoSeeSee(userId) {
//
let myUserId = "";
if (!app.isStrEmpty(app.getUserInfoSession())) {
myUserId = app.getUserInfoSession().id;
var info = storage.getVlogUserInfo()||null
if (info!=null) {
myUserId = info.id;
}
if (myUserId == userId) {
uni.switchTab({
@ -454,7 +415,6 @@ export default {
},
downloadVlog() {
var me = this;
var serverUrl = app.globalData.serverUrl;
var currentIndex = me.playerCur;
var vlog = me.playerList[currentIndex];
var pendingLength = vlog.url;
@ -483,37 +443,36 @@ export default {
this.playStatus = !playStatus;
},
displayVideoPaging(page, needClearList) {
async displayVideoPaging(page, needClearList) {
let me = this;
let vlogId = me.vlogId;
let myUserInfo = getApp().getUserInfoSession();
let myUserInfo = storage.getVlogUserInfo()||null;
let userId = "";
if (!app.isStrEmpty(myUserInfo)) {
if ((myUserInfo!=null)) {
userId = myUserInfo.id;
}
let serverUrl = app.globalData.serverUrl;
uni.request({
method: "GET",
url: serverUrl + "/vlog/detail?userId=" + userId + "&vlogId=" + vlogId,
success(result) {
if (result.data.status == 207) {
let vlog = result.data.data;
let playerList = [];
playerList.push(vlog);
me.playerList = playerList;
me.freshCommentCounts();
me.setThisVlogInfo();
} else {
uni.showToast({
title: result.data.msg,
icon: "none",
duration: 3000,
});
}
},
});
var result = await vlogDetail(vlogId,userId)
if (result.data.status == 200) {
let vlog = result.data.data;
let playerList = [];
playerList.push(vlog);
me.playerList = playerList;
if(this.videoContext!=null && playerList.length>0){
let videoContext = uni.createVideoContext("videoDetail");
this.videoContext = videoContext;
}
me.freshCommentCounts();
me.setThisVlogInfo();
} else {
uni.showToast({
title: result.data.msg,
icon: "none",
duration: 3000,
});
}
},
doplay: function (time) {
@ -532,8 +491,6 @@ export default {
// vlog
setThisVlogInfo() {
let me = this;
let serverUrl = app.globalData.serverUrl;
if (
me.playerList != null &&
me.playerList != undefined &&
@ -546,10 +503,12 @@ export default {
this.thisVlogerId = vlog.vlogerId;
}
},
freshCommentCounts() {
async freshCommentCounts() {
var me = this;
var userId = getApp().getUserInfoSession().id;
var serverUrl = app.globalData.serverUrl;
var uinfo = storage.getVlogUserInfo()||null
if(uinfo!=null){
var userId=uinfo.id
}
if (
me.playerList == null ||
me.playerList == undefined ||
@ -560,18 +519,12 @@ export default {
var currentIndex = me.playerCur;
var vlog = me.playerList[currentIndex];
var vlogId = vlog.vlogId;
var serverUrl = app.globalData.serverUrl;
uni.request({
method: "GET",
url: serverUrl + "/comment/counts?vlogId=" + vlogId,
success(result) {
if (result.data.status == 200) {
me.thisVlogTotalComentCounts = result.data.data;
} else {
me.thisVlogTotalComentCounts = 0;
}
},
});
var result = await vlogComment(vlogId)
if (result.data.status == 200) {
me.thisVlogTotalComentCounts = result.data.data;
} else {
me.thisVlogTotalComentCounts = 0;
}
},
commentToggle() {
this.$refs.comment.open();
@ -589,7 +542,7 @@ export default {
};
</script>
<style lang="scss">
<style scoped>
.icon {
width: 80rpx;
height: 80rpx;

View File

@ -9,6 +9,8 @@
"compatible" : {
"ignoreVersion" : true //trueHBuilderX1.9.0
},
"nvueStyleCompiler" : "uni-app",
"compilerVersion" : 3,
/* 5+App */
"usingComponents" : true,
"splashscreen" : {
@ -17,6 +19,7 @@
"autoclose" : true,
"delay" : 0
},
"screenOrientation" : [ "portrait-primary" ],
"modules" : {
"Payment" : {},
"Share" : {},

View File

@ -1,20 +1,4 @@
{
"id": "ir-tabs",
"name": "ir-tabstabstab选项卡组件",
"version": "1.0.3",
"description": "用于展示同一页面不同标题下内容可通过左右滑动和点击tab的方式切换页面支持自定义颜色、下拉刷新",
"keywords": [
"tab",
"tabs",
"选项卡",
"导航栏"
],
"dcloudext": {
"category": [
"前端组件",
"通用组件"
]
},
"dependencies": {
"@tencentcloud/chat-uikit-uniapp": "^2.4.3",
"@vue/runtime-core": "^3.5.13",

View File

@ -8,7 +8,7 @@
"path" : "pages/tabbar/vlog/index",
"style" : {
"app-plus" : {
"titleNView" : false //
"titleNView" : false //
},
"enablePullDownRefresh" : false //ios
@ -103,67 +103,76 @@
"navigationBarBackgroundColor" : "#181b27",
"enablePullDownRefresh" : false
}
}
// {
// "path" : "pages/me/vlogerInfo",
// "style" : {
// "app-plus" : {
// "titleNView" : false //
// }
// }
// }
// {
// "path" : "pages/me/me",
// "style" : {
// "app-plus" : {
// "titleNView" : false //
// }
// }
// }
// {
// "path" : "pages/me/myBackImg",
// "style" : {
// "app-plus" : {
// "titleNView" : false //
// }
// }
// },
// {
// "path" : "pages/me/myFace",
// "style" : {
// "app-plus" : {
// "titleNView" : false //
// }
// }
// },
// {
// "path" : "pages/me/myInfo",
// "style" : {
// "navigationBarTitleText" : "修改个人资料",
// "navigationBarBackgroundColor" : "#181b27"
// }
// },
// {
// "path" : "pages/me/modifyNickname",
// "style" : {
// "navigationBarTitleText" : "修改昵称",
// "navigationBarTextStyle" : "white",
// "navigationBarBackgroundColor" : "#181b27",
// "app-plus" : {
// "titleNView" : {
// "buttons" : [
// {
// "text" : "保存",
// "color" : "#ef274d",
// "width" : "60px",
// "fontSize" : "15px",
// "fontWeight" : "bold"
// }
// ]
// }
// }
// }
// },
},
{
"path" : "pages/me/vlogerInfo",
"style" : {
"app-plus" : {
"titleNView" : false //
}
}
},
{
"path" : "pages/me/vlog",
"style" : {
"app-plus" : {
"titleNView" : false //
}
}
},
{
"path" : "pages/me/me",
"style" : {
"app-plus" : {
"titleNView" : false //
}
}
},
{
"path" : "pages/me/myBackImg",
"style" : {
"app-plus" : {
"titleNView" : false //
}
}
},
{
"path" : "pages/me/myFace",
"style" : {
"app-plus" : {
"titleNView" : false //
}
}
},
{
"path" : "pages/me/myInfo",
"style" : {
"navigationBarTitleText" : "修改个人资料",
"navigationBarBackgroundColor" : "#181b27",
"navigationBarTextStyle": "white"
}
},
{
"path" : "pages/me/modifyNickname",
"style" : {
"navigationBarTitleText" : "修改昵称",
"navigationBarTextStyle" : "white",
"navigationBarBackgroundColor" : "#181b27",
"app-plus" : {
"titleNView" : {
"buttons" : [
{
"text" : "保存",
"color" : "#ef274d",
"width" : "60px",
"fontSize" : "15px",
"fontWeight" : "bold"
}
]
}
}
}
},
// {
// "path" : "pages/me/modifyPass",
// "style" : {
@ -185,127 +194,135 @@
// }
// }
// },
// {
// "path" : "pages/me/modifyTioktokNum",
// "style" : {
// "navigationBarTitleText" : "修改视频号",
// "navigationBarTextStyle" : "white",
// "navigationBarBackgroundColor" : "#181b27",
// "app-plus" : {
// "titleNView" : {
// "buttons" : [
// {
// "text" : "保存",
// "color" : "#ef274d",
// "width" : "60px",
// "fontSize" : "15px",
// "fontWeight" : "bold"
// }
// ]
// }
// }
// }
// },
// {
// "path" : "pages/me/modifyDesc",
// "style" : {
// "navigationBarTitleText" : "修改简介",
// "navigationBarTextStyle" : "white",
// "navigationBarBackgroundColor" : "#181b27",
// "app-plus" : {
// "titleNView" : {
// "buttons" : [
// {
// "text" : "保存",
// "color" : "#ef274d",
// "width" : "60px",
// "fontSize" : "15px",
// "fontWeight" : "bold"
// }
// ]
// }
// }
// }
// },
// {
// "path" : "pages/me/modifySex",
// "style" : {
// "navigationBarTitleText" : "修改性别",
// "navigationBarTextStyle" : "white",
// "navigationBarBackgroundColor" : "#181b27",
// "app-plus" : {
// "titleNView" : {
// "buttons" : [
// {
// "text" : "保存",
// "color" : "#ef274d",
// "width" : "60px",
// "fontSize" : "15px",
// "fontWeight" : "bold"
// }
// ]
// }
// }
// }
// },
// {
// "path" : "pages/me/modifyBirthday",
// "style" : {
// "navigationBarTitleText" : "修改生日",
// "navigationBarTextStyle" : "white",
// "navigationBarBackgroundColor" : "#181b27",
// "app-plus" : {
// "titleNView" : {
// "buttons" : [
// {
// "text" : "保存",
// "color" : "#ef274d",
// "width" : "60px",
// "fontSize" : "15px",
// "fontWeight" : "bold"
// }
// ]
// }
// }
// }
// },
// {
// "path" : "pages/me/modifyLocation",
// "style" : {
// "navigationBarTitleText" : "修改所在地",
// "navigationBarTextStyle" : "white",
// "navigationBarBackgroundColor" : "#181b27",
// "app-plus" : {
// "titleNView" : {
// "buttons" : [
// {
// "text" : "保存",
// "color" : "#ef274d",
// "width" : "60px",
// "fontSize" : "15px",
// "fontWeight" : "bold"
// }
// ]
// }
// }
// }
// },
// {
// "path" : "pages/me/chooseProvince",
// "style" : {
// "navigationBarTitleText" : "选择省份",
// "navigationBarTextStyle" : "white",
// "navigationBarBackgroundColor" : "#181b27"
// }
// },
// {
// "path" : "pages/me/chooseCity",
// "style" : {
// "navigationBarTitleText" : "选择城市",
// "navigationBarTextStyle" : "white",
// "navigationBarBackgroundColor" : "#181b27"
// }
// },
{
"path" : "pages/me/modifyTioktokNum",
"style" : {
"navigationBarTitleText" : "修改视频号",
"navigationBarTextStyle" : "white",
"navigationBarBackgroundColor" : "#181b27",
"app-plus" : {
"titleNView" : {
"buttons" : [
{
"text" : "保存",
"color" : "#ef274d",
"width" : "60px",
"fontSize" : "15px",
"fontWeight" : "bold"
}
]
}
}
}
},
{
"path" : "pages/me/modifyDesc",
"style" : {
"navigationBarTitleText" : "修改简介",
"navigationBarTextStyle" : "white",
"navigationBarBackgroundColor" : "#181b27",
"app-plus" : {
"titleNView" : {
"buttons" : [
{
"text" : "保存",
"color" : "#ef274d",
"width" : "60px",
"fontSize" : "15px",
"fontWeight" : "bold"
}
]
}
}
}
},
{
"path" : "pages/me/modifySex",
"style" : {
"navigationBarTitleText" : "修改性别",
"navigationBarTextStyle" : "white",
"navigationBarBackgroundColor" : "#181b27",
"app-plus" : {
"titleNView" : {
"buttons" : [
{
"text" : "保存",
"color" : "#ef274d",
"width" : "60px",
"fontSize" : "15px",
"fontWeight" : "bold"
}
]
}
}
}
},
{
"path" : "pages/me/modifyBirthday",
"style" : {
"navigationBarTitleText" : "修改生日",
"navigationBarTextStyle" : "white",
"navigationBarBackgroundColor" : "#181b27",
"app-plus" : {
"titleNView" : {
"buttons" : [
{
"text" : "保存",
"color" : "#ef274d",
"width" : "60px",
"fontSize" : "15px",
"fontWeight" : "bold"
}
]
}
}
}
},
{
"path" : "pages/me/modifyLocation",
"style" : {
"navigationBarTitleText" : "修改所在地",
"navigationBarTextStyle" : "white",
"navigationBarBackgroundColor" : "#181b27",
"app-plus" : {
"titleNView" : {
"buttons" : [
{
"text" : "保存",
"color" : "#ef274d",
"width" : "60px",
"fontSize" : "15px",
"fontWeight" : "bold"
}
]
}
}
}
},
{
"path" : "pages/me/chooseProvince",
"style" : {
"navigationBarTitleText" : "选择省份",
"navigationBarTextStyle" : "white",
"navigationBarBackgroundColor" : "#181b27"
}
},
{
"path" : "pages/me/chooseCity",
"style" : {
"navigationBarTitleText" : "选择城市",
"navigationBarTextStyle" : "white",
"navigationBarBackgroundColor" : "#181b27"
}
},
{
"path" : "pages/me/chooseDistrict",
"style" : {
"navigationBarTitleText" : "选择地区",
"navigationBarTextStyle" : "white",
"navigationBarBackgroundColor" : "#181b27"
}
},
// {
// "path" : "pages/me/settings",
// "style" : {
@ -314,30 +331,23 @@
// "navigationBarBackgroundColor" : "#181b27"
// }
// },
// {
// "path" : "pages/me/myFans",
// "style" : {
// "navigationBarTitleText" : "粉丝",
// "navigationBarTextStyle" : "white",
// "navigationBarBackgroundColor" : "#181b27"
// }
// },
// {
// "path" : "pages/me/myFollows",
// "style" : {
// "navigationBarTitleText" : "关注",
// "navigationBarTextStyle" : "white",
// "navigationBarBackgroundColor" : "#181b27"
// }
// },
// {
// "path" : "pages/me/chooseDistrict",
// "style" : {
// "navigationBarTitleText" : "选择地区",
// "navigationBarTextStyle" : "white",
// "navigationBarBackgroundColor" : "#181b27"
// }
// }
{
"path" : "pages/me/myFans",
"style" : {
"navigationBarTitleText" : "粉丝",
"navigationBarTextStyle" : "white",
"navigationBarBackgroundColor" : "#181b27"
}
},
{
"path" : "pages/me/myFollows",
"style" : {
"navigationBarTitleText" : "关注",
"navigationBarTextStyle" : "white",
"navigationBarBackgroundColor" : "#181b27"
}
}
],
"subPackages": [
@ -978,92 +988,92 @@
}
}
]
},
{
"root": "TUIKit",
"pages": [
{
"path": "components/TUIConversation/index",
"style": {
"navigationBarTitleText": "腾讯云 IM绘画",
"app-plus": {
"titleNView": {
"backButton": true //
}
}
}
},
{
"path": "components/TUIChat/index",
"style": {
"navigationBarTitleText": "腾讯云 IM",
"app-plus": {
"softinputMode": "adjustResize",
"titleNView": {
"buttons": [
{
"type": "menu"
}
]
}
},
"h5": {
"titleNView": {
"buttons": []
}
}
}
},
// chat :
{
"path": "components/TUIChat/video-play",
"style": {
"navigationBarTitleText": "腾讯云 IM1"
}
},
{
"path": "components/TUIChat/web-view",
"style": {
"navigationBarTitleText": "腾讯云 IM2"
}
},
{
"path": "components/TUIContact/index",
"style": {
"navigationBarTitleText": "腾讯云 IM3",
"app-plus": {
"titleNView": {
"backButton": true //
}
}
}
},
{
"path": "components/TUIGroup/index",
"style": {
"navigationBarTitleText": "腾讯云 IM4",
"app-plus": {
"titleNView": {
"backButton": true //
}
}
}
},
{
"path": "components/TUISearch/index",
"style": {
"navigationBarTitleText": "聊天记录"
}
}
]
}
}
// {
// "root": "TUIKit",
// "pages": [
// {
// "path": "components/TUIConversation/index",
// "style": {
// "navigationBarTitleText": "腾讯云 IM绘画",
// "app-plus": {
// "titleNView": {
// "backButton": true //
// }
// }
// }
// },
// {
// "path": "components/TUIChat/index",
// "style": {
// "navigationBarTitleText": "腾讯云 IM",
// "app-plus": {
// "softinputMode": "adjustResize",
// "titleNView": {
// "buttons": [
// {
// "type": "menu"
// }
// ]
// }
// },
// "h5": {
// "titleNView": {
// "buttons": []
// }
// }
// }
// },
// // chat :
// {
// "path": "components/TUIChat/video-play",
// "style": {
// "navigationBarTitleText": "腾讯云 IM1"
// }
// },
// {
// "path": "components/TUIChat/web-view",
// "style": {
// "navigationBarTitleText": "腾讯云 IM2"
// }
// },
// {
// "path": "components/TUIContact/index",
// "style": {
// "navigationBarTitleText": "腾讯云 IM3",
// "app-plus": {
// "titleNView": {
// "backButton": true //
// }
// }
// }
// },
// {
// "path": "components/TUIGroup/index",
// "style": {
// "navigationBarTitleText": "腾讯云 IM4",
// "app-plus": {
// "titleNView": {
// "backButton": true //
// }
// }
// }
// },
// {
// "path": "components/TUISearch/index",
// "style": {
// "navigationBarTitleText": "聊天记录"
// }
// }
// ]
// }
],
"globalStyle": {
"navigationBarTextStyle": "black",
"navigationBarTitleText": "Lili商城",
"titleColor": "#303133",
"navigationBarBackgroundColor": "#fff",
"backgroundColor": "#fff",
"backgroundColor": "#0e0d0d",
"color": "#FFFFFF",
"app-plus": {
//
@ -1091,7 +1101,7 @@
"text": "消息"
},
{
"pagePath": "pages/tabbar/user/my",
"pagePath": "pages/me/me",
"text": "我的"
}
],

115
pages/me/chooseCity.nvue Executable file
View File

@ -0,0 +1,115 @@
<template>
<view class="page">
<view class="line"></view>
<scroll-view scroll-y="true">
<view
v-for="(item, index) in cityList"
class="item"
:class="{ active: index == activeIndex }"
:key="index"
@click="chooseLocation(item.city_id, item.city_name)"
@touchstart="touchstartLocation(index)"
@touchend="touchendLocation">
<text class="item-text">
{{ item.city_name }}
</text>
<view class="right-part">
<image
class="right-arrow"
src="/static/images/icon-right-arrow2.png"></image>
</view>
</view>
</scroll-view>
</view>
</template>
<script>
import cityList from "@/json/area_city.js"
export default {
data() {
return {
cityList: [],
activeIndex: -1,
};
},
onLoad(params) {
let provinceId = params.provinceId;
console.log(params)
console.log(cityList)
let realCityList = [];
for (let i = 0; i < cityList.length; i++) {
let tempProvinceId = cityList[i].province_id;
if (tempProvinceId == provinceId) {
realCityList.push(cityList[i]);
}
}
this.cityList = realCityList;
},
methods: {
touchstartLocation(index) {
this.activeIndex = index;
},
touchendLocation() {
this.activeIndex = -1;
},
chooseLocation(cityId, cityName) {
uni.setStorageSync("myLocationCity", cityName);
uni.navigateTo({
url: "chooseDistrict?cityId=" + cityId,
});
},
},
};
</script>
<style lang="scss">
.page {
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
background-color: #181b27;
.line {
height: 1rpx;
background-color: #393a41;
width: 750rpx;
}
.item {
padding-left: 30rpx;
padding-right: 30rpx;
width: 750rpx;
height: 120rpx;
display: flex;
flex-direction: row;
justify-content: space-between;
.item-text {
color: #ffffff;
align-self: center;
font-size: 30rpx;
}
.right-part {
display: flex;
flex-direction: row;
justify-content: flex-start;
align-self: center;
.right-arrow {
align-self: center;
width: 32rpx;
height: 32rpx;
margin-left: 20rpx;
}
}
}
.active {
background-color: #4a4c52;
}
}
</style>

92
pages/me/chooseDistrict.nvue Executable file
View File

@ -0,0 +1,92 @@
<template>
<view class="page">
<view class="line"></view>
<scroll-view scroll-y="true">
<view
v-for="(item, index) in districtList"
class="item"
:class="{ active: index == activeIndex }"
:key="index"
@click="chooseLocation(item.district_id, item.district_name)"
@touchstart="touchstartLocation(index)"
@touchend="touchendLocation">
<text class="item-text">
{{ item.district_name }}
</text>
</view>
</scroll-view>
</view>
</template>
<script>
import districtList from "@/json/area_district.js";
export default {
data() {
return {
districtList: [],
activeIndex: -1,
};
},
onLoad(params) {
let cityId = params.cityId;
let realDistrictList = [];
for (let i = 0; i < districtList.length; i++) {
let tempCityId = districtList[i].city_id;
if (tempCityId == cityId) {
realDistrictList.push(districtList[i]);
}
}
this.districtList = realDistrictList;
},
methods: {
touchstartLocation(index) {
this.activeIndex = index;
},
touchendLocation() {
this.activeIndex = -1;
},
chooseLocation(districtId, districtName) {
uni.setStorageSync("myLocationDistrict", districtName);
uni.navigateBack({
delta: 3,
});
},
},
};
</script>
<style lang="scss">
.page {
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
background-color: #181b27;
.line {
height: 1rpx;
background-color: #393a41;
width: 750rpx;
}
.item {
padding-left: 30rpx;
padding-right: 30rpx;
width: 750rpx;
height: 120rpx;
display: flex;
flex-direction: row;
justify-content: space-between;
.item-text {
color: #ffffff;
align-self: center;
font-size: 30rpx;
}
}
.active {
background-color: #4a4c52;
}
}
</style>

106
pages/me/chooseProvince.nvue Executable file
View File

@ -0,0 +1,106 @@
<template>
<view class="page">
<view class="line"></view>
<scroll-view scroll-y="true">
<view
v-for="(item, index) in provinceList"
class="item"
:class="{ active: index == activeIndex }"
:key="index"
@click="chooseLocation(item.province_id, item.province_name)"
@touchstart="touchstartLocation(index)"
@touchend="touchendLocation">
<text class="item-text">
{{ item.province_name }}
</text>
<view class="right-part">
<image
class="right-arrow"
src="/static/images/icon-right-arrow2.png"></image>
</view>
</view>
</scroll-view>
</view>
</template>
<script>
import storage from "@/utils/storage.js"; //缓存
import provinceList from "@/json/area_province.js";
export default {
data() {
return {
provinceList: [],
activeIndex: -1,
};
},
onLoad() {
this.provinceList = provinceList;
},
methods: {
touchstartLocation(index) {
this.activeIndex = index;
},
touchendLocation() {
this.activeIndex = -1;
},
chooseLocation(provinceId, provinceName) {
uni.setStorageSync("myLocationProvince", provinceName);
uni.navigateTo({
url: "chooseCity?provinceId=" + provinceId,
});
},
},
};
</script>
<style lang="scss">
.page {
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
background-color: #181b27;
.line {
height: 1rpx;
background-color: #393a41;
width: 750rpx;
}
.item {
padding-left: 30rpx;
padding-right: 30rpx;
width: 750rpx;
height: 120rpx;
display: flex;
flex-direction: row;
justify-content: space-between;
.item-text {
color: #ffffff;
align-self: center;
font-size: 30rpx;
}
.right-part {
display: flex;
flex-direction: row;
justify-content: flex-start;
align-self: center;
.right-arrow {
align-self: center;
width: 32rpx;
height: 32rpx;
margin-left: 20rpx;
}
}
}
.active {
background-color: #4a4c52;
}
}
</style>

File diff suppressed because it is too large Load Diff

164
pages/me/modifyBirthday.vue Executable file
View File

@ -0,0 +1,164 @@
<template>
<view class="page">
<view class="line"></view>
<view class="picker-box">
<picker
class="birthday-item"
mode="date"
:value="date"
:start="startDate"
:end="endDate"
@change="bindDateChange">
<view class="left-picker-part">
<text class="date-lable">{{ date }}</text>
</view>
<view class="left-choose">
<image
src="/static/images/icon-datepicker.png"
class="icon-right"></image>
</view>
</picker>
</view>
<view class="notice">
<text class="tips">*点击即可选择生日噢~</text>
</view>
</view>
</template>
<script>
import storage from "@/utils/storage.js"; //
import {
vlogModifyUserInfo
} from "@/api/vlog"
import {
dateFormat
} from '@/utils/tools.js'
export default {
data() {
return {
date: "",
startDate: "1970-01-01",
endDate: "2088-08-08",
};
},
onNavigationBarButtonTap() {
this.updateBirthday();
},
onLoad() {
let birthday = storage.getVlogUserInfo().birthday;
this.date = this.getGraceDateStr(new Date(birthday));
},
methods: {
async updateBirthday() {
let me = this;
let userId = storage.getVlogUserInfo().id;
let birth = this.date;
let pendingUserInfo = {
id: userId,
birthday: birth,
type:4
};
var result = await vlogModifyUserInfo(pendingUserInfo,4)
if (result.data.status == 200) {
let userInfoUpdated = result.data.data;
//
storage.setVlogUserInfo(userInfoUpdated);
uni.showToast({
title: result.data.msg,
icon: "none",
duration: 3000,
});
var timer = setTimeout(() => {
clearTimeout(timer)
uni.navigateBack({
delta: 1,
animationType: "fade-out",
});
}, 1000);
} else {
uni.showToast({
title: result.data.msg,
icon: "none",
duration: 3000,
});
}
},
bindDateChange: function (e) {
this.date = e.detail.value;
},
getGraceDateStr(date) {
return dateFormat("YYYY-mm-dd", date);
},
},
};
</script>
<style lang="scss">
.page {
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
background-color: #181b27;
.line {
height: 1rpx;
background-color: #393a41;
width: 750rpx;
}
.picker-box {
align-self: center;
margin-top: 50rpx;
display: flex;
flex-direction: row;
.birthday-item {
background-color: #4a4c52;
display: flex;
flex-direction: row;
justify-content: space-between;
width:720rpx;
height: 140rpx;
border-radius: 40rpx;
.left-picker-part {
align-self: center;
display: flex;
flex-direction: row;
justify-content: flex-start;
width: 280rpx;
height: 120rpx;
.date-lable {
align-self: center;
color: #ffffff;
margin-left: 40rpx;
}
}
.left-choose {
align-self: center;
width: 80rpx;
height: 120rpx;
display: flex;
flex-direction: row;
justify-content: flex-start;
.icon-right {
align-self: center;
width: 60rpx;
height: 60rpx;
}
}
}
}
.notice {
margin-left: 30rpx;
.tips {
font-size: 24rpx;
font-weight: 400;
color: #bfbfbf;
width: 700rpx;
margin-top: 20rpx;
}
}
}
</style>

151
pages/me/modifyDesc.vue Executable file
View File

@ -0,0 +1,151 @@
<template>
<view class="page">
<view class="line"></view>
<view class="single-line-box">
<input
class="description-input"
type="text"
:value="description"
:model="description"
placeholder="请填入简介~"
maxlength="16"
@input="typingContent" />
<view class="length-cal">
<text class="length-text">{{ wordsLength }}/16</text>
</view>
</view>
<view class="notice">
<text class="tips">*请设置0-16字的个人简介</text>
</view>
</view>
</template>
<script>
import storage from "@/utils/storage.js"; //
import {
vlogModifyUserInfo
} from "@/api/vlog"
export default {
data() {
return {
description: storage.getVlogUserInfo().description,
wordsLength: 0,
};
},
onNavigationBarButtonTap() {
this.updateDesc();
},
onShow() {
this.wordsLength = this.description.length;
},
methods: {
async updateDesc() {
let me = this;
let userId = storage.getVlogUserInfo().id;
let description =
this.description == "" ? "这家伙很懒,什么都没留下~" : this.description;
let pendingUserInfo = {
id: userId,
description: description,
type:6
};
var result = await vlogModifyUserInfo(pendingUserInfo,6)
if (result.data.status == 200) {
let userInfoUpdated = result.data.data;
//
storage.setVlogUserInfo(userInfoUpdated);
uni.showToast({
title: result.data.msg,
icon: "none",
duration: 3000,
});
var timer = setTimeout(() => {
clearTimeout(timer)
uni.navigateBack({
delta: 1,
animationType: "fade-out",
});
}, 1000);
} else {
uni.showToast({
title: result.data.msg,
icon: "none",
duration: 3000,
});
}
},
typingContent(e) {
this.description = e.detail.value;
this.wordsLength = this.description.length;
},
},
};
</script>
<style lang="scss">
.page {
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
background-color: #181b27;
display: flex;
flex-direction: column;
justify-content: flex-start;
.line {
height: 1rpx;
background-color: #393a41;
width: 750rpx;
}
.single-line-box {
align-self: center;
display: flex;
flex-direction: column;
padding: 30rpx;
margin-top: 20rpx;
.description-input {
padding-left: 20rpx;
padding-top: 30rpx;
color: #ffffff;
font-size: 32rpx;
width: 700rpx;
height: 100rpx;
background-color: #4a4c52;
border-top-left-radius: 20rpx;
border-top-right-radius: 20rpx;
}
.length-cal {
width: 700rpx;
height: 20px;
background-color: #4a4c52;
padding-right: 20rpx;
display: flex;
flex-direction: row;
justify-content: flex-end;
padding-bottom: 12rpx;
border-bottom-left-radius: 20rpx;
border-bottom-right-radius: 20rpx;
.length-text {
font-size: 24rpx;
font-weight: 400;
color: #f1f1f1;
}
}
}
.notice {
align-self: center;
.tips {
font-size: 24rpx;
font-weight: 400;
color: #bfbfbf;
width: 700rpx;
}
}
}
</style>

196
pages/me/modifyLocation.vue Executable file
View File

@ -0,0 +1,196 @@
<template>
<view class="page">
<view class="line"></view>
<view
class="place"
:class="{ 'place-box': !placeTouched, 'place-box-touched': placeTouched }"
@click="chooseLocation"
@touchstart="touchstartLocation"
@touchend="touchendLocation">
<text class="country">中国</text>
<view class="location">
<text class="location-text">{{ areaText }}</text>
<image
class="right-arrow"
src="/static/images/icon-right-arrow2.png"></image>
</view>
</view>
<view class="notice">
<text class="tips">*点击即可选择省份与城市~</text>
</view>
</view>
</template>
<script>
import storage from "@/utils/storage.js"; //
import {
vlogModifyUserInfo
} from "@/api/vlog"
import {
isStrEmpty,
dateFormat
} from '@/utils/tools.js'
export default {
data() {
return {
areaText: "选择地区",
placeTouched: false,
chooseLocationDone: false, //
};
},
onNavigationBarButtonTap() {
let districtName = uni.getStorageSync("myLocationDistrict");
if (isStrEmpty(districtName)) {
uni.showToast({
icon: "none",
title: "请选择一个地区",
});
return;
}
this.updateLocation();
},
onShow() {
let provinceName = uni.getStorageSync("myLocationProvince");
let cityName = uni.getStorageSync("myLocationCity");
let districtName = uni.getStorageSync("myLocationDistrict");
if (isStrEmpty(districtName)) {
this.areaText = "选择地区";
} else {
this.areaText =
provinceName == cityName
? cityName + "·" + districtName
: provinceName + "·" + cityName + "·" + districtName;
}
},
methods: {
async updateLocation() {
let provinceName = uni.getStorageSync("myLocationProvince");
let cityName = uni.getStorageSync("myLocationCity");
let districtName = uni.getStorageSync("myLocationDistrict");
let me = this;
let userId = storage.getVlogUserInfo().id;
let pendingUserInfo = {
id: userId,
province: provinceName,
city: cityName,
district: districtName,
type:5
};
var result = await vlogModifyUserInfo(pendingUserInfo,5)
if (result.data.status == 200) {
let userInfoUpdated = result.data.data;
//
storage.setVlogUserInfo(userInfoUpdated);
uni.showToast({
title: result.data.msg,
icon: "none",
duration: 3000,
});
var timer = setTimeout(() => {
clearTimeout(timer)
uni.navigateBack({
delta: 1,
animationType: "fade-out",
});
}, 1000);
} else {
uni.showToast({
title: result.data.msg,
icon: "none",
duration: 3000,
});
}
// ,
uni.setStorageSync("myLocationProvince", "");
uni.setStorageSync("myLocationCity", "");
uni.setStorageSync("myLocationDistrict", "");
},
touchstartLocation() {
this.placeTouched = true;
},
touchendLocation() {
this.placeTouched = false;
},
chooseLocation() {
uni.navigateTo({
url: "chooseProvince",
});
},
},
};
</script>
<style lang="scss">
.page {
position: absolute;
display: flex;
flex-direction: column;
left: 0;
right: 0;
top: 0;
bottom: 0;
background-color: #181b27;
.line {
height: 1rpx;
background-color: #393a41;
width: 750rpx;
}
.place {
align-self: center;
margin-top: 40rpx;
padding-left: 30rpx;
padding-right: 30rpx;
width: 700rpx;
height: 120rpx;
display: flex;
flex-direction: row;
justify-content: space-between;
border-radius: 40rpx;
.country {
color: #ffffff;
align-self: center;
font-size: 30rpx;
}
.location {
display: flex;
flex-direction: row;
justify-content: flex-start;
align-self: center;
.location-text {
color: #ffffff;
font-size: 30rpx;
}
.right-arrow {
align-self: center;
width: 32rpx;
height: 32rpx;
margin-left: 20rpx;
}
}
}
.place-box {
background-color: #4a4c52;
}
.place-box-touched {
background-color: #6d6b6b;
}
.notice {
align-self: center;
.tips {
margin-left: 20rpx;
font-size: 24rpx;
font-weight: 400;
color: #bfbfbf;
width: 700rpx;
margin-top: 20rpx;
}
}
}
</style>

179
pages/me/modifyNickname.vue Executable file
View File

@ -0,0 +1,179 @@
<template>
<view class="page">
<view class="line"></view>
<view class="single-line-box">
<input
class="nickname-input"
type="text"
:value="nickname"
:model="nickname"
placeholder="请填入昵称~"
maxlength="16"
@input="typingContent" />
<view class="length-cal">
<text class="length-text">{{ wordsLength }}/16</text>
</view>
</view>
<view class="notice" style="align-self: center">
<text class="tips">*请设置5-16的昵称长度</text>
</view>
</view>
</template>
<script>
import storage from "@/utils/storage.js"; //
import {
vlogModifyUserInfo
} from "@/api/vlog"
export default {
data() {
return {
oldNickname: storage.getVlogUserInfo().nickname,
nickname: storage.getVlogUserInfo().nickname,
wordsLength: 0,
};
},
onNavigationBarButtonTap() {
let nickname = this.nickname;
if (nickname.length < 5) {
uni.showToast({
icon: "none",
title: "昵称太短!",
});
return;
}
if (nickname.search(/\s/) != -1) {
uni.showToast({
icon: "none",
title: "不允许包含空格!",
});
return;
}
let oldNickname = this.oldNickname;
if (oldNickname == nickname) {
uni.showToast({
icon: "none",
title: "昵称未改变!",
});
return;
}
this.updateNickname();
},
onShow() {
this.wordsLength = this.nickname.length;
},
methods: {
async updateNickname() {
let me = this;
let userId = storage.getVlogUserInfo().id;
let nickname = this.nickname;
let pendingUserInfo = {
id: userId,
nickname: nickname,
type:1
};
//
var result = await vlogModifyUserInfo(pendingUserInfo,1)
console.log(result)
if (result.data.status == 200) {
let userInfoUpdated = result.data.data;
//
storage.setVlogUserInfo(userInfoUpdated);
uni.showToast({
title: result.data.msg,
icon: "none",
duration: 3000,
});
var timer = setTimeout(() => {
clearTimeout(timer)
uni.navigateBack({
delta: 1,
animationType: "fade-out",
});
}, 1000);
} else {
uni.showToast({
title: result.data.msg,
icon: "none",
duration: 3000,
});
}
},
typingContent(e) {
this.nickname = e.detail.value;
this.wordsLength = this.nickname.length;
},
},
};
</script>
<style lang="scss">
.page {
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
background-color: #181b27;
display: flex;
flex-direction: column;
justify-content: flex-start;
.line {
height: 1rpx;
background-color: #393a41;
width: 750rpx;
}
.single-line-box {
align-self: center;
display: flex;
flex-direction: row;
justify-content: flex-start;
padding: 30rpx;
margin-top: 20rpx;
.nickname-input {
padding-left: 20rpx;
color: #ffffff;
font-size: 28rpx;
width: 600rpx;
height: 100rpx;
background-color: #4a4c52;
border-top-left-radius: 20rpx;
border-bottom-left-radius: 20rpx;
}
.length-cal {
width: 100rpx;
height: 100rpx;
background-color: #4a4c52;
padding-right: 20rpx;
display: flex;
flex-direction: column;
justify-content: flex-end;
padding-bottom: 12rpx;
border-top-right-radius: 20rpx;
border-bottom-right-radius: 20rpx;
.length-text {
font-size: 24rpx;
font-weight: 400;
color: #f1f1f1;
}
}
}
.notice {
align-self: center;
.tips {
font-size: 24rpx;
font-weight: 400;
color: #bfbfbf;
width: 700rpx;
}
}
}
</style>

203
pages/me/modifySex.vue Executable file
View File

@ -0,0 +1,203 @@
<template>
<view class="page">
<view class="line"></view>
<view class="sex-box">
<view class="item" :class="{ 'sex-item': !boyTouched, 'sex-item-touched': boyTouched }"
@click="switchSex(1)" @touchstart="touchstartBoy" @touchend="touchendBoy"
style="border-top-left-radius: 40rpx; border-top-right-radius: 40rpx;">
<view class="left-sex-part">
<text class="left-sex"></text>
</view>
<view class="left-choose">
<image v-if="sex == 1" src="/static/images/icon-right.png" class="rightIcon"></image>
</view>
</view>
<view class="line" style="align-self: center"></view>
<view class="item" :class="{ 'sex-item': !girlTouched, 'sex-item-touched': girlTouched }"
@click="switchSex(0)" @touchstart="touchstartGirl" @touchend="touchendGirl">
<view class="left-sex-part">
<text class="left-sex"></text>
</view>
<view class="left-choose">
<image v-if="sex == 0" src="/static/images/icon-right.png" class="rightIcon"></image>
</view>
</view>
<view class="line" style="align-self: center"></view>
<view class="item" :class="{
'sex-item': !secretTouched,
'sex-item-touched': secretTouched,
}" @click="switchSex(2)" @touchstart="touchstartSecret" @touchend="touchendSecret"
style="border-bottom-left-radius: 40rpx; border-bottom-right-radius: 40rpx;">
<view class="left-sex-part">
<text class="left-sex">保密</text>
</view>
<view class="left-choose">
<image v-if="sex == 2" src="/static/images/icon-right.png" class="rightIcon"></image>
</view>
</view>
</view>
</view>
</template>
<script>
import storage from "@/utils/storage.js"; //
import {
vlogModifyUserInfo
} from "@/api/vlog"
export default {
data() {
return {
sex: storage.getVlogUserInfo().sex,
boyTouched: false,
girlTouched: false,
secretTouched: false,
};
},
onNavigationBarButtonTap() {
this.updateSex();
},
methods: {
async updateSex() {
let me = this;
let userId = storage.getVlogUserInfo().id
let sex = this.sex;
let pendingUserInfo = {
id: userId,
sex: sex,
type: 3
};
var result = await vlogModifyUserInfo(pendingUserInfo, 3)
if (result.data.status == 200) {
let userInfoUpdated = result.data.data;
//
storage.setVlogUserInfo(userInfoUpdated);
uni.showToast({
title: result.data.msg,
icon: "none",
duration: 3000,
});
var timer = setTimeout(() => {
clearTimeout(timer)
uni.navigateBack({
delta: 1,
animationType: "fade-out",
});
}, 1000);
} else {
uni.showToast({
title: result.data.msg,
icon: "none",
duration: 3000,
});
}
},
switchSex(sex) {
this.sex = sex;
},
touchstartBoy() {
this.boyTouched = true;
},
touchendBoy() {
this.boyTouched = false;
},
touchstartGirl() {
this.girlTouched = true;
},
touchendGirl() {
this.girlTouched = false;
},
touchstartSecret() {
this.secretTouched = true;
},
touchendSecret() {
this.secretTouched = false;
},
},
};
</script>
<style lang="scss">
.page {
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
background-color: #181b27;
dispaly: flex;
flex-direction: column;
.line {
height: 1rpx;
background-color: #393a41;
width: 750rpx;
}
.sex-box {
align-self: center;
width: 680rpx;
height: 400rpx;
display: flex;
margin: 0 auto;
flex-direction: column;
justify-content: center;
margin-top: 30rpx;
background-color: #4a4c52;
border-radius: 40rpx;
.item {
display: flex;
flex-direction: row;
justify-content: center;
align-self: center;
.left-sex-part {
width: 580rpx;
height: 120rpx;
display: flex;
flex-direction: row;
justify-content: flex-start;
.left-sex {
align-self: center;
margin-left: 30rpx;
color: #ffffff;
}
}
.left-choose {
width: 100rpx;
height: 120rpx;
display: flex;
flex-direction: row;
justify-content: flex-start;
.rightIcon {
align-self: center;
width: 60rpx;
height: 60rpx;
}
}
}
.line {
width: 680rpx;
background-color: #393a41;
height: 1rpx;
}
.sex-item {
background-color: #4a4c52;
height: 140rpx;
}
.sex-item-touched {
background-color: #6d6b6b;
height: 140rpx;
}
}
}
</style>

221
pages/me/modifyTioktokNum.vue Executable file
View File

@ -0,0 +1,221 @@
<template>
<view class="page">
<view class="line"></view>
<view class="limit-wrapper" v-if="!canIModify">
<text class="tips-limit">👉🏻 修改次数已达上限</text>
</view>
<view class="single-line-box">
<input
class="imoocNum-input"
type="text"
:value="imoocNum"
:model="imoocNum"
placeholder="请填入漂亮的视频号~"
maxlength="16"
:disabled="!canIModify"
@input="typingContent" />
<view class="length-cal">
<text class="length-text">{{ wordsLength }}/16</text>
</view>
</view>
<view class="notice">
<text class="tips">
*请设置5-16的视频号长度视频号只能修改一次噢~
</text>
</view>
</view>
</template>
<script>
import storage from "@/utils/storage.js"; //
import {
vlogModifyUserInfo
} from "@/api/vlog"
export default {
data() {
return {
oldimoocNum: storage.getVlogUserInfo().imoocNum,
imoocNum: storage.getVlogUserInfo().imoocNum,
wordsLength: 0,
canIModify: false, //
};
},
onNavigationBarButtonTap() {
let imoocNum = this.imoocNum;
if (imoocNum.length < 5) {
uni.showToast({
icon: "none",
title: "视频号过短!",
});
return;
}
if (imoocNum.search(/\s/) != -1) {
uni.showToast({
icon: "none",
title: "不允许包含空格!",
});
return;
}
let oldimoocNum = this.oldimoocNum;
if (oldimoocNum == imoocNum) {
uni.showToast({
icon: "none",
title: "视频号未改变!",
});
return;
}
let canIModify = this.canIModify;
if (canIModify == false) {
uni.showToast({
icon: "none",
title: "修改次数已达上限!",
});
return;
}
this.updateIMoocNum();
},
onLoad() {
this.canIModify = storage.getVlogUserInfo().canImoocNumBeUpdated == 1;
//
if (!this.canIModify) {
let pages = getCurrentPages();
let page = pages[pages.length - 1];
let currentWebview = page.$getAppWebview();
currentWebview.setTitleNViewButtonStyle(0, {
text: "0",
width: 0,
});
}
},
onShow() {
this.wordsLength = this.imoocNum.length;
},
methods: {
async updateIMoocNum() {
let me = this;
let userId = storage.getVlogUserInfo().id;
let imoocNum = this.imoocNum;
// ,
let pendingUserInfo = {
id: userId,
imoocNum: imoocNum,
type:2
};
var result = await vlogModifyUserInfo(pendingUserInfo,2)
if (result.data.status == 200) {
let userInfoUpdated = result.data.data;
//
storage.setVlogUserInfo(userInfoUpdated);
uni.showToast({
title: result.data.msg,
icon: "none",
duration: 3000,
});
var timer = setTimeout(() => {
clearTimeout(timer)
uni.navigateBack({
delta: 1,
animationType: "fade-out",
});
}, 1000);
} else {
uni.showToast({
title: result.data.msg,
icon: "none",
duration: 3000,
});
}
},
typingContent(e) {
this.imoocNum = e.detail.value;
this.wordsLength = this.imoocNum.length;
},
},
};
</script>
<style lang="scss">
.page {
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
background-color: #181b27;
display: flex;
flex-direction: column;
justify-content: flex-start;
.line {
height: 1rpx;
background-color: #393a41;
width: 750rpx;
}
.limit-wrapper {
align-self: center;
background-color: #333030;
height: 60rpx;
display: flex;
flex-direction: column;
justify-content: center;
.tips-limit {
font-size: 26rpx;
font-weight: 500;
color: #deb887;
width: 750rpx;
padding-left: 30rpx;
}
}
.single-line-box {
display: flex;
flex-direction: row;
justify-content: flex-start;
padding: 30rpx;
margin-top: 5rpx;
.imoocNum-input {
padding-left: 20rpx;
color: #ffffff;
font-size: 28rpx;
width: 600rpx;
height: 100rpx;
background-color: #4a4c52;
border-top-left-radius: 20rpx;
border-bottom-left-radius: 20rpx;
}
.length-cal {
width: 100rpx;
height: 100rpx;
background-color: #4a4c52;
padding-right: 20rpx;
display: flex;
flex-direction: column;
justify-content: flex-end;
padding-bottom: 12rpx;
border-top-right-radius: 20rpx;
border-bottom-right-radius: 20rpx;
.length-text {
font-size: 24rpx;
font-weight: 400;
color: #f1f1f1;
}
}
}
.notice {
align-self: center;
.tips {
font-size: 24rpx;
font-weight: 400;
color: #bfbfbf;
width: 700rpx;
}
}
}
</style>

170
pages/me/myBackImg.nvue Executable file
View File

@ -0,0 +1,170 @@
<template>
<view class="mpage">
<view class="mbg-wrapper" :style="{ height: screenHeight + 'px' }">
<image v-if="bgUrl" :src="bgUrl" class="bg-size" mode="aspectFill"></image>
<view
class="mbtn"
:class="{
'button-change-bg': !changeTouched,
'button-change-bg-touched': changeTouched,
}"
@touchstart="touchstartChange"
@touchend="touchendChange"
@click="changeBg">
<text class="btn-text">更换背景</text>
</view>
<view
class="mbtn"
:class="{
'button-change-bg': !closeTouched,
'button-change-bg-touched': closeTouched,
}"
@touchstart="touchstartClose"
@touchend="touchendClose"
@click="close"
style="margin-top: 10rpx">
<text class="btn-text">返回</text>
</view>
</view>
</view>
</template>
<script>
let system = uni.getSystemInfoSync();
import * as filters from "@/utils/filters.js"
import api from "@/config/api.js";
import storage from "@/utils/storage.js"; //缓存
export default {
data() {
return {
bgUrl: '',
changeTouched: false,
closeTouched: false,
screenHeight: system.safeArea.bottom,
};
},
onShow() {
if (filters.isLogin("auth")) {
this.bgUrl = storage.getVlogUserInfo().bgImg
console.log(this.bgUrl)
}
},
methods: {
close() {
uni.navigateBack({
delta: 1,
animationType: "slide-out-bottom",
});
},
touchstartClose() {
this.closeTouched = true;
},
touchendClose() {
this.closeTouched = false;
},
touchstartChange() {
this.changeTouched = true;
},
touchendChange() {
this.changeTouched = false;
},
changeBg() {
let me = this;
let info = storage.getVlogUserInfo()
let userId = info.id
uni.chooseImage({
count: 1,
sizeType: ["original"],
// crop: {
// quality: 100,
// width: 400,
// height: 400,
// },
success: (e) => {
let newBg = e.tempFilePaths[0];
me.bgUrl = newBg;
// 上传
let serverUrl = api.vlog
uni.uploadFile({
header: {
headerUserId: userId,
headerUserToken: storage.getVlogToken(),
},
url:
serverUrl + "/userInfo/modifyImage?userId=" + userId + "&type=1",
name: "file",
filePath: newBg,
success(result) {
// console.log(result)
let userInfoUpdated = JSON.parse(result.data);
if ((userInfoUpdated.status = 200)) {
// 重置本地用户信息
storage.setVlogUserInfo(userInfoUpdated.data);
uni.showToast({
title: userInfoUpdated.msg,
icon: "none",
duration: 3000,
});
let timer = setTimeout(() => {
uni.navigateBack({
delta: 1,
animationType: "fade-out",
});
clearTimeout(timer)
}, 1000);
} else {
uni.showToast({
title: result.data.msg,
icon: "none",
});
}
},
});
},
});
},
},
};
</script>
<style scoped>
.bg-size {
align-self: center;
width: 750rpx;
height: 750rpx;
}
.btn-text {
color: #ffffff;
align-self: center;
}
.mbtn {
width: 250rpx;
height: 80rpx;
border-radius: 100rpx;
display: flex;
flex-direction: column;
justify-content: center;
margin-top: 150rpx;
align-self: center;
}
.button-change-bg {
background-color: #1e1e1e;
}
.button-change-bg-touched {
background-color: #646262;
}
.bg-wrapper {
display: flex;
flex-direction: column;
justify-content: center;
}
.mpage {
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
background-color: #000000;
}
</style>

160
pages/me/myFace.vue Executable file
View File

@ -0,0 +1,160 @@
<template>
<view class="page">
<view class="bg-wrapper" :style="{ height: screenHeight + 'px' }">
<image :src="faceUrl" class="bg-size" mode="aspectFill"></image>
<view
class="mbtn"
:class="{
'button-change-bg': !changeTouched,
'button-change-bg-touched': changeTouched,
}"
@touchstart="touchstartChange"
@touchend="touchendChange"
@click="changeFace">
<text class="btn-text">更换头像</text>
</view>
<view
class="mbtn"
:class="{
'button-change-bg': !closeTouched,
'button-change-bg-touched': closeTouched,
}"
@touchstart="touchstartClose"
@touchend="touchendClose"
@click="close"
style="margin-top: 10rpx">
<text class="btn-text">返回</text>
</view>
</view>
</view>
</template>
<script>
import storage from "@/utils/storage.js"; //
let system = uni.getSystemInfoSync();
import api from "@/config/api.js";
export default {
data() {
return {
faceUrl: storage.getVlogUserInfo().face,
changeTouched: false,
closeTouched: false,
screenHeight: system.safeArea.bottom,
};
},
methods: {
close() {
uni.navigateBack({
delta: 1,
animationType: "slide-out-bottom",
});
},
touchstartChange() {
this.changeTouched = true;
},
touchendChange() {
this.changeTouched = false;
},
touchstartClose() {
this.closeTouched = true;
},
touchendClose() {
this.closeTouched = false;
},
changeFace() {
let me = this;
let userId = storage.getVlogUserInfo().id;
uni.chooseImage({
count: 1,
sizeType: ["original"],
crop: {
quality: 100,
width: 400,
height: 400,
},
success: (e) => {
let newFace = e.tempFilePaths[0];
me.faceUrl = newFace;
//
uni.uploadFile({
header: {
headerUserId: userId,
headerUserToken: storage.getVlogToken(),
},
url:
api.vlog + "/userInfo/modifyImage?userId=" + userId + "&type=2",
name: "file",
filePath: newFace,
success(result) {
let userInfoUpdated = JSON.parse(result.data);
if (userInfoUpdated.status == 200) {
//
storage.setVlogUserInfo(userInfoUpdated.data);
uni.showToast({
title: userInfoUpdated.msg,
icon: "none",
duration: 3000,
});
var timer = setTimeout(() => {
clearTimeout(timer)
uni.navigateBack({
delta: 1,
animationType: "fade-out",
});
}, 1000);
} else {
uni.showToast({
title: userInfoUpdated.msg,
icon: "none",
});
}
},
});
},
});
},
},
};
</script>
<style lang="scss">
.page {
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
background-color: #000000;
.bg-wrapper {
display: flex;
flex-direction: column;
justify-content: center;
.bg-size {
align-self: center;
width: 750rpx;
height: 750rpx;
}
.mbtn {
width: 250rpx;
height: 80rpx;
border-radius: 100rpx;
display: flex;
flex-direction: column;
justify-content: center;
margin-top: 150rpx;
align-self: center;
.btn-text {
color: #ffffff;
align-self: center;
}
}
.button-change-bg {
background-color: #1e1e1e;
}
.button-change-bg-touched {
background-color: #646262;
}
}
}
</style>

246
pages/me/myFans.nvue Executable file
View File

@ -0,0 +1,246 @@
<template>
<view class="mpage">
<view class="line"></view>
<scroll-view scroll-y="true" @scrolltolower="pagingFansList()">
<view class="user-wrapper" v-for="(f, index) in fansList" :key="index">
<view class="user-info" @click="goTovlogerInfo(f.fanId)">
<image class="face" :src="f.face" />
<text class="user-name">
{{ f.nickname }}
</text>
</view>
<view v-if="isLogin && f.me" class="operator-wrapper">
<text class="operator-words" style="color: #ffffff">你</text>
</view>
<view v-else-if="!isLogin || isLogin && !f.follow && !f.fan" class="operator-wrapper">
<text class="operator-words" style="color: #ffffff" @click="followMe(f.fanId)">
关注
</text>
</view>
<view v-else-if="isLogin && !f.follow && f.fan" class="operator-wrapper">
<text class="operator-words" style="color: #ffffff" @click="followMe(f.fanId)">
回粉
</text>
</view>
<view v-else-if="isLogin && f.follow && !f.fan" class="operator-wrapper">
<text class="operator-words" style="color: #ef274d" @click="cancelFollow(f.fanId)">
已关注
</text>
</view>
<view v-else-if="isLogin && f.follow && f.fan" class="operator-wrapper">
<text class="operator-words" style="color: #ef274d" @click="cancelFollow(f.fanId)">
互关
</text>
</view>
</view>
</scroll-view>
</view>
</template>
<script>
let system = uni.getSystemInfoSync();
import storage from "@/utils/storage.js"; //缓存
import {
vlogFansCancel,
vlogFansFollow,
vlogQueryMyFans
} from "@/api/vlog"
import {
isStrEmpty
} from '@/utils/tools.js'
export default {
data() {
return {
userId: "",
currentUserId: "",
isLogin: false,
screenHeight: 0,
page: 0,
totalPage: 0,
fansList: [],
};
},
onLoad(param) {
var uinfo = storage.getVlogUserInfo()
if (uinfo == null) {
return
}
this.isLogin = true;
this.currentUserId = uinfo.id
this.userId = param.userId;
this.queryMyFansList(0);
},
methods: {
goTovlogerInfo(vlogerId) {
// 是否是当前登录的用户
if (this.currentUserId == vlogerId) {
uni.switchTab({
url: "me",
});
} else {
uni.navigateTo({
url: "vlogerInfo?userPageId=" + vlogerId,
});
}
},
// 关注/取关后的list重新状态刷新设置
reFreshList(vlogerId, status) {
let me = this;
let fansList = me.fansList;
for (let i = 0; i < fansList.length; i++) {
let fan = fansList[i];
if (fan.fanId == vlogerId) {
fan.follow = status;
fansList.splice(i, 1, fan);
}
}
me.fansList = fansList;
},
async cancelFollow(vlogerId) {
let me = this;
let userId = storage.getVlogUserInfo().id
let data = {
myId: userId,
vlogerId
}
var result = await vlogFansCancel(data)
console.log(result)
if (result.data.status == 200) {
me.reFreshList(vlogerId, false);
} else {
uni.showToast({
title: result.data.msg,
icon: "none",
duration: 3000,
});
}
},
async followMe(vlogerId) {
let me = this;
let userId = this.currentUserId;
let data = {
myId: userId,
vlogerId
}
var result = await vlogFansFollow(data)
console.log(result)
if (result.data.status == 200) {
me.reFreshList(vlogerId, true);
} else {
uni.showToast({
title: result.data.msg,
icon: "none",
duration: 3000,
});
}
},
async queryMyFansList(page) {
let me = this;
page = page + 1;
let userId = me.userId;
let currentUserId = this.currentUserId;
var data = {
myId:userId,
// vlogerId: userId,
// currentUserId: currentUserId,
page: page,
pageSize: 10
}
var result = await vlogQueryMyFans(data)
if (result.data.status == 200) {
let fansList = result.data.data.rows;
let totalPage = result.data.data.total;
me.fansList = me.fansList.concat(fansList);
me.page = page;
me.totalPage = totalPage;
}
},
// 上滑分页粉丝列表
pagingFansList() {
if (this.page >= this.totalPage) {
return;
}
this.queryMyFansList(this.page);
},
},
};
</script>
<style scoped>
.user-info {
display: flex;
flex-direction: row;
justify-content: flex-start;
}
.face {
align-self: center;
width: 110rpx;
height: 110rpx;
border-radius: 100rpx;
border-width: 2rpx;
border-color: #f1f1f1;
}
.user-name {
align-self: center;
color: #ffffff;
font-size: 30rpx;
margin-left: 20rpx;
}
.line {
height: 1rpx;
background-color: #393a41;
width: 750rpx;
}
.mpage {
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
background-color: #181b27;
}
.user-wrapper {
padding-left: 30rpx;
padding-right: 30rpx;
width: 750rpx;
height: 120rpx;
display: flex;
flex-direction: row;
justify-content: space-between;
margin-top: 20rpx;
margin-bottom: 20rpx;
}
.operator-wrapper {
width: 140rpx;
height: 60rpx;
display: flex;
flex-direction: row;
justify-content: center;
background-color: #ef274d;
border-radius: 20rpx;
align-self: center;
border-width: 2rpx;
border-color: #ef274d;
background-color: #181b27;
}
.operator-words {
align-self: center;
font-size: 28rpx;
}
</style>

240
pages/me/myFollows.nvue Executable file
View File

@ -0,0 +1,240 @@
<template>
<view class="mpage">
<view class="line"></view>
<scroll-view scroll-y="true" @scrolltolower="pagingFollowsList">
<view class="user-wrapper" v-for="(f, index) in followsList" :key="index">
<view class="user-info" @click="goTovlogerInfo(f.vlogerId)">
<image class="face" :src="f.face" />
<text class="user-name">
{{ f.nickname }}
</text>
</view>
<view v-if="f.me" class="operator-wrapper">
<text class="operator-words" style="color: #ffffff">你</text>
</view>
<view v-else-if="!f.follow" class="operator-wrapper">
<text class="operator-words" style="color: #ffffff" @click="followMe(f.vlogerId)">
关注
</text>
</view>
<view v-else-if="f.follow && !f.fan" class="operator-wrapper">
<text class="operator-words" style="color: #ef274d" @click="cancelFollow(f.vlogerId)">
已关注
</text>
</view>
<view v-else-if="f.follow && f.fan" class="operator-wrapper">
<text class="operator-words" style="color: #ef274d" @click="cancelFollow(f.vlogerId)">
互关
</text>
</view>
</view>
</scroll-view>
</view>
</template>
<script>
import storage from "@/utils/storage.js"; //缓存
import {
vlogFansCancel,
vlogFansFollow,
vlogQueryMyFollows
} from "@/api/vlog"
import {
isStrEmpty
} from '@/utils/tools.js'
let system = uni.getSystemInfoSync();
export default {
data() {
return {
userId: "",
currentUserId: "",
screenHeight: 0,
page: 0,
totalPage: 0,
followsList: [],
};
},
onLoad(param) {
var uinfo = storage.getVlogUserInfo()
if (uinfo==null) {
return
}
this.currentUserId = uinfo.id
this.userId = param.userId;
this.queryMyFollowList(0);
},
methods: {
goTovlogerInfo(vlogerId) {
// 是否是当前登录的用户
if (this.currentUserId == vlogerId) {
uni.switchTab({
url: "me",
});
} else {
uni.navigateTo({
url: "vlogerInfo?userPageId=" + vlogerId,
});
}
},
// 关注, 取关后的list重新状态刷新设置
reFreshList(vlogerId, status) {
let me = this;
let followsList = me.followsList;
for (let i = 0; i < followsList.length; i++) {
let vloger = followsList[i];
if (vloger.vlogerId == vlogerId) {
vloger.follow = status;
followsList.splice(i, 1, vloger);
}
}
me.followsList = followsList;
},
async cancelFollow(vlogerId) {
let me = this;
let userId = this.currentUserId;
var data ={
myId: userId,
vlogerId
}
var result = await vlogFansCancel(data)
console.log(result)
if (result.data.status == 200) {
me.reFreshList(vlogerId, false);
} else {
uni.showToast({
title: result.data.msg,
icon: "none",
duration: 3000,
});
}
},
async followMe(vlogerId) {
let me = this;
let userId = this.currentUserId;
let data = {
myId: userId,
vlogerId
}
var result = await vlogFansFollow(data)
console.log(result)
if (result.data.status == 200) {
me.reFreshList(vlogerId, true);
} else {
uni.showToast({
title: result.data.msg,
icon: "none",
duration: 3000,
});
}
},
async queryMyFollowList(page) {
let me = this;
page = page + 1;
let userId = me.userId;
let currentUserId = this.currentUserId;
var data = {
myId:userId,
// vlogerId: userId,
// currentUserId: currentUserId,
page: page,
pageSize: 10
}
var result = await vlogQueryMyFollows(data)
if (result.data.status == 200) {
let followsList = result.data.data.rows;
let totalPage = result.data.data.total;
me.followsList = me.followsList.concat(followsList);
me.page = page;
me.totalPage = totalPage;
}
},
// 上滑分页粉丝列表
pagingFollowsList() {
if (this.page >= this.totalPage) {
return;
}
this.queryMyFollowList(this.page);
},
},
};
</script>
<style scoped>
.face {
align-self: center;
width: 110rpx;
height: 110rpx;
border-radius: 100rpx;
border-width: 2rpx;
border-color: #f1f1f1;
}
.user-name {
align-self: center;
color: #ffffff;
font-size: 30rpx;
margin-left: 20rpx;
}
.mpage {
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
background-color: #181b27;
}
.line {
height: 1rpx;
background-color: #393a41;
width: 750rpx;
}
.user-wrapper {
padding-left: 30rpx;
padding-right: 30rpx;
width: 750rpx;
height: 120rpx;
display: flex;
flex-direction: row;
justify-content: space-between;
margin-top: 20rpx;
margin-bottom: 20rpx;
}
.user-info {
display: flex;
flex-direction: row;
justify-content: flex-start;
}
.operator-wrapper {
width: 140rpx;
height: 60rpx;
display: flex;
flex-direction: row;
justify-content: center;
background-color: #ef274d;
border-radius: 20rpx;
align-self: center;
border-width: 2rpx;
border-color: #ef274d;
background-color: #181b27;
}
.operator-words {
align-self: center;
font-size: 28rpx;
}
</style>

248
pages/me/myInfo.vue Executable file
View File

@ -0,0 +1,248 @@
<template>
<view class="page">
<view class="line"></view>
<view class="face-box">
<image
class="user-face"
mode="aspectFill"
@click="changeMyFace"
:src="myInfo.face"></image>
</view>
<view class="single-line-box">
<text class="left-lable">昵称</text>
<view class="right-part" @click="modifyNickname">
<text class="right-content">
{{ myInfo.nickname }}
</text>
<image
class="right-arrow"
src="/static/images/icon-right-arrow2.png"></image>
</view>
</view>
<view class="single-line-box" @click="modifyTiktokNum">
<text class="left-lable">视频号</text>
<view class="right-part">
<text class="right-content">
{{ myInfo.imoocNum }}
</text>
<image
class="right-arrow"
src="/static/images/icon-right-arrow2.png"></image>
</view>
</view>
<view class="single-line-box">
<text class="left-lable">性别</text>
<view class="right-part" @click="modifySex">
<text v-if="myInfo.sex == 1" class="right-content"></text>
<text v-else-if="myInfo.sex == 0" class="right-content"></text>
<text v-else class="right-content">保密</text>
<image
class="right-arrow"
src="/static/images/icon-right-arrow2.png"></image>
</view>
</view>
<view class="single-line-box">
<text class="left-lable">生日</text>
<view class="right-part" @click="modifyBirthday">
<text class="right-content">
{{ getGraceDateStr(new Date(myInfo.birthday)) }}
</text>
<image
class="right-arrow"
src="/static/images/icon-right-arrow2.png"></image>
</view>
</view>
<view class="single-line-box">
<text class="left-lable">所在地</text>
<view class="right-part" @click="modifyLocation">
<text class="right-content">
{{ myInfo.province == myInfo.city ? "" : myInfo.province + "·"
}}{{ myInfo.city == "" ? "" : myInfo.city
}}{{ myInfo.district == "" ? "" : "·" + myInfo.district }}
</text>
<image
class="right-arrow"
src="/static/images/icon-right-arrow2.png"></image>
</view>
</view>
<view class="single-line-box">
<text class="left-lable">简介</text>
<view class="right-part" @click="modifyDescription">
<text class="right-content">
{{ myInfo.description }}
</text>
<image
class="right-arrow"
src="/static/images/icon-right-arrow2.png"></image>
</view>
</view>
<!-- <view class="single-line-box">
<text class="left-lable">修改密码</text>
<view class="right-part" @click="modifyPassword">
<text class="right-content">我猜你忘记密码了~</text>
<image
class="right-arrow"
src="/static/images/icon-right-arrow2.png"></image>
</view>
</view> -->
</view>
</template>
<script>
import storage from "@/utils/storage.js"; //
import api from "@/config/api.js";
import {
isStrEmpty,
dateFormat
} from '@/utils/tools.js'
export default {
data() {
return {
myInfo: {},
};
},
onShow() {
let myInfo = storage.getVlogUserInfo()
if (isStrEmpty(myInfo.face)) {
//
myInfo.face = "";
}
this.myInfo = myInfo;
},
methods: {
getGraceDateStr(date) {
return dateFormat("YYYY-mm-dd", date);
},
//
changeMyFace() {
uni.navigateTo({
animationType: "fade-in",
url: "myFace",
});
},
//
modifyNickname() {
uni.navigateTo({
animationType: "fade-in",
url: "modifyNickname",
});
},
//
modifyTiktokNum() {
uni.navigateTo({
animationType: "fade-in",
url: "modifyTioktokNum",
});
},
//
modifySex() {
uni.navigateTo({
animationType: "fade-in",
url: "modifySex",
});
},
//
modifyBirthday() {
uni.navigateTo({
animationType: "fade-in",
url: "modifyBirthday",
});
},
//
modifyLocation() {
uni.navigateTo({
animationType: "fade-in",
url: "modifyLocation",
});
},
//
modifyDescription() {
uni.navigateTo({
animationType: "fade-in",
url: "modifyDesc",
});
},
//
modifyPassword() {
uni.navigateTo({
animationType: "fade-in",
url: "modifyPass",
});
},
},
};
</script>
<style lang="scss" scoped>
.page {
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
background-color: #181b27;
.line {
height: 1rpx;
background-color: #393a41;
width: 750rpx;
}
.face-box {
display: flex;
flex-direction: row;
justify-content: center;
margin-top: 80rpx;
margin-bottom: 80rpx;
.user-face {
width: 200rpx;
height: 200rpx;
border-radius: 100rpx;
border-width: 2rpx;
border-color: #f1f1f1;
}
}
.single-line-box {
display: flex;
flex-direction: row;
justify-content: space-between;
padding: 30rpx;
.left-lable {
align-self: center;
color: #ffffff;
font-size: 30rpx;
font-weight: 500;
}
.right-part {
display: flex;
flex-direction: row;
justify-content: flex-end;
.right-content {
align-self: center;
color: #bfbfbf;
font-size: 30rpx;
font-weight: 300;
}
.right-arrow {
align-self: center;
width: 32rpx;
height: 32rpx;
margin-left: 20rpx;
}
}
}
}
</style>

87
pages/me/vlog.vue Executable file
View File

@ -0,0 +1,87 @@
<template>
<view class="mpage">
<swiper style="my-swiper" :style="{ height: screenHeight + 'px' }">
<swiper-item>
<video-detail
:screenHeight="screenHeight"
:playStatus="playStatus"
:vlogId="vlogId"></video-detail>
</swiper-item>
</swiper>
<view class="mheader" :style="{ marginTop: statusBarHeight + 'px' }">
<image
class="header-left"
src="/static/images/icon-back.png"
@click="back()" />
</view>
</view>
</template>
<script>
let system = uni.getSystemInfoSync();
import videoDetail from "@/components/vlog/videoDetail.vue";
export default {
components: {
videoDetail,
},
data() {
return {
vlogId: "",
playStatus: true,
screenHeight: 0,
statusBarHeight: 0,
};
},
onLoad(option) {
this.statusBarHeight = system.statusBarHeight;
let screenHeight = system.safeArea.bottom + 50;
this.screenHeight = screenHeight;
//
let vlogId = option.vlogId||1;
this.vlogId = vlogId;
},
onHide() {
// TODO
},
methods: {
back() {
uni.navigateBack({
delta: 1,
});
},
},
};
</script>
<style scoped>
.mpage {
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
background-color: #000000;
}
.mheader {
position: absolute;
left: 0;
right: 0;
flex-direction: row;
height: 100rpx;
line-height: 100rpx;
align-items: center;
padding-left: 40rpx;
padding-right: 40rpx;
}
.header-left {
color: #999;
line-height: 100rpx;
align-items: flex-start;
justify-content: flex-end;
font-family: iconfont;
width: 40rpx;
height: 40rpx;
opacity: 0.8;
}
</style>

View File

@ -1,724 +0,0 @@
<template>
<view class="page">
<scroll-view
class="isLogin-info-wrapper"
:style="{ height: screenHeight + 'px' }"
scroll-y="true"
@scrolltolower="loadMore">
<image class="mybg" :src="pageUserInfo.bgImg" mode="aspectFill" />
<!-- 安卓下使用一个灰色图片来替代阴影效果, ios支持阴影, 安卓则不支持 -->
<!-- <image
v-if="isAndroid"
:src="pageUserInfo.bgImg"
mode="aspectFill"
style="width: 750rpx; height: 750rpx; opacity: 0.5" /> -->
<view class="header" :style="{ marginTop: statusBarHeight + 'px' }">
<image
class="header-right-search"
src="../../static/images/icon-back.png"
@click="back()" />
</view>
<view class="my-info-wrapper">
<view class="my-info">
<image :src="pageUserInfo.face" mode="aspectFill" class="my-face" />
<view class="info-wrapper">
<text class="nickname">
{{ pageUserInfo.nickname }}
</text>
<view class="tiktok-num-wrapper">
<text class="tiktok-num">视频号:</text>
<text class="tiktok-num">
{{ pageUserInfo.tiktokNum }}
</text>
</view>
<view class="location">
<text class="location-text">所在地:</text>
<text class="location-text">
{{ pageUserInfo.city == "" ? "中国" : "" + pageUserInfo.city
}}{{
pageUserInfo.district == "" ? "" : "·" + pageUserInfo.district
}}
</text>
</view>
<view class="sex-wrapper">
<view class="constellation">
<image
class="sex-img"
v-if="pageUserInfo.sex == 1"
src="../../static/images/icon-sex-boy.png" />
<image
class="sex-img"
v-if="pageUserInfo.sex == 0"
src="../../static/images/icon-sex-girl.png" />
<image
class="sex-img"
v-if="pageUserInfo.sex == 2"
src="../../static/images/icon-sex-secret.png" />
<text class="astro">{{ astro }}座</text>
</view>
<view class="animal">
<text class="animal-text">
{{ animal }}
</text>
</view>
</view>
</view>
</view>
</view>
<text class="desc">
{{ pageUserInfo.description }}
</text>
<view class="bottom-wrapper">
<view class="bottom">
<view class="bottom-item" @click="goMyFollows(pageUserInfo.id)">
<text class="item-num">
{{ getGraceNumber(pageUserInfo.myFollowsCounts) }}
</text>
<text class="item-text">关注</text>
</view>
<view class="bottom-item" @click="goMyFans(pageUserInfo.id)">
<text class="item-num">
{{ getGraceNumber(pageUserInfo.myFansCounts) }}
</text>
<text class="item-text">粉丝</text>
</view>
<view class="bottom-item">
<text class="item-num">
{{ getGraceNumber(pageUserInfo.totalLikeMeCounts) }}
</text>
<text class="item-text">获赞</text>
</view>
</view>
<view class="edit">
<view
v-if="isFollow && !isFan"
@click="cancelFollow()"
class="follow-btn">
<text class="follow-text">已关注</text>
</view>
<view
v-if="isFollow && isFan"
@click="cancelFollow()"
class="follow-btn">
<text class="follow-text">相互关注</text>
</view>
<view
v-if="!isFollow"
@click="followMe()"
class="follow-btn"
style="background-color: #ef274d">
<text class="follow-text">关注我</text>
</view>
</view>
</view>
<view class="tab-wrapper">
<view class="tab-item" @click="switchTab(0)">
<text class="tab-normal" :class="{ 'tab-selected': currentTab == 0 }">
作品
</text>
<view v-if="currentTab == 0" class="selected-tab"></view>
</view>
<view class="tab-item" @click="switchTab(1)">
<text class="tab-normal" :class="{ 'tab-selected': currentTab == 1 }">
私密
</text>
<view v-if="currentTab == 1" class="selected-tab"></view>
</view>
<view class="tab-item" @click="switchTab(2)">
<text class="tab-normal" :class="{ 'tab-selected': currentTab == 2 }">
赞过
</text>
<view v-if="currentTab == 2" class="selected-tab"></view>
</view>
</view>
<view class="vlog-list">
<block v-for="(vlog, index) in vlogList" :key="index">
<image
class="vlog-cover"
:src="vlog.cover"
@click="goToVlog(vlog)"
mode="aspectFill"></image>
</block>
</view>
<view v-if="vlogList.length == 0" class="empty">
<text class="empty-text">~ 空空如也 ~</text>
</view>
<view v-if="vlogList.length > 0" class="not-empty">
<text class="not-empty-text">~ 没有更多了 ~</text>
</view>
</scroll-view>
</view>
</template>
<script>
let system = uni.getSystemInfoSync();
const app = getApp();
export default {
data() {
return {
pageUserInfo: {},
userPageId: "",
astro: "",
animal: "",
loginWords: "请登录",
statusBarHeight: 0,
screenHeight: 0,
screenHeightUnLogin: 0,
currentTab: 0,
isFollow: false,
isFan: false,
isAndroid: uni.getSystemInfoSync().platform == "android",
page: 0,
totalpage: 0,
vlogList: [],
};
},
onLoad(params) {
this.statusBarHeight = system.statusBarHeight;
let screenHeight = system.safeArea.bottom + 50;
this.screenHeight = screenHeight;
let screenHeightUnLogin = system.safeArea.bottom;
this.screenHeightUnLogin = screenHeightUnLogin;
let me = this;
// 从视频页面, 点击用户头像传递过来的id
let userPageId = params.userPageId;
if (app.isStrEmpty(userPageId)) {
uni.showToast({
title: "出错啦~",
icon: " none",
duration: 2000,
});
settimeout(() => {
uni.navigateBack({
delta: 1,
});
}, 1500);
}
me.userPageId = userPageId;
let serverUrl = app.globalData.serverUrl;
// 查询用户信息
uni.request({
method: "GET",
url: serverUrl + "/userInfo/query?userId=" + userPageId,
success(result) {
if (result.data.status == 200) {
me.pageUserInfo = result.data.data;
me.setBasicUserInfo(me.pageUserInfo);
} else {
uni.showToast({
title: result.data.msg,
icon: "none",
duration: 3000,
});
}
},
});
this.switchTab(0);
let myUserId = "";
if (!app.isStrEmpty(app.getUserInfoSession())) {
myUserId = app.getUserInfoSession().id;
}
if (!app.isStrEmpty(myUserId)) {
// 查询用户是否关注博主
uni.request({
method: "GET",
header: {
headerUserId: myUserId,
headerUserToken: app.getUserSessionToken(),
},
url:
serverUrl +
"/fans/queryRelationship?myId=" +
myUserId +
"&vlogerId=" +
userPageId,
success(result) {
if (result.data.status == 200) {
me.isFollow = result.data.data.follow;
me.isFan = result.data.data.fan;
} else {
uni.showToast({
title: result.data.msg,
icon: "none",
duration: 3000,
});
}
},
});
}
},
methods: {
setBasicUserInfo(myUserInfo) {
if (app.isStrEmpty(myUserInfo.bgImg)) {
myUserInfo.bgImg = "http://120.26.164.63:9000/tiktok/IMG_4566.HEIC";
}
if (app.isStrEmpty(myUserInfo.face)) {
myUserInfo.face = "http://120.26.164.63:9000/tiktok/IMG_4845.JPG";
}
// 根据生日判断星座
let birthday = myUserInfo.birthday;
let birth = app.dateFormat("YYYY-mm-dd", new Date(birthday));
let birthArr = birth.split("-");
let year = birthArr[0];
let month = birthArr[1];
let day = birthArr[2];
let astro = app.getAstro(month, day);
this.astro = astro;
// 根据生日判断生肖
let animal = app.getAnimal(year);
this.animal = animal;
},
switchTab(index) {
this.currentTab = index;
if (index == 0) {
this.vlogList = [];
this.page = 0;
this.toalPage = 0;
this.myList(0,'myPublicList');
} else if (index == 1) {
this.vlogList = [];
} else if (index == 2) {
this.vlogList = [];
this.page = 0;
this.toalPage = 0;
this.myList(2,'myLikedList');
}
},
loadMore() {
let requestArr = ['myPublicList','myPrivateList','myLikedList']
if (this.page >= this.toalPage) {
return;
} else {
this.myList(this.page,requestArr[this.currentTab]);
}
},
myList(page,requrl) {
let me = this;
page = page + 1;
me.page = page;
let vlogerId = me.userPageId;
let serverUrl = app.globalData.serverUrl;
uni.request({
method: "GET",
url:`${serverUrl}/vlog/${requrl}`,
data:{
userId:vlogerId,
page,
pageSize:20
},
success(result) {
if (result.data.status == 200) {
let vlogList = result.data.data.rows;
let toalPage = result.data.data.total;
me.vlogList = me.vlogList.concat(vlogList);
me.page = page;
me.toalPage = toalPage;
}
},
});
},
back() {
uni.navigateBack({
delta: 1,
});
},
cancelFollow() {
let me = this;
let vlogerId = me.userPageId;
let userId = getApp().getUserInfoSession().id;
let serverUrl = app.globalData.serverUrl;
uni.request({
method: "POST",
header: {
headerUserId: userId,
headerUserToken: app.getUserSessionToken(),
},
url:
serverUrl + "/fans/cancel?myId=" + userId + "&vlogerId=" + vlogerId,
success(result) {
if (result.data.status == 200) {
me.isFollow = false;
uni.setStorageSync("justCancelVlogerId", vlogerId);
// 刷新当前页的粉丝数
let pendingInfo = me.pageUserInfo;
me.pageUserInfo.myFansCounts = pendingInfo.myFansCounts - 1;
} else {
uni.showToast({
title: result.data.msg,
icon: "none",
duration: 3000,
});
}
},
});
},
// 关注
followMe() {
let me = this;
let myUserInfo = getApp().getUserInfoSession();
if (app.isStrEmpty(myUserInfo)) {
uni.showToast({
duration: 3000,
title: "请登录后再进行操作~",
icon: "none",
});
uni.switchTab({
url: "me",
});
uni.navigateTo({
url: "../loginRegist/loginRegist",
animationType: "slide-in-bottom",
success() {
me.loginWords = "请登录";
},
});
return;
}
let vlogerId = me.userPageId;
let userId = myUserInfo.id;
let serverUrl = app.globalData.serverUrl;
uni.request({
method: "POST",
header: {
headerUserId: userId,
headerUserToken: app.getUserSessionToken(),
},
url:
serverUrl + "/fans/follow?myId=" + userId + "&vlogerId=" + vlogerId,
success(result) {
if (result.data.status == 200) {
me.isFollow = true;
uni.setStorageSync("justFollowVlogerId", vlogerId);
// 刷新当前页的粉丝数
let pendingInfo = me.pageUserInfo;
me.pageUserInfo.myFansCounts = pendingInfo.myFansCounts + 1;
} else {
uni.showToast({
title: result.data.msg,
icon: "none",
duration: 3000,
});
}
},
});
},
// 把超过1000或10000的数字调整, 比如1.3k/6.8w
getGraceNumber(num) {
return getApp().graceNumber(num);
},
goToVlog(vlog) {
let vlogId = vlog.id ? vlog.id : vlog.vlogId;
uni.navigateTo({
url: "../vlog/vlog?type=mine&isNeedPage=1&vlogId=" + vlogId,
});
},
goMyFans(userId) {
uni.navigateTo({
animationType: "fade-in",
url: "myFans?userId=" + userId,
});
},
goMyFollows(userId) {
uni.navigateTo({
animationType: "fade-in",
url: "myFollows?userId=" + userId,
});
},
},
};
</script>
<style lang="scss">
.page {
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
background-color: #000000;
.isLogin-info-wrapper {
.header {
position: absolute;
left: 0;
right: 0;
flex-direction: row;
height: 100rpx;
line-height: 100rpx;
align-items: center;
padding-left: 40rpx;
padding-right: 40rpx;
.header-right-search {
width: 40rpx;
height: 40rpx;
opacity: 0.8;
}
}
.mybg {
width: 750rpx;
height: 750rpx;
box-shadow: inset 0 -150px 180px #313030;
}
.my-info-wrapper {
position: relative;
left: 30rpx;
top: -560rpx;
display: flex;
flex-direction: column;
width: 1000rpx;
.my-info {
display: flex;
flex-direction: row;
.my-face {
width: 200rpx;
height: 200rpx;
border-radius: 100rpx;
border-width: 1px;
border-color: #f1f1f1;
}
.info-wrapper {
margin-left: 30rpx;
padding-top: 20rpx;
width: 500rpx;
.nickname {
font-size: 20px;
color: #ffffff;
font-weight: 600;
}
.tiktok-num-wrapper {
display: flex;
flex-direction: row;
.tiktok-num {
font-size: 10px;
color: #ffffff;
font-weight: 300;
}
}
.location {
display: flex;
flex-direction: row;
height: 20px;
margin-top: 2px;
font-size: 1px;
.location-text {
line-height: 20px;
color: #ffffff;
font-size: 10px;
font-weight: 300;
}
}
.sex-wrapper {
display: flex;
flex-direction: row;
margin-top: 10rpx;
.constellation {
display: flex;
flex-direction: row;
justify-content: center;
background-color: #000000;
opacity: 0.5;
width: 130rpx;
height: 40rpx;
border-radius: 10px;
.sex-img {
width: 22rpx;
height: 22rpx;
align-self: center;
}
.astro {
font-size: 10px;
color: #ffffff;
line-height: 20px;
font-weight: bold;
margin-left: 6rpx;
align-self: center;
}
}
.animal {
margin-left: 10rpx;
display: flex;
flex-direction: row;
justify-content: center;
background-color: #000000;
opacity: 0.5;
width: 60rpx;
height: 40rpx;
border-radius: 10px;
.animal-text {
font-size: 10px;
color: #ffffff;
line-height: 20px;
font-weight: bold;
align-self: center;
}
}
}
}
}
}
.desc {
position: relative;
top: -520rpx;
color: #ffffff;
font-size: 14px;
margin: 0 30rpx;
}
.bottom-wrapper {
position: relative;
top: -510rpx;
display: flex;
flex-direction: row;
justify-content: space-between;
.bottom {
display: flex;
flex-direction: row;
.bottom-item {
margin-left: 30rpx;
display: flex;
flex-direction: column;
justify-content: center;
.item-num {
color: #ffffff;
font-size: 14px;
font-weight: bold;
align-self: center;
}
.item-text {
color: #ffffff;
font-size: 12px;
font-weight: 300;
align-self: center;
}
}
}
.edit {
display: flex;
flex-direction: row;
justify-content: center;
margin-right: 30rpx;
.follow-btn {
margin-right: 20rpx;
border-width: 1px;
border-color: #ffffff;
width: 200rpx;
height: 66rpx;
background-color: #545456;
opacity: 0.8;
border-radius: 40rpx;
display: flex;
flex-direction: row;
justify-content: center;
align-self: center;
.follow-text {
font-size: 13px;
color: #ffffff;
font-weight: 500;
align-self: center;
}
}
}
}
.tab-wrapper {
position: relative;
top: -480rpx;
height: 40px;
background-color: #171825;
display: flex;
flex-direction: row;
justify-content: space-between;
padding-top: 3px;
border-top-left-radius: 12px;
border-top-right-radius: 12px;
.tab-item {
width: 250rpx;
align-self: center;
.tab-normal {
font-size: 18px;
font-weight: 500;
align-self: center;
color: #808080;
}
.tab-selected {
color: #ffffff;
}
.selected-tab {
margin-top: 5px;
height: 5rpx;
width: 250rpx;
border-radius: 6rpx;
background-color: #ef274d;
}
}
}
.vlog-list {
position: relative;
top: -480rpx;
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: flex-start;
background-color: #000000;
.vlog-cover {
align-self: center;
width: 248rpx;
height: 360rpx;
border-width: 1rpx;
}
}
.empty {
background-color: #000000;
width: 750rpx;
height: 300rpx;
display: flex;
flex-direction: row;
justify-content: center;
position: relative;
top: -480rpx;
.empty-text {
color: #ffffff;
font-size: 14px;
margin-top: 200rpx;
}
}
.not-empty {
width: 750rpx;
display: flex;
flex-direction: row;
justify-content: center;
position: relative;
top: -260rpx;
.not-empty-text {
color: #ffffff;
font-size: 14px;
}
}
}
}
</style>

0
pages/me/vlogerInfo.vue Executable file
View File

View File

@ -1,7 +1,7 @@
<template>
<div class="wrapper">
<div v-if="!wechatLogin">
<u-navbar :is-back="true" :border-bottom="false"></u-navbar>
<u-navbar :is-back="true" :border-bottom="false" :custom-back="customback"></u-navbar>
<div>
<div class="title">{{ loginTitleWay[current].title }}</div>
<div :class="current == 1 ? 'desc-light' : 'desc'">
@ -143,9 +143,11 @@
title: "Apple",
code: "APPLE",
},
],
],
initurl:false
};
},
},
onShow() {
//#ifdef H5
let isWXBrowser = /micromessenger/i.test(navigator.userAgent);
@ -282,13 +284,26 @@
}
},
},
onLoad(options) {
onLoad(options) {
if(options.init=='index'){
this.initurl = true
}
console.log((options))
if (options && options.state) {
this.stateLogin(options.state);
}
}
},
methods: {
methods: {
customback(){
if(this.initurl){
uni.switchTab({
url:'/pages/tabbar/vlog/index?init=ok'
})
}else{
uni.navigateBack()
}
},
//
stateLogin(state) {
loginCallback(state).then((res) => {

View File

@ -1,7 +1,7 @@
<template>
<view class="page">
<view class="prpage">
<video
class="video"
class="prvideo"
:style="{ height: screenSafeHeight + 'px' }"
:src="videoUrl"
autoplay="true"
@ -39,17 +39,16 @@ export default {
};
</script>
<style lang="scss">
.page {
<style scoped>
.prpage {
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
background-color: #181b27;
.video {
width: 750rpx;
}
}
.prvideo {
width: 750rpx;
}
</style>

View File

@ -10,7 +10,8 @@
<!-- 发布主体内容 -->
<view class="main-body" v-if="percentCompleted == 100">
<image class="main-body-img" :src="tempCover" mode="widthFix" />
<image class="main-body-img-m" v-if="tempCover" :src="tempCover" mode="widthFix" />
<image class="main-body-img-m" v-if="!tempCover" src='/static/images/loading-4.gif' mode="aspectFit" />
<view class="main-body-content">
<view class="preplay-wrapper" @click="preview" @touchstart="touchstartPreplay"
@touchend="touchendPreplay">
@ -23,12 +24,12 @@
</view>
<textarea class="vlog-content" placeholder-style="color: #9798a0;" placeholder="添加合适的描述内容~" :value="title"
:model="title" maxlength="60" @input="typingContent" confirm-type="done"></textarea>
<view class="btn" :class="{
'btn-publish': !publishTouched,
'btn-publish-touched': publishTouched,
}" @touchstart="touchstartPublish" @touchend="touchendPublish" @click="doPublich">
<text class="btn-text">发布视频</text>
</view>
<view class="mbtn" :class="{
'btn-publish': !publishTouched,
'btn-publish-touched': publishTouched,
}" @touchstart="touchstartPublish" @touchend="touchendPublish" @click="doPublich">
<text class="btn-text">发布视频</text>
</view>
</view>
</scroll-view>
</template>
@ -240,29 +241,30 @@
right: 0;
top: 0;
bottom: 0;
background-color: #181b27;
background-color: #181b27;
}
.main-body-img {
.main-body-img-m {
min-height: 400rpx;
/* width: 750rpx; */
flex: 1;
border: 2rpx solid #545456;
border-radius: 20rpx;
align-self: center;
align-items: center;
}
.choose-cover-text {
color: #ffffff;
font-size: 28rpx;
align-self: center;
align-items: center;
}
.choose-cover {
display: flex;
flex-direction: column;
justify-content: center;
margin-left: 100rpx;
margin-left: 100rpx;
margin-top: 10px;
width: 200rpx;
height: 100rpx;
position: relative;
@ -273,13 +275,13 @@
.preplay-icon {
width: 22rpx;
height: 22rpx;
align-self: center;
align-items: center;
}
.preplay-text {
color: #e6e6e6;
font-size: 28rpx;
align-self: center;
align-items: center;
margin-left: 15rpx;
}
@ -292,7 +294,7 @@
}
.main-body-content {
display: flex;
/* display: flex; */
flex-direction: row;
justify-content: flex-start;
@ -314,30 +316,34 @@
.btn-text {
color: #e6e6e6;
font-size: 36rpx;
align-self: center;
align-items: center;
font-weight: 500;
}
.btn {
.mbtn {
margin-top: 30rpx;
height: 90rpx;
display: flex;
justify-content: center;
border-radius: 40rpx;
/* display: flex; */
justify-content: center;
align-items: center;
border-radius: 40rpx;
border: transparent;
}
.btn-publish {
background-color: #ef274d;
background-color: #ef274d;
overflow: hidden;
}
.btn-publish-touched {
background-color: #de6981;
background-color: #de6981;
overflow: hidden;
}
.main-body {
margin-top: 20rpx;
padding: 0 20rpx;
}
.line {
@ -347,7 +353,7 @@
}
.progress {
margintop: 60rpx;
margin-top: 60rpx;
display: flex;
flex-direction: column;
justify-content: center;
@ -364,6 +370,6 @@
.progress-img {
width: 600rpx;
height: 600rpx;
align-self: center;
align-items: center;
}
</style>

View File

@ -1,285 +1,3 @@
<template>
<div style="height: 100%">
<div class="jolkp">
<div class="fan" :style="{ marginRight: statue == 0 ? '56%' : '70%' }">
<span @click="hui(0)">消息</span>
</div>
<!-- <TUIContact v-else-if="statue==1" :stu="2" /> -->
<div @click="hui(1)" class="jolkp_h" v-if="statue == 0"></div>
<div @click="fnkiopl" class="jolkp_l"></div>
<!-- 弹出框 -->
<div v-if="isPopupVisible" class="popup">
<ul>
<li @click="handleAddFriend">添加好友/群聊</li>
<li @click="handleMenu()">发起群聊</li>
<li>扫一扫</li>
</ul>
</div>
</div>
<div class="three">
<div class="con">
<div class="three_div1"></div>
<div class="title">点赞</div>
</div>
<div class="con">
<div class="three_div2"></div>
<div class="title">关注</div>
</div>
<div class="con">
<div class="three_div3"></div>
<div class="title">评论</div>
</div>
</div>
<!-- 搜索添加 -->
<TUIContactsea v-if="statue == 2" />
<!-- 联系人 -->
<TUIContact v-else-if="statue == 1" />
<SelectFriend v-else-if="statue == 3" @con="confn" />
<SelectFriendqlioa v-else-if="statue == 4" @concen="concen" />
<!-- 会话 -->
<TUIConversation v-else />
</div>
</template>
<script>
//
import TUIConversation from "@/TUIKit/components/TUIConversation/index";
import TUIContact from "@/TUIKit/components/TUIContact/index";
import TUIContactsea from "@/TUIKit/components/TUIContact/indexsea";
import { TUILogin } from "@tencentcloud/tui-core";
import ContactSearch from "@/TUIKit/components/TUIContact/contact-search/index.vue";
import { TUIChatKit } from "@/TUIKit";
import SelectFriend from "@/TUIKit/components/TUIContact/select-friend/index.vue";
import SelectFriendqlioa from "@/TUIKit/components/TUIGroup/index.vue";
import TUICore, { ExtensionInfo, TUIConstants } from "@tencentcloud/tui-core";
import storage from "@/utils/storage.js";
import { getUserimInfo } from "@/api/members";
TUIChatKit.init();
let vueVersion = 2;
// vueVersion = 3;
export default {
//
components: {
TUIConversation,
TUIContact,
TUIContactsea,
ContactSearch,
SelectFriend,
SelectFriendqlioa,
TUIChatKit,
},
data() {
return {
statue: 0, //1 2/ 0 3 4
isPopupVisible: false, //
isq: false,
};
},
created() {},
onShow() {
//
//
getUserimInfo()
.then(({ data }) => {
console.log(data)
if (data.code == 200) {
console.log(data);
const par = data.result;
uni.$SDKAppID = par.sdkAppId; // Your SDKAppID
uni.$userID = par.userID; // Your userID
uni.$userSig = par.userSig;
TUILogin.login({
SDKAppID: uni.$SDKAppID,
userID: uni.$userID,
userSig: uni.$userSig,
useUploadPlugin: true, // If you need to send rich media messages, please set to true.
framework: `vue${vueVersion}`, // framework used vue2 / vue3
});
} else {
// 200
uni.navigateTo({
url: "/pages/passport/login",
});
}
})
.catch(() => {
//
uni.navigateTo({
url: "/pages/passport/login",
});
});
},
mounted() {},
methods: {
//
confn() {
this.statue = 4;
},
concen() {
this.statue = 0;
this.isPopupVisible = false;
},
hui(index) {
this.statue = index;
},
fnkiopl() {
this.isPopupVisible = !this.isPopupVisible;
},
handleMenu() {
const fn = [
...TUICore.getExtensionList(
TUIConstants.TUISearch.EXTENSION.SEARCH_MORE.EXT_ID
),
];
const item = fn[1];
const {
listener = {
onClicked: () => {},
},
} = item;
listener?.onClicked?.(item);
this.statue = 3;
},
// /
handleAddFriend() {
this.statue = 2;
this.isPopupVisible = false;
},
// //
// openConversationList() {
// uni.navigateTo({
// url: '/TUIKit/components/TUIConversation/index'
// });
// },
// //
// openContact() {
// uni.navigateTo({
// url: '/TUIKit/components/TUIContact/index'
// });
// },
},
};
</script>
<style>
.jolkp {
height: 66px;
display: flex;
font-size: 15px;
justify-content: end;
/* 设置背景图 */
background-image: url("@/static/im/Rectangle.png");
/* 让背景图覆盖整个元素 */
background-size: cover;
/* 背景图不重复 */
background-repeat: no-repeat;
}
.jolkp_l {
width: 2rem;
height: 2rem;
background-image: url("@/static/im/Frame.png");
/* 让背景图覆盖整个元素 */
background-size: cover;
/* 背景图不重复 */
background-repeat: no-repeat;
margin-top: 35px;
margin-right: 20px;
}
.jolkp_h {
width: 2rem;
height: 2rem;
background-image: url("@/static/im/user.png");
/* 让背景图覆盖整个元素 */
background-size: cover;
/* 背景图不重复 */
background-repeat: no-repeat;
margin-top: 35px;
margin-right: 20px;
}
.popup {
position: absolute;
top: 65px;
/* 调整弹出框的位置 */
right: 5px;
background-color: #fff;
border: 1px solid #ccc;
border-radius: 4px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
z-index: 3;
}
.popup ul {
list-style-type: none;
padding: 0;
margin: 0;
}
.popup li {
padding: 10px 20px;
cursor: pointer;
}
.popup li:hover {
background-color: #f0f0f0;
}
.fan {
width: 10%;
height: "100%";
font-size: 18px;
display: flex;
align-items: end;
padding: 5px;
}
.three {
width: 100%;
height: 10%;
display: flex;
justify-content: space-around;
align-items: center;
background: rgb(255, 255, 255);
}
.con{
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.three_div1 {
height: 3rem;
width: 40%;
background-image: url("@/static/im/kf.png");
background-size: 100% 100%;
background-repeat: no-repeat;
display: flex;
align-items: center;
justify-content: end;
}
.three_div2 {
width: 40%;
height: 3rem;
background-image: url("@/static/im/hy.png");
background-size: 100% 100%;
background-repeat: no-repeat;
width: 40%;
}
.three_div3 {
height: 3rem;
background-image: url("@/static/im/da.png");
background-size: 100% 100%;
background-repeat: no-repeat;
width: 40%;
}
</style>
<div>im</div>
</template>

View File

@ -1,5 +1,5 @@
<template>
<view class="mypage" :id="pageId">
<view class="page" :id="pageId">
<!-- <list :id="pageId" class="page" :bounce="true" isSwiperList="true"> -->
<!-- 左中右的三个页面切换, 依次是: 附近 - 关注 - 推荐 -->
<swiper ref="swiper1" id="tab-bar-view" style="my-swiper" :style="{height: screenHeight + 'px'}"
@ -11,9 +11,9 @@
</view>
</swiper-item> -->
<swiper-item>
<!-- <view v-if="myUserInfo == null" ref="videoFollowComp" class="my-follow" :style="{height: screenHeight+'px'}">
<view v-if="myUserInfo == null" ref="videoFollowComp" class="my-follow" :style="{height: screenHeight+'px'}">
<text class="warn-info">请登录后查看!</text>
</view> -->
</view>
<video-follow-comp ref="videoFollowComp" :pid="1" :parentId="pageId" :screenHeight="screenHeight"
:playFollowStatus="playFollowStatus" :videoList="videoList" :refreshList="refreshList"
:pagingList="pagingList" @showLoading="showLoading" @hideLoading="hideLoading"
@ -96,15 +96,15 @@
import {
isStrEmpty
} from '@/utils/tools.js'
import videoComp from '@/components/vlog/videoComp.nvue';
import videoFollowComp from '@/components/vlog/videoFollowComp.nvue';
import videoComp from '@/components/vlog/videoComp';
import videoFollowComp from '@/components/vlog/videoFollowComp';
export default {
components: {
videoComp,
videoFollowComp
},
data() {
return {
return {
isLoading: false,
statusBarHeight: system.statusBarHeight,
screenHeight: system.screenHeight,
@ -143,11 +143,11 @@
this.tabbarWidth = 0;
this.tabListSize = {};
this._touchTabIndex = 0;
this._headHeight = 100;
this._headHeight = 100;
var timer = setTimeout(()=>{
this.selectorQuery();
clearTimeout(timer)
},100)
},300);
},
onTabItemTap: function(e) {
@ -163,10 +163,13 @@
// me.playStatus = true;
// me.playFollowStatus = false;
// }
},
},
onShow() {
let me = this;
this.myUserInfo = storage.getVlogUserInfo() || null;
if(uni.getStorageSync('refreshVlogIndex')=='1'){
storage.setRefreshVlogIndex('0') //不需要刷新
this.$refs.videoComp.displayVideoPaging(1, true);
}
// 如果当前没有list, 则relaunch
if (this.$refs.videoComp != undefined) {
@ -209,16 +212,16 @@
},
// 当前页下拉刷新
onPullDownRefresh() {
var me = this;
// 下拉刷新判断如果是不同tab那么组件中刷新的请求也不同
if (me.curIndex == 0) {
this.$refs.videoFollowComp.displayVideoPaging(1, true);
} else if (me.curIndex == 1) {
this.$refs.videoComp.displayVideoPaging(1, true);
}
// onPullDownRefresh() {
// var me = this;
// // 下拉刷新判断如果是不同tab那么组件中刷新的请求也不同
// if (me.curIndex == 0) {
// this.$refs.videoFollowComp.displayVideoPaging(1, true);
// } else if (me.curIndex == 1) {
// this.$refs.videoComp.displayVideoPaging(1, true);
// }
},
// },
methods: {
// 前往搜索页面
goSearch() {
@ -266,8 +269,9 @@
});
},
onswiperscroll(e) {
var offsetX = e.detail.dx;
onswiperscroll(e) {
// if(!this.tabListSize[this._lastTabIndex]) return
var offsetX = e.detail.dx;
var preloadIndex = this._lastTabIndex;
if (offsetX > TAB_PRELOAD_OFFSET) {
preloadIndex++;
@ -282,7 +286,7 @@
if (obj.playerList.length === 0) {
// this.loadTabData(preloadIndex);
}
// console.log(this.tabListSize)
var percentage = Math.abs(this.swiperWidth / offsetX);
var currentSize = this.tabListSize[this._lastTabIndex];
var preloadSize = this.tabListSize[preloadIndex];
@ -290,27 +294,35 @@
var lineW = currentSize.width + (preloadSize.width - currentSize.width) / percentage;
this.updateIndicator(lineL, lineW);
},
animationfinish(e) {
let index = e.detail.current;
this._lastTabIndex = index;
this.switchTab(index);
this.updateIndicator(this.tabListSize[index].left, this.tabListSize[index].width);
animationfinish(e) {
let index = e.detail.current;
this._lastTabIndex = index;
this.switchTab(index);
if(!this.tabListSize[index]) {
return
}else{
this.updateIndicator(this.tabListSize[index].left, this.tabListSize[index].width);
}
},
updateIndicator(left, width) {
// console.log(left)
// console.log(width)
this.indicatorLineLeft = left
this.indicatorLineLeft = left;
this.indicatorLineWidth = width;
},
switchTab(index) {
// console.dir(this.$refs)
let props = this.pageList[index]
let props = this.pageList[index]
console.log(props)
console.log(index)
let obj = this.$refs[props]
if (obj.playerList.length === 0) {
// this.loadTabData(index);
}
// if (obj.playerList.length === 0) {
// var info = storage.getVlogUserInfo() || null
// if(info!=null&&index==0){
// obj.displayVideoPaging(this.page + 1, true);
// }
// }
obj.setScrollRef(this._headHeight);
@ -368,15 +380,15 @@
this.switchTab(current)
this.curIndex = current;
this.tabIndex = current
this.playFollowStatus = this.curIndex === 1 ? true : false;
this.playStatus = this.curIndex === 2 ? true : false;
this.playFollowStatus = this.curIndex === 0 ? true : false;
this.playStatus = this.curIndex === 1 ? true : false;
},
// 点击头部选项卡,切换页面
tapFollow: function(current) {
this.curIndex = current;
this.tabIndex = current
this.playFollowStatus = this.curIndex === 1 ? true : false;
this.playStatus = this.curIndex === 2 ? true : false;
this.playFollowStatus = this.curIndex === 0 ? true : false;
this.playStatus = this.curIndex === 1 ? true : false;
},
// 下拉刷新改变head的字样显示
@ -395,7 +407,7 @@
<style scoped>
/* index start */
.mypage {
.page {
position: absolute;
left: 0;
right: 0;
@ -517,13 +529,13 @@
flex: 1;
height: 84upx;
flex-direction: row;
white-space: nowrap;
lines: 1;
text-overflow: ellipsis;
justify-content: center;
align-items: center;
}
.uni-tab-item {
display: inline-block;
flex-wrap: nowrap;
/* padding-left: 25px; */
/* padding-right: 25px; */
@ -535,7 +547,8 @@
height: 80upx;
line-height: 80upx;
flex-wrap: nowrap;
white-space: nowrap;
lines: 1;
text-overflow: ellipsis;
}
.uni-tab-item-title-active {

View File

@ -63,11 +63,13 @@ $font-weight: 400;
.main-color {
color: $main-color !important;
}
.bg-light-color {
background-color: $light-color !important;
/deep/ * {
background-color: $light-color !important;
}
.bg-light-color {
/* #ifndef APP-NVUE */
background-color: $light-color !important;
/deep/ * {
background-color: $light-color !important;
}
/* #endif */
}
.bg-main-color {
background-color: $main-color !important;
@ -76,11 +78,15 @@ $font-weight: 400;
// 渐变主题颜色
.bg-linear-gradient {
background-image: linear-gradient(25deg, #fa123b, #ff6b35, #ff9f28, #ffcc03);
}
}
/* #ifndef APP-NVUE */
.uni-tabbar .uni-tabbar__icon {
width: 20px;
height: 18px;
}
}
/* #endif */
.flex {
display: flex;
@ -89,8 +95,11 @@ $font-weight: 400;
.btn {
background-color: $light-color;
color: #ffffff;
border-width: 0px;
border: none;
border-width: 0px;
/* #ifndef APP-NVUE */
border: none;
/* #endif */
border-color: transparent;
border-radius: 44px;
height: 44px;
box-shadow: none;
@ -98,8 +107,11 @@ $font-weight: 400;
font-style: normal;
line-height: 44px;
text-align: center;
&::after {
border: none;
&::after {
/* #ifndef APP-NVUE */
border: none;
/* #endif */
border-color: transparent;
}
}
.button-hover {
@ -153,7 +165,7 @@ $font-weight: 400;
.relative {
position: relative;
}
/* #ifndef APP-NVUE */
.wes {
/* 多出部分用省略号表示 , 用于一行 */
overflow: hidden;
@ -161,11 +173,12 @@ $font-weight: 400;
white-space: nowrap;
text-overflow: ellipsis;
}
.wes-2 {
/* 适用于webkit内核和移动端 */
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
overflow: hidden;
}
}
/* #endif */

View File

@ -0,0 +1,10 @@
## 2.0.232021-08-09
## 2.0.222021-08-09
## 2.0.212021-07-28
## 2.0.22021-07-28
2.0.2 新增延迟绘制。
## 2.0.12021-07-26
2.0.1 调整为uni_modules目录规范。

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,32 @@
<template>
<view class="uqrcode">
<canvas id="qrcode" canvas-id="qrcode" :style="{'width': `${options.size}px`, 'height': `${options.size}px`}" />
</view>
</template>
<script>
import uqrcode from './common/uqrcode'
export default {
name: 'uqrcode',
data() {
return {
options: {
canvasId: 'qrcode',
size: 354,
margin: 10,
text: ''
}
}
},
methods: {
make(options) {
return uqrcode.make(Object.assign(this.options, options), this)
}
}
}
</script>
<style>
</style>

View File

@ -0,0 +1,78 @@
{
"id": "Sansnn-uQRCode",
"displayName": "uQRCode 二维码生成插件",
"version": "2.0.23",
"description": "uQRCode 是一款使用方式简单,易于扩展的二维码生成插件。",
"keywords": [
"uQRCode",
"二维码",
"qrcode"
],
"repository": "https://github.com/Sansnn/uQRCode",
"engines": {
"HBuilderX": "^3.1.0"
},
"dcloudext": {
"category": [
"JS SDK",
"通用 SDK"
],
"sale": {
"regular": {
"price": "0.00"
},
"sourcecode": {
"price": "0.00"
}
},
"contact": {
"qq": ""
},
"declaration": {
"ads": "无",
"data": "无",
"permissions": "无"
},
"npmurl": ""
},
"uni_modules": {
"dependencies": [],
"encrypt": [],
"platforms": {
"cloud": {
"tcb": "y",
"aliyun": "y"
},
"client": {
"App": {
"app-vue": "y",
"app-nvue": "y"
},
"H5-mobile": {
"Safari": "y",
"Android Browser": "y",
"微信浏览器(Android)": "y",
"QQ浏览器(Android)": "y"
},
"H5-pc": {
"Chrome": "y",
"IE": "y",
"Edge": "y",
"Firefox": "y",
"Safari": "y"
},
"小程序": {
"微信": "y",
"阿里": "u",
"百度": "u",
"字节跳动": "u",
"QQ": "u"
},
"快应用": {
"华为": "u",
"联盟": "u"
}
}
}
}
}

View File

@ -0,0 +1,167 @@
# uQRCode
uQRCode 生成方式简单可扩展性高如有复杂需求可通过自定义组件或修改源码完成需求。已测试H5、微信小程序、iPhoneXsMax真机。
支持自定义二维码渲染规则,可通过 ``getModules`` 方法得到矩阵信息后自行实现canvas渲染二维码如随机颜色、圆点、方块、块与块之间的间距等详情见示例中的 ``custom``。
支持nvue生成但暂不支持保存。
### 二维码
**什么是QR码**
QR码属于矩阵式二维码中的一个种类由DENSO(日本电装)公司开发由JIS和ISO将其标准化。
**QR码的特点**
一是高速读取(QR就是取自“Quick Response”的首字母),通过摄像头从拍摄到解码到显示内容也就三秒左右,对摄像的角度也没有什么要求;
二是高容量、高密度理论上内容经过压缩处理后可以存7089个数字4296个字母和数字混合字符2953个8位字节数据1817个汉字
三是支持纠错处理按照QR码的标准文档说明QR码的纠错分为4个级别分别是
- level L : 最大 7% 的错误能够被纠正;
- level M : 最大 15% 的错误能够被纠正;
- level Q : 最大 25% 的错误能够被纠正;
- level H : 最大 30% 的错误能够被纠正;
四是结构化,看似无规则的图形,其实对区域有严格的定义。
更多二维码介绍及原理:[https://blog.csdn.net/jason_ldh/article/details/11801355](https://blog.csdn.net/jason_ldh/article/details/11801355)
### 简单使用
在 ``template`` 中创建 ``<uqrcode/>`` 并设置 ``ref`` 属性
```html
<uqrcode ref="uqrcode"></uqrcode>
```
在 ``script`` 中调用生成方法
```javascript
export default {
onReady() {
this.$refs
.uqrcode
.make({
size: 354,
text: 'uQRCode'
})
.then(res => {
// 返回的res与uni.canvasToTempFilePath返回一致
console.log(res)
})
}
}
```
### 高级使用
在 ``template`` 中创建 ``<canvas/>`` 并设置 ``id``,画布宽高
```html
<canvas id="qrcode" canvas-id="qrcode" style="width: 354px;height: 354px;" />
```
在 ``script`` 中引用js文件并调用生成方法
```javascript
import uQRCode from '@/components/uqrcode/common/uqrcode.js'
export default {
onReady() {
uQRCode.make({
canvasId: 'qrcode',
componentInstance: this,
size: 354,
margin: 10,
text: 'uQRCode',
backgroundColor: '#ffffff',
foregroundColor: '#ff0000',
fileType: 'png',
errorCorrectLevel: uQRCode.errorCorrectLevel.H
})
.then(res => {
console.log(res)
})
}
}
```
### 属性说明
|属性名|说明|
|---|:---|
|errorCorrectLevel|纠错等级,包含 `errorCorrectLevel.L``errorCorrectLevel.M``errorCorrectLevel.Q``errorCorrectLevel.H` 四个级别,`L`: 最大 7% 的错误能够被纠正;`M`: 最大 15% 的错误能够被纠正;`Q`: 最大 25% 的错误能够被纠正;`H`: 最大 30% 的错误能够被纠正。|
|defaults|二维码生成参数的默认值。|
### 方法说明
|方法名|说明|
|---|:---|
|[make](#makeoptions)|生成二维码。|
|[getModules](#getModulesoptions)|可以得到二维码矩阵信息,可根据返回的矩阵信息自行实现二维码生成。|
### make(options)
生成二维码
**options参数说明**
|参数|类型|必填|说明|
|---|---|---|:---|
|canvasId|String|是|画布标识,传入 `<canvas/>``canvas-id`|
|componentInstance|Object|否|自定义组件实例 `this` ,表示在这个自定义组件下查找拥有 `canvas-id``<canvas/>` ,如果省略,则不在任何自定义组件内查找|
|text|String|是|二维码内容|
|size|Number|否|画布尺寸大小,请与 `<canvas/>` 所设 `width` `height` 保持一致(默认:`354`|
|margin|Number|否|边距,二维码实际尺寸会根据所设边距值进行缩放调整(默认:`0`|
|backgroundColor|String|否|背景色,若设置为透明背景, `fileType` 需设置为 `'png'` 然后设置背景色为 `'rgba(255,255,255,0)'` 即可(默认:`'#ffffff'`|
|foregroundColor|String|否|前景色(默认:`'#000000'`|
|fileType|String|否|输出图片的类型,只支持 `'jpg'``'png'`(默认:`'png'`|
|errorCorrectLevel|Number|否|纠错等级,参考属性说明 `errorCorrectLevel`(默认:`errorCorrectLevel.H`|
|enableDelay|Boolen|否|启用延迟绘制(默认:`false`|
### getModules(options)
根据内容得到二维码矩阵信息
|参数|类型|必填|说明|
|---|---|---|:---|
|text|String|是|二维码内容|
|errorCorrectLevel|Number|否|纠错等级,参考属性说明 `errorCorrectLevel`(默认:`errorCorrectLevel.H`|
### 使用建议
如需在进入页面时生成二维码,建议使用`onReady`,不推荐在`onLoad`中生成。
关于高级使用canvas在二维码生成中请当做一个生成工具来看待它的作用仅是绘制出二维码。应把生成回调得到的资源保存并使用显示用image图片组件原因是方便操作例如调整大小或是H5端长按保存或识别所以canvas应将它放在看不见的地方。不能用`display:none;overflow:hidden;`隐藏否则生成空白。这里推荐canvas的隐藏样式代码
```html
<style>
.canvas-hide {
/* 1 */
position: fixed;
right: 100vw;
bottom: 100vh;
/* 2 */
z-index: -9999;
/* 3 */
opacity: 0;
}
</style>
```
### 常见问题
**二维码生成不完整**
size的单位是px请尽量避免使用rpx如果canvas的单位是rpx那么不同设备屏幕分辨率不一样rpx转换成px后的画布尺寸不足以放下全部内容实际绘制图案超出就会出现不完整或者没有填充完整画布的情况。
另外还可以尝试延迟绘制,``enableDelay`` 设置为 ``true``。
**如何扫码跳转指定网页**
text参数直接放入完整的网页地址即可例如`https://ext.dcloud.net.cn/plugin?id=1287`。微信客户端不能是ip地址。
**H5长按识别**
canvas无法长按识别长按识别需要是图片才行所以只需将回调过来的资源用image组件显示即可。
### Tips
- 示例项目中的图片采集于互联网,仅作为案例展示,不作为广告/商业,如有侵权,请告知删除。下载使用的用户,请勿把示例项目中的图片应用到你的项目。

View File

@ -0,0 +1,35 @@
## 1.6.12021-07-30
- 优化 vue3下事件警告的问题
## 1.6.02021-07-13
- 组件兼容 vue3如何创建vue3项目详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834)
## 1.5.02021-06-23
- 新增 mask-click 遮罩层点击事件
## 1.4.52021-06-22
- 修复 nvue 平台中间弹出后点击内容再点击遮罩无法关闭的Bug
## 1.4.42021-06-18
- 修复 H5平台中间弹出后点击内容再点击遮罩无法关闭的Bug
## 1.4.32021-06-08
- 修复 错误的 watch 字段
- 修复 safeArea 属性不生效的问题
- 修复 点击内容再点击遮罩无法关闭的Bug
## 1.4.22021-05-12
- 新增 组件示例地址
## 1.4.12021-04-29
- 修复 组件内放置 input 、textarea 组件,无法聚焦的问题
## 1.4.0 2021-04-29
- 新增 type 属性的 left\right 值,支持左右弹出
- 新增 open(String:type) 方法参数 ,可以省略 type 属性 ,直接传入类型打开指定弹窗
- 新增 backgroundColor 属性,可定义主窗口背景色,默认不显示背景色
- 新增 safeArea 属性,是否适配底部安全区
- 修复 App\h5\微信小程序底部安全区占位不对的Bug
- 修复 App 端弹出等待的Bug
- 优化 提升低配设备性能,优化动画卡顿问题
- 优化 更简单的组件自定义方式
## 1.2.92021-02-05
- 优化 组件引用关系通过uni_modules引用组件
## 1.2.82021-02-05
- 调整为uni_modules目录规范
## 1.2.72021-02-05
- 调整为uni_modules目录规范
- 新增 支持 PC 端
- 新增 uni-popup-message 、uni-popup-dialog扩展组件支持 PC 端

View File

@ -0,0 +1,728 @@
<style lang="scss" scoped>
.uni-popup-share {
background-color: #181717;
border-top-left-radius: 16rpx;
border-top-right-radius: 16rpx;
}
.uni-share-title {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: row;
align-items: center;
justify-content: space-between;
height: 40px;
}
.uni-share-title-text {
font-size: 12px;
color: #ffffff;
font-weight: 500;
}
.uni-share-content {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
// flex-direction: row;
flex-direction: column;
// justify-content: center;
// padding-top: 10px;
}
.uni-share-content-box {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: row;
flex-wrap: wrap;
width: 360px;
}
.uni-share-content-item {
width: 90px;
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: column;
justify-content: center;
padding: 10px 0;
align-items: center;
}
.uni-share-content-item:active {
background-color: #f5f5f5;
}
.uni-share-image {
width: 30px;
height: 30px;
}
.uni-share-text {
margin-top: 10px;
font-size: 14px;
color: #3B4144;
}
.uni-share-button-box {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: row;
padding: 10px 15px;
}
.uni-share-button {
flex: 1;
border-radius: 50px;
color: #666;
font-size: 16px;
}
.uni-share-button::after {
border-radius: 50px;
}
.icon-close-left {
width: 20rpx;
height: 20rpx;
margin-left: 30rpx;
opacity: 0;
}
.icon-close-right {
width: 22rpx;
height: 22rpx;
margin-right: 30rpx;
}
.comment-wrapper {
// height: 40px;
padding: 10px 10px 10px 10px;
display: flex;
flex-direction: row;
justify-content: space-around;
}
.commentWrapperBlack {
background-color: #0e0d0d;
}
.commentWrapperWhite {
background-color: #ffffff;
}
.comment-box {
font-size: 15px;
height: 40px;
border-radius: 20px;
padding: 0 18px 0 18px;
}
.commentBoxBlack {
color: #FFFFFF;
background-color: #151515;
}
.commentBoxWhite {
color: #000000;
background-color: #f2f2f5;
}
.comment-box-placeholder {
font-size: 15px;
}
.icon-comment {
width: 30px;
height: 30px;
}
.all-comments {
height: 800rpx;
// padding: 16rpx 30rpx;
}
.img-face {
width: 80rpx;
height: 80rpx;
border-radius: 100rpx;
}
.like-or-not {
margin-top: 16px;
width: 50rpx;
height: 50rpx;
}
.comments-wrapper {
display: flex;
flex-direction: column;
}
.comments-wrapper-sub-up {
display: flex;
flex-direction: row;
justify-content: space-between;
}
.comments-wrapper-sub-down {
display: flex;
flex-direction: row;
margin-top: 2px;
}
.vlogger-wrapper {
display: flex;
flex-direction: row;
}
.tag-writer {
display: flex;
flex-direction: column;
justify-content: center;
background-color: #f02a50;
border-radius: 3px;
width: 30px;
height: 16px;
margin-left: 2px;
}
.writer-words {
font-size: 26rpx;
color: #FFFFFF;
text-align: center;
}
.single-comment-box {
background-color: #181717;
}
.single-comment-box-touched {
background-color: #202020;
}
.active {
background-color: #202020;
}
</style>
<template>
<view class="uni-popup-share">
<view class="uni-share-title">
<image src="/static/images/icon-close.png" class="icon-close-left"></image>
<text class="uni-share-title-text">{{getGraceNumber(thisVlogTotalComentCounts)}}条评论</text>
<image src="/static/images/icon-close.png" class="icon-close-right" @click="close"></image>
</view>
<view class="uni-share-content">
<!-- <view class="uni-share-content-box"> -->
<view class="" style="height: 800rpx;">
<scroll-view class="all-comments" :style="{width: screenWidth + 'px'}" scroll-y="true"
lower-threshold="150" @scrolltolower="loadMore" :scroll-top="scrollTop">
<view v-for="(commentContent, index) in commentList" :key="index" :data-index="index"
:class="{active : index == activeIndex}" @touchstart="touchstartComment(index)"
@touchend="touchendComment()"
@longpress="deleteComment(commentContent.commentUserId, commentContent.commentId)">
<view class="comments-wrapper"
style="margin-left: 16rpx;margin-top: 16rpx;margin-right: 16rpx;">
<view class="comments-wrapper-sub-up">
<view class="vlogger-wrapper">
<image :src="commentContent.commentUserFace" class="img-face"></image>
<view style="margin-left: 10px;width: 456rpx;">
<view style="display: flex;flex-direction: row;">
<text
style="font-size: 30rpx;color: #878585;align-self: center;">{{commentContent.commentUserNickname}}</text>
<view v-if="commentContent.vlogerId == thisVlogerId" class="tag-writer"
style="align-self: center;">
<text class="writer-words" style="align-self: center;">作者</text>
</view>
<image
v-if="commentContent.replyedUserNickname != null && commentContent.replyedUserNickname != ''"
src="/static/images/icon-right-arrow3.png" class=""
style="opacity: 0.8;width: 40rpx;height: 40rpx;margin-left: 16rpx;margin-right: 10rpx;align-self: center;">
</image>
<text
v-if="commentContent.replyedUserNickname != null && commentContent.replyedUserNickname != ''"
style="font-size: 30rpx;color: #878585;align-self: center;">{{commentContent.replyedUserNickname}}</text>
</view>
<text
style="font-size: 32rpx;color: #FFFFFF;margin-top: 2px;">{{commentContent.content}}</text>
</view>
</view>
<view style="display: flex;flex-direction: column;width: 26px;">
<image v-if="commentContent.isLike == 1" src="/static/images/icon-comment-like.png"
class="like-or-not" style="align-self: center;"
@click="unlike(commentContent.commentUserId, commentContent.commentId, index)">
</image>
<image v-if="commentContent.isLike == 0"
src="/static/images/icon-comment-unlike.png" class="like-or-not"
style="align-self: center;"
@click="like(commentContent.commentUserId, commentContent.commentId, index)">
</image>
<text
style="font-size: 22rpx;color: #878585;align-self: center;">{{commentContent.likeCounts}}</text>
</view>
</view>
<view class="comments-wrapper-sub-down">
<image src="/static/face/face-arrow-1.png" class="img-face" style="opacity: 0;"></image>
<text
style="font-size: 30rpx;color: #878585;margin-left: 10px;">{{getGraceDateBeforeNow(commentContent.createTime)}}</text>
<text style="font-size: 30rpx;color: #878585;margin-left: 20px;"
@click="replyComment(commentContent.commentId, commentContent.commentUserNickname)">回复</text>
</view>
</view>
</view>
<!-- TODO: 判断总评论数和当前list中数量是否一致如果一致则显然如下 -->
<view
style="display: flex;flex-direction: row;justify-content: center;margin-top: 50rpx;height: 100rpx;">
<text style="color: #444446;font-size: 13px;">{{bottomTxt}}</text>
</view>
</scroll-view>
</view>
<!-- 评论输入框 -->
<view class="comment-wrapper" v-if="isLogin"
:class="{commentWrapperBlack: commentWrapperBlack, commentWrapperWhite: commentWrapperWhite}">
<input class="comment-box" :class="{commentBoxBlack: commentBoxBlack, commentBoxWhite: commentBoxWhite}"
placeholder-class="comment-box-placeholder" :style="{width: screenWidth-70 + 'px'}"
:placeholder="placeholder" cursor-spacing="10px" v-model="currentComment" confirm-type="done"
:focus="commentFocus" @focus="typingComment" @blur="noTypingComment">
<!-- @confirm="doCommentPublish" -->
<view style="display: flex;flex-direction: column;justify-content: center;">
<image src="/static/images/icon-comment.png" class="icon-comment" @click="doCommentPublish()">
</image>
</view>
</view>
</view>
</view>
</template>
<script>
import storage from "@/utils/storage.js"; //
import {
vlogCommentCounts,
vlogCommentUnLike,
vlogCommentLike,
vlogCommentDelete,
vlogCommentList,
vlogCommentCreate
} from "@/api/vlog"
import {
dateFormat,
graceNumber,
getDateBeforeNow
} from '@/utils/tools.js'
import popup from '../uni-popup/popup.js'
export default {
name: 'UniPopupShare',
mixins: [popup],
emits: ['select'],
props: {
title: {
type: String,
default: '分享到'
},
beforeClose: {
type: Boolean,
default: false
},
thisVlogerId: {
type: String,
default: ''
},
thisVlogId: {
type: String,
default: ''
},
},
data() {
return {
isLogin: false,
commentWrapperBlack: true,
commentWrapperWhite: false,
commentBoxBlack: true,
commentBoxWhite: false,
// commentWrapperBlack: false,
// commentWrapperWhite: true,
// commentBoxBlack: false,
// commentBoxWhite: true,
screenWidth: uni.getSystemInfoSync().screenWidth,
currentComment: "",
scrollTop: 0,
old: {
scrollTop: 0
},
// commentTouched: false,
activeIndex: -1,
bottomTxt: "到底了哦~",
placeholder: "快发条评论吧~",
commentFocus: false,
thisFatherCommentId: "0", // id
thisVlogTotalComentCounts: 0,
loginUserId: "",
page: 0,
totalPage: 0,
commentCounts: 88,
commentList: [],
}
},
onShow() {
},
created() {
var me = this;
var myUserInfo = storage.getVlogUserInfo()
var userId = "";
if (myUserInfo != null) {
userId = myUserInfo.id;
this.isLogin = true
} else {
this.isLogin = false
}
me.loginUserId = userId;
this.freshCommentCounts();
this.doCommentPagingList(this.page + 1, true);
},
methods: {
//
async freshCommentCounts() {
var me = this;
var vlogId = me.thisVlogId;
var result = await vlogCommentCounts(vlogId)
if (result.data.status == 200) {
me.thisVlogTotalComentCounts = result.data.data;
} else {
me.thisVlogTotalComentCounts = 0;
}
if (me.thisVlogTotalComentCounts == 0) {
me.bottomTxt = "抢一个沙发吧~";
} else {
me.bottomTxt = "到底了哦~";
}
},
async unlike(commentUserId, commentId, index) {
var me = this;
var result = await vlogCommentUnLike(me.loginUserId, commentId)
if (result.data.status == 200) {
me.reLikeCommentList(index, 0);
me.reCountsCommentList(index, -1);
} else {
uni.showToast({
title: result.data.msg,
icon: "none",
duration: 3000
});
}
},
async like(commentUserId, commentId, index) {
var me = this;
var myUserInfo = storage.getVlogUserInfo();
if (myUserInfo == null) {
uni.showTabBar({
animation: false
});
uni.navigateTo({
url: "/pages/passport/login",
animationType: "slide-in-bottom",
});
return;
}
var result = await vlogCommentLike(me.loginUserId, commentId)
if (result.data.status == 200) {
me.reLikeCommentList(index, 1);
me.reCountsCommentList(index, 1);
} else {
uni.showToast({
title: result.data.msg,
icon: "none",
duration: 3000
});
}
},
reCountsCommentList(index, number) {
var me = this;
var commentList = me.commentList;
commentList[index].likeCounts = commentList[index].likeCounts + number;
commentList.splice(index, 1, commentList[index]);
me.commentList = commentList;
},
reLikeCommentList(index, isLike) {
var me = this;
var commentList = me.commentList;
commentList[index].isLike = isLike;
commentList.splice(index, 1, commentList[index]);
me.commentList = commentList;
},
deleteComment(commentUserId, commentId) {
var me = this;
var vlogId = me.thisVlogId;
// userIdid
if (commentUserId != me.loginUserId) {
return;
}
uni.showModal({
title: '提示',
content: '确认删除评论吗?',
success: async (res) => {
if (res.confirm) {
var result = await vlogCommentDelete(vlogId, commentUserId, commentId)
if (result.data.status == 200) {
me.doCommentPagingList(1, true);
} else {
uni.showToast({
title: result.data.msg,
icon: "none",
duration: 3000
});
}
me.freshCommentCounts();
}
}
});
},
loadMore() {
if (this.page == this.totalPage) {
return;
}
this.doCommentPagingList(this.page + 1, false);
},
//
async doCommentPagingList(page, needClearList) {
//
var me = this;
me.page = page;
var vlogId = me.thisVlogId;
var result = await vlogCommentList(page, 10, vlogId, me.loginUserId)
if (result.data.status == 200) {
var commentList = result.data.data.rows;
var totalPage = result.data.data.total;
if (needClearList) {
me.commentList = [];
}
me.commentList = me.commentList.concat(commentList);
me.totalPage = totalPage;
} else {
uni.showToast({
title: result.data.msg,
icon: "none",
duration: 3000
});
}
},
//
typingComment() {
this.commentWrapperBlack = false;
this.commentWrapperWhite = true;
this.commentBoxBlack = false;
this.commentBoxWhite = true;
// console.log(this.thisFatherCommentId);
},
//
noTypingComment() {
this.commentWrapperBlack = true;
this.commentWrapperWhite = false;
this.commentBoxBlack = true;
this.commentBoxWhite = false;
this.thisFatherCommentId = "0"; // fatherId0
this.commentFocus = false;
this.placeholder = "爱评论的人都是天使~";
},
//
replyComment(commentId, commentUserNickname) {
var me = this;
var myUserInfo = storage.getVlogUserInfo()
if (myUserInfo == null) {
uni.showTabBar({
animation: false
});
uni.navigateTo({
url: "/pages/passport/login",
animationType: "slide-in-bottom",
});
return;
}
this.thisFatherCommentId = commentId;
this.commentFocus = true;
this.placeholder = "回复 @" + commentUserNickname;
// this.typingComment();
},
//
async doCommentPublish() {
console.log('发表评论')
var me = this;
var myUserInfo = storage.getVlogUserInfo()
if (myUserInfo == null) {
uni.showTabBar({
animation: false
});
uni.navigateTo({
url: "/pages/passport/login",
animationType: "slide-in-bottom",
});
return;
}
if (me.currentComment == null || me.currentComment == "" || me.currentComment == undefined) {
uni.showToast({
title: "请填入您的评论~",
mask: true,
position: "bottom"
});
return;
}
if (me.currentComment.length > 50) {
uni.showToast({
title: "评论字数限制50以内噢~",
mask: true,
position: "bottom"
});
return;
}
var userId = myUserInfo.id;
var pendingCommentObject = {
vlogId: me.thisVlogId,
vlogerId: me.thisVlogerId,
fatherCommentId: me.thisFatherCommentId,
commentUserId: userId,
content: me.currentComment,
};
var result = await vlogCommentCreate(pendingCommentObject)
console.log(result);
if (result.data.status == 200) {
var newCommentObject = result.data.data;
newCommentObject.commentId = newCommentObject.id;
newCommentObject.commentUserNickname = myUserInfo.nickname;
newCommentObject.commentUserFace = myUserInfo.face;
newCommentObject.isLike = 0;
newCommentObject.vlogerId = userId
me.doCommentPagingList(1, true);
// /thisFatherCommentId0
me.thisFatherCommentId = "0";
//
me.commentList.unshift(newCommentObject);
//
me.currentComment = "";
//
uni.hideKeyboard();
//
me.noTypingComment();
// list
me.scrollTop = me.scrollTop + 1;
me.$nextTick(() => {
me.scrollTop = 0 //0
});
} else {
uni.showToast({
title: result.data.msg,
icon: "none",
duration: 3000
});
}
me.freshCommentCounts();
// uni.request({
// method: "POST",
// header: {
// headerUserId: userId,
// headerUserToken: app.getUserSessionToken()
// },
// url: serverUrl + "/comment/create",
// data: pendingCommentObject,
// success(result) {
// }
// });
},
// 1000100001.3k/6.8w
getGraceNumber(num) {
return graceNumber(num);
},
// /xx/...
getGraceDateBeforeNow(dateTimeStr) {
var date = dateFormat("YYYY-mm-dd", new Date(dateTimeStr));
return getDateBeforeNow(date);
},
/**
* 选择内容
*/
select(item, index) {
this.$emit('select', {
item,
index
})
this.close()
},
/**
* 关闭窗口
*/
close() {
if (this.beforeClose) return
this.popup.close();
uni.showTabBar({
animation: true
});
},
touchstartComment(index) {
// this.commentTouched = true;
this.activeIndex = index;
},
touchendComment() {
// this.commentTouched = false;
this.activeIndex = -1;
},
}
}
</script>

View File

@ -0,0 +1,45 @@
// #ifdef H5
export default {
name: 'Keypress',
props: {
disable: {
type: Boolean,
default: false
}
},
mounted () {
const keyNames = {
esc: ['Esc', 'Escape'],
tab: 'Tab',
enter: 'Enter',
space: [' ', 'Spacebar'],
up: ['Up', 'ArrowUp'],
left: ['Left', 'ArrowLeft'],
right: ['Right', 'ArrowRight'],
down: ['Down', 'ArrowDown'],
delete: ['Backspace', 'Delete', 'Del']
}
const listener = ($event) => {
if (this.disable) {
return
}
const keyName = Object.keys(keyNames).find(key => {
const keyName = $event.key
const value = keyNames[key]
return value === keyName || (Array.isArray(value) && value.includes(keyName))
})
if (keyName) {
// 避免和其他按键事件冲突
setTimeout(() => {
this.$emit(keyName, {})
}, 0)
}
}
document.addEventListener('keyup', listener)
this.$once('hook:beforeDestroy', () => {
document.removeEventListener('keyup', listener)
})
},
render: () => {}
}
// #endif

View File

@ -0,0 +1,244 @@
<template>
<view class="uni-popup-dialog">
<view class="uni-dialog-title">
<text class="uni-dialog-title-text" :class="['uni-popup__'+dialogType]">{{title}}</text>
</view>
<view v-if="mode === 'base'" class="uni-dialog-content">
<slot>
<text class="uni-dialog-content-text">{{content}}</text>
</slot>
</view>
<view v-else class="uni-dialog-content">
<slot>
<input class="uni-dialog-input" v-model="val" type="text" :placeholder="placeholder" :focus="focus" >
</slot>
</view>
<view class="uni-dialog-button-group">
<view class="uni-dialog-button" @click="closeDialog">
<text class="uni-dialog-button-text">取消</text>
</view>
<view class="uni-dialog-button uni-border-left" @click="onOk">
<text class="uni-dialog-button-text uni-button-color">确定</text>
</view>
</view>
</view>
</template>
<script>
import popup from '../uni-popup/popup.js'
/**
* PopUp 弹出层-对话框样式
* @description 弹出层-对话框样式
* @tutorial https://ext.dcloud.net.cn/plugin?id=329
* @property {String} value input 模式下的默认值
* @property {String} placeholder input 模式下输入提示
* @property {String} type = [success|warning|info|error] 主题样式
* @value success 成功
* @value warning 提示
* @value info 消息
* @value error 错误
* @property {String} mode = [base|input] 模式
* @value base 基础对话框
* @value input 可输入对话框
* @property {String} content 对话框内容
* @property {Boolean} beforeClose 是否拦截取消事件
* @event {Function} confirm 点击确认按钮触发
* @event {Function} close 点击取消按钮触发
*/
export default {
name: "uniPopupDialog",
mixins: [popup],
emits:['confirm','close'],
props: {
value: {
type: [String, Number],
default: ''
},
placeholder: {
type: [String, Number],
default: '请输入内容'
},
type: {
type: String,
default: 'error'
},
mode: {
type: String,
default: 'base'
},
title: {
type: String,
default: '提示'
},
content: {
type: String,
default: ''
},
beforeClose: {
type: Boolean,
default: false
}
},
data() {
return {
dialogType: 'error',
focus: false,
val: ""
}
},
watch: {
type(val) {
this.dialogType = val
},
mode(val) {
if (val === 'input') {
this.dialogType = 'info'
}
},
value(val) {
this.val = val
}
},
created() {
//
this.popup.disableMask()
// this.popup.closeMask()
if (this.mode === 'input') {
this.dialogType = 'info'
this.val = this.value
} else {
this.dialogType = this.type
}
},
mounted() {
this.focus = true
},
methods: {
/**
* 点击确认按钮
*/
onOk() {
if (this.mode === 'input'){
this.$emit('confirm', this.val)
}else{
this.$emit('confirm')
}
if(this.beforeClose) return
this.popup.close()
},
/**
* 点击取消按钮
*/
closeDialog() {
this.$emit('close')
if(this.beforeClose) return
this.popup.close()
},
close(){
this.popup.close()
}
}
}
</script>
<style lang="scss" scoped>
.uni-popup-dialog {
width: 300px;
border-radius: 15px;
background-color: #fff;
}
.uni-dialog-title {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: row;
justify-content: center;
padding-top: 15px;
padding-bottom: 5px;
}
.uni-dialog-title-text {
font-size: 16px;
font-weight: 500;
}
.uni-dialog-content {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: row;
justify-content: center;
align-items: center;
padding: 5px 15px 15px 15px;
}
.uni-dialog-content-text {
font-size: 14px;
color: #6e6e6e;
}
.uni-dialog-button-group {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: row;
border-top-color: #f5f5f5;
border-top-style: solid;
border-top-width: 1px;
}
.uni-dialog-button {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex: 1;
flex-direction: row;
justify-content: center;
align-items: center;
height: 45px;
}
.uni-border-left {
border-left-color: #f0f0f0;
border-left-style: solid;
border-left-width: 1px;
}
.uni-dialog-button-text {
font-size: 14px;
}
.uni-button-color {
color: #007aff;
}
.uni-dialog-input {
flex: 1;
font-size: 14px;
border: 1px #eee solid;
height: 40px;
padding: 0 10px;
border-radius: 5px;
color: #555;
}
.uni-popup__success {
color: #4cd964;
}
.uni-popup__warn {
color: #f0ad4e;
}
.uni-popup__error {
color: #dd524d;
}
.uni-popup__info {
color: #909399;
}
</style>

View File

@ -0,0 +1,143 @@
<template>
<view class="uni-popup-message">
<view class="uni-popup-message__box fixforpc-width" :class="'uni-popup__'+type">
<slot>
<text class="uni-popup-message-text" :class="'uni-popup__'+type+'-text'">{{message}}</text>
</slot>
</view>
</view>
</template>
<script>
import popup from '../uni-popup/popup.js'
/**
* PopUp 弹出层-消息提示
* @description 弹出层-消息提示
* @tutorial https://ext.dcloud.net.cn/plugin?id=329
* @property {String} type = [success|warning|info|error] 主题样式
* @value success 成功
* @value warning 提示
* @value info 消息
* @value error 错误
* @property {String} message 消息提示文字
* @property {String} duration 显示时间设置为 0 则不会自动关闭
*/
export default {
name: 'uniPopupMessage',
mixins:[popup],
props: {
/**
* 主题 success/warning/info/error 默认 success
*/
type: {
type: String,
default: 'success'
},
/**
* 消息文字
*/
message: {
type: String,
default: ''
},
/**
* 显示时间设置为 0 则不会自动关闭
*/
duration: {
type: Number,
default: 3000
},
maskShow:{
type:Boolean,
default:false
}
},
data() {
return {}
},
created() {
this.popup.maskShow = this.maskShow
this.popup.messageChild = this
},
methods: {
timerClose(){
if(this.duration === 0) return
clearTimeout(this.timer)
this.timer = setTimeout(()=>{
this.popup.close()
},this.duration)
}
}
}
</script>
<style lang="scss" scoped>
.uni-popup-message {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: row;
justify-content: center;
}
.uni-popup-message__box {
background-color: #e1f3d8;
padding: 10px 15px;
border-color: #eee;
border-style: solid;
border-width: 1px;
flex: 1;
}
@media screen and (min-width: 500px) {
.fixforpc-width {
margin-top: 20px;
border-radius: 4px;
flex: none;
min-width: 380px;
/* #ifndef APP-NVUE */
max-width: 50%;
/* #endif */
/* #ifdef APP-NVUE */
max-width: 500px;
/* #endif */
}
}
.uni-popup-message-text {
font-size: 14px;
padding: 0;
}
.uni-popup__success {
background-color: #e1f3d8;
}
.uni-popup__success-text {
color: #67C23A;
}
.uni-popup__warn {
background-color: #faecd8;
}
.uni-popup__warn-text {
color: #E6A23C;
}
.uni-popup__error {
background-color: #fde2e2;
}
.uni-popup__error-text {
color: #F56C6C;
}
.uni-popup__info {
background-color: #F2F6FC;
}
.uni-popup__info-text {
color: #909399;
}
</style>

View File

@ -0,0 +1,268 @@
<style>
.page {
background-color: #000000;
opacity: 0.9;
}
.btn-cancel {
background-color: #1d1d1e;
border-color: #3a3a3d;
}
.btn-cancel-touched {
background-color: #515156;
border-color: #2b2b2f;
}
.all-box {
display: flex;
flex-direction: row;
justify-content: space-around;
height: 280rpx;
}
.share-item {
display: flex;
flex-direction: column;
margin-top: 60rpx;
}
.icon-wrapper {
width: 120rpx;
height: 120rpx;
background-color: #343437;
border-radius: 100px;
display: flex;
flex-direction: row;
justify-content: center;
opacity: 0.8;
}
.icon-image {
width: 60rpx;
height: 60rpx;
}
.icon-tag-text {
color: #FFFFFF;
font-size: 14px;
margin-top: 10rpx;
}
</style>
<template>
<view class="page">
<view class="all-box">
<view class="share-item" @click="downloadVlog()">
<view class="icon-wrapper" style="align-self: center;">
<image class="icon-image" src="/static/images/icon-download.png" style="align-self: center;"></image>
</view>
<text class="icon-tag-text" style="align-self: center;">保存到相册</text>
</view>
<view class="share-item" @click="copyLink()">
<view class="icon-wrapper" style="align-self: center;">
<image class="icon-image" src="/static/images/icon-copy.png" style="align-self: center;"></image>
</view>
<text class="icon-tag-text" style="align-self: center;">复制链接</text>
</view>
<view class="share-item" @click="gotoQRCode()">
<view class="icon-wrapper" style="align-self: center;">
<image class="icon-image" src="/static/images/icon-qrcode.png" style="align-self: center;"></image>
</view>
<text class="icon-tag-text" style="align-self: center;">二维码</text>
</view>
<!-- 判断只有我自己才能显示这个按钮 -->
<view v-if="(thisVlogerId == userId) && (isPrivate == 0)" class="share-item" @click="changeVlogToPrivate()">
<view class="icon-wrapper" style="align-self: center;">
<image class="icon-image" src="/static/images/icon-private.png" style="align-self: center;"></image>
</view>
<text class="icon-tag-text" style="align-self: center;">转为私密</text>
</view>
<view v-if="(thisVlogerId == userId) && (isPrivate == 1)" class="share-item" @click="changeVlogToPublic()">
<view class="icon-wrapper" style="align-self: center;">
<image class="icon-image" src="/static/images/icon-private.png" style="align-self: center;"></image>
</view>
<text class="icon-tag-text" style="align-self: center;">转为公开</text>
</view>
</view>
<view class="" style="padding: 0 20rpx;">
<!-- :class="{'btn-preplay':!preplayTouched, 'btn-preplay-touched': preplayTouched}"
@click="preview"
@touchstart="touchstartPreplay"
@touchend="touchendPreplay" -->
<view :class="{'btn-cancel':!cancelTouched, 'btn-cancel-touched': cancelTouched}"
@click="close"
@touchstart="touchstartCancel"
@touchend="touchendCancel"
style="height: 50px;display: flex;flex-direction: column;justify-content: center;border-width: 1rpx;border-radius: 10px;">
<text class="" style="color: #FFFFFF;font-size: 16px;align-self: center;align-self: center;">取消</text>
</view>
</view>
</view>
</template>
<script>
import storage from "@/utils/storage.js"; //
import {
vlogChangeToPublic,
vlogChangeToPrivate
} from "@/api/vlog"
import {
dateFormat,
graceNumber,
getDateBeforeNow
} from '@/utils/tools.js'
import popup from '../uni-popup/popup.js'
export default {
name: 'UniPopupShare',
mixins:[popup],
emits:['select'],
props: {
title: {
type: String,
default: ''
},
beforeClose: {
type: Boolean,
default: false
},
thisVlogerId: {
type: String,
default: ''
},
thisVlogId: {
type: String,
default: ''
},
vlogUrl: {
type: String,
default: ''
},
isPrivate: {
type: Number,
default: 0
}
},
data() {
return {
userId: "",
cancelTouched: false
}
},
created() {
var info = storage.getVlogUserInfo()
if(info==null){
// uni.showTabBar({
// animation: false
// });
// uni.navigateTo({
// url: "/pages/passport/login",
// animationType: "slide-in-bottom",
// });
// return;
}else{
this.userId = userId;
}
},
methods: {
/**
* 选择内容
*/
select(item, index) {
this.$emit('select', {
item,
index
})
this.close();
},
/**
* 关闭窗口
*/
close() {
if(this.beforeClose) return
this.popup.close();
uni.showTabBar({
animation: true
})
},
touchstartCancel() {
this.cancelTouched = true;
},
touchendCancel() {
this.cancelTouched = false;
},
downloadVlog() {
console.log("downloadVlog...thisVlogId = " + this.vlogUrl);
uni.showLoading();
uni.downloadFile({
url: this.vlogUrl,
success: (res) => {
if (res.statusCode === 200) {
console.log('下载成功');
uni.saveVideoToPhotosAlbum({
filePath: res.tempFilePath,
success: function () {
console.log('save success');
uni.hideLoading();
uni.showToast({
title: "保存成功~",
duration: 5000
})
}
});
}
}
});
},
copyLink() {
uni.setClipboardData({
data: this.vlogUrl,
success:()=>{
uni.showToast({//
title:'复制成功'
})
}
});
},
gotoQRCode() {
uni.navigateTo({
url: "/pages/qrcode/qrcode?vlogId=" + this.thisVlogId
})
},
async changeVlogToPublic() {
var vlogId = this.thisVlogId;
var me = this;
var info = storage.getVlogUserInfo()
var userId = info.id;
var result = await vlogChangeToPublic(userId,vlogId)
if (result.data.status == 200) {
uni.showToast({
title: "设置完毕~"
})
}
},
async changeVlogToPrivate() {
var vlogId = this.thisVlogId;
var me = this;
var info = storage.getVlogUserInfo()
var userId = info.id;
var result = await vlogChangeToPrivate(userId,vlogId)
if (result.data.status == 200) {
uni.showToast({
title: "设置完毕~"
})
}
}
}
}
</script>

View File

@ -0,0 +1,45 @@
// #ifdef H5
export default {
name: 'Keypress',
props: {
disable: {
type: Boolean,
default: false
}
},
mounted () {
const keyNames = {
esc: ['Esc', 'Escape'],
tab: 'Tab',
enter: 'Enter',
space: [' ', 'Spacebar'],
up: ['Up', 'ArrowUp'],
left: ['Left', 'ArrowLeft'],
right: ['Right', 'ArrowRight'],
down: ['Down', 'ArrowDown'],
delete: ['Backspace', 'Delete', 'Del']
}
const listener = ($event) => {
if (this.disable) {
return
}
const keyName = Object.keys(keyNames).find(key => {
const keyName = $event.key
const value = keyNames[key]
return value === keyName || (Array.isArray(value) && value.includes(keyName))
})
if (keyName) {
// 避免和其他按键事件冲突
setTimeout(() => {
this.$emit(keyName, {})
}, 0)
}
}
document.addEventListener('keyup', listener)
// this.$once('hook:beforeDestroy', () => {
// document.removeEventListener('keyup', listener)
// })
},
render: () => {}
}
// #endif

View File

@ -0,0 +1,26 @@
export default {
data() {
return {
}
},
created(){
this.popup = this.getParent()
},
methods:{
/**
* 获取父元素实例
*/
getParent(name = 'uniPopup') {
let parent = this.$parent;
let parentName = parent.$options.name;
while (parentName !== name) {
parent = parent.$parent;
if (!parent) return false
parentName = parent.$options.name;
}
return parent;
},
}
}

View File

@ -0,0 +1,404 @@
<template>
<view v-if="showPopup" class="uni-popup" :class="[popupstyle, isDesktop ? 'fixforpc-z-index' : '']" @touchmove.stop.prevent="clear">
<view @touchstart="touchstart" >
<uni-transition key="1" v-if="maskShow" name="mask" mode-class="fade" :styles="maskClass" :duration="duration" :show="showTrans" @click="onTap" />
<uni-transition key="2" :mode-class="ani" name="content" :styles="transClass" :duration="duration" :show="showTrans" @click="onTap">
<view class="uni-popup__wrapper" :style="{ backgroundColor: bg }" :class="[popupstyle]" @click="clear"><slot /></view>
</uni-transition>
</view>
<!-- #ifdef H5 -->
<keypress v-if="maskShow" @esc="onTap" />
<!-- #endif -->
</view>
</template>
<script>
// #ifdef H5
import keypress from './keypress.js'
// #endif
/**
* PopUp 弹出层
* @description 弹出层组件为了解决遮罩弹层的问题
* @tutorial https://ext.dcloud.net.cn/plugin?id=329
* @property {String} type = [top|center|bottom|left|right|message|dialog|share] 弹出方式
* @value top 顶部弹出
* @value center 中间弹出
* @value bottom 底部弹出
* @value left 左侧弹出
* @value right 右侧弹出
* @value message 消息提示
* @value dialog 对话框
* @value share 底部分享示例
* @property {Boolean} animation = [ture|false] 是否开启动画
* @property {Boolean} maskClick = [ture|false] 蒙版点击是否关闭弹窗
* @property {String} backgroundColor 主窗口背景色
* @property {Boolean} safeArea 是否适配底部安全区
* @event {Function} change 打开关闭弹窗触发e={show: false}
*/
export default {
name: 'uniPopup',
components: {
// #ifdef H5
keypress
// #endif
},
emits:['change','maskClick'],
props: {
//
animation: {
type: Boolean,
default: true
},
// top: bottomcenter
// message: ; dialog :
type: {
type: String,
default: 'center'
},
// maskClick
maskClick: {
type: Boolean,
default: true
},
backgroundColor: {
type: String,
default: 'none'
},
safeArea:{
type: Boolean,
default: true
}
},
watch: {
/**
* 监听type类型
*/
type: {
handler: function(type) {
if (!this.config[type]) return
this[this.config[type]](true)
},
immediate: true
},
isDesktop: {
handler: function(newVal) {
if (!this.config[newVal]) return
this[this.config[this.type]](true)
},
immediate: true
},
/**
* 监听遮罩是否可点击
* @param {Object} val
*/
maskClick: {
handler: function(val) {
this.mkclick = val
},
immediate: true
}
},
data() {
return {
duration: 300,
ani: [],
showPopup: false,
showTrans: false,
popupWidth: 0,
popupHeight: 0,
config: {
top: 'top',
bottom: 'bottom',
center: 'center',
left: 'left',
right: 'right',
message: 'top',
dialog: 'center',
share: 'bottom',
comment: 'bottom'
},
maskClass: {
position: 'fixed',
bottom: 0,
top: 0,
left: 0,
right: 0,
backgroundColor: 'rgba(0, 0, 0, 0.4)'
},
transClass: {
position: 'fixed',
left: 0,
right: 0
},
maskShow: true,
mkclick: true,
popupstyle: this.isDesktop ? 'fixforpc-top' : 'top'
}
},
computed: {
isDesktop() {
return this.popupWidth >= 500 && this.popupHeight >= 500
},
bg() {
if (this.backgroundColor === '' || this.backgroundColor === 'none') {
return 'transparent'
}
return this.backgroundColor
}
},
mounted() {
const fixSize = () => {
const { windowWidth, windowHeight, windowTop, safeAreaInsets } = uni.getSystemInfoSync()
this.popupWidth = windowWidth
this.popupHeight = windowHeight + windowTop
//
if(this.safeArea){
this.safeAreaInsets = safeAreaInsets
}else{
this.safeAreaInsets = 0
}
}
fixSize()
// #ifdef H5
// window.addEventListener('resize', fixSize)
// this.$once('hook:beforeDestroy', () => {
// window.removeEventListener('resize', fixSize)
// })
// #endif
},
created() {
this.mkclick = this.maskClick
if (this.animation) {
this.duration = 300
} else {
this.duration = 0
}
// TODO message
this.messageChild = null
// TODO
this.clearPropagation = false
},
methods: {
/**
* 公用方法不显示遮罩层
*/
closeMask() {
this.maskShow = false
},
/**
* 公用方法遮罩层禁止点击
*/
disableMask() {
this.mkclick = false
},
// TODO nvue
clear(e) {
// #ifndef APP-NVUE
e.stopPropagation()
// #endif
this.clearPropagation = true
},
open(direction) {
let innerType = ['top', 'center', 'bottom', 'left', 'right', 'message', 'dialog', 'share', 'comment']
if (!(direction && innerType.indexOf(direction) !== -1)) {
direction = this.type
}
if (!this.config[direction]) {
console.error('缺少类型:', direction)
return
}
this[this.config[direction]]()
this.$emit('change', {
show: true,
type: direction
})
},
close(type) {
this.showTrans = false
this.$emit('change', {
show: false,
type: this.type
})
clearTimeout(this.timer)
// //
// this.customOpen && this.customClose()
this.timer = setTimeout(() => {
this.showPopup = false
}, 300)
},
// TODO
touchstart(){
this.clearPropagation = false
},
onTap() {
if (this.clearPropagation) {
// fix by mehaotian nvue
this.clearPropagation = false
return
}
this.$emit('maskClick')
if (!this.mkclick) return
this.close();
// console.log("");
uni.showTabBar({
animation: true
})
},
/**
* 顶部弹出样式处理
*/
top(type) {
this.popupstyle = this.isDesktop ? 'fixforpc-top' : 'top'
this.ani = ['slide-top']
this.transClass = {
position: 'fixed',
left: 0,
right: 0,
backgroundColor: this.bg
}
// TODO type
if (type) return
this.showPopup = true
this.showTrans = true
this.$nextTick(() => {
if (this.messageChild && this.type === 'message') {
this.messageChild.timerClose()
}
})
},
/**
* 底部弹出样式处理
*/
bottom(type) {
this.popupstyle = 'bottom'
this.ani = ['slide-bottom']
this.transClass = {
position: 'fixed',
left: 0,
right: 0,
bottom: 0,
paddingBottom: (this.safeAreaInsets && this.safeAreaInsets.bottom) || 0,
backgroundColor: this.bg
}
// TODO type
if (type) return
this.showPopup = true
this.showTrans = true
},
/**
* 中间弹出样式处理
*/
center(type) {
this.popupstyle = 'center'
this.ani = ['zoom-out', 'fade']
this.transClass = {
position: 'fixed',
/* #ifndef APP-NVUE */
display: 'flex',
flexDirection: 'column',
/* #endif */
bottom: 0,
left: 0,
right: 0,
top: 0,
justifyContent: 'center',
alignItems: 'center'
}
// TODO type
if (type) return
this.showPopup = true
this.showTrans = true
},
left(type) {
this.popupstyle = 'left'
this.ani = ['slide-left']
this.transClass = {
position: 'fixed',
left: 0,
bottom: 0,
top: 0,
backgroundColor: this.bg,
/* #ifndef APP-NVUE */
display: 'flex',
flexDirection: 'column'
/* #endif */
}
// TODO type
if (type) return
this.showPopup = true
this.showTrans = true
},
right(type) {
this.popupstyle = 'right'
this.ani = ['slide-right']
this.transClass = {
position: 'fixed',
bottom: 0,
right: 0,
top: 0,
backgroundColor: this.bg,
/* #ifndef APP-NVUE */
display: 'flex',
flexDirection: 'column'
/* #endif */
}
// TODO type
if (type) return
this.showPopup = true
this.showTrans = true
}
}
}
</script>
<style lang="scss" scoped>
.uni-popup {
position: fixed;
/* #ifndef APP-NVUE */
z-index: 99;
/* #endif */
&.top,
&.left,
&.right {
/* #ifdef H5 */
top: var(--window-top);
/* #endif */
/* #ifndef H5 */
top: 0;
/* #endif */
}
.uni-popup__wrapper {
/* #ifndef APP-NVUE */
display: block;
/* #endif */
position: relative;
/* iphonex 等安全区设置,底部安全区适配 */
/* #ifndef APP-NVUE */
// padding-bottom: constant(safe-area-inset-bottom);
// padding-bottom: env(safe-area-inset-bottom);
/* #endif */
&.left,
&.right {
/* #ifndef H5 */
padding-top: 0;
/* #endif */
flex: 1;
}
}
}
.fixforpc-z-index {
/* #ifndef APP-NVUE */
z-index: 999;
/* #endif */
}
.fixforpc-top {
top: 0;
}
</style>

View File

@ -0,0 +1,85 @@
{
"id": "uni-popup",
"displayName": "uni-popup 弹出层",
"version": "1.6.1",
"description": " Popup 组件,提供常用的弹层",
"keywords": [
"uni-ui",
"弹出层",
"弹窗",
"popup",
"弹框"
],
"repository": "https://github.com/dcloudio/uni-ui",
"engines": {
"HBuilderX": ""
},
"directories": {
"example": "../../temps/example_temps"
},
"dcloudext": {
"category": [
"前端组件",
"通用组件"
],
"sale": {
"regular": {
"price": "0.00"
},
"sourcecode": {
"price": "0.00"
}
},
"contact": {
"qq": ""
},
"declaration": {
"ads": "无",
"data": "无",
"permissions": "无"
},
"npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui"
},
"uni_modules": {
"dependencies": [
"uni-transition"
],
"encrypt": [],
"platforms": {
"cloud": {
"tcb": "y",
"aliyun": "y"
},
"client": {
"App": {
"app-vue": "y",
"app-nvue": "y"
},
"H5-mobile": {
"Safari": "y",
"Android Browser": "y",
"微信浏览器(Android)": "y",
"QQ浏览器(Android)": "y"
},
"H5-pc": {
"Chrome": "y",
"IE": "y",
"Edge": "y",
"Firefox": "y",
"Safari": "y"
},
"小程序": {
"微信": "y",
"阿里": "y",
"百度": "y",
"字节跳动": "y",
"QQ": "y"
},
"快应用": {
"华为": "u",
"联盟": "u"
}
}
}
}
}

296
uni_modules/uni-popup/readme.md Executable file
View File

@ -0,0 +1,296 @@
## Popup 弹出层
> **组件名uni-popup**
> 代码块: `uPopup`
> 关联组件:`uni-popup-dialog`,`uni-popup-message`,`uni-popup-share`,`uni-transition`
弹出层组件,在应用中弹出一个消息提示窗口、提示框等
> **注意事项**
> 为了避免错误使用,给大家带来不好的开发体验,请在使用组件前仔细阅读下面的注意事项,可以帮你避免一些错误。
> - 组件需要依赖 `sass` 插件 ,请自行手动安装
> - `uni-popup-message``uni-popup-dialog` 等扩展ui组件需要和 `uni-popup` 配套使用,暂不支持单独使用
> - `nvue` 中使用 `uni-popup` 时,尽量将组件置于其他元素后面,避免出现层级问题
> - `uni-popup` 并不能完全阻止页面滚动,可在打开 `uni-popup` 的时候手动去做一些处理,禁止页面滚动
> - 如果想在页面渲染完毕后就打开 `uni-popup` ,请在 `onReady``mounted` 生命周期内调用,确保组件渲染完毕
> - 在微信小程序开发者工具中启用真机调试popup 会延时出现,是因为 setTimeout 在真机调试中的延时问题导致的,预览和发布小程序不会出现此问题
> - 使用 `npm` 方式引入组件,如果确认引用正确,但是提示未注册组件或显示不正常,请尝试重新编译项目
> - `uni-popup` 中尽量不要使用 `scroll-view` 嵌套过多的内容,可能会影响组件的性能,导致组件无法打开或者打开卡顿
> - `uni-popup` 不会覆盖原生 tabbar 和原生导航栏
> - 组件支持 nvue ,需要在 `manifest.json > app-plus` 节点下配置 `"nvueStyleCompiler" : "uni-app"`
> - 如使用过程中有任何问题或者您对uni-ui有一些好的建议欢迎加入 uni-ui 交流群871950839
### 安装方式
本组件符合[easycom](https://uniapp.dcloud.io/collocation/pages?id=easycom)规范,`HBuilderX 2.5.5`起,只需将本组件导入项目,在页面`template`中即可直接使用,无需在页面中`import`和注册`components`
如需通过`npm`方式使用`uni-ui`组件,另见文档:[https://ext.dcloud.net.cn/plugin?id=55](https://ext.dcloud.net.cn/plugin?id=55)
### 基本用法
**示例**
```html
<button @click="open">打开弹窗</button>
<uni-popup ref="popup" type="bottom">底部弹出 Popup</uni-popup>
```
```javascript
export default {
methods:{
open(){
// 通过组件定义的ref调用uni-popup方法 ,如果传入参数 type 属性将失效 ,仅支持 ['top','left','bottom','right','center']
this.$refs.popup.open('top')
}
}
}
```
### 设置主窗口背景色
在大多数场景下,并不需要设置 `background-color` 属性,因为`uni-popup`的主窗口默认是透明的,在向里面插入内容的时候 ,样式完全交由用户定制,如果设置了背景色 ,例如 `uni-popup-dialog` 中的圆角就很难去实现,不设置背景色,更适合用户去自由发挥。
而也有特例,需要我们主动去设置背景色,例如 `type = 'bottom'` 的时候 ,在异型屏中遇到了底部安全区问题(如 iphone 11因为 `uni-popup`的主要内容避开了安全区(设置`safe-area:true`),导致底部的颜色我们无法自定义,这时候使用 `background-color` 就可以解决这个问题。
**示例**
```html
<button @click="open">打开弹窗</button>
<uni-popup ref="popup" type="bottom" background-color="#fff">底部弹出 Popup</uni-popup>
```
### 禁用打开动画
在某些场景 ,可能不希望弹层有动画效果 ,只需要将 `animation` 属性设置为 `false` 即可以关闭动画。
**示例**
```html
<button @click="open">打开弹窗</button>
<uni-popup ref="popup" type="center" :animation="false">中间弹出 Popup</uni-popup>
```
### 禁用点击遮罩关闭
默认情况下,点击遮罩会自动关闭`uni-popup`,如不想点击关闭,只需将`mask-click`设置为`false`,这时候要关闭`uni-popup`,只能手动调用 `close` 方法。
**示例**
```html
<button @click="open">打开弹窗</button>
<uni-popup ref="popup" :mask-click="false">
<text>Popup</text>
<button @click="close">关闭</button>
</uni-popup>
```
```javascript
export default {
data() {
return {}
},
onReady() {},
methods: {
open() {
this.$refs.popup.open('top')
},
close() {
this.$refs.popup.close()
}
}
}
```
## API
### Popup Props
|属性名|类型|默认值|说明|
|:-:|:-:|:-:|:-:|
|animation|Boolean|true|是否开启动画|
|type|String|'center'|弹出方式|
|mask-click|Boolean|true|蒙版点击是否关闭弹窗|
|background-color|String|'none'|主窗口背景色|
|safe-area|Boolean|true|是否适配底部安全区|
#### Type Options
|属性名|说明|
|:-:| :-:|
|top|顶部弹出 |
|center|居中弹出|
|bottom|底部弹出|
|left|左侧弹出|
|right|右侧弹出|
|message|预置样式 :消息提示|
|dialog|预置样式 :对话框|
|share|预置样式 :底部弹出分享示例 |
### Popup Methods
|方法称名 |说明|参数|
|:-:|:-:|:-:|
|open|打开弹出层|open(String:type) ,如果参数可代替 type 属性|
|close|关闭弹出层 |-|
### Popup Events
|事件称名|说明|返回值|
|:-:|:-:|:-:|
|change|组件状态发生变化触发|e={show: truefalse,type:当前模式}|
|maskClick|点击遮罩层触发|-|
## 扩展组件说明
`uni-popup` 其实并没有任何样式,只提供基础的动画效果,给用户一个弹出层解决方案,仅仅是这样并不能满足开发需求,所以我们提供了三种基础扩展样式
### uni-popup-message 提示信息
`uni-popup``type`属性改为 `message`,并引入对应组件即可使用消息提示 *该组件不支持单独使用*
**示例**
```html
<uni-popup ref="popup" type="message">
<uni-popup-message type="success" message="成功消息" :duration="2000"></uni-popup-message>
</uni-popup>
```
### PopupMessage Props
|属性名|类型|默认值|说明|
|:-:|:-:|:-:|:-:|
|type|String|success|消息提示主题|
|message|String|-|消息提示文字|
|duration|Number|3000|消息显示时间超过显示时间组件自动关闭设置为0 将不会关闭,需手动调用 close 方法关闭|
#### Type Options
|属性名|说明|
|:-:| :-:|
|success|成功 |
|warn|警告|
|error|失败|
|info|消息|
### PopupMessage Slots
|名称|说明|
|:-:|:-:|
|default|消息内容,会覆盖 message 属性|
### uni-popup-dialog 对话框
`uni-popup``type`属性改为 `dialog`,并引入对应组件即可使用对话框 *该组件不支持单独使用*
**示例**
```html
<button @click="open">打开弹窗</button>
<uni-popup ref="popup" type="dialog">
<uni-popup-dialog mode="input" message="成功消息" :duration="2000" :before-close="true" @close="close" @confirm="confirm"></uni-popup-dialog>
</uni-popup>
```
```javascript
export default {
methods: {
open() {
this.$refs.popup.open()
},
/**
* 点击取消按钮触发
* @param {Object} done
*/
close() {
// TODO 做一些其他的事情before-close 为true的情况下手动执行 close 才会关闭对话框
// ...
this.$refs.popup.close()
},
/**
* 点击确认按钮触发
* @param {Object} done
* @param {Object} value
*/
confirm(value) {
// 输入框的值
console.log(value)
// TODO 做一些其他的事情,手动执行 close 才会关闭对话框
// ...
this.$refs.popup.close()
}
}
}
```
### PopupDialog Props
|属性名|类型|默认值|说明|
|:-:|:-:|:-:|:-:|
|type|String|success|对话框标题主题,可选值: success/warn/info/error|
|mode|String|base| 对话框模式可选值base提示对话框/input可输入对话框|
|title|String|-|对话框标题|
|content|String|-|对话框内容base模式下生效|
|value| String\Number|-|输入框默认值input模式下生效|
|placeholder|String|-|输入框提示文字input模式下生效|
|before-close|Boolean|false | 是否拦截按钮事件如为true则不会关闭对话框关闭需要手动执行 uni-popup 的 close 方法|
#### PopupDialog Events
|事件称名 |说明|返回值|
|:-:|:-:|:-:|
|close|点击dialog取消按钮触发|-|
|confirm|点击dialog确定按钮触发|e={value:input模式下输入框的值}|
### PopupDialog Slots
|名称|说明|
|:-:|:-:|
|default|自定义内容,回覆盖原有的内容显示|
### uni-popup-share 分享示例
分享示例,不作为最终可使用的组件,只做为样式组件,供用户自行修改,`后续的开发计划是实现实际的分享逻辑,参数可配置`
`uni-popup``type` 属性改为 `share`,并引入对应组件即可使用 *该组件不支持单独使用*
**示例**
```html
<uni-popup ref="popup" type="share">
<uni-popup-share title="分享到" @select="select"></uni-popup-share>
</uni-popup>
```
### PopupShare Props
|属性名|类型|默认值|说明|
|:-:|:-:|:-:| :-: |
|title|String|-|分享弹窗标题|
|before-close|Boolean|false | 是否拦截按钮事件如为true则不会关闭对话框关闭需要手动执行 uni-popup 的 close 方法|
### PopupShare Events
|事件称名|说明|返回值|
|:-:|:-:|:-:|
|select|选择触发|e = {item,index}:所选参数|
**Tips**
- share 分享组件,只是作为一个扩展示例,如果需要修改数据源,请到组件内修改
## 帮助
在使用中如遇到无法解决的问题,请提 [Issues](https://github.com/dcloudio/uni-ui/issues) 给我们。
## 组件示例
点击查看:[https://hellouniapp.dcloud.net.cn/pages/extUI/popup/popup](https://hellouniapp.dcloud.net.cn/pages/extUI/popup/popup)

View File

@ -0,0 +1,13 @@
## 1.2.02021-07-30
- 组件兼容 vue3如何创建vue3项目详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834)
## 1.1.12021-05-12
- 新增 示例地址
- 修复 示例项目缺少组件的Bug
## 1.1.02021-04-22
- 新增 通过方法自定义动画
- 新增 custom-class 非 NVUE 平台支持自定义 class 定制样式
- 优化 动画触发逻辑,使动画更流畅
- 优化 支持单独的动画类型
- 优化 文档示例
## 1.0.22021-02-05
- 调整为uni_modules目录规范

View File

@ -0,0 +1,128 @@
// const defaultOption = {
// duration: 300,
// timingFunction: 'linear',
// delay: 0,
// transformOrigin: '50% 50% 0'
// }
// #ifdef APP-NVUE
const nvueAnimation = uni.requireNativePlugin('animation')
// #endif
class MPAnimation {
constructor(options, _this) {
this.options = options
this.animation = uni.createAnimation(options)
this.currentStepAnimates = {}
this.next = 0
this.$ = _this
}
_nvuePushAnimates(type, args) {
let aniObj = this.currentStepAnimates[this.next]
let styles = {}
if (!aniObj) {
styles = {
styles: {},
config: {}
}
} else {
styles = aniObj
}
if (animateTypes1.includes(type)) {
if (!styles.styles.transform) {
styles.styles.transform = ''
}
let unit = ''
if(type === 'rotate'){
unit = 'deg'
}
styles.styles.transform += `${type}(${args+unit}) `
} else {
styles.styles[type] = `${args}`
}
this.currentStepAnimates[this.next] = styles
}
_animateRun(styles = {}, config = {}) {
let ref = this.$.$refs['ani'].ref
if (!ref) return
return new Promise((resolve, reject) => {
nvueAnimation.transition(ref, {
styles,
...config
}, res => {
resolve()
})
})
}
_nvueNextAnimate(animates, step = 0, fn) {
let obj = animates[step]
if (obj) {
let {
styles,
config
} = obj
this._animateRun(styles, config).then(() => {
step += 1
this._nvueNextAnimate(animates, step, fn)
})
} else {
this.currentStepAnimates = {}
typeof fn === 'function' && fn()
this.isEnd = true
}
}
step(config = {}) {
// #ifndef APP-NVUE
this.animation.step(config)
// #endif
// #ifdef APP-NVUE
this.currentStepAnimates[this.next].config = Object.assign({}, this.options, config)
this.currentStepAnimates[this.next].styles.transformOrigin = this.currentStepAnimates[this.next].config.transformOrigin
this.next++
// #endif
return this
}
run(fn) {
// #ifndef APP-NVUE
this.$.animationData = this.animation.export()
this.$.timer = setTimeout(() => {
typeof fn === 'function' && fn()
}, this.$.durationTime)
// #endif
// #ifdef APP-NVUE
this.isEnd = false
let ref = this.$.$refs['ani'] && this.$.$refs['ani'].ref
if(!ref) return
this._nvueNextAnimate(this.currentStepAnimates, 0, fn)
this.next = 0
// #endif
}
}
const animateTypes1 = ['matrix', 'matrix3d', 'rotate', 'rotate3d', 'rotateX', 'rotateY', 'rotateZ', 'scale', 'scale3d',
'scaleX', 'scaleY', 'scaleZ', 'skew', 'skewX', 'skewY', 'translate', 'translate3d', 'translateX', 'translateY',
'translateZ'
]
const animateTypes2 = ['opacity', 'backgroundColor']
const animateTypes3 = ['width', 'height', 'left', 'right', 'top', 'bottom']
animateTypes1.concat(animateTypes2, animateTypes3).forEach(type => {
MPAnimation.prototype[type] = function(...args) {
// #ifndef APP-NVUE
this.animation[type](...args)
// #endif
// #ifdef APP-NVUE
this._nvuePushAnimates(type, args)
// #endif
return this
}
})
export function createAnimation(option, _this) {
if(!_this) return
clearTimeout(_this.timer)
return new MPAnimation(option, _this)
}

View File

@ -0,0 +1,277 @@
<template>
<view v-if="isShow" ref="ani" :animation="animationData" :class="customClass" :style="transformStyles" @click="onClick"><slot></slot></view>
</template>
<script>
import { createAnimation } from './createAnimation'
/**
* Transition 过渡动画
* @description 简单过渡动画组件
* @tutorial https://ext.dcloud.net.cn/plugin?id=985
* @property {Boolean} show = [false|true] 控制组件显示或隐藏
* @property {Array|String} modeClass = [fade|slide-top|slide-right|slide-bottom|slide-left|zoom-in|zoom-out] 过渡动画类型
* @value fade 渐隐渐出过渡
* @value slide-top 由上至下过渡
* @value slide-right 由右至左过渡
* @value slide-bottom 由下至上过渡
* @value slide-left 由左至右过渡
* @value zoom-in 由小到大过渡
* @value zoom-out 由大到小过渡
* @property {Number} duration 过渡动画持续时间
* @property {Object} styles 组件样式 css 样式注意带-连接符的属性需要使用小驼峰写法如`backgroundColor:red`
*/
export default {
name: 'uniTransition',
emits:['click','change'],
props: {
show: {
type: Boolean,
default: false
},
modeClass: {
type: [Array, String],
default() {
return 'fade'
}
},
duration: {
type: Number,
default: 300
},
styles: {
type: Object,
default() {
return {}
}
},
customClass:{
type: String,
default: ''
}
},
data() {
return {
isShow: false,
transform: '',
opacity: 1,
animationData: {},
durationTime: 300,
config: {}
}
},
watch: {
show: {
handler(newVal) {
if (newVal) {
this.open()
} else {
// close,
if (this.isShow) {
this.close()
}
}
},
immediate: true
}
},
computed: {
//
stylesObject() {
let styles = {
...this.styles,
'transition-duration': this.duration / 1000 + 's'
}
let transform = ''
for (let i in styles) {
let line = this.toLine(i)
transform += line + ':' + styles[i] + ';'
}
return transform
},
//
transformStyles() {
return 'transform:' + this.transform + ';' + 'opacity:' + this.opacity + ';' + this.stylesObject
}
},
created() {
//
this.config = {
duration: this.duration,
timingFunction: 'ease',
transformOrigin: '50% 50%',
delay: 0
}
this.durationTime = this.duration
},
methods: {
/**
* ref 触发 初始化动画
*/
init(obj = {}) {
if (obj.duration) {
this.durationTime = obj.duration
}
this.animation = createAnimation(Object.assign(this.config, obj))
},
/**
* 点击组件触发回调
*/
onClick() {
this.$emit('click', {
detail: this.isShow
})
},
/**
* ref 触发 动画分组
* @param {Object} obj
*/
step(obj, config = {}) {
if (!this.animation) return
for (let i in obj) {
try {
if(typeof obj[i] === 'object'){
this.animation[i](...obj[i])
}else{
this.animation[i](obj[i])
}
} catch (e) {
console.error(`方法 ${i} 不存在`)
}
}
this.animation.step(config)
return this
},
/**
* ref 触发 执行动画
*/
run(fn) {
if (!this.animation) return
this.animation.run(fn)
},
//
open() {
clearTimeout(this.timer)
this.transform = ''
this.isShow = true
let { opacity, transform } = this.styleInit(false)
if (typeof opacity !== 'undefined') {
this.opacity = opacity
}
this.transform = transform
// nextTick wx
this.$nextTick(() => {
// TODO
this.timer = setTimeout(() => {
this.animation = createAnimation(this.config, this)
this.tranfromInit(false).step()
this.animation.run()
this.$emit('change', {
detail: this.isShow
})
}, 20)
})
},
//
close(type) {
if (!this.animation) return
this.tranfromInit(true)
.step()
.run(() => {
this.isShow = false
this.animationData = null
this.animation = null
let { opacity, transform } = this.styleInit(false)
this.opacity = opacity || 1
this.transform = transform
this.$emit('change', {
detail: this.isShow
})
})
},
//
styleInit(type) {
let styles = {
transform: ''
}
let buildStyle = (type, mode) => {
if (mode === 'fade') {
styles.opacity = this.animationType(type)[mode]
} else {
styles.transform += this.animationType(type)[mode] + ' '
}
}
if (typeof this.modeClass === 'string') {
buildStyle(type, this.modeClass)
} else {
this.modeClass.forEach(mode => {
buildStyle(type, mode)
})
}
return styles
},
//
tranfromInit(type) {
let buildTranfrom = (type, mode) => {
let aniNum = null
if (mode === 'fade') {
aniNum = type ? 0 : 1
} else {
aniNum = type ? '-100%' : '0'
if (mode === 'zoom-in') {
aniNum = type ? 0.8 : 1
}
if (mode === 'zoom-out') {
aniNum = type ? 1.2 : 1
}
if (mode === 'slide-right') {
aniNum = type ? '100%' : '0'
}
if (mode === 'slide-bottom') {
aniNum = type ? '100%' : '0'
}
}
this.animation[this.animationMode()[mode]](aniNum)
}
if (typeof this.modeClass === 'string') {
buildTranfrom(type, this.modeClass)
} else {
this.modeClass.forEach(mode => {
buildTranfrom(type, mode)
})
}
return this.animation
},
animationType(type) {
return {
fade: type ? 1 : 0,
'slide-top': `translateY(${type ? '0' : '-100%'})`,
'slide-right': `translateX(${type ? '0' : '100%'})`,
'slide-bottom': `translateY(${type ? '0' : '100%'})`,
'slide-left': `translateX(${type ? '0' : '-100%'})`,
'zoom-in': `scaleX(${type ? 1 : 0.8}) scaleY(${type ? 1 : 0.8})`,
'zoom-out': `scaleX(${type ? 1 : 1.2}) scaleY(${type ? 1 : 1.2})`
}
},
//
animationMode() {
return {
fade: 'opacity',
'slide-top': 'translateY',
'slide-right': 'translateX',
'slide-bottom': 'translateY',
'slide-left': 'translateX',
'zoom-in': 'scale',
'zoom-out': 'scale'
}
},
// 线
toLine(name) {
return name.replace(/([A-Z])/g, '-$1').toLowerCase()
}
}
}
</script>
<style></style>

View File

@ -0,0 +1,83 @@
{
"id": "uni-transition",
"displayName": "uni-transition 过渡动画",
"version": "1.2.0",
"description": "元素的简单过渡动画",
"keywords": [
"uni-ui",
"uniui",
"动画",
"过渡",
"过渡动画"
],
"repository": "https://github.com/dcloudio/uni-ui",
"engines": {
"HBuilderX": ""
},
"directories": {
"example": "../../temps/example_temps"
},
"dcloudext": {
"category": [
"前端组件",
"通用组件"
],
"sale": {
"regular": {
"price": "0.00"
},
"sourcecode": {
"price": "0.00"
}
},
"contact": {
"qq": ""
},
"declaration": {
"ads": "无",
"data": "无",
"permissions": "无"
},
"npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui"
},
"uni_modules": {
"dependencies": [],
"encrypt": [],
"platforms": {
"cloud": {
"tcb": "y",
"aliyun": "y"
},
"client": {
"App": {
"app-vue": "y",
"app-nvue": "y"
},
"H5-mobile": {
"Safari": "y",
"Android Browser": "y",
"微信浏览器(Android)": "y",
"QQ浏览器(Android)": "y"
},
"H5-pc": {
"Chrome": "y",
"IE": "y",
"Edge": "y",
"Firefox": "y",
"Safari": "y"
},
"小程序": {
"微信": "y",
"阿里": "y",
"百度": "y",
"字节跳动": "y",
"QQ": "y"
},
"快应用": {
"华为": "u",
"联盟": "u"
}
}
}
}
}

View File

@ -0,0 +1,397 @@
## Transition 过渡动画
> **组件名uni-transition**
> 代码块: `uTransition`
元素过渡动画
> **注意事项**
> 为了避免错误使用,给大家带来不好的开发体验,请在使用组件前仔细阅读下面的注意事项,可以帮你避免一些错误。
> - 组件需要依赖 `sass` 插件 ,请自行手动安装
> - rotate 旋转动画不需要填写 deg 单位,在小程序上填写单位动画不会执行
> - NVUE 下修改宽高动画,不能定位到中心点
> - 百度小程序下修改宽高 ,可能会影响其他动画,需注意
> - nvue 不支持 costom-class , 请使用 styles
> - 如使用过程中有任何问题或者您对uni-ui有一些好的建议欢迎加入 uni-ui 交流群871950839
### 安装方式
本组件符合[easycom](https://uniapp.dcloud.io/collocation/pages?id=easycom)规范,`HBuilderX 2.5.5`起,只需将本组件导入项目,在页面`template`中即可直接使用,无需在页面中`import`和注册`components`
如需通过`npm`方式使用`uni-ui`组件,另见文档:[https://ext.dcloud.net.cn/plugin?id=55](https://ext.dcloud.net.cn/plugin?id=55)
### 基本用法
在 ``template`` 中使用组件
```html
<template>
<view>
<button type="primary" @click="open">fade</button>
<uni-transition mode-class="fade" :styles="{'width':'100px','height':'100px','backgroundColor':'red'}" :show="show" @change="change" />
</view>
</template>
<script>
export default {
data() {
return {
show: false,
}
},
onLoad() {},
methods: {
open(mode) {
this.show = !this.show
},
change() {
console.log('触发动画')
}
}
}
</script>
```
### 样式覆盖
**注意:`nvue` 不支持 `custom-class` 属性 ,需要使用 `styles` 属性进行兼容**
使用 `custom-class` 属性绑定样式,可以自定义 `uni-transition` 的样式
```html
<template>
<view class="content">
<uni-transition custom-class="custom-transition" mode-class="fade" :duration="0" :show="true" />
</view>
</template>
<style>
/* 常规样式覆盖 */
.content >>> .custom-transition {
width:100px;
height:100px;
background-color:red;
}
</style>
<style lang="scss">
/* 如果使用 scss 需要使用 /deep/ */
.content /deep/ .custom-transition {
width:100px;
height:100px;
background-color:red;
}
</style>
```
如果使用 `styles` 注意带’-‘连接符的属性需要使用小驼峰写法如:`backgroundColor:red`
```html
<template>
<view class="content">
<uni-transition :styles="styles" mode-class="fade" :duration="0" :show="true" />
</view>
</template>
<script>
export default {
data() {
return {
styles:{
'width':'100px',
'height':'100px',
'backgroundColor':'red'
}
}
}
}
</script>
```
### 自定义动画
当内置动画类型不能满足需求的时候 ,可以使用 `step()``run()` 自定义动画,入参以及具体用法参考下方属性说明
`init()` 方法可以覆盖默认配置
```html
<template>
<view>
<button type="primary" @click="run">执行动画</button>
<uni-transition ref="ani" :styles="{'width':'100px','height':'100px','backgroundColor':'red'}" :show="show" />
</view>
</template>
<script>
export default {
data() {
return {
show: true,
}
},
onReady() {
this.$refs.ani.init({
duration: 1000,
timingFunction: 'linear',
transformOrigin: '50% 50%',
delay: 500
})
},
methods: {
run() {
// 同时右平移到 100px,旋转 360 读
this.$refs.ani.step({
translateX: '100px',
rotate: '360'
})
// 上面的动画执行完成后等待200毫秒平移到 0px,旋转到 0 读
this.$refs.ani.step({
translateX: '0px',
rotate: '0'
},
{
timingFunction: 'ease-in',
duration: 200
})
// 开始执行动画
this.$refs.ani.run(()=>{
console.log('动画支持完毕')
})
}
}
}
</script>
```
## API
### Transition Props
|属性名 |类型 |默认值 |说明 |
|:-: |:-: |:-: |:-:|
|show |Boolean|false |控制组件显示或隐藏 |
|mode-class |Array/String |- |内置过渡动画类型 |
|custom-class |String |- |自定义类名 |
|duration |Number |300 |过渡动画持续时间 |
|styles |Object |- |组件样式,同 css 样式,注意带’-‘连接符的属性需要使用小驼峰写法如:`backgroundColor:red` |
#### mode-class 内置过渡动画类型说明
**格式为** `'fade'` 或者 `['fade','slide-top']`
|属性名 |说明 |
|:-: |:-: |
|fade |渐隐渐出过渡 |
|slide-top |由上至下过渡 |
|slide-right |由右至左过渡 |
|slide-bottom |由下至上过渡 |
|slide-left |由左至右过渡 |
|zoom-in |由小到大过渡 |
|zoom-out |由大到小过渡 |
**注意**
组合使用时同一种类型相反的过渡动画如slide-top、slide-bottom同时使用时只有最后一个生效
### Transition Events
|事件名 |说明 |返回值 |
|:-: |:-: |:-: |
|click |点击组件触发 |- |
|change |过渡动画结束时触发 | e = {detail:true} |
### Transition Methons
|方法名|说明|参数|
|:-:|:-:|:-:|
|init()|手动初始化配置|Function(OBJECT:config)|
|step()|动画队列|Function(OBJECT:type,OBJECT:config)|
|run()|执行动画|Function(FUNCTION:callback) |
### init(OBJECT:config)
**通过 ref 调用方法**
手动设置动画配置,需要在页面渲染完毕后调用
```javascript
this.$refs.ani.init({
duration: 1000,
timingFunction:'ease',
delay:500,
transformOrigin:'left center'
})
```
### step(OBJECT:type,OBJECT:config) 动画队列
**通过 ref 调用方法**
调用 `step()` 来表示一组动画完成,`step` 第一个参数可以传入任意多个动画方法,一组动画中的所有动画会同时开始,一组动画完成后才会进行下一组动画。`step` 第二个参数可以传入一个跟 `uni.createAnimation()` 一样的配置参数用于指定当前组动画的配置。
Tips
- 第一个参数支持的动画参考下面的 `支持的动画`
- 第二个参数参考下面的 `动画配置`,可省略,如果省略继承`init`的配置
```javascript
this.$refs.ani.step({
translateX: '100px'
},{
duration: 1000,
timingFunction:'ease',
delay:500,
transformOrigin:'left center'
})
```
### run(FUNCTION:callback) 执行动画
**通过 ref 调用方法**
在执行 `step()` 后,需要调用 `run()` 来运行动画 ,否则动画会一直等待
`run()` 方法可以传入一个 `callback` 函数 ,会在所有动画执行完毕后回调
```javascript
this.$refs.ani.step({
translateX: '100px'
})
this.$refs.ani.run(()=>{
console.log('动画执行完毕')
})
```
### 动画配置
动画配置 `init()``step()` 第二个参数配置相同 ,如果配置`step() `第二个参数,将会覆盖 `init()` 的配置
|属性名|值|必填|默认值|说明|平台差异|
|:-:|:-:|:-:|:-:|:-:|:-:|
|duration|Number|否|400|动画持续时间单位ms|-|
|timingFunction|String|否|"linear"|定义动画的效果|-|
|delay|Number|否|0|动画延迟时间,单位 ms|-|
|needLayout|Boolean|否|false |动画执行是否影响布局|仅 nvue 支持|
|transformOrigin|String |否|"center center"|设置 [transform-origin](https://developer.mozilla.org/en-US/docs/Web/CSS/transform-origin)|-|
### timingFunction 属性说明
|值|说明|平台差异|
|:-:|:-:|:-:|
|linear|动画从头到尾的速度是相同的|-|
|ease|动画以低速开始,然后加快,在结束前变慢|-|
|ease-in| 动画以低速开始|-|
|ease-in-out| 动画以低速开始和结束|-|
|ease-out|动画以低速结束|-|
|step-start|动画第一帧就跳至结束状态直到结束|nvue不支持|
|step-end|动画一直保持开始状态,最后一帧跳到结束状态|nvue不支持|
```javascript
// init 配置
this.$refs.ani.init({
duration: 1000,
timingFunction:'ease',
delay:500,
transformOrigin:'left center'
})
// step 配置
this.$refs.ani.step({
translateX: '100px'
},{
duration: 1000,
timingFunction:'ease',
delay:500,
transformOrigin:'left center'
})
```
### 支持的动画
动画方法
如果同一个动画方法有多个值,多个值使用数组分隔
```javascript
this.$refs.ani.step({
width:'100px',
scale: [1.2,0.8],
})
```
**样式:**
|属性名|值|说明|平台差异|
|:-:|:-:|:-:|:-:|
|opacity|value|透明度,参数范围 0~1|-|
|backgroundColor|color|颜色值|-|
|width|length|长度值,如果传入 Number 则默认使用 px可传入其他自定义单位的长度值|-|
|height|length|长度值,如果传入 Number 则默认使用 px可传入其他自定义单位的长度值|-|
|top|length|长度值,如果传入 Number 则默认使用 px可传入其他自定义单位的长度值|nvue 不支持|
|left|length|长度值,如果传入 Number 则默认使用 px可传入其他自定义单位的长度值|nvue 不支持|
|bottom|length|长度值,如果传入 Number 则默认使用 px可传入其他自定义单位的长度值|nvue 不支持|
|right|length|长度值,如果传入 Number 则默认使用 px可传入其他自定义单位的长度值|nvue 不支持|
```javascript
this.$refs.ani.step({
opacity: 1,
backgroundColor: '#ff5a5f',
widht:'100px',
height:'50rpx',
})
```
**旋转:**
旋转属性的值不需要填写单位
|属性名|值|说明|平台差异 |
|:-:|:-:|:-:|:-:|
|rotate|deg|deg的范围-180~180从原点顺时针旋转一个deg角度 |-|
|rotateX|deg|deg的范围-180~180在X轴旋转一个deg角度 |-|
|rotateY|deg|deg的范围-180~180在Y轴旋转一个deg角度 |-|
|rotateZ|deg|deg的范围-180~180在Z轴旋转一个deg角度 |nvue不支持|
|rotate3d|x,y,z,deg| 同 [transform-function rotate3d](https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function/rotate3d()) |nvue不支持|
```javascript
this.$refs.ani.step({
rotateX: 45,
rotateY: 45
})
```
**缩放:**
|属性名|值|说明|平台差异|
|:-:|:-:|:-: |:-:|
|scale|sx,[sy]|一个参数时表示在X轴、Y轴同时缩放sx倍数两个参数时表示在X轴缩放sx倍数在Y轴缩放sy倍数|-|
|scaleX|sx|在X轴缩放sx倍数|-|
|scaleY|sy|在Y轴缩放sy倍数|-|
|scaleZ|sz|在Z轴缩放sy倍数|nvue不支持|
|scale3d|sx,sy,sz|在X轴缩放sx倍数在Y轴缩放sy倍数在Z轴缩放sz倍数|nvue不支持|
```javascript
this.$refs.ani.step({
scale: [1.2,0.8]
})
```
**偏移:**
|属性名|值|说明|平台差异|
|:-:|:-:|:-:|:-:|
|translate|tx,[ty]|一个参数时表示在X轴偏移tx单位px两个参数时表示在X轴偏移tx在Y轴偏移ty单位px。|-|
|translateX|tx| 在X轴偏移tx单位px|-|
|translateY|ty| 在Y轴偏移tx单位px|-|
|translateZ|tz| 在Z轴偏移tx单位px|nvue不支持|
|translate3d|tx,ty,tz| 在X轴偏移tx在Y轴偏移ty在Z轴偏移tz单位px|nvue不支持|
```javascript
this.$refs.ani.step({
translateX: '100px'
})
```
## 组件示例
点击查看:[https://hellouniapp.dcloud.net.cn/pages/extUI/transition/transition](https://hellouniapp.dcloud.net.cn/pages/extUI/transition/transition)

View File

@ -81,9 +81,12 @@ export function checkBankno(bankno) {
*/
export function whetherNavigate(type = "default") {
let navigation = getCurrentPages()[getCurrentPages().length - (getCurrentPages().length ) ];
let navigation = getCurrentPages()[getCurrentPages().length - (getCurrentPages().length ) ];
console.log(navigation.route)
console.log(getCurrentPages().length)
uni.setStorageSync('refreshVlogIndex','1') //需要刷新
if (getCurrentPages().length > 1) {
console.log(navigation, getCurrentPages());
// console.log(navigation, getCurrentPages());
if (navigation.route == "pages/passport/login") {
navigationToBack(type);
} else {
@ -94,10 +97,11 @@ export function whetherNavigate(type = "default") {
delta: getCurrentPages().length,
});
}
}
}
} else {
uni.switchTab({
url: "/pages/tabbar/home/index",
url: "/pages/tabbar/vlog/index",
});
}
}
@ -224,7 +228,7 @@ function navigationToBack(type) {
});
} else {
uni.switchTab({
url: "/pages/tabbar/home/index",
url: "/pages/tabbar/vlog/index",
});
}
}

View File

@ -30,9 +30,9 @@ function cleanStorage() {
// 清理vlog信息
storage.setVlogToken("")
storage.setVlogUserInfo({})
// 清除初始化数据内容
storage.setRefreshVlogIndex('0') //不需要刷新
// 防抖处理跳转
// #ifdef MP-WEIXIN
@ -194,6 +194,9 @@ http.interceptors.response.use(
duration: 1500,
});
}
}
else if (response.data.code==502){
cleanStorage();
}
return response;
},

View File

@ -11,7 +11,15 @@ const FINGER_LOGIN = isDev ? "finger_login_dev" : "finger_login";
const CART_BACKBTN = isDev ? "cart_backbtn_dev" : "cart_backbtn";
const AFTERSALE_DATA = isDev ? "aftersale_data_dev" : "aftersale_data";
export default {
/**
* 写入RefreshVlogIndex
*/
setRefreshVlogIndex(val) {
return uni.setStorageSync('refreshVlogIndex',val) //0=不需要刷新
},
getRefreshVlogIndex() {
return uni.getStorageSync('refreshVlogIndex') //0=不需要刷新
},
/**
* 获取Vlogtoken
*/
@ -34,7 +42,7 @@ export default {
* 获取VlogUserInfo
*/
getVlogUserInfo(val) {
return uni.getStorageSync(VLOG_USER_INFO);
return uni.getStorageSync(VLOG_USER_INFO)||null;
},
// 写入热门搜索时间戳

View File

@ -151,6 +151,82 @@ const isStrEmpty = (str) => {
}
}
// 获得星座
const getAstro = (m, d) => {
return "魔羯水瓶双鱼白羊金牛双子巨蟹狮子处女天秤天蝎射手魔羯".substr(
m * 2 - (d < "102223444433".charAt(m - 1) - -19) * 2,
2
);
}
// 获得生肖
const getAnimal = (year) => {
year = year % 12;
let animal = "";
switch (year) {
case 1:
animal = "鸡";
break;
case 2:
animal = "狗";
break;
case 3:
animal = "猪";
break;
case 4:
animal = "鼠";
break;
case 5:
animal = "牛";
break;
case 6:
animal = "虎";
break;
case 7:
animal = "兔";
break;
case 8:
animal = "龙";
break;
case 9:
animal = "蛇";
break;
case 10:
animal = "马";
break;
case 11:
animal = "羊";
break;
case 0:
animal = "猴";
break;
}
return animal;
}
// 日期格式化
const dateFormat = (fmt, date) => {
let ret;
const opt = {
"Y+": date.getFullYear().toString(), // 年
"m+": (date.getMonth() + 1).toString(), // 月
"d+": date.getDate().toString(), // 日
"H+": date.getHours().toString(), // 时
"M+": date.getMinutes().toString(), // 分
"S+": date.getSeconds().toString(), // 秒
};
for (let k in opt) {
ret = new RegExp("(" + k + ")").exec(fmt);
if (ret) {
fmt = fmt.replace(
ret[1],
ret[1].length == 1 ? opt[k] : opt[k].padStart(ret[1].length, "0")
);
}
}
return fmt;
}
export {
getNetworkType,
@ -158,6 +234,9 @@ export {
countTimeDown,
theNextDayTime,
graceNumber,
getDateBeforeNow,
isStrEmpty
getDateBeforeNow,
isStrEmpty,
getAstro,
getAnimal,
dateFormat
};