客户端app
This commit is contained in:
@@ -0,0 +1,620 @@
|
||||
<template>
|
||||
<view class="friendsCircle-content-item">
|
||||
<image class="friendsCircle-content-avatar" :src="content.avatar" mode="aspectFill"></image>
|
||||
<view class="friendsCircle-content-right">
|
||||
<view class="friendsCircle-content-nikeName">{{ content.nikeName }}</view>
|
||||
<view class="friendsCircle-content-text">{{ content.text }}</view>
|
||||
<view class="friendsCircle-content-imgs" v-if="content.topicType=='IMAGE'&&content.files.length>0">
|
||||
<image v-for="(item, ii) in content.files" :key="ii" class="friendsCircle-content-img" :class="'fci' + content.files.length" :src="item.url" mode="aspectFill" @click="pimgs(content.files,ii)"></image>
|
||||
</view>
|
||||
<view class="friendsCircle-content-video" @click="openVideo(content.files[0].videoUrl)" v-if="content.topicType=='VIDEO'&&content.files.length>0">
|
||||
<image class="friendsCircle-content-video-icon" src="../../static/img/bf.png" mode="aspectFill"></image>
|
||||
<image class="friendsCircle-content-video-img" :src="content.files[0].url" mode="aspectFill"></image>
|
||||
</view>
|
||||
<view v-if="content.location" class="friendsCircle-content-location" @click="goMap(content.location)">{{ content.location.name }}</view>
|
||||
<view class="friendsCircle-content-tools">
|
||||
<view class="friendsCircle-content-time">{{ content.time }}</view>
|
||||
<view class="friendsCircle-content-tool" :class="{ 'tabon': tabToolIndex }">
|
||||
<view class="wxfont caidan" @click="tabTool(i)"></view>
|
||||
<view class="friendsCircle-content-tool-absolute">
|
||||
<view class="friendsCircle-popup">
|
||||
<view class="friendsCircle-popup-item" @click="zan(content)">
|
||||
<view class="friendsCircle-popup-icon wxfont zan"></view>
|
||||
<view class="friendsCircle-popup-text" v-if="content.like=='Y'">取消</view>
|
||||
<view class="friendsCircle-popup-text" v-else>赞</view>
|
||||
</view>
|
||||
<view class="friendsCircle-popup-item" @click="comment(content)">
|
||||
<view class="friendsCircle-popup-icon wxfont pinglun"></view>
|
||||
<view class="friendsCircle-popup-text">评论</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
</view>
|
||||
|
||||
</view>
|
||||
<view class="friendsCircle-content-item-detail">
|
||||
<view class="friendsCircle-content-item-detail-item" v-if="content.likeList&&content.likeList.length>0">
|
||||
<view class="friendsCircle-like-icon wxfont zan"></view>
|
||||
<view class="friendsCircle-like">
|
||||
<image class="friendsCircle-like-img" mode="aspectFill" v-for="(z,zindex) in content.likeList" :src="z.portrait"></image>
|
||||
</view>
|
||||
</view>
|
||||
<view class="friendsCircle-content-item-detail-item" v-if="content.replyList&&content.replyList.length>0">
|
||||
<view class="friendsCircle-comment-icon wxfont pinglun"></view>
|
||||
<view class="friendsCircle-comment">
|
||||
<view class="friendsCircle-comment-item" v-for="(c,ci) in content.replyList" :key="ci">
|
||||
<image class="friendsCircle-comment-img" :src="c.portrait" mode="aspectFill"></image>
|
||||
<view class="friendsCircle-comment-item-text">
|
||||
<view class="friendsCircle-comment-item-name">
|
||||
<text class="friendsCircle-comment-text">{{c.nickName}}</text>
|
||||
<text class="friendsCircle-comment-item-time">{{c.createTime}}</text>
|
||||
</view>
|
||||
<view style="width: 100%;" @click="replyclick(c,ci)">
|
||||
<view class="friendsCircle-comment-feedback" v-if="c.replyType=='2'">
|
||||
<text>回复</text>
|
||||
<text class="friendsCircle-comment-text">{{c.toNickName}}</text>
|
||||
</view>
|
||||
<text class="friendsCircle-comment-textx">{{c.content}}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view style="height: 120rpx;"></view>
|
||||
<view class="zfb-tk-send-tool" :style="{bottom:keyboardHeight+'px'}">
|
||||
<form @submit="sendMsg(msg)">
|
||||
<view class="zfb-tk-send-tool-c">
|
||||
<view class="zfb-tk-send-tool-input-box" @click="msgFocus=true">
|
||||
<textarea class="zfb-tk-send-tool-input" :adjust-position="false" :focus="msgFocus" v-model="msg" :placeholder="placeholder" confirm-type="send" @confirm="sendMsg(msg)" hold-keyboard :maxlength="-1" auto-height />
|
||||
</view>
|
||||
<view class="zfb-tk-send-tool-text" @click="sendMsg(msg)" :style="{ background: msg !== '' ? '#1BC418' : '#F7F7F7', color: msg !== '' ? '#fff' : '#ddd', 'border-color': msg !== '' ? '#1BC418' : '#ddd' }">发送</view>
|
||||
</view>
|
||||
</form>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
// 朋友圈列表内容区
|
||||
data() {
|
||||
return {
|
||||
timer:null,
|
||||
placeholder:'评论',
|
||||
keyboardHeight:0,
|
||||
msg: '',
|
||||
type:'msg',
|
||||
replydata:'',
|
||||
msgFocus:false,
|
||||
tabToolIndex: false,
|
||||
content:this.detail
|
||||
};
|
||||
},
|
||||
props:{
|
||||
detail:{
|
||||
type:Object
|
||||
}
|
||||
},
|
||||
watch:{
|
||||
detail(v){
|
||||
this.content=v
|
||||
}
|
||||
},
|
||||
computed:{
|
||||
userInfo(){
|
||||
return this.$store.state.userInfo
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
// #ifdef APP-PLUS
|
||||
uni.onKeyboardHeightChange(res => {
|
||||
this.keyboardHeight=res.height
|
||||
})
|
||||
// #endif
|
||||
},
|
||||
methods: {
|
||||
scrolltoBottom() {
|
||||
this.$nextTick(()=>{
|
||||
this.timer = setTimeout(() => {
|
||||
uni.pageScrollTo({
|
||||
scrollTop: 9999999,
|
||||
duration: 10
|
||||
});
|
||||
this.$forceUpdate()
|
||||
}, 100);
|
||||
})
|
||||
},
|
||||
replyclick(e,ci){
|
||||
if(e.canDeleted=='Y'){
|
||||
this.hidenTool()
|
||||
uni.showActionSheet({
|
||||
itemList: ['复制','删除'],
|
||||
success: (res) => {
|
||||
switch (res.tapIndex){
|
||||
case 0:
|
||||
uni.setClipboardData({
|
||||
data: e.content,
|
||||
success: function() {
|
||||
uni.showToast({
|
||||
title: '复制成功',
|
||||
icon: 'none',
|
||||
position: 'bottom'
|
||||
})
|
||||
}
|
||||
});
|
||||
break;
|
||||
case 1:
|
||||
this.$http.request({
|
||||
url: '/topic/removeReply/'+e.replyId,
|
||||
success: (res) => {
|
||||
if (res.data.code == 200) {
|
||||
uni.showToast({
|
||||
title:'删除成功',
|
||||
icon:'none'
|
||||
})
|
||||
this.content.replyList.splice(ci,1)
|
||||
}
|
||||
}
|
||||
});
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
}else{
|
||||
this.replydata=e
|
||||
this.type='reply'
|
||||
this.placeholder='回复'+e.nickName
|
||||
this.$nextTick(()=>{
|
||||
this.msgFocus=true
|
||||
})
|
||||
}
|
||||
},
|
||||
gofriend(e){
|
||||
uni.navigateTo({
|
||||
url:'../../wx/personInfo/detail?param='+e.userId
|
||||
})
|
||||
},
|
||||
pimgs(arr,ii){
|
||||
var imgs=[]
|
||||
for (var i = 0; i < arr.length; i++) {
|
||||
imgs.push(arr[i].url)
|
||||
}
|
||||
this.$fc.previewImages(imgs, ii)
|
||||
},
|
||||
goMap(e) {
|
||||
uni.openLocation({
|
||||
latitude: e.latitude,
|
||||
longitude: e.longitude,
|
||||
success: function() {}
|
||||
});
|
||||
},
|
||||
openVideo(e){
|
||||
this.$fc.plusDownload({onlinePath:e}).then(res=>{
|
||||
this.$fc.plusOpenFile({filePath:res})
|
||||
})
|
||||
},
|
||||
tabTool(e) {
|
||||
this.tabToolIndex=!this.tabToolIndex
|
||||
},
|
||||
comment(e) {
|
||||
this.hidenTool()
|
||||
//评论
|
||||
this.type='msg'
|
||||
this.placeholder='评论'
|
||||
this.$nextTick(()=>{
|
||||
this.msgFocus=true
|
||||
})
|
||||
},
|
||||
zan(e,i){//点赞
|
||||
switch (e.like){
|
||||
case 'N':
|
||||
this.$http.request({
|
||||
url: '/topic/like/'+e.topicId,
|
||||
success: (res) => {
|
||||
if (res.data.code == 200) {
|
||||
var like=e.like=='N' ? e.like='Y' : e.like='N'
|
||||
this.content.like=like
|
||||
this.content.likeList.push({
|
||||
userId: this.userInfo.userId,
|
||||
nickName: this.userInfo.nickName,
|
||||
portrait: this.userInfo.portrait
|
||||
})
|
||||
}
|
||||
}
|
||||
});
|
||||
break;
|
||||
case 'Y':
|
||||
this.$http.request({
|
||||
url: '/topic/cancelLike/'+e.topicId,
|
||||
success: (res) => {
|
||||
if (res.data.code == 200) {
|
||||
var like=e.like=='N' ? e.like='Y' : e.like='N'
|
||||
this.content.like=like
|
||||
var thisObj=this.$fc.arrFindkey({arr:this.content.likeList,key:'userId',val:this.userInfo.userId})
|
||||
this.content.likeList.splice(thisObj.index,1)
|
||||
}
|
||||
}
|
||||
});
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
},
|
||||
sendMsg(e) {
|
||||
if (!e) {
|
||||
return;
|
||||
}
|
||||
var replyId=''
|
||||
var replyType=''
|
||||
if(this.type=='msg'){
|
||||
replyId=this.content.topicId
|
||||
replyType='1'
|
||||
}
|
||||
if(this.type=='reply'){
|
||||
replyId=this.replydata.replyId
|
||||
replyType='2'
|
||||
}
|
||||
this.$http.request({
|
||||
url: '/topic/reply',
|
||||
method: 'POST',
|
||||
data:JSON.stringify({
|
||||
replyId: replyId,
|
||||
replyType: replyType,
|
||||
content: e
|
||||
}),
|
||||
success: (res) => {
|
||||
if (res.data.code == 200) {
|
||||
this.content.replyList.push(res.data.data)
|
||||
this.$nextTick(()=>{
|
||||
this.scrolltoBottom()
|
||||
})
|
||||
}
|
||||
}
|
||||
});
|
||||
this.msg=''
|
||||
},
|
||||
hidenTool() {//隐藏选项和输入框
|
||||
this.tabToolIndex = false;
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.zfb-tk-send-tool {
|
||||
background: #f7f7f7;
|
||||
position: fixed;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.zfb-tk-send-tool-c {
|
||||
padding: 16rpx 12rpx;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: space-around;
|
||||
border: 1px #ddd solid;
|
||||
border-left: none;
|
||||
border-right: none;
|
||||
}
|
||||
|
||||
.zfb-tk-send-tool-c .zfb-tk-send-tool-btn {
|
||||
transition: color 0.5s;
|
||||
}
|
||||
|
||||
.zfb-tk-send-tool .zfb-tk-send-tool-input {
|
||||
padding:0 24rpx;
|
||||
box-sizing: border-box !important;
|
||||
width: 100%;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.zfb-tk-send-tool-text {
|
||||
white-space: nowrap;
|
||||
padding: 10rpx 24rpx;
|
||||
border-radius: 12rpx;
|
||||
border: 1px #ddd solid;
|
||||
background: #f7f7f7;
|
||||
color: #ddd;
|
||||
}
|
||||
.friendsCircle-content-item{
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
padding:24rpx;
|
||||
}
|
||||
.friendsCircle-content-item-detail{
|
||||
margin:0 24rpx;
|
||||
border-radius: 8rpx;
|
||||
margin-top: 24rpx;
|
||||
padding-bottom: 0;
|
||||
margin-bottom: 1px;
|
||||
}
|
||||
.friendsCircle-content-avatar{
|
||||
border-radius: 10rpx;
|
||||
width: 90rpx;
|
||||
height: 90rpx;
|
||||
min-width: 90rpx;
|
||||
}
|
||||
.friendsCircle-content-right{
|
||||
display: flex;flex-direction: column;
|
||||
padding-left: 18rpx;
|
||||
flex: 1;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.friendsCircle-content-nikeName{
|
||||
font-size: 32rpx;
|
||||
color: #5F698C;
|
||||
margin-bottom: 10rpx;
|
||||
}
|
||||
.friendsCircle-content-text{
|
||||
font-size: 32rpx;
|
||||
color: #333;
|
||||
}
|
||||
.friendsCircle-content-imgs{
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
flex: 1;
|
||||
margin-top: 24rpx;
|
||||
}
|
||||
.friendsCircle-content-img{
|
||||
max-width: 100%;
|
||||
}
|
||||
.friendsCircle-content-img.fci1{
|
||||
height: 550rpx;
|
||||
max-width: 500rpx;
|
||||
margin-right: 5px;
|
||||
}
|
||||
.friendsCircle-content-img.fci2{
|
||||
width: 185rpx;
|
||||
height: 185rpx;
|
||||
margin-right: 5rpx;
|
||||
margin-bottom: 5rpx;
|
||||
}
|
||||
.friendsCircle-content-img.fci2:nth-child(3n){
|
||||
margin-right: 0;
|
||||
}
|
||||
.friendsCircle-content-img.fci3{
|
||||
width: 185rpx;
|
||||
height: 185rpx;
|
||||
margin-right: 5rpx;
|
||||
margin-bottom: 5rpx;
|
||||
}
|
||||
.friendsCircle-content-img.fci3:nth-child(3n){
|
||||
margin-right: 0;
|
||||
}
|
||||
.friendsCircle-content-img.fci4{
|
||||
width: 185rpx;
|
||||
height: 185rpx;
|
||||
margin-right: 5rpx;
|
||||
margin-bottom: 5rpx;
|
||||
}
|
||||
.friendsCircle-content-img.fci4:nth-child(2n){
|
||||
margin-right: 185rpx;
|
||||
}
|
||||
.friendsCircle-content-img.fci5{
|
||||
width: 185rpx;
|
||||
height: 185rpx;
|
||||
margin-right: 5rpx;
|
||||
margin-bottom: 5rpx;
|
||||
}
|
||||
.friendsCircle-content-img.fci5:nth-child(3n){
|
||||
margin-right: 0;
|
||||
}
|
||||
.friendsCircle-content-img.fci6{
|
||||
width: 185rpx;
|
||||
height: 185rpx;
|
||||
margin-right: 5rpx;
|
||||
margin-bottom: 5rpx;
|
||||
}
|
||||
.friendsCircle-content-img.fci6:nth-child(3n){
|
||||
margin-right: 0;
|
||||
}
|
||||
.friendsCircle-content-img.fci7{
|
||||
width: 185rpx;
|
||||
height: 185rpx;
|
||||
margin-right: 5rpx;
|
||||
margin-bottom: 5rpx;
|
||||
}
|
||||
.friendsCircle-content-img.fci7:nth-child(3n){
|
||||
margin-right: 0;
|
||||
}
|
||||
.friendsCircle-content-img.fci8{
|
||||
width: 185rpx;
|
||||
height: 185rpx;
|
||||
margin-right: 5rpx;
|
||||
margin-bottom: 5rpx;
|
||||
}
|
||||
.friendsCircle-content-img.fci8:nth-child(3n){
|
||||
margin-right: 0;
|
||||
}
|
||||
.friendsCircle-content-img.fci9{
|
||||
width: 185rpx;
|
||||
height: 185rpx;
|
||||
margin-right: 5rpx;
|
||||
margin-bottom: 5rpx;
|
||||
}
|
||||
.friendsCircle-content-img.fci9:nth-child(3n){
|
||||
margin-right: 0;
|
||||
}
|
||||
.friendsCircle-content-location{
|
||||
font-size: 24rpx;
|
||||
color: #5F698C;
|
||||
margin-top: 12rpx;
|
||||
}
|
||||
.friendsCircle-content-time{
|
||||
font-size: 24rpx;
|
||||
color: #666666;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
.friendsCircle-content-tools{
|
||||
margin-top: 24rpx;
|
||||
display: flex;flex-direction: row;align-items: center;
|
||||
}
|
||||
.friendsCircle-content-tool{
|
||||
padding:4rpx 16rpx;
|
||||
border-radius: 10rpx;
|
||||
background-color: #F8F8FA;
|
||||
color: #63678C;
|
||||
display: flex;flex-direction: row;
|
||||
position: relative;
|
||||
}
|
||||
.tabon .friendsCircle-content-tool-absolute{
|
||||
display: block;
|
||||
}
|
||||
.friendsCircle-content-tool-absolute{
|
||||
position: absolute;
|
||||
right: 100%;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
display: none;
|
||||
}
|
||||
.friendsCircle-popup{
|
||||
margin-right: 24rpx;
|
||||
border-radius: 12rpx;
|
||||
background-color: rgba(0,0,0,0.7);
|
||||
height: 75rpx;
|
||||
display: flex;flex-direction: row;align-items: center;
|
||||
padding:0 24rpx;
|
||||
}
|
||||
.friendsCircle-popup-item{
|
||||
color: #fff;
|
||||
padding:0 25rpx;
|
||||
height: 100%;
|
||||
display: flex;flex-direction: row;align-items: center;
|
||||
}
|
||||
.friendsCircle-popup-item:nth-child(1):active .friendsCircle-popup-icon{
|
||||
font-size: 56rpx;
|
||||
}
|
||||
.friendsCircle-popup-icon{
|
||||
font-size: 46rpx;
|
||||
}
|
||||
.friendsCircle-popup-text{
|
||||
white-space: nowrap;
|
||||
}
|
||||
.friendsCircle-like{
|
||||
display: flex;flex-direction: row;align-items: center;flex-wrap: wrap;
|
||||
|
||||
}
|
||||
.friendsCircle-like-icon,.friendsCircle-like-text,.friendsCircle-comment-text{
|
||||
color: #5F698C !important;
|
||||
font-size: 24rpx;
|
||||
}
|
||||
.friendsCircle-comment-feedback .friendsCircle-comment-text{
|
||||
margin:0 6rpx;
|
||||
}
|
||||
.friendsCircle-comment-feedback .friendsCircle-comment-text::after{
|
||||
content: ":";
|
||||
color: #333;
|
||||
}
|
||||
.friendsCircle-comment-item-name{
|
||||
display: flex;flex-direction: row;
|
||||
width: 100%;
|
||||
}
|
||||
.friendsCircle-comment-item-time{
|
||||
margin-left: auto;
|
||||
font-size: 24rpx;
|
||||
color: #999;
|
||||
}
|
||||
.friendsCircle-like-icon,.friendsCircle-comment-icon{
|
||||
width: 40rpx;
|
||||
min-width: 40rpx;
|
||||
height: 60rpx;
|
||||
display: flex;flex-direction: row;align-items: center;justify-content: center;
|
||||
font-size: 32rpx;
|
||||
}
|
||||
.friendsCircle-like-text{
|
||||
margin-left: 4rpx;
|
||||
}
|
||||
.friendsCircle-like-text::after{
|
||||
content: ",";
|
||||
}
|
||||
.friendsCircle-like-text:nth-last-child(1)::after{
|
||||
content: "";
|
||||
}
|
||||
.friendsCircle-comment{
|
||||
background-color: #F7F7F7;
|
||||
border-radius: 8rpx;
|
||||
flex: 1;
|
||||
}
|
||||
.friendsCircle-comment-item{
|
||||
font-size: 28rpx;
|
||||
padding: 12rpx;
|
||||
white-space: pre-wrap;
|
||||
display: flex;flex-direction: row;
|
||||
}
|
||||
.friendsCircle-comment-feedback{
|
||||
display: inline-block;
|
||||
}
|
||||
.friendsCircle-comment-feedback text{
|
||||
font-size: 28rpx;
|
||||
color: #333;
|
||||
}
|
||||
.friendsCircle-comment-textx{
|
||||
word-break: break-all;
|
||||
}
|
||||
.friendsCircle-like-img,.friendsCircle-comment-img{
|
||||
width: 60rpx;
|
||||
height: 60rpx;
|
||||
border-radius: 12rpx;
|
||||
margin-left: 10rpx;
|
||||
margin-bottom: 12rpx;
|
||||
}
|
||||
.friendsCircle-comment-img{
|
||||
margin-right: 12rpx;
|
||||
margin-left: 0px;
|
||||
}
|
||||
.friendsCircle-content-item-detail-item{
|
||||
display: flex;flex-direction: row;
|
||||
padding: 12rpx;
|
||||
padding-bottom: 0;
|
||||
margin-bottom: 4rpx;
|
||||
border-radius: 8rpx;
|
||||
background-color: #F7F7F7;
|
||||
}
|
||||
.friendsCircle-comment-item-text{
|
||||
flex: 1;
|
||||
display: flex;flex-direction: column;
|
||||
align-items:flex-start;
|
||||
}
|
||||
.friendsCircle-content-video{
|
||||
height: 550rpx;
|
||||
max-width: 400rpx;
|
||||
position: relative;
|
||||
margin-right: 14rpx;
|
||||
margin-top: 24rpx;
|
||||
}
|
||||
.friendsCircle-content-video-img{
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
.friendsCircle-content-video-icon{
|
||||
z-index: 1;
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
width: 60rpx !important;
|
||||
height: 60rpx !important;
|
||||
transform: translate(-50%,-50%);
|
||||
}
|
||||
.zfb-tk-send-tool-input-box{
|
||||
overflow: auto;
|
||||
width: 100%;
|
||||
margin: 0 12rpx;
|
||||
min-height: 75rpx;
|
||||
background-color: #fff;
|
||||
border-radius: 24rpx;
|
||||
padding-top: 18rpx;
|
||||
max-height: 225rpx;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,558 @@
|
||||
<template>
|
||||
<view class="friendsCircle-content-item" v-for="(v, i) in content" :key="i">
|
||||
<image class="friendsCircle-content-avatar" :src="v.avatar" mode="aspectFill" @click="gofriend(v)"></image>
|
||||
<view class="friendsCircle-content-right">
|
||||
<view class="friendsCircle-content-nickName" @click="gofriend(v)">{{ v.nickName }}</view>
|
||||
<view class="friendsCircle-content-text">{{ v.text }}</view>
|
||||
<view class="friendsCircle-content-imgs" v-if="v.topicType=='IMAGE'&&v.files.length>0">
|
||||
<image v-for="(item, ii) in v.files" :key="ii" class="friendsCircle-content-img" :class="'fci' + v.files.length" :src="item.url" mode="aspectFill" @click="pimgs(v.files,ii)"></image>
|
||||
</view>
|
||||
<view class="friendsCircle-content-video" @click="openVideo(v.files[0].videoUrl)" v-if="v.topicType=='VIDEO'&&v.files.length>0">
|
||||
<image class="friendsCircle-content-video-icon" src="../../static/img/bf.png" mode="aspectFill"></image>
|
||||
<image class="friendsCircle-content-video-img" :src="v.files[0].url" mode="aspectFill"></image>
|
||||
</view>
|
||||
<view class="friendsCircle-content-location" v-if="v.location.name" @click="goMap(v.location)">{{ v.location.name }}</view>
|
||||
<view class="friendsCircle-content-tools">
|
||||
<view class="friendsCircle-content-time">{{ v.time }}</view>
|
||||
<view class="friendsCircle-content-tool" :class="{ tabon: i == showToolIndex }">
|
||||
<view class="wxfont caidan" @click="showTool(i)"></view>
|
||||
<view class="friendsCircle-content-tool-absolute">
|
||||
<view class="friendsCircle-popup">
|
||||
<view class="friendsCircle-popup-item" @click="zan(v,i)">
|
||||
<view class="friendsCircle-popup-icon wxfont zan"></view>
|
||||
<view class="friendsCircle-popup-text" v-if="v.like=='Y'">取消</view>
|
||||
<view class="friendsCircle-popup-text" v-else>赞</view>
|
||||
</view>
|
||||
<view class="friendsCircle-popup-item" @click="comment(v)">
|
||||
<view class="friendsCircle-popup-icon wxfont pinglun"></view>
|
||||
<view class="friendsCircle-popup-text">评论</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="friendsCircle-like" v-if="v.likeList&&v.likeList.length>0">
|
||||
<view class="friendsCircle-like-icon wxfont zan"></view>
|
||||
<text class="friendsCircle-like-text" v-for="(z,zindex) in v.likeList">{{z.nickName}}</text>
|
||||
</view>
|
||||
<view class="friendsCircle-comment" v-if="v.replyList&&v.replyList.length>0">
|
||||
<view class="friendsCircle-comment-item" v-for="(c,ci) in v.replyList" :key="ci">
|
||||
<text class="friendsCircle-comment-text" @click="gofriend(c)">{{c.nickName}}</text>
|
||||
<view class="friendsCircle-comment-feedback" v-if="c.replyType=='2'">
|
||||
回复
|
||||
<text class="friendsCircle-comment-text" @click="gofriend(c)">{{c.toNickName}}</text>
|
||||
</view>
|
||||
<view class="friendsCircle-comment-content" v-if="c.content" @click="replyclick(c,ci,i)">
|
||||
<text>{{c.content}}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="zfb-tk-send-tool" v-if="toggleMsgBox" :style="{bottom:keyboardHeight+'px'}">
|
||||
<form @submit="sendMsg(msg)">
|
||||
<view class="zfb-tk-send-tool-c">
|
||||
<view class="zfb-tk-send-tool-input-box" @click="msgFocus=true">
|
||||
<textarea class="zfb-tk-send-tool-input" :adjust-position="false" :focus="msgFocus" v-model="msg" :placeholder="placeholder" confirm-type="send" @confirm="sendMsg(msg)" hold-keyboard :maxlength="-1" auto-height />
|
||||
</view>
|
||||
<view class="zfb-tk-send-tool-text" @click="sendMsg(msg)" :style="{ background: msg !== '' ? '#1BC418' : '#F7F7F7', color: msg !== '' ? '#fff' : '#ddd', 'border-color': msg !== '' ? '#1BC418' : '#ddd' }">发送</view>
|
||||
</view>
|
||||
</form>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
// 朋友圈列表内容区
|
||||
data() {
|
||||
return {
|
||||
keyboardHeight:0,
|
||||
msg: '',
|
||||
msgFocus:false,
|
||||
toggleMsgBox: false,
|
||||
showToolIndex: null,
|
||||
chooseUserIndex:null,
|
||||
type:'msg',
|
||||
placeholder:'评论',
|
||||
replydata:''
|
||||
};
|
||||
},
|
||||
props:{
|
||||
content:{
|
||||
type:Array,
|
||||
default:[]
|
||||
}
|
||||
},
|
||||
computed:{
|
||||
userInfo(){
|
||||
return this.$store.state.userInfo
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
// #ifdef APP-PLUS
|
||||
uni.onKeyboardHeightChange(res => {
|
||||
this.keyboardHeight=res.height
|
||||
})
|
||||
// #endif
|
||||
},
|
||||
methods: {
|
||||
replyclick(e,ci,i){
|
||||
this.chooseUserIndex=i
|
||||
if(e.canDeleted=='Y'){
|
||||
this.hidenTool()
|
||||
uni.showActionSheet({
|
||||
itemList: ['复制','删除'],
|
||||
success: (res) => {
|
||||
switch (res.tapIndex){
|
||||
case 0:
|
||||
uni.setClipboardData({
|
||||
data: e.content,
|
||||
success: function() {
|
||||
uni.showToast({
|
||||
title: '复制成功',
|
||||
icon: 'none',
|
||||
position: 'bottom'
|
||||
})
|
||||
}
|
||||
});
|
||||
break;
|
||||
case 1:
|
||||
this.$http.request({
|
||||
url: '/topic/removeReply/'+e.replyId,
|
||||
success: (res) => {
|
||||
if (res.data.code == 200) {
|
||||
uni.showToast({
|
||||
title:'删除成功',
|
||||
icon:'none'
|
||||
})
|
||||
this.content[i].replyList.splice(ci,1)
|
||||
}
|
||||
}
|
||||
});
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
}else{
|
||||
this.replydata=e
|
||||
this.type='reply'
|
||||
this.placeholder='回复'+e.nickName
|
||||
this.$nextTick(()=>{
|
||||
this.toggleMsgBox = true;
|
||||
this.msgFocus=true
|
||||
})
|
||||
}
|
||||
},
|
||||
gofriend(e){
|
||||
uni.navigateTo({
|
||||
url:'../../wx/personInfo/detail?param='+e.userId
|
||||
})
|
||||
},
|
||||
pimgs(arr,ii){
|
||||
var imgs=[]
|
||||
for (var i = 0; i < arr.length; i++) {
|
||||
imgs.push(arr[i].url)
|
||||
}
|
||||
this.$fc.previewImages(imgs, ii)
|
||||
},
|
||||
goMap(e) {
|
||||
uni.openLocation({
|
||||
latitude: e.latitude,
|
||||
longitude: e.longitude,
|
||||
success: function() {}
|
||||
});
|
||||
},
|
||||
openVideo(e){
|
||||
this.$fc.plusDownload({onlinePath:e}).then(res=>{
|
||||
this.$fc.plusOpenFile({filePath:res})
|
||||
})
|
||||
},
|
||||
returnParse(txt) {
|
||||
return JSON.parse(txt);
|
||||
},
|
||||
showTool(e) {
|
||||
this.chooseUserIndex=e
|
||||
if (this.showToolIndex === e) {
|
||||
this.showToolIndex = null;
|
||||
} else {
|
||||
this.showToolIndex = e;
|
||||
}
|
||||
},
|
||||
comment(e) {
|
||||
//评论
|
||||
this.showToolIndex = null;
|
||||
this.type='msg'
|
||||
this.placeholder='评论'
|
||||
this.$nextTick(()=>{
|
||||
this.toggleMsgBox = true;
|
||||
this.msgFocus=true
|
||||
})
|
||||
},
|
||||
zan(e,i){//点赞
|
||||
switch (e.like){
|
||||
case 'N':
|
||||
this.$http.request({
|
||||
url: '/topic/like/'+e.topicId,
|
||||
success: (res) => {
|
||||
if (res.data.code == 200) {
|
||||
this.hidenTool()
|
||||
var like=e.like=='N' ? e.like='Y' : e.like='N'
|
||||
this.content[this.chooseUserIndex].like=like
|
||||
this.content[this.chooseUserIndex].likeList.push({
|
||||
userId: this.userInfo.userId,
|
||||
nickName: this.userInfo.nickName,
|
||||
portrait: this.userInfo.portrait
|
||||
})
|
||||
}
|
||||
}
|
||||
});
|
||||
break;
|
||||
case 'Y':
|
||||
this.$http.request({
|
||||
url: '/topic/cancelLike/'+e.topicId,
|
||||
success: (res) => {
|
||||
if (res.data.code == 200) {
|
||||
this.hidenTool()
|
||||
var like=e.like=='N' ? e.like='Y' : e.like='N'
|
||||
this.content[this.chooseUserIndex].like=like
|
||||
var thisObj=this.$fc.arrFindkey({arr:this.content[this.chooseUserIndex].likeList,key:'userId',val:this.userInfo.userId})
|
||||
this.content[this.chooseUserIndex].likeList.splice(thisObj.index,1)
|
||||
}
|
||||
}
|
||||
});
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
},
|
||||
sendMsg(e) {
|
||||
if (!e) {
|
||||
return;
|
||||
}
|
||||
var replyId=''
|
||||
var replyType=''
|
||||
if(this.type=='msg'){
|
||||
replyId=this.content[this.chooseUserIndex].topicId
|
||||
replyType='1'
|
||||
}
|
||||
if(this.type=='reply'){
|
||||
replyId=this.replydata.replyId
|
||||
replyType='2'
|
||||
}
|
||||
this.$http.request({
|
||||
url: '/topic/reply',
|
||||
method: 'POST',
|
||||
data:JSON.stringify({
|
||||
replyId: replyId,
|
||||
replyType: replyType,
|
||||
content: e
|
||||
}),
|
||||
success: (res) => {
|
||||
if (res.data.code == 200) {
|
||||
this.hidenTool()
|
||||
this.content[this.chooseUserIndex].replyList.push(res.data.data)
|
||||
}
|
||||
}
|
||||
});
|
||||
this.msg=''
|
||||
},
|
||||
hidenTool() {//隐藏选项和输入框
|
||||
this.showToolIndex = null;
|
||||
this.toggleMsgBox = false;
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.zfb-tk-send-tool {
|
||||
background: #f7f7f7;
|
||||
position: fixed;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.zfb-tk-send-tool-c {
|
||||
padding: 16rpx 12rpx;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: space-around;
|
||||
border: 1px #ddd solid;
|
||||
border-left: none;
|
||||
border-right: none;
|
||||
}
|
||||
|
||||
.zfb-tk-send-tool-c .zfb-tk-send-tool-btn {
|
||||
transition: color 0.5s;
|
||||
}
|
||||
|
||||
.zfb-tk-send-tool .zfb-tk-send-tool-input {
|
||||
padding:0 24rpx;
|
||||
box-sizing: border-box !important;
|
||||
width: 100%;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.zfb-tk-send-tool-text {
|
||||
white-space: nowrap;
|
||||
padding: 10rpx 24rpx;
|
||||
border-radius: 12rpx;
|
||||
border: 1px #ddd solid;
|
||||
background: #f7f7f7;
|
||||
color: #ddd;
|
||||
}
|
||||
.friendsCircle-content-item{
|
||||
display: flex;flex-direction: row;
|
||||
padding:24rpx 34rpx;
|
||||
border-bottom: 1px #F2F2F2 solid;
|
||||
}
|
||||
.friendsCircle-content-avatar{
|
||||
border-radius: 10rpx;
|
||||
width: 90rpx;
|
||||
height: 90rpx;
|
||||
min-width: 90rpx;
|
||||
}
|
||||
.friendsCircle-content-right{
|
||||
display: flex;flex-direction: column;
|
||||
padding-left: 18rpx;
|
||||
flex: 1;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.friendsCircle-content-nickName{
|
||||
font-size: 32rpx;
|
||||
color: #5F698C;
|
||||
margin-bottom: 10rpx;
|
||||
}
|
||||
.friendsCircle-content-text{
|
||||
font-size: 32rpx;
|
||||
color: #333;
|
||||
}
|
||||
.friendsCircle-content-imgs{
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
flex: 1;
|
||||
margin-top: 24rpx;
|
||||
}
|
||||
.friendsCircle-content-img{
|
||||
max-width: 100%;
|
||||
}
|
||||
.friendsCircle-content-img.fci1{
|
||||
height: 550rpx;
|
||||
max-width: 500rpx;
|
||||
margin-right: 5px;
|
||||
}
|
||||
.friendsCircle-content-img.fci2{
|
||||
width: 185rpx;
|
||||
height: 185rpx;
|
||||
margin-right: 5rpx;
|
||||
margin-bottom: 5rpx;
|
||||
}
|
||||
.friendsCircle-content-img.fci2:nth-child(3n){
|
||||
margin-right: 0;
|
||||
}
|
||||
.friendsCircle-content-img.fci3{
|
||||
width: 185rpx;
|
||||
height: 185rpx;
|
||||
margin-right: 5rpx;
|
||||
margin-bottom: 5rpx;
|
||||
}
|
||||
.friendsCircle-content-img.fci3:nth-child(3n){
|
||||
margin-right: 0;
|
||||
}
|
||||
.friendsCircle-content-img.fci4{
|
||||
width: 185rpx;
|
||||
height: 185rpx;
|
||||
margin-right: 5rpx;
|
||||
margin-bottom: 5rpx;
|
||||
}
|
||||
.friendsCircle-content-img.fci4:nth-child(2n){
|
||||
margin-right: 185rpx;
|
||||
}
|
||||
.friendsCircle-content-img.fci5{
|
||||
width: 185rpx;
|
||||
height: 185rpx;
|
||||
margin-right: 5rpx;
|
||||
margin-bottom: 5rpx;
|
||||
}
|
||||
.friendsCircle-content-img.fci5:nth-child(3n){
|
||||
margin-right: 0;
|
||||
}
|
||||
.friendsCircle-content-img.fci6{
|
||||
width: 185rpx;
|
||||
height: 185rpx;
|
||||
margin-right: 5rpx;
|
||||
margin-bottom: 5rpx;
|
||||
}
|
||||
.friendsCircle-content-img.fci6:nth-child(3n){
|
||||
margin-right: 0;
|
||||
}
|
||||
.friendsCircle-content-img.fci7{
|
||||
width: 185rpx;
|
||||
height: 185rpx;
|
||||
margin-right: 5rpx;
|
||||
margin-bottom: 5rpx;
|
||||
}
|
||||
.friendsCircle-content-img.fci7:nth-child(3n){
|
||||
margin-right: 0;
|
||||
}
|
||||
.friendsCircle-content-img.fci8{
|
||||
width: 185rpx;
|
||||
height: 185rpx;
|
||||
margin-right: 5rpx;
|
||||
margin-bottom: 5rpx;
|
||||
}
|
||||
.friendsCircle-content-img.fci8:nth-child(3n){
|
||||
margin-right: 0;
|
||||
}
|
||||
.friendsCircle-content-img.fci9{
|
||||
width: 185rpx;
|
||||
height: 185rpx;
|
||||
margin-right: 5rpx;
|
||||
margin-bottom: 5rpx;
|
||||
}
|
||||
.friendsCircle-content-img.fci9:nth-child(3n){
|
||||
margin-right: 0;
|
||||
}
|
||||
.friendsCircle-content-location{
|
||||
font-size: 24rpx;
|
||||
color: #5F698C;
|
||||
margin-top: 12rpx;
|
||||
}
|
||||
.friendsCircle-content-time{
|
||||
font-size: 24rpx;
|
||||
color: #666666;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
.friendsCircle-content-tools{
|
||||
margin-top: 24rpx;
|
||||
display: flex;flex-direction: row;align-items: center;
|
||||
margin-bottom: 14rpx;
|
||||
}
|
||||
.friendsCircle-content-tool{
|
||||
padding:4rpx 16rpx;
|
||||
border-radius: 10rpx;
|
||||
background-color: #F8F8FA;
|
||||
color: #63678C;
|
||||
display: flex;flex-direction: row;
|
||||
position: relative;
|
||||
}
|
||||
.tabon .friendsCircle-content-tool-absolute{
|
||||
display: block;
|
||||
}
|
||||
.friendsCircle-content-tool-absolute{
|
||||
position: absolute;
|
||||
right: 100%;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
display: none;
|
||||
}
|
||||
.friendsCircle-popup{
|
||||
margin-right: 24rpx;
|
||||
border-radius: 12rpx;
|
||||
background-color: rgba(0,0,0,0.7);
|
||||
height: 75rpx;
|
||||
display: flex;flex-direction: row;align-items: center;
|
||||
padding:0 24rpx;
|
||||
}
|
||||
.friendsCircle-popup-item{
|
||||
color: #fff;
|
||||
padding:0 25rpx;
|
||||
height: 100%;
|
||||
display: flex;flex-direction: row;align-items: center;
|
||||
}
|
||||
.friendsCircle-popup-item:nth-child(1):active .friendsCircle-popup-icon{
|
||||
font-size: 56rpx;
|
||||
}
|
||||
.friendsCircle-popup-icon{
|
||||
font-size: 46rpx;
|
||||
}
|
||||
.friendsCircle-popup-text{
|
||||
white-space: nowrap;
|
||||
}
|
||||
.friendsCircle-like{
|
||||
border-radius: 8rpx;
|
||||
padding: 12rpx;
|
||||
background-color: #F7F7F7;
|
||||
display: flex;flex-direction: row;align-items: center;flex-wrap: wrap;
|
||||
margin-bottom: 1px;
|
||||
}
|
||||
.friendsCircle-like-icon,.friendsCircle-like-text,.friendsCircle-comment-text{
|
||||
color: #5F698C !important;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
.friendsCircle-comment-feedback .friendsCircle-comment-text{
|
||||
margin:0 6rpx;
|
||||
}
|
||||
.friendsCircle-comment-text::after{
|
||||
content: ":";
|
||||
color: #333;
|
||||
}
|
||||
.friendsCircle-like-text{
|
||||
margin-left: 4rpx;
|
||||
margin-right: 10rpx;
|
||||
}
|
||||
.friendsCircle-like-text::after{
|
||||
content: ",";
|
||||
}
|
||||
.friendsCircle-like-text:nth-last-child(1)::after{
|
||||
content: "";
|
||||
}
|
||||
.friendsCircle-comment{
|
||||
background-color: #F7F7F7;
|
||||
border-radius: 8rpx;
|
||||
}
|
||||
.friendsCircle-comment-item{
|
||||
line-height: 40rpx;
|
||||
font-size: 28rpx;
|
||||
padding: 12rpx;
|
||||
white-space: pre-wrap;
|
||||
display: flex;flex-direction: row;flex-wrap: wrap;
|
||||
}
|
||||
.friendsCircle-comment-feedback{
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.friendsCircle-content-video{
|
||||
width: auto;
|
||||
height: 550rpx;
|
||||
max-width: 400rpx;
|
||||
position: relative;
|
||||
margin-top: 24rpx;
|
||||
}
|
||||
.friendsCircle-content-video-img{
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
.friendsCircle-content-video-icon{
|
||||
z-index: 1;
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
width: 80rpx !important;
|
||||
height: 80rpx !important;
|
||||
transform: translate(-50%,-50%);
|
||||
}
|
||||
.friendsCircle-comment-content{
|
||||
}
|
||||
.friendsCircle-comment-content text{
|
||||
word-break: break-all;
|
||||
}
|
||||
.zfb-tk-send-tool-input-box{
|
||||
overflow: auto;
|
||||
width: 100%;
|
||||
margin: 0 12rpx;
|
||||
min-height: 75rpx;
|
||||
background-color: #fff;
|
||||
border-radius: 24rpx;
|
||||
padding-top: 18rpx;
|
||||
max-height: 225rpx;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,225 @@
|
||||
<template>
|
||||
<view class="friends-circle-person-item" v-for="(v, i) in content" :key="i">
|
||||
<view class="friends-circle-person-item-date"><!-- -->
|
||||
<text class="day">{{returnDate(v.createTime,'d')}}</text>
|
||||
<text class="month">{{returnDate(v.createTime,'m')}}月</text>
|
||||
<view class="year">{{returnDate(v.createTime,'y')}}</view>
|
||||
<view class="year" v-if="v.location.name">{{v.location.name}}</view>
|
||||
</view>
|
||||
<view class="friends-circle-person-view" @click="clickItem(v)">
|
||||
<view class="friends-circle-person-content" v-if="v.topicType=='IMAGE'&&v.files.length>0">
|
||||
<view class="friends-circle-person-imgs">
|
||||
<image v-for="(item, ii) in v.files.slice(0,4)" :key="ii" :class="'fci' + v.files.slice(0,4).length" :src="item.url" mode="aspectFill"></image>
|
||||
</view>
|
||||
<view class="friends-circle-person-imgs-text">
|
||||
<text>{{v.text}}</text>
|
||||
<view class="friends-circle-person-imgs-total">共{{v.files.length}}张</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="friends-circle-person-content" v-if="v.topicType=='VIDEO'&&v.files.length>0">
|
||||
<view class="friendsCircle-content-video">
|
||||
<image class="friendsCircle-content-video-icon" src="../../static/img/bf.png" mode="aspectFill"></image>
|
||||
<image class="friendsCircle-content-video-img" :src="v.files[0].url" mode="aspectFill"></image>
|
||||
</view>
|
||||
<view class="friends-circle-person-imgs-text">
|
||||
<text>{{v.text}}</text>
|
||||
</view>
|
||||
</view>
|
||||
<view v-if="v.topicType=='TEXT'" class="friends-circle-person-content">
|
||||
<view class="friends-circle-person-text">
|
||||
<text>{{v.text}}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="friends-circle-nodata" v-if="content.length<=0">
|
||||
<view class="friends-circle-nodata-line"></view>
|
||||
<view class="friends-circle-nodata-text">未发布朋友圈</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
// 朋友圈单人列表
|
||||
emits:['clickItem'],
|
||||
data() {
|
||||
return {
|
||||
};
|
||||
},
|
||||
props:{
|
||||
content:{
|
||||
type:Array,
|
||||
default:[]
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
returnDate(e,format){
|
||||
return this.$fc.getNewDate(format,true,e)
|
||||
},
|
||||
clickItem(e){
|
||||
this.$emit('clickItem',e)
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
|
||||
.friends-circle-person-item{
|
||||
display: flex;flex-direction: row;
|
||||
margin-bottom: 60rpx;
|
||||
width: 100%;
|
||||
}
|
||||
.friends-circle-person-view{
|
||||
flex: 1;
|
||||
}
|
||||
.friends-circle-person-item-date{
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
margin-right: 40rpx;
|
||||
width: 115rpx;
|
||||
min-width: 115rpx;
|
||||
line-height: 60rpx;
|
||||
text-align: right;
|
||||
}
|
||||
.friends-circle-person-item-date .day{
|
||||
flex: 1;
|
||||
font-size: 43rpx;
|
||||
}
|
||||
.friends-circle-person-item-date .month{
|
||||
font-size: 26rpx;
|
||||
flex: 1;
|
||||
}
|
||||
.friends-circle-person-item-date .year{
|
||||
width: 100%;
|
||||
min-width: 100%;
|
||||
font-size: 24rpx;
|
||||
color: #999;
|
||||
line-height: initial;
|
||||
}
|
||||
.friends-circle-person-content{
|
||||
flex: 1;
|
||||
display: flex;flex-direction: row;
|
||||
}
|
||||
.friends-circle-person-text{
|
||||
padding: 12rpx;
|
||||
background-color: #eee;
|
||||
border-radius: 4rpx;
|
||||
}
|
||||
.friends-circle-person-text text{
|
||||
font-size: 28rpx;
|
||||
color: #333;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: 2;
|
||||
-webkit-box-orient: vertical;
|
||||
}
|
||||
.friends-circle-person-imgs{
|
||||
width: 140rpx;
|
||||
min-width: 140rpx;
|
||||
height: 140rpx;
|
||||
margin-right: 14rpx;
|
||||
}
|
||||
.friends-circle-person-imgs image{float: left;}
|
||||
.friends-circle-person-imgs .fci1{
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
.friends-circle-person-imgs .fci2{
|
||||
margin-right: 2%;
|
||||
width: 49%;
|
||||
height: 100%;
|
||||
}
|
||||
.friends-circle-person-imgs .fci2:nth-child(2n){
|
||||
margin-right: 0;
|
||||
}
|
||||
.friends-circle-person-imgs .fci3{
|
||||
margin-right: 2%;
|
||||
width: 49%;
|
||||
height: 48%;
|
||||
}
|
||||
.friends-circle-person-imgs .fci3:nth-child(1){
|
||||
height: 98%;
|
||||
}
|
||||
.friends-circle-person-imgs .fci3:nth-child(2){
|
||||
margin-bottom: 2%;
|
||||
}
|
||||
.friends-circle-person-imgs .fci3:nth-child(2),.friends-circle-person-imgs .fci3:nth-child(3){
|
||||
margin-right: 0;
|
||||
}
|
||||
.friends-circle-person-imgs .fci4{
|
||||
margin-right: 2%;
|
||||
width: 49%;
|
||||
height: 49%;
|
||||
margin-bottom: 2%;
|
||||
}
|
||||
.friends-circle-person-imgs .fci4:nth-child(2n){
|
||||
margin-right: 0;
|
||||
}
|
||||
.friends-circle-person-imgs-text{
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
}
|
||||
.friends-circle-person-imgs-text text{
|
||||
line-height: 1.2;
|
||||
font-size: 28rpx;
|
||||
color: #333;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: 3;
|
||||
-webkit-box-orient: vertical;
|
||||
}
|
||||
.friends-circle-person-imgs-total{
|
||||
color: #999;
|
||||
font-size: 24rpx;
|
||||
}
|
||||
.friends-circle-nodata{
|
||||
display: flex;flex-direction: column;
|
||||
}
|
||||
.friends-circle-nodata-line{
|
||||
margin: 50rpx;
|
||||
margin-bottom: 30rpx;
|
||||
height: 1px;
|
||||
position: relative;
|
||||
background-color: #eee;
|
||||
}
|
||||
.friends-circle-nodata-line::after{
|
||||
content: " ";
|
||||
width: 13rpx;
|
||||
height: 13rpx;
|
||||
border-radius: 50%;
|
||||
background-color: #eee;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%,-50%);
|
||||
}
|
||||
.friends-circle-nodata-text{
|
||||
font-size: 24rpx;
|
||||
text-align: center;
|
||||
color: #999;
|
||||
}
|
||||
.friendsCircle-content-video{
|
||||
width: 140rpx;
|
||||
height: 140rpx;
|
||||
position: relative;
|
||||
margin-right: 14rpx;
|
||||
}
|
||||
.friendsCircle-content-video-img{
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
.friendsCircle-content-video-icon{
|
||||
z-index: 1;
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
width: 60rpx !important;
|
||||
height: 60rpx !important;
|
||||
transform: translate(-50%,-50%);
|
||||
}
|
||||
</style>
|
||||
327
im-uniapp/components/friends-circle-top/friends-circle-top.vue
Normal file
327
im-uniapp/components/friends-circle-top/friends-circle-top.vue
Normal file
@@ -0,0 +1,327 @@
|
||||
<template>
|
||||
<view class="friendsCircle-top" :class="{ 'friendsCircle-top-opend': CircleTop, 'friendsCircle-top-type-img': cover.type == 'img' }" :key="ikey">
|
||||
<view style="width: 100%;height: 100%;" v-if="cover.type == 'img'">
|
||||
<image class="friendsCircle-top-img" @click="changeCircleTop" :src="cover.url" mode="aspectFill"></image>
|
||||
<view class="friendsCircle-top-post" @click="changePoster" v-if="showChangePoster">
|
||||
<view class="wxfont tupian"></view>
|
||||
<text class="text">换封面</text>
|
||||
</view>
|
||||
<view class="friendsCircle-top-information" @click="userClick" v-if="userInfo">
|
||||
<view class="friendsCircle-top-information-user">
|
||||
<view class="friendsCircle-top-information-nikeName">{{userInfo.nickName}}</view>
|
||||
<image class="friendsCircle-top-information-avatar" :src="userInfo.portrait" mode="aspectFill"></image>
|
||||
</view>
|
||||
<view class="friendsCircle-top-information-signature">{{userInfo.intro}}</view>
|
||||
</view>
|
||||
</view>
|
||||
<video v-else class="friendsCircle-top-video" id="videodemo" ref="videodemo" :key="vkey" :autoplay="false" :src="cover.url" :controls="false" :loop="true" :show-center-play-btn="false" object-fit="cover" muted>
|
||||
<cover-view class="friendsCircle-top-video-model-img-box"><cover-image class="friendsCircle-top-video-model-img" :src="cover.screenShot"></cover-image></cover-view>
|
||||
<cover-view class="friendsCircle-top-video-model" @click="changeCircleTop"></cover-view>
|
||||
<cover-view class="friendsCircle-top-post" @click="changePoster" v-if="showChangePoster">
|
||||
<cover-image @click="changePoster" class="friendsCircle-top-post-img" src="../../static/img/f01.png"></cover-image>
|
||||
<cover-view @click="changePoster" class="text">换封面</cover-view>
|
||||
</cover-view>
|
||||
<cover-view class="friendsCircle-top-information" @click="userClick" v-if="userInfo">
|
||||
<cover-view class="friendsCircle-top-information-user">
|
||||
<cover-view class="friendsCircle-top-information-nikeName">{{userInfo.nickName}}</cover-view>
|
||||
<cover-image class="friendsCircle-top-information-avatar" :src="userInfo.portrait" mode="aspectFill"></cover-image>
|
||||
</cover-view>
|
||||
<cover-view class="friendsCircle-top-information-signature">{{userInfo.intro}}</cover-view>
|
||||
</cover-view>
|
||||
</video>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
emits:['userClick'],
|
||||
data() {
|
||||
return {
|
||||
CircleTop: false,
|
||||
vkey: 0,
|
||||
ikey:0,
|
||||
videodemo: null
|
||||
};
|
||||
},
|
||||
props:{
|
||||
cover:{
|
||||
type:Object,
|
||||
default(){
|
||||
return{
|
||||
type:'img',
|
||||
name:'',
|
||||
url:''
|
||||
}
|
||||
}
|
||||
},
|
||||
userInfo:{
|
||||
type:[Object,String]
|
||||
},
|
||||
showChangePoster:{
|
||||
type:[Boolean],
|
||||
default:true
|
||||
},
|
||||
},
|
||||
watch:{
|
||||
cover(v){
|
||||
this.ikey++
|
||||
this.vkey++;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
userClick(){//前往个人朋友圈
|
||||
this.$emit('userClick',this.cover,this.userInfo)
|
||||
},
|
||||
changeCircleTop() {//顶部预览
|
||||
this.CircleTop = !this.CircleTop;
|
||||
if(this.type=='img'){
|
||||
return
|
||||
}
|
||||
this.videodemo = uni.createVideoContext('videodemo', this);
|
||||
this.$nextTick(() => {
|
||||
setTimeout(() => {
|
||||
this.vkey++;
|
||||
this.$nextTick(() => {
|
||||
if (this.CircleTop) {
|
||||
this.videodemo.seek(0);
|
||||
this.videodemo.play();
|
||||
} else {
|
||||
this.videodemo.pause();
|
||||
this.videodemo.seek(0);
|
||||
}
|
||||
});
|
||||
}, 105);
|
||||
});
|
||||
},
|
||||
updateCover(formdata){
|
||||
this.$http.request({
|
||||
url: '/topic/editCover',
|
||||
method: 'POST',
|
||||
data:JSON.stringify({
|
||||
cover:JSON.stringify(formdata)
|
||||
}),
|
||||
success: (res) => {
|
||||
if (res.data.code == 200) {
|
||||
this.$store.dispatch('get_UserInfo')
|
||||
this.changeCircleTop()
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
changePoster() {//修改封面
|
||||
uni.showActionSheet({
|
||||
// itemList: ['图片封面', '视频封面'],
|
||||
itemList: ['图片封面'],
|
||||
success: (res) => {
|
||||
switch (res.tapIndex){
|
||||
case 0:
|
||||
uni.chooseImage({
|
||||
count: 1,
|
||||
sizeType: ['original', 'compressed'], //可以指定是原图还是压缩图,默认二者都有
|
||||
sourceType: ['album','camera'], //从相册选择
|
||||
success: (res) => {
|
||||
uni.showLoading({
|
||||
title:'上传中'
|
||||
})
|
||||
this.$http.uploadFile({
|
||||
url: '/file/upload',
|
||||
filePath: res.tempFilePaths[0],
|
||||
name: 'file',
|
||||
fileType: 'image',
|
||||
success: (res) => {
|
||||
var data=JSON.parse(res.data)
|
||||
if (data.code == 200) {
|
||||
var formdata={
|
||||
type:'img',
|
||||
name:data.data.fileName,
|
||||
url:data.data.fullPath
|
||||
}
|
||||
this.updateCover(formdata)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
});
|
||||
break;
|
||||
case 1:
|
||||
uni.chooseVideo({
|
||||
sourceType: ['camera', 'album'],
|
||||
success: (res) => {
|
||||
uni.showLoading({
|
||||
title:'上传中'
|
||||
})
|
||||
this.$http.uploadFile({
|
||||
url: '/file/uploadVideo',
|
||||
filePath: res.tempFilePath,
|
||||
name: 'file',
|
||||
fileType: 'video',
|
||||
success: (res) => {
|
||||
var data=JSON.parse(res.data)
|
||||
if (data.code == 200) {
|
||||
var formdata={
|
||||
type:'video',
|
||||
name:data.data.fileName,
|
||||
url:data.data.fullPath,
|
||||
screenShot:data.data.screenShot
|
||||
}
|
||||
this.updateCover(formdata)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
});
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
},
|
||||
fail: function (res) {
|
||||
console.log(res.errMsg);
|
||||
}
|
||||
});
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.friendsCircle-top{
|
||||
transition: all 0.1s;
|
||||
width: 750rpx;
|
||||
height: 590rpx;
|
||||
position: relative;
|
||||
background-image: linear-gradient( 135deg, #9708CC 10%, #43CBFF 100%);
|
||||
}
|
||||
.friendsCircle-top-type-img{
|
||||
transition: all 0.3s;
|
||||
}
|
||||
.friendsCircle-top-img{
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
.friendsCircle-top-opend{
|
||||
height: 80vh;
|
||||
}
|
||||
.friendsCircle-top-post-img{
|
||||
width: 40rpx;
|
||||
height: 40rpx;
|
||||
margin: 0 auto;
|
||||
}
|
||||
.friendsCircle-top-post{
|
||||
text-align: center;
|
||||
z-index:99;
|
||||
position: absolute;
|
||||
bottom: 24rpx;
|
||||
right: 24rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
display: none;
|
||||
}
|
||||
.friendsCircle-top-post .tupian{
|
||||
color: #f5f5f5;
|
||||
font-size: 38rpx;
|
||||
}
|
||||
.friendsCircle-top-post .text{
|
||||
font-size: 18rpx;
|
||||
color: #f5f5f5;
|
||||
}
|
||||
.friendsCircle-top-video-model-img-box{
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 80vh;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
z-index: 2;
|
||||
}
|
||||
.friendsCircle-top-video-model-img{
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
.friendsCircle-top-video-model{
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
top: 0;
|
||||
left: 0;
|
||||
z-index: 2;
|
||||
// background-color: rgba(255,0,0,0.3);
|
||||
}
|
||||
.friendsCircle-top-opend .friendsCircle-top-post{
|
||||
display: block;
|
||||
}
|
||||
.friendsCircle-top-video{
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
.friendsCircle-top-opend .friendsCircle-top-video-model-img-box{
|
||||
display: none;
|
||||
}
|
||||
.friendsCircle-top-opend .friendsCircle-top-video{
|
||||
height: 80vh;
|
||||
}
|
||||
.friendsCircle-top-information{
|
||||
|
||||
}
|
||||
.friendsCircle-top-information-nikeName{
|
||||
font-size: 32rpx;
|
||||
color: #fff;
|
||||
margin-top: 20rpx;
|
||||
margin-right: 14rpx;
|
||||
font-weight: bold;
|
||||
text-shadow: 0px 0px 5px rgba(0,0,0,0.9);
|
||||
}
|
||||
.friendsCircle-top-information-avatar{
|
||||
width: 120rpx;
|
||||
min-width: 120rpx;
|
||||
height: 120rpx;
|
||||
border-radius: 12rpx;
|
||||
}
|
||||
.friendsCircle-top-information{
|
||||
z-index: 99;
|
||||
display: flex;flex-direction: row;flex-wrap: wrap;
|
||||
position: absolute;
|
||||
bottom: -45rpx;
|
||||
right: 24rpx;
|
||||
display: flex;flex-direction: column;
|
||||
}
|
||||
.friendsCircle-top-information-signature{
|
||||
position: absolute;
|
||||
right: 0;
|
||||
bottom: -45rpx;
|
||||
width: 100%;
|
||||
font-size: 24rpx;
|
||||
color: #666;
|
||||
text-align: right;
|
||||
}
|
||||
.friendsCircle-top-information-user{
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
// border-radius: 12rpx;
|
||||
// background-color: #f00;
|
||||
}
|
||||
.friendsCircle-top-opend .friendsCircle-top-information{
|
||||
display: none;
|
||||
}
|
||||
|
||||
.friendsCircle-top-video .friendsCircle-top-information{
|
||||
bottom: -65rpx;
|
||||
}
|
||||
.friendsCircle-top-video .friendsCircle-top-information-user{
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
}
|
||||
.friendsCircle-top-video .friendsCircle-top-information-avatar{
|
||||
float: left;
|
||||
}
|
||||
|
||||
.friendsCircle-top-video .friendsCircle-top-information-nikeName{
|
||||
float: left;
|
||||
}
|
||||
.friendsCircle-top-video .friendsCircle-top-information-signature{
|
||||
position: inherit;
|
||||
float: left;
|
||||
margin-top: 10rpx;
|
||||
}
|
||||
</style>
|
||||
145
im-uniapp/components/tool-list-wx/tool-list-wx.vue
Normal file
145
im-uniapp/components/tool-list-wx/tool-list-wx.vue
Normal file
@@ -0,0 +1,145 @@
|
||||
<template>
|
||||
<view class="xw-tool-list">
|
||||
<view class="xw-tool-list-content" v-if="type=='list'">
|
||||
<template v-for="(item, i) in list" :key="i">
|
||||
<view class="xw-tool-item" @click="onClick(item,i)" @longpress="onlongpress(item,i)" v-if="item.title">
|
||||
<image v-if="item.icon" class="xw-tool-img" :src="item.icon" mode="aspectFill"></image>
|
||||
<view class="xw-tool-text">
|
||||
<uni-badge v-if="item.type == 'dottext'" text="1" is-dot absolute="rightTop" size="normal">
|
||||
<text>{{ item.title }}</text>
|
||||
</uni-badge>
|
||||
<text v-else>{{ item.title }}</text>
|
||||
</view>
|
||||
<view class="xw-tool-else">
|
||||
<view v-for="(v, index) in item.else" :key="index">
|
||||
<uni-badge v-if="v.type == 'dotimg'" class="xw-tool-badge" text="1" is-dot absolute="rightTop" size="normal"><image :src="v.content" mode="aspectFill"></image></uni-badge>
|
||||
<image v-if="v.type == 'img'" :src="v.content" mode="aspectFill"></image>
|
||||
<uni-badge v-if="v.type == 'dottext'" class="xw-tool-badge" text="1" is-dot absolute="rightTop" size="normal"><view class="text">{{ v.content }}</view></uni-badge>
|
||||
<view class="text" v-if="v.type == 'text'">{{ v.content }}</view>
|
||||
</view>
|
||||
</view>
|
||||
<uni-icons v-if="!item.hideRight" class="xw-tool-right" type="right" size="16" color="#b5b5b5"></uni-icons>
|
||||
</view>
|
||||
</template>
|
||||
</view>
|
||||
<view class="xw-tool-list-content" v-if="type=='btns'">
|
||||
<view class="xw-tool-btn-item" v-for="(item, i) in list" :key="i" @click="onClick(item,i)" @longpress="onlongpress(item,i)">
|
||||
<view class="xw-tool-btn-icon wxfont " :class="item.icon"></view>
|
||||
<view class="xw-tool-btn-text">{{item.title}}</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'toolListWx', //微信功能列表
|
||||
data() {
|
||||
return {};
|
||||
},
|
||||
emits: ['itemClick','onlongpress'],
|
||||
props: {
|
||||
list: {
|
||||
type: Array
|
||||
},
|
||||
type: {
|
||||
type: String,
|
||||
default: 'list' //list列表icon为图片,btns按钮组icon为字体
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
onlongpress(e,i){
|
||||
this.$emit('onlongpress', e,i);
|
||||
},
|
||||
onClick(e,i) {
|
||||
this.$emit('itemClick', e,i);
|
||||
if (e.path=='#') {
|
||||
return;
|
||||
}
|
||||
if (!e.path&&!e.hideRight) {
|
||||
uni.showToast({
|
||||
title: '未开通',
|
||||
icon: 'none'
|
||||
});
|
||||
return;
|
||||
}
|
||||
uni.navigateTo({
|
||||
url: e.path
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.xw-tool-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background-color: #ffffff;
|
||||
margin-bottom: 18rpx;
|
||||
}
|
||||
|
||||
.xw-tool-item {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
padding: 26rpx 24rpx;
|
||||
border-bottom: 1px #eee solid;
|
||||
}
|
||||
.xw-tool-item:nth-last-child(1) {
|
||||
border: none;
|
||||
}
|
||||
.xw-tool-img {
|
||||
width: 52rpx;
|
||||
height: 52rpx;
|
||||
margin-right: 24rpx;
|
||||
}
|
||||
|
||||
.xw-tool-text {
|
||||
white-space: nowrap;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
.xw-tool-badge {
|
||||
}
|
||||
|
||||
.xw-tool-else {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
.xw-tool-else image {
|
||||
width: 60rpx;
|
||||
height: 60rpx;
|
||||
border-radius: 6rpx;
|
||||
}
|
||||
.xw-tool-else .text {
|
||||
color: #666;
|
||||
overflow: hidden;
|
||||
text-overflow:ellipsis;
|
||||
white-space: nowrap;
|
||||
max-width: 520rpx;
|
||||
}
|
||||
.xw-tool-else image,
|
||||
.xw-tool-else .text {
|
||||
margin-left: 12rpx;
|
||||
}
|
||||
|
||||
.xw-tool-right {
|
||||
margin-left: 12rpx;
|
||||
}
|
||||
.xw-tool-btn-item{
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 34rpx 44rpx;
|
||||
border-bottom: 1px #eee solid;
|
||||
font-weight: bold;
|
||||
color: #5F698C;
|
||||
}
|
||||
.xw-tool-btn-icon{
|
||||
margin-right: 14rpx;
|
||||
}
|
||||
</style>
|
||||
156
im-uniapp/components/top-right-tool-wx/top-right-tool-wx.vue
Normal file
156
im-uniapp/components/top-right-tool-wx/top-right-tool-wx.vue
Normal file
@@ -0,0 +1,156 @@
|
||||
<template>
|
||||
<view @touchmove.stop.prevent="moveHandle('touchmove')" @click="moveHandle('click')" v-if="show">
|
||||
<view class="top-right-tool-wx" :animation="animationData" :style="{ top: height + 'px' }">
|
||||
<view class="top-right-tool-wx-icon"></view>
|
||||
<view class="top-right-tool-wx-list">
|
||||
<view class="top-right-tool-wx-list-item" @click="groupChat">
|
||||
<view class="top-right-tool-wx-list-item-icon"><view class="wxfont xiaoxi"></view></view>
|
||||
<view class="text">发起群聊</view>
|
||||
</view>
|
||||
<view class="top-right-tool-wx-list-item" @click="goSearchFriends">
|
||||
<view class="top-right-tool-wx-list-item-icon"><view class="wxfont jiahaoyou"></view></view>
|
||||
<view class="text">添加朋友</view>
|
||||
</view>
|
||||
<view class="top-right-tool-wx-list-item" @click="saoyisao">
|
||||
<view class="top-right-tool-wx-list-item-icon"><view class="wxfont saoyisao"></view></view>
|
||||
<view class="text">扫一扫</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="top-right-tool-wx-model"></view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
height: 0 ,//距离顶部高度
|
||||
show:false,
|
||||
animationData: {}
|
||||
};
|
||||
},
|
||||
props: {
|
||||
list: {
|
||||
type: Array,
|
||||
default() {
|
||||
return [{}];
|
||||
}
|
||||
}
|
||||
},
|
||||
onShow() {
|
||||
|
||||
},
|
||||
mounted() {
|
||||
this.getstatusBarHeight();
|
||||
var animation = uni.createAnimation({
|
||||
duration: 300,
|
||||
timingFunction: 'linear'
|
||||
});
|
||||
this.animation = animation;
|
||||
},
|
||||
methods: {
|
||||
groupChat(){
|
||||
uni.navigateTo({
|
||||
url:'../../wx/group/createGroup'
|
||||
})
|
||||
},
|
||||
goSearchFriends(){
|
||||
uni.navigateTo({
|
||||
url:'../../wx/search-friends/index'
|
||||
})
|
||||
},
|
||||
saoyisao(){
|
||||
this.$fc.saoyisao()
|
||||
},
|
||||
showAnimation() {
|
||||
this.animation.opacity(1).step();
|
||||
this.animationData = this.animation.export();
|
||||
},
|
||||
hideAnimation() {
|
||||
this.animation.opacity(0).step();
|
||||
this.animationData = this.animation.export();
|
||||
},
|
||||
moveHandle(e) {
|
||||
this.hiddenTab()
|
||||
},
|
||||
showTab(){
|
||||
this.show=true
|
||||
setTimeout(()=>{
|
||||
this.showAnimation()
|
||||
},30)
|
||||
},
|
||||
hiddenTab(){
|
||||
this.show=false
|
||||
this.hideAnimation()
|
||||
},
|
||||
getstatusBarHeight() {
|
||||
var SystemInfo = uni.getSystemInfoSync();
|
||||
// #ifdef H5
|
||||
this.height = SystemInfo.safeArea.top + SystemInfo.windowTop;
|
||||
// #endif
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<style scoped>
|
||||
.top-right-tool-wx {
|
||||
width: 300rpx;
|
||||
position: fixed;
|
||||
z-index: 9999;
|
||||
top: -10px;
|
||||
right: 16rpx;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
opacity: 0;
|
||||
}
|
||||
.top-right-tool-wx-model{
|
||||
background-color: rgba(0,0,0,0);
|
||||
position: fixed;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
left: 0;
|
||||
z-index: 9998;
|
||||
}
|
||||
.top-right-tool-wx-icon {
|
||||
width: 0px;
|
||||
height: 0px;
|
||||
border: 10px solid transparent;
|
||||
border-bottom-color: #4C4C4C;
|
||||
margin-left: auto;
|
||||
margin-right: 20rpx;
|
||||
}
|
||||
.top-right-tool-wx-list {
|
||||
width: 100%;
|
||||
background-color: #4C4C4C;
|
||||
border-radius: 10rpx;
|
||||
}
|
||||
.top-right-tool-wx-list-item {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
padding: 0rpx 36rpx;
|
||||
padding-right: 0;
|
||||
}
|
||||
.top-right-tool-wx-list-item-icon {
|
||||
width: 38rpx;
|
||||
height: 38rpx;
|
||||
margin-right: 28rpx;
|
||||
color: #fff;
|
||||
}
|
||||
.top-right-tool-wx-list-item-icon .wxfont {
|
||||
font-size: 40rpx;
|
||||
}
|
||||
.top-right-tool-wx-list-item .text {
|
||||
color: #fff;
|
||||
font-size: 32rpx;
|
||||
border-bottom: 1px #535353 solid;
|
||||
padding: 30rpx 0rpx;
|
||||
flex: 1;
|
||||
}
|
||||
.top-right-tool-wx-list-item:nth-last-child(1) .text{
|
||||
border: none;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,105 @@
|
||||
<template>
|
||||
<view>
|
||||
<view v-if="loaded || list.itemIndex < 15" class="xw-book-wrapper">
|
||||
<view v-if="list.items && list.items.length > 0" class="xw-book-sort">{{ list.key }}</view>
|
||||
</view>
|
||||
<view v-if="(loaded || list.itemIndex < 15) && list.items && list.items.length > 0" class="xw-book-userlist">
|
||||
<view v-for="(item, index) in list.items" :key="index">
|
||||
<view class="xw-book-user" @click="onClick(idx, index)">
|
||||
<view v-if="showSelect" class="xw-book-user-checked">
|
||||
<uni-icons :type="item.checked ? 'checkbox-filled' : 'circle'" :color="item.checked ? '#09C160' : '#C0C0C0'" size="28" />
|
||||
</view>
|
||||
<image class="xw-book-user-avatar" :src="item.data.avatar" mode="aspectFill"></image>
|
||||
<view class="xw-book-user-name">{{item.data.name}}</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'UniIndexedListWX',
|
||||
emits: ['itemClick'],
|
||||
props: {
|
||||
loaded: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
idx: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
list: {
|
||||
type: Object,
|
||||
default () {
|
||||
return {}
|
||||
}
|
||||
},
|
||||
showSelect: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
onClick(idx, index) {
|
||||
this.$emit("itemClick", {
|
||||
idx,
|
||||
index
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.xw-book-wrapper {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
width: 100%;
|
||||
/* #endif */
|
||||
}
|
||||
.xw-book-sort {
|
||||
padding: 0 24rpx;
|
||||
flex: 1;
|
||||
line-height: 60rpx;
|
||||
background-color: #fafafa;
|
||||
font-size: 26rpx;
|
||||
}
|
||||
.xw-book-userlist {
|
||||
padding: 0 24rpx;
|
||||
padding-right: 0;
|
||||
border-radius: 24rpx;
|
||||
box-shadow: 0px 0px 10rpx rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
.xw-book-user {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.xw-book-user-avatar {
|
||||
width: 90rpx;
|
||||
height: 90rpx;
|
||||
border-radius: 10rpx;
|
||||
}
|
||||
|
||||
.xw-book-user-name {
|
||||
font-size: 32rpx;
|
||||
margin-left: 26rpx;
|
||||
height: 90rpx;
|
||||
line-height: 90rpx;
|
||||
padding-bottom: 13rpx;
|
||||
padding-top: 13rpx;
|
||||
border-bottom: 1px #f8f8f8 solid;
|
||||
max-width: 560rpx;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.xw-book-user-checked{
|
||||
margin-right: 20rpx;
|
||||
}
|
||||
</style>
|
||||
456
im-uniapp/components/uni-indexed-list-wx/uni-indexed-list-wx.vue
Normal file
456
im-uniapp/components/uni-indexed-list-wx/uni-indexed-list-wx.vue
Normal file
@@ -0,0 +1,456 @@
|
||||
<template>
|
||||
<view class="uni-indexed-list" ref="list" id="list">
|
||||
<!-- #ifdef APP-NVUE -->
|
||||
<list class="uni-indexed-list__scroll" scrollable="true" show-scrollbar="false">
|
||||
<cell v-for="(list, idx) in lists" :key="idx" :ref="'uni-indexed-list-' + idx">
|
||||
<!-- #endif -->
|
||||
<!-- #ifndef APP-NVUE -->
|
||||
<scroll-view :scroll-into-view="scrollViewId" class="uni-indexed-list__scroll" scroll-y>
|
||||
<view class="xw-book-add" v-if="showAdd">
|
||||
<view class="xw-book-add-item" v-for="(v,i) in addlist" :key="i" @click="gopath(v)">
|
||||
<uni-badge v-if="v.num" :text="v.num+''" absolute="rightTop">
|
||||
<view class="xw-book-add-icon">
|
||||
<view class="wxfont jiahaoyou"></view>
|
||||
</view>
|
||||
</uni-badge>
|
||||
<view v-else class="xw-book-add-icon" :style="{background:v.color}">
|
||||
<view class="wxfont jiahaoyou"></view>
|
||||
</view>
|
||||
<view class="xw-book-add-item-text">{{v.title}}</view>
|
||||
</view>
|
||||
</view>
|
||||
<view v-for="(list, idx) in lists" :key="idx" :id="'uni-indexed-list-' + idx">
|
||||
<!-- #endif -->
|
||||
<indexed-list-item :list="list" :loaded="loaded" :idx="idx" :showSelect="showSelect"
|
||||
@itemClick="onClick"></indexed-list-item>
|
||||
<!-- #ifndef APP-NVUE -->
|
||||
</view>
|
||||
</scroll-view>
|
||||
<!-- #endif -->
|
||||
<!-- #ifdef APP-NVUE -->
|
||||
</cell>
|
||||
|
||||
</list>
|
||||
<!-- #endif -->
|
||||
<view class="uni-indexed-list__menu" @touchstart="touchStart" @touchmove.stop.prevent="touchMove"
|
||||
@touchend="touchEnd" @mousedown.stop="mousedown" @mousemove.stop.prevent="mousemove"
|
||||
@mouseleave.stop="mouseleave">
|
||||
<view v-for="(list, key) in lists" :key="key" class="uni-indexed-list__menu-item"
|
||||
:class="touchmoveIndex == key ? 'uni-indexed-list__menu--active' : ''">
|
||||
<text class="uni-indexed-list__menu-text"
|
||||
:class="touchmoveIndex == key ? 'uni-indexed-list__menu-text--active' : ''">{{ list.key }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<view v-if="touchmove" class="uni-indexed-list__alert-wrapper">
|
||||
<text class="uni-indexed-list__alert">{{ lists[touchmoveIndex].key }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
<script>
|
||||
import indexedListItem from './uni-indexed-list-item.vue'
|
||||
// #ifdef APP-NVUE
|
||||
const dom = weex.requireModule('dom');
|
||||
// #endif
|
||||
// #ifdef APP-PLUS
|
||||
function throttle(func, delay) {
|
||||
var prev = Date.now();
|
||||
return function() {
|
||||
var context = this;
|
||||
var args = arguments;
|
||||
var now = Date.now();
|
||||
if (now - prev >= delay) {
|
||||
func.apply(context, args);
|
||||
prev = Date.now();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function touchMove(e) {
|
||||
let pageY = e.touches[0].pageY
|
||||
let index = Math.floor((pageY - this.winOffsetY) / this.itemHeight)
|
||||
if (this.touchmoveIndex === index) {
|
||||
return false
|
||||
}
|
||||
let item = this.lists[index]
|
||||
if (item) {
|
||||
// #ifndef APP-NVUE
|
||||
this.scrollViewId = 'uni-indexed-list-' + index
|
||||
this.touchmoveIndex = index
|
||||
// #endif
|
||||
// #ifdef APP-NVUE
|
||||
dom.scrollToElement(this.$refs['uni-indexed-list-' + index][0], {
|
||||
animated: false
|
||||
})
|
||||
this.touchmoveIndex = index
|
||||
// #endif
|
||||
}
|
||||
}
|
||||
const throttleTouchMove = throttle(touchMove, 40)
|
||||
// #endif
|
||||
|
||||
/**
|
||||
* IndexedList 索引列表 微信版
|
||||
* @description 用于展示索引列表
|
||||
* @tutorial https://ext.dcloud.net.cn/plugin?id=375
|
||||
* @property {Boolean} showSelect = [true|false] 展示模式
|
||||
* @value true 展示模式
|
||||
* @value false 选择模式
|
||||
* @property {Object} options 索引列表需要的数据对象
|
||||
* @event {Function} click 点击列表事件 ,返回当前选择项的事件对象
|
||||
* @example <uni-indexed-list options="" showSelect="false" @click=""></uni-indexed-list>
|
||||
*/
|
||||
export default {
|
||||
name: 'UniIndexedListWX',
|
||||
components: {
|
||||
indexedListItem
|
||||
},
|
||||
emits: ['click'],
|
||||
props: {
|
||||
options: {
|
||||
type: Array,
|
||||
default () {
|
||||
return []
|
||||
}
|
||||
},
|
||||
showSelect: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
showAdd: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
||||
lists: [],
|
||||
winHeight: 0,
|
||||
itemHeight: 0,
|
||||
winOffsetY: 0,
|
||||
touchmove: false,
|
||||
touchmoveIndex: -1,
|
||||
scrollViewId: '',
|
||||
touchmovable: true,
|
||||
loaded: false,
|
||||
isPC: false
|
||||
}
|
||||
},
|
||||
computed:{
|
||||
friendApply() {
|
||||
return this.$store.state.friendApply
|
||||
},
|
||||
addlist(){
|
||||
return [{
|
||||
title:'新的朋友',
|
||||
path:'../../wx/search-friends/index',
|
||||
num:this.$store.state.friendApply.count ? this.$store.state.friendApply.count : '',
|
||||
icon:'jiahaoyou',
|
||||
color:'#FB9E3E'
|
||||
},{
|
||||
title:'群聊',
|
||||
path:'../../wx/groupInfo/grouplist',
|
||||
icon:'qunl',
|
||||
num:'',
|
||||
color:'#0ABF62'
|
||||
}]
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
options: {
|
||||
handler: function() {
|
||||
this.setList()
|
||||
},
|
||||
deep: true
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
// #ifdef H5
|
||||
this.isPC = this.IsPC()
|
||||
// #endif
|
||||
setTimeout(() => {
|
||||
this.setList()
|
||||
}, 50)
|
||||
setTimeout(() => {
|
||||
this.loaded = true
|
||||
}, 300);
|
||||
},
|
||||
methods: {
|
||||
gopath(e){
|
||||
uni.navigateTo({
|
||||
url:e.path
|
||||
})
|
||||
},
|
||||
setList() {
|
||||
let index = 0;
|
||||
this.lists = []
|
||||
this.options.forEach((value, index) => {
|
||||
if (value.data.length === 0) {
|
||||
return
|
||||
}
|
||||
let indexBefore = index
|
||||
let items = value.data.map(item => {
|
||||
let obj = {}
|
||||
obj['key'] = value.letter
|
||||
obj['data'] = item
|
||||
obj['itemIndex'] = index
|
||||
index++
|
||||
obj.checked = item.checked ? item.checked : false
|
||||
return obj
|
||||
})
|
||||
this.lists.push({
|
||||
title: value.letter,
|
||||
key: value.letter,
|
||||
items: items,
|
||||
itemIndex: indexBefore
|
||||
})
|
||||
})
|
||||
// #ifndef APP-NVUE
|
||||
uni.createSelectorQuery()
|
||||
.in(this)
|
||||
.select('#list')
|
||||
.boundingClientRect()
|
||||
.exec(ret => {
|
||||
this.winOffsetY = ret[0].top
|
||||
this.winHeight = ret[0].height
|
||||
this.itemHeight = this.winHeight / this.lists.length
|
||||
})
|
||||
// #endif
|
||||
// #ifdef APP-NVUE
|
||||
dom.getComponentRect(this.$refs['list'], (res) => {
|
||||
this.winOffsetY = res.size.top
|
||||
this.winHeight = res.size.height
|
||||
this.itemHeight = this.winHeight / this.lists.length
|
||||
})
|
||||
// #endif
|
||||
},
|
||||
touchStart(e) {
|
||||
this.touchmove = true
|
||||
let pageY = this.isPC ? e.pageY : e.touches[0].pageY
|
||||
let index = Math.floor((pageY - this.winOffsetY) / this.itemHeight)
|
||||
let item = this.lists[index]
|
||||
if (item) {
|
||||
this.scrollViewId = 'uni-indexed-list-' + index
|
||||
this.touchmoveIndex = index
|
||||
// #ifdef APP-NVUE
|
||||
dom.scrollToElement(this.$refs['uni-indexed-list-' + index][0], {
|
||||
animated: false
|
||||
})
|
||||
// #endif
|
||||
}
|
||||
},
|
||||
touchMove(e) {
|
||||
// #ifndef APP-PLUS
|
||||
let pageY = this.isPC ? e.pageY : e.touches[0].pageY
|
||||
let index = Math.floor((pageY - this.winOffsetY) / this.itemHeight)
|
||||
if (this.touchmoveIndex === index) {
|
||||
return false
|
||||
}
|
||||
let item = this.lists[index]
|
||||
if (item) {
|
||||
this.scrollViewId = 'uni-indexed-list-' + index
|
||||
this.touchmoveIndex = index
|
||||
}
|
||||
// #endif
|
||||
// #ifdef APP-PLUS
|
||||
throttleTouchMove.call(this, e)
|
||||
// #endif
|
||||
},
|
||||
touchEnd() {
|
||||
this.touchmove = false
|
||||
// this.touchmoveIndex = -1
|
||||
},
|
||||
|
||||
/**
|
||||
* 兼容 PC @tian
|
||||
*/
|
||||
|
||||
mousedown(e) {
|
||||
if (!this.isPC) return
|
||||
this.touchStart(e)
|
||||
},
|
||||
mousemove(e) {
|
||||
if (!this.isPC) return
|
||||
this.touchMove(e)
|
||||
},
|
||||
mouseleave(e) {
|
||||
if (!this.isPC) return
|
||||
this.touchEnd(e)
|
||||
},
|
||||
|
||||
// #ifdef H5
|
||||
IsPC() {
|
||||
var userAgentInfo = navigator.userAgent;
|
||||
var Agents = ["Android", "iPhone", "SymbianOS", "Windows Phone", "iPad", "iPod"];
|
||||
var flag = true;
|
||||
for (let v = 0; v < Agents.length - 1; v++) {
|
||||
if (userAgentInfo.indexOf(Agents[v]) > 0) {
|
||||
flag = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return flag;
|
||||
},
|
||||
// #endif
|
||||
|
||||
|
||||
onClick(e) {
|
||||
let {
|
||||
idx,
|
||||
index
|
||||
} = e
|
||||
let obj = {}
|
||||
for (let key in this.lists[idx].items[index]) {
|
||||
obj[key] = this.lists[idx].items[index][key]
|
||||
}
|
||||
let select = []
|
||||
if (this.showSelect) {
|
||||
this.lists[idx].items[index].checked = !this.lists[idx].items[index].checked
|
||||
this.lists.forEach((value, idx) => {
|
||||
value.items.forEach((item, index) => {
|
||||
if (item.checked) {
|
||||
let obj = {}
|
||||
for (let key in this.lists[idx].items[index]) {
|
||||
obj[key] = this.lists[idx].items[index][key]
|
||||
}
|
||||
select.push(obj)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
this.$emit('click', {
|
||||
item: obj,
|
||||
select: select
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.uni-indexed-list {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.uni-indexed-list__scroll {
|
||||
flex: 1;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.uni-indexed-list__menu {
|
||||
width: 24px;
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.uni-indexed-list__menu-item {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
flex: 1;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
/* #ifdef H5 */
|
||||
cursor: pointer;
|
||||
/* #endif */
|
||||
}
|
||||
|
||||
.uni-indexed-list__menu-text {
|
||||
font-size: 12px;
|
||||
text-align: center;
|
||||
color: #aaa;
|
||||
}
|
||||
|
||||
.uni-indexed-list__menu--active {
|
||||
// background-color: rgb(200, 200, 200);
|
||||
}
|
||||
|
||||
.uni-indexed-list__menu--active {}
|
||||
|
||||
.uni-indexed-list__menu-text--active {
|
||||
border-radius: 16px;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
line-height: 16px;
|
||||
// background-color: #007aff;
|
||||
// color: #fff;
|
||||
}
|
||||
|
||||
.uni-indexed-list__alert-wrapper {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.uni-indexed-list__alert {
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
border-radius: 80px;
|
||||
text-align: center;
|
||||
line-height: 80px;
|
||||
font-size: 35px;
|
||||
color: #fff;
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
.h5-buchang{
|
||||
height: 140rpx;
|
||||
display: none;
|
||||
}
|
||||
.uni-scroll-view-content view:nth-last-child(1) .h5-buchang{
|
||||
display: block;
|
||||
}
|
||||
.xw-book-add{
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding:0 24rpx;
|
||||
box-sizing: border-box;
|
||||
// height: 120rpx;
|
||||
}
|
||||
.xw-book-add-item{
|
||||
display: flex;flex-direction: row;align-items: center;
|
||||
// height: 90rpx;
|
||||
// line-height: 90rpx;
|
||||
padding-bottom: 16rpx;
|
||||
padding-top: 16rpx;
|
||||
// border-bottom: 1px #f8f8f8 solid;
|
||||
}
|
||||
.xw-book-add-icon{
|
||||
background: #FB9E3E;
|
||||
border-radius: 10rpx;
|
||||
width: 90rpx;
|
||||
height: 90rpx;
|
||||
display: flex;flex-direction: row;align-items: center;justify-content: center;
|
||||
}
|
||||
|
||||
.xw-book-add-icon .wxfont{
|
||||
color: #fff;
|
||||
font-size: 58rpx;
|
||||
}
|
||||
.xw-book-add-item-text{
|
||||
flex: 1;
|
||||
font-size: 32rpx;
|
||||
margin-left: 26rpx;
|
||||
// height: 90rpx;
|
||||
// line-height: 90rpx;
|
||||
// border-bottom: 1px #f8f8f8 solid;
|
||||
}
|
||||
</style>
|
||||
173
im-uniapp/components/uni-list-chat-wx/openTool.vue
Normal file
173
im-uniapp/components/uni-list-chat-wx/openTool.vue
Normal file
@@ -0,0 +1,173 @@
|
||||
<template>
|
||||
<view @touchmove.stop.prevent="moveHandle('touchmove')" @click="moveHandle('click')" v-if="show">
|
||||
<view class="openTool-wx" :animation="animationData">
|
||||
<view class="openTool-wx-list" v-if="data">
|
||||
<view class="openTool-wx-list-item" @click="zhiding">
|
||||
<view class="text" v-if="data.top=='Y'">取消置顶</view>
|
||||
<view class="text" v-if="data.top=='N'">置顶该聊天</view>
|
||||
</view>
|
||||
<view class="openTool-wx-list-item" @click="shanchu">
|
||||
<view class="text">删除该聊天</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="openTool-wx-model"></view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
show:false,
|
||||
animationData: {}
|
||||
};
|
||||
},
|
||||
props: {
|
||||
data:{
|
||||
type:[Object,String]
|
||||
},
|
||||
itemKey:{
|
||||
type:[Object,String,Number]
|
||||
},
|
||||
list: {
|
||||
type: Array,
|
||||
default() {
|
||||
return [{}];
|
||||
}
|
||||
}
|
||||
},
|
||||
onShow() {
|
||||
|
||||
},
|
||||
computed: {
|
||||
chatList() {
|
||||
return this.$store.state.chatlist
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
var animation = uni.createAnimation({
|
||||
duration: 300,
|
||||
timingFunction: 'linear'
|
||||
});
|
||||
this.animation = animation;
|
||||
},
|
||||
methods: {
|
||||
zhiding(){
|
||||
var data=JSON.parse(JSON.stringify(this.data))
|
||||
var yn = data.top=='N' ? 'Y' : 'N';
|
||||
data.top=yn
|
||||
this.$store.dispatch('updateChatListInfoById', {
|
||||
userId: this.data.userId,
|
||||
data: data
|
||||
})
|
||||
this.$store.dispatch('getChatList')
|
||||
if(data.windowType=='GROUP'){
|
||||
var formData = {
|
||||
groupId: this.data.userId,
|
||||
top: yn
|
||||
};
|
||||
this.$http.request({
|
||||
url: '/group/editTop',
|
||||
method: 'POST',
|
||||
data: JSON.stringify(formData),
|
||||
success: res => {
|
||||
if (res.data.code == 200) {
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
if(data.windowType=='SINGLE'){
|
||||
var formData = {
|
||||
userId: this.data.userId,
|
||||
top: yn
|
||||
};
|
||||
this.$http.request({
|
||||
url: '/friend/top',
|
||||
method: 'POST',
|
||||
data: JSON.stringify(formData),
|
||||
success: res => {
|
||||
if (res.data.code == 200) {
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
shanchu(){
|
||||
delete this.chatList[this.data.userId]
|
||||
this.$store.dispatch('updateChatListInfoById',{
|
||||
userId: this.data.userId,
|
||||
data: {}
|
||||
});
|
||||
this.$store.dispatch('updateChatById', {
|
||||
userId: this.data.userId,
|
||||
data: []
|
||||
});
|
||||
},
|
||||
showAnimation() {
|
||||
this.animation.opacity(1).step();
|
||||
this.animationData = this.animation.export();
|
||||
},
|
||||
hideAnimation() {
|
||||
this.animation.opacity(0).step();
|
||||
this.animationData = this.animation.export();
|
||||
},
|
||||
moveHandle(e) {
|
||||
this.hiddenTab()
|
||||
},
|
||||
showTab(){
|
||||
this.show=true
|
||||
setTimeout(()=>{
|
||||
this.showAnimation()
|
||||
},30)
|
||||
},
|
||||
hiddenTab(){
|
||||
this.show=false
|
||||
this.hideAnimation()
|
||||
},
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<style scoped>
|
||||
.openTool-wx {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex-wrap: wrap;
|
||||
opacity: 0;
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
}
|
||||
.openTool-wx-model{
|
||||
background-color: rgba(0,0,0,0);
|
||||
position: fixed;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
left: 0;
|
||||
z-index: 1;
|
||||
}
|
||||
.openTool-wx-list {
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
background-color: #fff;
|
||||
box-shadow: 0px 0px 10px rgba(0,0,0,0.3);
|
||||
border-radius: 10rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
.openTool-wx-list-item {
|
||||
padding: 24rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.openTool-wx-list-item .text {
|
||||
color: #333;
|
||||
font-size: 28rpx;
|
||||
flex: 1;
|
||||
}
|
||||
.openTool-wx-list-item:nth-last-child(1) .text{
|
||||
border: none;
|
||||
}
|
||||
</style>
|
||||
583
im-uniapp/components/uni-list-chat-wx/uni-list-chat-wx.vue
Normal file
583
im-uniapp/components/uni-list-chat-wx/uni-list-chat-wx.vue
Normal file
@@ -0,0 +1,583 @@
|
||||
<template>
|
||||
<!-- #ifdef APP-NVUE -->
|
||||
<cell>
|
||||
<!-- #endif -->
|
||||
<view :hover-class="!clickable && !link ? '' : 'uni-list-chat--hover'" :style="{background:color}" class="uni-list-chat" @longpress="longpressItem($event,itemKey,item)">
|
||||
<openTool class="openTool" :ref="'toolx'+itemKey" :data="item" :itemKey="itemKey"></openTool>
|
||||
<view :class="{ 'uni-list--border': border, 'uni-list-chat--first': isFirstChild }"></view>
|
||||
<view class="uni-list-chat__container" @click="onClick">
|
||||
<view class="uni-list-chat__header-warp">
|
||||
<view v-if="item.windowType=='SINGLE'" class="uni-list-chat__header" :class="{ 'header--circle': avatarCircle }">
|
||||
<image class="uni-list-chat__header-image" :src="item.portrait" mode="aspectFill"></image>
|
||||
</view>
|
||||
<!-- 头像组 -->
|
||||
<view v-if="item.windowType=='GROUP'" class="uni-list-chat__header">
|
||||
<view v-for="(item, index) in avatarList" :key="index" class="uni-list-chat__header-box" :class="computedAvatar"
|
||||
:style="{ width: imageWidth + 'px', height: imageWidth + 'px' }">
|
||||
<image class="uni-list-chat__header-image" :style="{ width: imageWidth + 'px', height: imageWidth + 'px' }" :src="item.url"
|
||||
mode="aspectFill"></image>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view v-if="badgeText && badgePositon === 'left'" class="uni-list-chat__badge uni-list-chat__badge-pos" :class="[isSingle]">
|
||||
<text class="uni-list-chat__badge-text">{{ badgeText === 'dot' ? '' : badgeText }}</text>
|
||||
</view>
|
||||
<view class="uni-list-chat__content">
|
||||
<view class="uni-list-chat__content-main">
|
||||
<text class="uni-list-chat__content-title uni-ellipsis">{{ title }}</text>
|
||||
<text class="uni-list-chat__content-note uni-ellipsis">{{ note }}</text>
|
||||
</view>
|
||||
<view class="uni-list-chat__content-extra">
|
||||
<slot>
|
||||
<text class="uni-list-chat__content-extra-text">{{ time }}</text>
|
||||
<view v-if="badgeText && badgePositon === 'right'" class="uni-list-chat__badge" :class="[isSingle, badgePositon === 'right' ? 'uni-list-chat--right' : '']">
|
||||
<text class="uni-list-chat__badge-text">{{ badgeText === 'dot' ? '' : badgeText }}</text>
|
||||
</view>
|
||||
</slot>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<!-- #ifdef APP-NVUE -->
|
||||
</cell>
|
||||
<!-- #endif -->
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import openTool from './openTool.vue'
|
||||
// 头像大小
|
||||
const avatarWidth = 45;
|
||||
|
||||
/**
|
||||
* ListChat 聊天列表
|
||||
* @description 聊天列表,用于创建聊天类列表
|
||||
* @tutorial https://ext.dcloud.net.cn/plugin?id=24
|
||||
* @property {String} title 标题
|
||||
* @property {String} note 描述
|
||||
* @property {Boolean} clickable = [true|false] 是否开启点击反馈,默认为false
|
||||
* @property {String} badgeText 数字角标内容
|
||||
* @property {String} badgePositon = [left|right] 角标位置,默认为 right
|
||||
* @property {String} link = [false|navigateTo|redirectTo|reLaunch|switchTab] 是否展示右侧箭头并开启点击反馈,默认为false
|
||||
* @value false 不开启
|
||||
* @value navigateTo 同 uni.navigateTo()
|
||||
* @value redirectTo 同 uni.redirectTo()
|
||||
* @value reLaunch 同 uni.reLaunch()
|
||||
* @value switchTab 同 uni.switchTab()
|
||||
* @property {String | PageURIString} to 跳转目标页面
|
||||
* @property {String} time 右侧时间显示
|
||||
* @property {Boolean} avatarCircle = [true|false] 是否显示圆形头像,默认为false
|
||||
* @property {String} avatar 头像地址,avatarCircle 不填时生效
|
||||
* @property {Array} avatarList 头像组,格式为 [{url:''}]
|
||||
* @event {Function} click 点击 uniListChat 触发事件
|
||||
*/
|
||||
export default {
|
||||
components:{
|
||||
openTool
|
||||
},
|
||||
name: 'UniListChatWx',
|
||||
emits:['click','longpressItem'],
|
||||
props: {
|
||||
color: {
|
||||
type: String,
|
||||
default: '#fff'
|
||||
},
|
||||
title: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
note: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
clickable: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
link: {
|
||||
type: [Boolean, String],
|
||||
default: false
|
||||
},
|
||||
to: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
badgeText: {
|
||||
type: [String, Number],
|
||||
default: ''
|
||||
},
|
||||
badgePositon: {
|
||||
type: String,
|
||||
default: 'right'
|
||||
},
|
||||
time: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
avatarCircle: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
avatar: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
// avatarList: {
|
||||
// type: Array,
|
||||
// default () {
|
||||
// return [];
|
||||
// }
|
||||
// },
|
||||
item: {
|
||||
type: Object,
|
||||
default: {}
|
||||
},
|
||||
itemKey: {
|
||||
type: Number
|
||||
},
|
||||
longTapItemKey: {
|
||||
type: [Number,String],
|
||||
default:''
|
||||
}
|
||||
},
|
||||
// inject: ['list'],
|
||||
computed: {
|
||||
isSingle() {
|
||||
if (this.badgeText === 'dot') {
|
||||
return 'uni-badge--dot';
|
||||
} else {
|
||||
const badgeText = this.badgeText.toString();
|
||||
if (badgeText.length > 1) {
|
||||
return 'uni-badge--complex';
|
||||
} else {
|
||||
return 'uni-badge--single';
|
||||
}
|
||||
}
|
||||
},
|
||||
avatarList(){
|
||||
return this.returnAvatar(this.item.portrait)
|
||||
},
|
||||
computedAvatar() {
|
||||
if (this.avatarList.length > 4) {
|
||||
this.imageWidth = avatarWidth * 0.31;
|
||||
return 'avatarItem--3';
|
||||
} else if (this.avatarList.length > 1) {
|
||||
this.imageWidth = avatarWidth * 0.47;
|
||||
return 'avatarItem--2';
|
||||
} else {
|
||||
this.imageWidth = avatarWidth;
|
||||
return 'avatarItem--1';
|
||||
}
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
isFirstChild: false,
|
||||
border: true,
|
||||
// avatarList: 3,
|
||||
imageWidth: 50
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
this.list = this.getForm()
|
||||
if (this.list) {
|
||||
if (!this.list.firstChildAppend) {
|
||||
this.list.firstChildAppend = true;
|
||||
this.isFirstChild = true;
|
||||
}
|
||||
this.border = this.list.border;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
returnAvatar(text){
|
||||
var data=JSON.parse(text)
|
||||
var avatars=[]
|
||||
for(var i=0;i<data.length;i++){
|
||||
avatars.push({
|
||||
url:data[i]
|
||||
})
|
||||
}
|
||||
return avatars
|
||||
},
|
||||
longpressItem(e,i,v) {//长按回调
|
||||
this.$emit('longpressItem',e,i,v)
|
||||
if(this.itemKey==this.longTapItemKey){
|
||||
this.$refs['toolx'+this.itemKey].showTab();
|
||||
}
|
||||
},
|
||||
/**
|
||||
* 获取父元素实例
|
||||
*/
|
||||
getForm(name = 'uniList') {
|
||||
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;
|
||||
},
|
||||
onClick() {
|
||||
if (this.to !== '') {
|
||||
this.openPage();
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.clickable || this.link) {
|
||||
this.$emit('click', {
|
||||
data: {}
|
||||
});
|
||||
}
|
||||
},
|
||||
openPage() {
|
||||
if (['navigateTo', 'redirectTo', 'reLaunch', 'switchTab'].indexOf(this.link) !== -1) {
|
||||
this.pageApi(this.link);
|
||||
} else {
|
||||
this.pageApi('navigateTo');
|
||||
}
|
||||
},
|
||||
pageApi(api) {
|
||||
uni[api]({
|
||||
url: this.to,
|
||||
success: res => {
|
||||
this.$emit('click', {
|
||||
data: res
|
||||
});
|
||||
},
|
||||
fail: err => {
|
||||
this.$emit('click', {
|
||||
data: err
|
||||
});
|
||||
console.error(err.errMsg);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
$uni-font-size-lg:16px;
|
||||
$uni-spacing-row-sm: 5px;
|
||||
$uni-spacing-row-base: 10px;
|
||||
$uni-spacing-row-lg: 15px;
|
||||
$background-color: #fff;
|
||||
$divide-line-color: #e5e5e5;
|
||||
$avatar-width: 45px;
|
||||
$avatar-border-radius: 5px;
|
||||
$avatar-border-color: #eee;
|
||||
$avatar-border-width: 1px;
|
||||
$title-size: 16px;
|
||||
$title-color: #3b4144;
|
||||
$title-weight: normal;
|
||||
$note-size: 12px;
|
||||
$note-color: #999;
|
||||
$note-weight: normal;
|
||||
$right-text-size: 12px;
|
||||
$right-text-color: #999;
|
||||
$right-text-weight: normal;
|
||||
$badge-left: 0px;
|
||||
$badge-top: 0px;
|
||||
$dot-width: 10px;
|
||||
$dot-height: 10px;
|
||||
$badge-size: 18px;
|
||||
$badge-font: 12px;
|
||||
$badge-color: #fff;
|
||||
$badge-background-color: #ff5a5f;
|
||||
$badge-space: 6px;
|
||||
$hover: #f5f5f5;
|
||||
.openTool{
|
||||
width: 100%;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
display: flex;flex-direction: row;justify-content: center;
|
||||
}
|
||||
.uni-list-chat {
|
||||
font-size: $uni-font-size-lg;
|
||||
position: relative;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
background-color: $background-color;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
// .uni-list-chat--disabled {
|
||||
// opacity: 0.3;
|
||||
// }
|
||||
|
||||
.uni-list-chat--hover {
|
||||
background-color: $hover;
|
||||
}
|
||||
|
||||
.uni-list--border {
|
||||
position: relative;
|
||||
margin-left: $uni-spacing-row-lg;
|
||||
/* #ifdef APP-PLUS */
|
||||
border-top-color: $divide-line-color;
|
||||
border-top-style: solid;
|
||||
border-top-width: 0.5px;
|
||||
/* #endif */
|
||||
}
|
||||
|
||||
/* #ifndef APP-NVUE */
|
||||
.uni-list--border:after {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
left: 0;
|
||||
height: 1px;
|
||||
content: '';
|
||||
-webkit-transform: scaleY(0.5);
|
||||
transform: scaleY(0.5);
|
||||
background-color: $divide-line-color;
|
||||
}
|
||||
|
||||
.uni-list-item--first:after {
|
||||
height: 0px;
|
||||
}
|
||||
|
||||
/* #endif */
|
||||
|
||||
.uni-list-chat--first {
|
||||
border-top-width: 0px;
|
||||
}
|
||||
|
||||
.uni-ellipsis {
|
||||
/* #ifndef APP-NVUE */
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
/* #endif */
|
||||
/* #ifdef APP-NVUE */
|
||||
lines: 1;
|
||||
/* #endif */
|
||||
}
|
||||
|
||||
.uni-ellipsis-2 {
|
||||
/* #ifndef APP-NVUE */
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: 2;
|
||||
-webkit-box-orient: vertical;
|
||||
/* #endif */
|
||||
|
||||
/* #ifdef APP-NVUE */
|
||||
lines: 2;
|
||||
/* #endif */
|
||||
}
|
||||
|
||||
.uni-list-chat__container {
|
||||
position: relative;
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
flex-direction: row;
|
||||
flex: 1;
|
||||
padding: $uni-spacing-row-base $uni-spacing-row-lg;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.uni-list-chat__header-warp {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.uni-list-chat__header {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
align-content: center;
|
||||
/* #endif */
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
flex-wrap: wrap-reverse;
|
||||
/* #ifdef APP-NVUE */
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
/* #endif */
|
||||
/* #ifndef APP-NVUE */
|
||||
width: $avatar-width;
|
||||
height: $avatar-width;
|
||||
/* #endif */
|
||||
|
||||
border-radius: $avatar-border-radius;
|
||||
border-color: $avatar-border-color;
|
||||
border-width: $avatar-border-width;
|
||||
border-style: solid;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.uni-list-chat__header-box {
|
||||
/* #ifndef APP-PLUS */
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
width: $avatar-width;
|
||||
height: $avatar-width;
|
||||
/* #endif */
|
||||
/* #ifdef APP-NVUE */
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
/* #endif */
|
||||
overflow: hidden;
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
.uni-list-chat__header-image {
|
||||
margin: 1px;
|
||||
/* #ifdef APP-NVUE */
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
/* #endif */
|
||||
/* #ifndef APP-NVUE */
|
||||
width: $avatar-width;
|
||||
height: $avatar-width;
|
||||
/* #endif */
|
||||
}
|
||||
|
||||
/* #ifndef APP-NVUE */
|
||||
.uni-list-chat__header-image {
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.avatarItem--1 {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.avatarItem--2 {
|
||||
width: 47%;
|
||||
height: 47%;
|
||||
}
|
||||
|
||||
.avatarItem--3 {
|
||||
width: 32%;
|
||||
height: 32%;
|
||||
}
|
||||
|
||||
/* #endif */
|
||||
.header--circle {
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.uni-list-chat__content {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
flex-direction: row;
|
||||
flex: 1;
|
||||
overflow: hidden;
|
||||
padding: 2px 0;
|
||||
}
|
||||
|
||||
.uni-list-chat__content-main {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
padding-left: $uni-spacing-row-base;
|
||||
flex: 1;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.uni-list-chat__content-title {
|
||||
font-size: $title-size;
|
||||
color: $title-color;
|
||||
font-weight: $title-weight;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.uni-list-chat__content-note {
|
||||
margin-top: 3px;
|
||||
color: $note-color;
|
||||
font-size: $note-size;
|
||||
font-weight: $title-weight;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.uni-list-chat__content-extra {
|
||||
/* #ifndef APP-NVUE */
|
||||
flex-shrink: 0;
|
||||
display: flex;
|
||||
/* #endif */
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
align-items: flex-end;
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
||||
.uni-list-chat__content-extra-text {
|
||||
color: $right-text-color;
|
||||
font-size: $right-text-size;
|
||||
font-weight: $right-text-weight;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.uni-list-chat__badge-pos {
|
||||
position: absolute;
|
||||
/* #ifdef APP-NVUE */
|
||||
left: 55px;
|
||||
top: 3px;
|
||||
/* #endif */
|
||||
/* #ifndef APP-NVUE */
|
||||
left: calc(#{$avatar-width} + 10px - #{$badge-space} + #{$badge-left});
|
||||
top: calc(#{$uni-spacing-row-base}/ 2 + 1px + #{$badge-top});
|
||||
/* #endif */
|
||||
}
|
||||
|
||||
.uni-list-chat__badge {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
border-radius: 100px;
|
||||
background-color: $badge-background-color;
|
||||
}
|
||||
|
||||
.uni-list-chat__badge-text {
|
||||
color: $badge-color;
|
||||
font-size: $badge-font;
|
||||
}
|
||||
|
||||
.uni-badge--single {
|
||||
/* #ifndef APP-NVUE */
|
||||
// left: calc(#{$avatar-width} + 7px + #{$badge-left});
|
||||
/* #endif */
|
||||
width: $badge-size;
|
||||
height: $badge-size;
|
||||
}
|
||||
|
||||
.uni-badge--complex {
|
||||
/* #ifdef APP-NVUE */
|
||||
left: 50px;
|
||||
/* #endif */
|
||||
/* #ifndef APP-NVUE */
|
||||
width: auto;
|
||||
/* #endif */
|
||||
height: $badge-size;
|
||||
padding: 0 $badge-space;
|
||||
}
|
||||
|
||||
.uni-badge--dot {
|
||||
/* #ifdef APP-NVUE */
|
||||
left: 60px;
|
||||
top: 6px;
|
||||
/* #endif */
|
||||
/* #ifndef APP-NVUE */
|
||||
left: calc(#{$avatar-width} + 15px - #{$dot-width}/ 2 + 1px + #{$badge-left});
|
||||
/* #endif */
|
||||
width: $dot-width;
|
||||
height: $dot-height;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.uni-list-chat--right {
|
||||
/* #ifdef APP-NVUE */
|
||||
left: 0;
|
||||
/* #endif */
|
||||
}
|
||||
</style>
|
||||
108
im-uniapp/components/uni-list-wx/uni-list-wx.vue
Normal file
108
im-uniapp/components/uni-list-wx/uni-list-wx.vue
Normal file
@@ -0,0 +1,108 @@
|
||||
<template>
|
||||
<!-- #ifndef APP-NVUE -->
|
||||
<view class="uni-list uni-border-top-bottom">
|
||||
<view v-if="border" class="uni-list--border-top"></view>
|
||||
<slot />
|
||||
<view v-if="border" class="uni-list--border-bottom"></view>
|
||||
</view>
|
||||
<!-- #endif -->
|
||||
<!-- #ifdef APP-NVUE -->
|
||||
<list class="uni-list" :class="{ 'uni-list--border': border }" :enableBackToTop="enableBackToTop" loadmoreoffset="15"><slot /></list>
|
||||
<!-- #endif -->
|
||||
</template>
|
||||
|
||||
<script>
|
||||
/**
|
||||
* List 列表
|
||||
* @description 列表组件
|
||||
* @tutorial https://ext.dcloud.net.cn/plugin?id=24
|
||||
* @property {String} border = [true|false] 标题
|
||||
*/
|
||||
export default {
|
||||
name: 'uniListWx',
|
||||
'mp-weixin': {
|
||||
options: {
|
||||
multipleSlots: false
|
||||
}
|
||||
},
|
||||
props: {
|
||||
enableBackToTop: {
|
||||
type: [Boolean, String],
|
||||
default: false
|
||||
},
|
||||
scrollY: {
|
||||
type: [Boolean, String],
|
||||
default: false
|
||||
},
|
||||
border: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
}
|
||||
},
|
||||
// provide() {
|
||||
// return {
|
||||
// list: this
|
||||
// };
|
||||
// },
|
||||
created() {
|
||||
this.firstChildAppend = false;
|
||||
},
|
||||
methods: {
|
||||
loadMore(e) {
|
||||
this.$emit('scrolltolower');
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
$uni-bg-color:#ffffff;
|
||||
$uni-border-color:#e5e5e5;
|
||||
.uni-list {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
background-color: $uni-bg-color;
|
||||
position: relative;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.uni-list--border {
|
||||
position: relative;
|
||||
/* #ifdef APP-NVUE */
|
||||
border-top-color: $uni-border-color;
|
||||
border-top-style: solid;
|
||||
border-top-width: 0.5px;
|
||||
border-bottom-color: $uni-border-color;
|
||||
border-bottom-style: solid;
|
||||
border-bottom-width: 0.5px;
|
||||
/* #endif */
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
/* #ifndef APP-NVUE */
|
||||
|
||||
.uni-list--border-top {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
left: 0;
|
||||
height: 1px;
|
||||
-webkit-transform: scaleY(0.5);
|
||||
transform: scaleY(0.5);
|
||||
background-color: $uni-border-color;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.uni-list--border-bottom {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
left: 0;
|
||||
height: 1px;
|
||||
-webkit-transform: scaleY(0.5);
|
||||
transform: scaleY(0.5);
|
||||
background-color: $uni-border-color;
|
||||
}
|
||||
|
||||
/* #endif */
|
||||
</style>
|
||||
140
im-uniapp/components/uni-section/uni-section.vue
Normal file
140
im-uniapp/components/uni-section/uni-section.vue
Normal file
@@ -0,0 +1,140 @@
|
||||
<template>
|
||||
<view class="uni-section">
|
||||
<view class="uni-section-header" nvue>
|
||||
<view v-if="type" class="uni-section__head">
|
||||
<view :class="type" class="uni-section__head-tag"/>
|
||||
</view>
|
||||
<view class="uni-section__content">
|
||||
<text :class="{'distraction':!subTitle}" :style="{color:color}" class="uni-section__content-title">{{ title }}</text>
|
||||
<text v-if="subTitle" class="uni-section__content-sub">{{ subTitle }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<view :style="{padding: padding ? '10px' : ''}">
|
||||
<slot/>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
/**
|
||||
* Section 标题栏
|
||||
* @description 标题栏
|
||||
* @property {String} type = [line|circle] 标题装饰类型
|
||||
* @value line 竖线
|
||||
* @value circle 圆形
|
||||
* @property {String} title 主标题
|
||||
* @property {String} subTitle 副标题
|
||||
*/
|
||||
|
||||
export default {
|
||||
name: 'UniSection',
|
||||
emits:['click'],
|
||||
props: {
|
||||
type: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
title: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
color:{
|
||||
type: String,
|
||||
default: '#333'
|
||||
},
|
||||
subTitle: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
padding: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {}
|
||||
},
|
||||
watch: {
|
||||
title(newVal) {
|
||||
if (uni.report && newVal !== '') {
|
||||
uni.report('title', newVal)
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
onClick() {
|
||||
this.$emit('click')
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
$uni-primary: #2979ff !default;
|
||||
|
||||
.uni-section {
|
||||
background-color: #fff;
|
||||
// overflow: hidden;
|
||||
margin-top: 10px;
|
||||
}
|
||||
.uni-section-header {
|
||||
position: relative;
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
padding: 12px 10px;
|
||||
// height: 50px;
|
||||
font-weight: normal;
|
||||
}
|
||||
.uni-section__head {
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.line {
|
||||
height: 12px;
|
||||
background-color: $uni-primary;
|
||||
border-radius: 10px;
|
||||
width: 4px;
|
||||
}
|
||||
|
||||
.circle {
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
border-top-right-radius: 50px;
|
||||
border-top-left-radius: 50px;
|
||||
border-bottom-left-radius: 50px;
|
||||
border-bottom-right-radius: 50px;
|
||||
background-color: $uni-primary;
|
||||
}
|
||||
|
||||
.uni-section__content {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
flex-direction: column;
|
||||
flex: 1;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.uni-section__content-title {
|
||||
font-size: 14px;
|
||||
color: $uni-primary;
|
||||
}
|
||||
|
||||
.distraction {
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.uni-section__content-sub {
|
||||
font-size: 12px;
|
||||
color: #999;
|
||||
line-height: 16px;
|
||||
margin-top: 2px;
|
||||
}
|
||||
</style>
|
||||
20
im-uniapp/components/watermark/watermark.vue
Normal file
20
im-uniapp/components/watermark/watermark.vue
Normal file
@@ -0,0 +1,20 @@
|
||||
<template>
|
||||
<zmm-watermark :opacity="0.05" :watermark="watermark"></zmm-watermark>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'watermark',
|
||||
data() {
|
||||
return {};
|
||||
},
|
||||
computed: {
|
||||
watermark() {
|
||||
return this.$store.state.watermark;
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
</style>
|
||||
187
im-uniapp/components/zmm-city-picker/zmm-city-picker.vue
Normal file
187
im-uniapp/components/zmm-city-picker/zmm-city-picker.vue
Normal file
@@ -0,0 +1,187 @@
|
||||
<template>
|
||||
<view class="zmm-picker-region" :style="{'cursor':disabled ? 'move' : 'default'}">
|
||||
<picker
|
||||
:disabled="disabled"
|
||||
mode="multiSelector"
|
||||
@columnchange="Citycolumnchange($event)"
|
||||
@change="pickerchange"
|
||||
:value="Index"
|
||||
:range="pickerArr"
|
||||
range-key="label"
|
||||
@tap="iconopen"
|
||||
@cancel="opend = false"
|
||||
>
|
||||
<view class="zmm-picker-region-uni-input" :style="{'color':disabled ? '#666' : '#333'}" :class="{ 'zmm-picker-region-placeholder': modelValue == '' }">
|
||||
<text :style="{ 'text-align': textAlign }" v-if="modelValue == ''">{{ placeholder }}</text>
|
||||
<text :style="{ 'text-align': textAlign }" v-else>{{ modelValue }}</text>
|
||||
</view>
|
||||
</picker>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import citydata from '@/common/city.js';
|
||||
export default {
|
||||
emits: ['update:modelValue','change'],
|
||||
data() {
|
||||
return {
|
||||
opend: false,
|
||||
Index: [0,0,0],
|
||||
citydata:citydata.data
|
||||
};
|
||||
},
|
||||
behaviors: ['uni://form-field'], //必须要写不然微信小程序收不到值
|
||||
props: {
|
||||
rangeLeave:{//联动级别
|
||||
type:Number,
|
||||
default:2
|
||||
},
|
||||
textAlign: {
|
||||
type: String,
|
||||
default: 'center'
|
||||
},
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
placeholder: {
|
||||
type: String,
|
||||
default: '请点击选择'
|
||||
},
|
||||
modelValue: {
|
||||
type: [String]
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
},
|
||||
computed:{
|
||||
pickerArr(){
|
||||
var arr=[]
|
||||
function findarr(arrx){
|
||||
var arr=[]
|
||||
for (var i = 0; i < arrx.length; i++) {
|
||||
var item = arrx[i]
|
||||
arr.push({
|
||||
label:item.label,
|
||||
value:item.value,
|
||||
position:item.position
|
||||
})
|
||||
}
|
||||
return arr
|
||||
}
|
||||
for (var i = 0; i < this.rangeLeave; i++) {
|
||||
arr.push([])
|
||||
if(i==0){//一级数据
|
||||
arr[i]=findarr(this.citydata)
|
||||
}
|
||||
if(i==1){//二级数据
|
||||
if(this.citydata[this.Index[0]]){
|
||||
arr[i]=findarr(this.citydata[this.Index[0]]['children'])
|
||||
}else{
|
||||
arr[i]=[]
|
||||
}
|
||||
}
|
||||
if(i==2){//三级数据
|
||||
if(this.citydata[this.Index[0]]&&this.citydata[this.Index[0]]['children'][this.Index[1]]){
|
||||
arr[i]=findarr(this.citydata[this.Index[0]]['children'][this.Index[1]]['children'])
|
||||
}else{
|
||||
arr[i]=[]
|
||||
}
|
||||
}
|
||||
}
|
||||
return arr
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
modelValue:{
|
||||
deep: true,
|
||||
immediate:true,
|
||||
handler(val) {
|
||||
this.iniIndex()
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
iniIndex(){
|
||||
var arr=this.modelValue.split(',')
|
||||
function findLabelIndex(arr,label){
|
||||
if(!label){
|
||||
return 0
|
||||
}
|
||||
for (var i = 0; i < arr.length; i++) {
|
||||
if(arr[i].label==label){
|
||||
return i
|
||||
break;
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
for (var i = 0; i < arr.length; i++) {
|
||||
this.Index[i]=findLabelIndex(this.pickerArr[i],arr[i])
|
||||
}
|
||||
},
|
||||
iconopen() {
|
||||
if (this.disabled) {
|
||||
return;
|
||||
}
|
||||
this.opend = true;
|
||||
},
|
||||
pickerchange(e) {
|
||||
var text=[]
|
||||
if(this.rangeLeave==1){
|
||||
text.push(this.pickerArr[0][e.detail.value[0]].label)
|
||||
}
|
||||
if(this.rangeLeave==2){
|
||||
text.push(this.pickerArr[0][e.detail.value[0]].label)
|
||||
text.push(this.pickerArr[1][e.detail.value[1]].label)
|
||||
}
|
||||
if(this.rangeLeave==3){
|
||||
text.push(this.pickerArr[0][e.detail.value[0]].label)
|
||||
text.push(this.pickerArr[1][e.detail.value[1]].label)
|
||||
text.push(this.pickerArr[2][e.detail.value[2]].label)
|
||||
}
|
||||
this.opend = !this.opend;
|
||||
this.$emit('update:modelValue', text.toString());
|
||||
this.$emit('change', text.toString())
|
||||
},
|
||||
Citycolumnchange(e) {
|
||||
if (e.detail.column == 0&&this.rangeLeave>1) {//第一行发生变化重置第二列索引
|
||||
this.Index.splice(1, 1, 0);
|
||||
}
|
||||
if (e.detail.column == 1&&this.rangeLeave>2) {
|
||||
this.Index.splice(2, 1, 0);
|
||||
}
|
||||
this.Index[e.detail.column] = e.detail.value;//设置index
|
||||
this.$forceUpdate();
|
||||
},
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.zmm-picker-region {
|
||||
}
|
||||
.zmm-picker-region-uni-input {
|
||||
height: 90rpx;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.zmm-picker-region-uni-input text {
|
||||
flex: 1;
|
||||
font-size: 28rpx;
|
||||
padding:0 12rpx;
|
||||
}
|
||||
|
||||
|
||||
.zmm-picker-region-placeholder {
|
||||
width: 100%;
|
||||
}
|
||||
.zmm-picker-region-placeholder text{
|
||||
color: #666;
|
||||
|
||||
}
|
||||
</style>
|
||||
105
im-uniapp/components/zmm-radio-group/zmm-radio-group.vue
Normal file
105
im-uniapp/components/zmm-radio-group/zmm-radio-group.vue
Normal file
@@ -0,0 +1,105 @@
|
||||
<template>
|
||||
<view>
|
||||
<radio-group class="zmm-radio-group" @change="radioChange">
|
||||
<label class="zmm-radio-group-label" v-for="(item,index) in ranges" :key="index" :class="{'checked':index === current}">
|
||||
<view class="zmm-radio-group-radio">
|
||||
<radio style="transform:scale(0.9)" :value="item.value" :checked="index === current" />
|
||||
</view>
|
||||
<view class="zmm-radio-group-label-text">{{ item.label }}</view>
|
||||
<uni-icons class="zmm-radio-group-label-icon" type="checkmarkempty" color="#09C160" size="20"></uni-icons>
|
||||
</label>
|
||||
</radio-group>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
emits: ['update:modelValue','change'],
|
||||
data() {
|
||||
return {
|
||||
current: '',
|
||||
val: '',
|
||||
ranges: []
|
||||
};
|
||||
},
|
||||
props: {
|
||||
modelValue: {
|
||||
type: [String]
|
||||
},
|
||||
range: {
|
||||
//数组label value
|
||||
type: Array,
|
||||
default: []
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
range(v) {
|
||||
this.init();
|
||||
},
|
||||
modelValue(val) {
|
||||
this.init();
|
||||
},
|
||||
},
|
||||
created() {
|
||||
this.init();
|
||||
},
|
||||
methods: {
|
||||
init() {
|
||||
this.ranges = JSON.parse(JSON.stringify(this.range));
|
||||
this.getval(this.modelValue);
|
||||
},
|
||||
getval(e) {
|
||||
if (!e) {
|
||||
return;
|
||||
}
|
||||
var val = e;
|
||||
var items = this.ranges;
|
||||
for (var i = 0; i < items.length; ++i) {
|
||||
const item = items[i];
|
||||
if (item.value==val) {
|
||||
this.current=i
|
||||
break;
|
||||
}
|
||||
}
|
||||
},
|
||||
radioChange(e) {
|
||||
this.getval(e.detail.value);
|
||||
this.$emit('update:modelValue', e.detail.value)
|
||||
this.$emit('change', e.detail.value)
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<style>
|
||||
.zmm-radio-group {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
.zmm-radio-group-radio{
|
||||
display: none;
|
||||
}
|
||||
.zmm-radio-group-label.checked{
|
||||
}
|
||||
.zmm-radio-group-label-icon{display: none;}
|
||||
.zmm-radio-group-label.checked .zmm-radio-group-label-icon{
|
||||
display: block;
|
||||
}
|
||||
.zmm-radio-group-label {
|
||||
height: 90rpx;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
background-color: #fff;
|
||||
border-bottom: 1px #eee solid;
|
||||
padding: 24rpx;
|
||||
}
|
||||
.zmm-radio-group-label:nth-last-child(1){
|
||||
margin-right: 0;
|
||||
}
|
||||
.zmm-radio-group-label-text{
|
||||
margin-left: 10rpx;
|
||||
font-size: 28rpx;
|
||||
margin-right: auto;
|
||||
}
|
||||
</style>
|
||||
277
im-uniapp/components/zmm-recorder/zmm-recorder.vue
Normal file
277
im-uniapp/components/zmm-recorder/zmm-recorder.vue
Normal file
@@ -0,0 +1,277 @@
|
||||
<template>
|
||||
<view v-if="show">
|
||||
<view class="uni-padding-wrap">
|
||||
<block v-if="!recording && !playing && !hasRecord">
|
||||
<view class="page-body-time">
|
||||
<text class="time-big">{{formatedRecordTime}}</text>
|
||||
</view>
|
||||
<view class="page-body-buttons">
|
||||
<view class="page-body-button" @click="startRecord">
|
||||
<image src="@/static/record.png"></image>
|
||||
</view>
|
||||
</view>
|
||||
</block>
|
||||
<block v-if="recording === true">
|
||||
<view class="page-body-time">
|
||||
<text class="time-big">{{formatedRecordTime}}</text>
|
||||
</view>
|
||||
<view class="page-body-buttons">
|
||||
<view class="page-body-button" @click="stopRecord">
|
||||
<view class="button-stop-record"></view>
|
||||
</view>
|
||||
</view>
|
||||
</block>
|
||||
<block v-if="hasRecord === true && playing === false">
|
||||
<view class="page-body-time">
|
||||
<text class="time-big">{{formatedPlayTime}}</text>
|
||||
<text class="time-small">{{formatedRecordTime}}</text>
|
||||
</view>
|
||||
<view class="page-body-buttons">
|
||||
<view class="page-body-button" @click="playVoice">
|
||||
<image src="@/static/play.png"></image>
|
||||
</view>
|
||||
<view class="page-body-button" @click="clear">
|
||||
<image src="@/static/trash.png"></image>
|
||||
</view>
|
||||
</view>
|
||||
</block>
|
||||
<block v-if="hasRecord === true && playing === true">
|
||||
<view class="page-body-time">
|
||||
<text class="time-big">{{formatedPlayTime}}</text>
|
||||
<text class="time-small">{{formatedRecordTime}}</text>
|
||||
</view>
|
||||
<view class="page-body-buttons">
|
||||
<view class="page-body-button" @click="stopVoice">
|
||||
<image src="@/static/stop.png"></image>
|
||||
</view>
|
||||
<view class="page-body-button" @click="clear">
|
||||
<image src="@/static/trash.png"></image>
|
||||
</view>
|
||||
</view>
|
||||
</block>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
<script>
|
||||
// #ifdef APP-PLUS
|
||||
import permision from "@/common/permission.js"
|
||||
// #endif
|
||||
var playTimeInterval = null;
|
||||
var recordTimeInterval = null;
|
||||
var recorderManager = null;
|
||||
var music = null;
|
||||
export default {
|
||||
props:{
|
||||
show:{
|
||||
type:Boolean,
|
||||
default:true
|
||||
}
|
||||
},
|
||||
emits:['recorderStop'],
|
||||
data() {
|
||||
return {
|
||||
recording: false, //录音中
|
||||
playing: false, //播放中
|
||||
hasRecord: false, //是否有了一个
|
||||
tempFilePath: '',
|
||||
recordTime: 0,
|
||||
playTime: 0,
|
||||
formatedRecordTime: '00:00:00', //录音的总时间
|
||||
formatedPlayTime: '00:00:00' //播放录音的当前时间
|
||||
}
|
||||
},
|
||||
beforeDestroy: function() {
|
||||
this.clear();
|
||||
},
|
||||
mounted() {
|
||||
music = uni.createInnerAudioContext();
|
||||
music.onEnded(() => {
|
||||
clearInterval(playTimeInterval)
|
||||
var playTime = 0
|
||||
// console.log('play voice finished')
|
||||
this.playing = false;
|
||||
this.formatedPlayTime = this.formatTime(playTime);
|
||||
this.playTime = playTime;
|
||||
});
|
||||
recorderManager = uni.getRecorderManager();
|
||||
recorderManager.onStart(() => {
|
||||
// console.log('recorder start');
|
||||
this.recording = true;
|
||||
recordTimeInterval = setInterval(() => {
|
||||
this.recordTime += 1;
|
||||
this.formatedRecordTime = this.formatTime(this.recordTime);
|
||||
}, 1000)
|
||||
});
|
||||
recorderManager.onStop((res) => {
|
||||
// console.log('on stop');
|
||||
music.src = res.tempFilePath;
|
||||
this.hasRecord = true;
|
||||
this.recording = false;
|
||||
this.$emit('recorderStop',{
|
||||
formatedRecordTime:this.formatedRecordTime,
|
||||
recordTime:this.recordTime<1 ? this.recordTime+1 : this.recordTime,
|
||||
recordFilePath:res.tempFilePath
|
||||
})
|
||||
this.clear()
|
||||
});
|
||||
recorderManager.onError(() => {
|
||||
console.log('recorder onError');
|
||||
});
|
||||
},
|
||||
methods: {
|
||||
formatTime(time) {
|
||||
if (typeof time !== 'number' || time < 0) {
|
||||
return time
|
||||
}
|
||||
|
||||
var hour = parseInt(time / 3600)
|
||||
time = time % 3600
|
||||
var minute = parseInt(time / 60)
|
||||
time = time % 60
|
||||
var second = time
|
||||
|
||||
return ([hour, minute, second]).map(function(n) {
|
||||
n = n.toString()
|
||||
return n[1] ? n : '0' + n
|
||||
}).join(':')
|
||||
},
|
||||
async startRecord() { //开始录音
|
||||
// #ifdef APP-PLUS
|
||||
let status = await this.checkPermission();
|
||||
if (status !== 1) {
|
||||
return;
|
||||
}
|
||||
// #endif
|
||||
|
||||
// TODO ios 在没有请求过权限之前无法得知是否有相关权限,这种状态下需要直接调用录音,但没有状态或回调判断用户拒绝
|
||||
recorderManager.start({
|
||||
duration:600000,
|
||||
sampleRate:44100,
|
||||
format:'mp3'
|
||||
});
|
||||
},
|
||||
stopRecord() { //停止录音
|
||||
recorderManager.stop();
|
||||
|
||||
},
|
||||
playVoice() {
|
||||
// console.log('play voice');
|
||||
this.playing = true;
|
||||
playTimeInterval = setInterval(() => {
|
||||
this.playTime += 1;
|
||||
this.formatedPlayTime = this.formatTime(this.playTime);
|
||||
}, 1000)
|
||||
music.play();
|
||||
},
|
||||
stopVoice() {
|
||||
clearInterval(playTimeInterval)
|
||||
this.playing = false;
|
||||
this.formatedPlayTime = this.formatTime(0);
|
||||
this.playTime = 0;
|
||||
music.stop();
|
||||
},
|
||||
end() {
|
||||
music.stop();
|
||||
recorderManager.stop();
|
||||
clearInterval(recordTimeInterval)
|
||||
clearInterval(playTimeInterval);
|
||||
this.recording = false, this.playing = false, this.hasRecord = false;
|
||||
this.playTime = 0, this.recordTime = 0;
|
||||
this.formatedRecordTime = "00:00:00", this.formatedRecordTime = "00:00:00";
|
||||
},
|
||||
clear() {
|
||||
this.end();
|
||||
}
|
||||
// #ifdef APP-PLUS
|
||||
,
|
||||
async checkPermission() {
|
||||
let status = permision.isIOS ? await permision.requestIOS('record') :
|
||||
await permision.requestAndroid('android.permission.RECORD_AUDIO');
|
||||
|
||||
if (status === null || status === 1) {
|
||||
status = 1;
|
||||
} else if (status === 2) {
|
||||
uni.showModal({
|
||||
content: "系统麦克风已关闭",
|
||||
confirmText: "确定",
|
||||
showCancel: false,
|
||||
success: function(res) {
|
||||
}
|
||||
})
|
||||
} else {
|
||||
uni.showModal({
|
||||
content: "需要麦克风权限",
|
||||
confirmText: "设置",
|
||||
success: function(res) {
|
||||
if (res.confirm) {
|
||||
permision.gotoAppSetting();
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
return status;
|
||||
}
|
||||
// #endif
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.uni-padding-wrap{}
|
||||
image {
|
||||
width: 130rpx;
|
||||
height: 130rpx;
|
||||
}
|
||||
|
||||
.page-body-wrapper {
|
||||
justify-content: space-between;
|
||||
flex-grow: 1;
|
||||
margin-bottom: 300rpx;
|
||||
}
|
||||
|
||||
.page-body-time {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.time-big {
|
||||
font-size: 26rpx;
|
||||
margin: 20rpx;
|
||||
}
|
||||
|
||||
.time-small {
|
||||
font-size: 26rpx;
|
||||
}
|
||||
|
||||
.page-body-buttons{
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
}
|
||||
|
||||
.page-body-button {
|
||||
/* width: 250rpx; */
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.button-stop-record {
|
||||
box-sizing: border-box;
|
||||
width: 130rpx;
|
||||
height: 130rpx;
|
||||
border: 20rpx solid #fff;
|
||||
background-color: #4CD964;
|
||||
border-radius: 50%;
|
||||
animation: colors 1s linear infinite;
|
||||
}
|
||||
@keyframes colors {
|
||||
0% {
|
||||
opacity: 1;
|
||||
}
|
||||
50% {
|
||||
opacity: .7;
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
158
im-uniapp/components/zmm-upload-avatar/zmm-upload-avatar.vue
Normal file
158
im-uniapp/components/zmm-upload-avatar/zmm-upload-avatar.vue
Normal file
@@ -0,0 +1,158 @@
|
||||
<template>
|
||||
<view>
|
||||
<image class="zmm-upload-avatar" :src="modelValue" :style="{ width: imgSize + 'rpx', height: imgSize + 'rpx', 'border-radius': imgRadius + 'rpx' }" mode="aspectFill" @click="selectImage"></image>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import http from '@/common/request.js';
|
||||
export default {
|
||||
name: 'zmm-upload-avatar',
|
||||
emits: ['update:modelValue','change'],
|
||||
props: {
|
||||
modelValue: {
|
||||
type: [String]
|
||||
},
|
||||
imgSize: {
|
||||
//图片大小
|
||||
type: Number,
|
||||
default: 120
|
||||
},
|
||||
imgRadius: {
|
||||
//图片圆角
|
||||
type: Number,
|
||||
default: 12
|
||||
},
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
action: {
|
||||
//后台上传接口
|
||||
type: String,
|
||||
default: http.baseUrl + '/file/upload'
|
||||
},
|
||||
formData: {
|
||||
//上传所附带数据
|
||||
type: Object
|
||||
},
|
||||
header: {
|
||||
//自定义头
|
||||
type: Object,
|
||||
default() {
|
||||
return {
|
||||
Authorization: uni.getStorageSync('Authorization'),
|
||||
device: uni.getStorageSync('device'),
|
||||
version: uni.getStorageSync('version')
|
||||
};
|
||||
}
|
||||
},
|
||||
fileKey: {
|
||||
//后端接受的filekey
|
||||
type: String,
|
||||
default: 'file'
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
isDestroyed: false,
|
||||
showUploadProgress: true
|
||||
};
|
||||
},
|
||||
mounted: function() {},
|
||||
destroyed: function() {
|
||||
this.isDestroyed = true;
|
||||
},
|
||||
computed: {},
|
||||
methods: {
|
||||
selectImage: function() {
|
||||
var _self = this;
|
||||
uni.chooseImage({
|
||||
count: 1,
|
||||
sourceType: ['album', 'camera'],
|
||||
success: function(e) {
|
||||
var imagePathArr = e.tempFilePaths;
|
||||
//检查服务器地址是否设置,设置即表示图片要上传到服务器
|
||||
if (_self.action) {
|
||||
uni.showToast({
|
||||
title: '上传中',
|
||||
icon: 'none',
|
||||
mask: false
|
||||
});
|
||||
|
||||
var remoteIndexStart = 1 - imagePathArr.length;
|
||||
var promiseWorkList = [];
|
||||
var keyname = _self.fileKey ? _self.fileKey : 'upload-images';
|
||||
var completeImages = 0;
|
||||
|
||||
for (let i = 0; i < imagePathArr.length; i++) {
|
||||
promiseWorkList.push(
|
||||
new Promise((resolve, reject) => {
|
||||
let remoteUrlIndex = remoteIndexStart + i;
|
||||
uni.uploadFile({
|
||||
url: _self.action,
|
||||
fileType: 'image',
|
||||
header: _self.header,
|
||||
formData: _self.formData,
|
||||
filePath: imagePathArr[i],
|
||||
name: keyname,
|
||||
success: function(res) {
|
||||
if (res.statusCode === 200) {
|
||||
if (_self.isDestroyed) {
|
||||
return;
|
||||
}
|
||||
|
||||
completeImages++;
|
||||
|
||||
if (_self.showUploadProgress) {
|
||||
uni.showToast({
|
||||
title: '上传中',
|
||||
icon: 'none',
|
||||
mask: false,
|
||||
duration: 500
|
||||
});
|
||||
}
|
||||
// console.log('success to upload image: ' + res.data)
|
||||
resolve(res.data);
|
||||
} else {
|
||||
console.log('fail to upload image:' + res.data);
|
||||
reject('fail to upload image:' + remoteUrlIndex);
|
||||
}
|
||||
},
|
||||
fail: function(res) {
|
||||
uni.showToast({
|
||||
title: '上传失败请检查网络',
|
||||
icon: 'none'
|
||||
});
|
||||
console.log('fail to upload image:' + res);
|
||||
reject('fail to upload image:' + remoteUrlIndex);
|
||||
}
|
||||
});
|
||||
})
|
||||
);
|
||||
}
|
||||
Promise.all(promiseWorkList).then(result => {
|
||||
if (_self.isDestroyed) {
|
||||
return;
|
||||
}
|
||||
for (let i = 0; i < result.length; i++) {
|
||||
var resItem = JSON.parse(result[i]);
|
||||
_self.$emit('update:modelValue', resItem.data.fullPath);
|
||||
_self.$emit('change', resItem.data.fullPath);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
_self.$emit('update:modelValue', '../../static/img/avatar/avatar2.jpg');
|
||||
_self.$emit('change', '../../static/img/avatar/avatar2.jpg');
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.zmm-upload-avatar {
|
||||
}
|
||||
</style>
|
||||
319
im-uniapp/components/zmm-upload-image/zmm-upload-image-drag.vue
Normal file
319
im-uniapp/components/zmm-upload-image/zmm-upload-image-drag.vue
Normal file
@@ -0,0 +1,319 @@
|
||||
<template>
|
||||
<view @touchmove.stop.prevent="moveHandle" class="moveWrap">
|
||||
<movable-area class="movarea" ref="areaBox" id="areaBox" :style="{height:imgSize*rowNum +200+ 'rpx'}">
|
||||
<view class="imgBox" :style="{height:imgSize*rowNum + 'rpx'}">
|
||||
<view :id="'img' + idx" class="imgItem" v-for="(item, idx) in imgList" :key="idx"
|
||||
:style="{transition:addJump?' all 0.5s':'',opacity:idx===selectIdx?'0':'1', width: imgSize + 'rpx', height: imgSize + 'rpx', borderRadius:imgRadius+'rpx',padding:imgPadding+'rpx',left:(hoverImgIdx==='img'+idx?curHoverBoxMove.x+'rpx':''),top:(hoverImgIdx==='img'+idx?curHoverBoxMove.y+'rpx':'')}">
|
||||
<view class="imgItem-img" @tap="itemclick(item,idx)" @touchstart="tstr(idx, $event)" @touchmove="tsmo" @touchend="toend">
|
||||
<image v-if="item.videoUrl" class="imgItem-play" src="../../static/img/bf.png" mode="aspectFill"></image>
|
||||
<image :style="{borderRadius:imgRadius+'rpx' }" :ref="'img' + idx" :src="item.url" mode="aspectFill"></image>
|
||||
</view>
|
||||
</view>
|
||||
<slot></slot>
|
||||
</view>
|
||||
<movable-view v-if="moveSrc" :animation="false" class="moveV" :x="x" :y="y" direction="all"
|
||||
@change="onChange"
|
||||
:style="{ width: imgSize + 'rpx', height: imgSize + 'rpx',padding:imgPadding+'rpx' }">
|
||||
<image v-if="moveSrc.videoUrl" class="imgItem-play" src="../../static/img/bf.png" mode="aspectFill"></image>
|
||||
<image :style="{borderRadius:imgRadius+'rpx' }" :src="moveSrc.url" mode="aspectFill"></image>
|
||||
</movable-view>
|
||||
</movable-area>
|
||||
<view v-if="showDelete">
|
||||
<view class="delete" :class="{'deleteType':deleteType}">
|
||||
<text v-if="deleteType">松开删除</text>
|
||||
<text v-else>拖动到此处删除</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
emits:['itemclick','update:imgList','deleteImage','change','moveEndList'],
|
||||
props: {
|
||||
//图片列表
|
||||
imgList: {
|
||||
type: Array,
|
||||
default: function() {
|
||||
return [];
|
||||
}
|
||||
},
|
||||
//图片大小
|
||||
imgSize: {
|
||||
type: Number
|
||||
},
|
||||
//图片间距
|
||||
imgPadding: {
|
||||
type: Number
|
||||
},
|
||||
//图片行数
|
||||
rowNum: {
|
||||
type: Number
|
||||
},
|
||||
//图片圆角
|
||||
imgRadius: {
|
||||
type: Number
|
||||
}
|
||||
},
|
||||
components: {},
|
||||
data() {
|
||||
return {
|
||||
showDelete:false,
|
||||
touchobj:null,
|
||||
deleteType:false,
|
||||
addJump:false,
|
||||
areaBoxInfo: {},
|
||||
x: 0,
|
||||
y: 0,
|
||||
selectIdx: null,
|
||||
moveSrc: null,
|
||||
areaBoxTop: 0,
|
||||
hoverImgIdx: '',
|
||||
inBoxXY: {},
|
||||
curHoverBoxMove: {
|
||||
x: 0,
|
||||
y: 0
|
||||
}
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
hoverImgIdx(e) {
|
||||
let idx = this.selectIdx
|
||||
let hoverIdx = parseInt(e.split('img')[1]);
|
||||
if (this.imgList[idx]) {
|
||||
let selectRow = this.imgList[idx].y / uni.upx2px(this.imgSize)
|
||||
let selectColum= this.imgList[idx].x / uni.upx2px(this.imgSize)
|
||||
let hoverRow = this.imgList[hoverIdx].y / uni.upx2px(this.imgSize)
|
||||
let hoverColum= this.imgList[hoverIdx].x / uni.upx2px(this.imgSize)
|
||||
let left = -(this.imgSize * (hoverColum - selectColum))
|
||||
let top= -(this.imgSize * (hoverRow - selectRow))
|
||||
this.curHoverBoxMove = {
|
||||
x: left,
|
||||
y: top,
|
||||
}
|
||||
}
|
||||
},
|
||||
// imgList(e){
|
||||
// console.log('变化了item')
|
||||
// this.$nextTick(()=>{
|
||||
// this.setImgXy()
|
||||
// })
|
||||
// }
|
||||
imgList: {
|
||||
deep: true,//深度监听可见听对象中的元素变化例:obj.id
|
||||
immediate:false,//在进入页面时,第一次绑定值,不会立刻执行监听,只有数据发生改变才会执行handler中的操作
|
||||
handler(val) {//watch事件
|
||||
// console.log('变化了item')
|
||||
this.$nextTick(()=>{
|
||||
this.setImgXy()
|
||||
})
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
itemclick(e,i){
|
||||
this.$emit('itemclick',e,i)
|
||||
},
|
||||
moveHandle() {
|
||||
return;
|
||||
},
|
||||
deleteImage: function(e) {
|
||||
var index = e
|
||||
var deletedImage = this.imgList[index]
|
||||
this.imgList.splice(index, 1)
|
||||
this.$emit('deleteImage', deletedImage)
|
||||
},
|
||||
onChange(e) {
|
||||
var boxHeight=this.imgSize * this.rowNum
|
||||
var deleteHeight=(boxHeight-80)/2
|
||||
if(e.detail.y>deleteHeight){
|
||||
this.deleteType=true
|
||||
}else{
|
||||
this.deleteType=false
|
||||
}
|
||||
this.showDelete=true
|
||||
this.$emit('change',e)
|
||||
},
|
||||
tstr(e, s) {
|
||||
this.touchobj=this.imgList[e]
|
||||
this.addJump=true
|
||||
this.getDomInfo('areaBox', info => {
|
||||
this.areaBoxInfo = info;
|
||||
//获取拖拽区域的上边距和下边距
|
||||
let areaBoxTop = this.areaBoxInfo.top;
|
||||
let areaBoxLeft = this.areaBoxInfo.left;
|
||||
|
||||
// 设置可移动方块的初始位置为当前所选中图片的位置坐标
|
||||
this.x = this.imgList[e].x;
|
||||
this.y = this.imgList[e].y;
|
||||
//显示可移动方块
|
||||
this.moveSrc = this.imgList[e];
|
||||
//保存当前所选择的图片索引
|
||||
this.selectIdx = e;
|
||||
var x = s.changedTouches[0].clientX - areaBoxLeft;
|
||||
var y = s.changedTouches[0].clientY - areaBoxTop;
|
||||
// 保存鼠标在图片内的坐标
|
||||
this.inBoxXY = {
|
||||
x: x - this.imgList[e].x,
|
||||
y: y - this.imgList[e].y,
|
||||
}
|
||||
});
|
||||
|
||||
},
|
||||
tsmo(e) {
|
||||
let areaBoxTop = this.areaBoxInfo.top;
|
||||
let areaBoxLeft = this.areaBoxInfo.left;
|
||||
let imgSize = this.imgSize;
|
||||
//重置为以拖拽盒子左上角为坐标原点
|
||||
var x = e.changedTouches[0].clientX - areaBoxLeft;
|
||||
var y = e.changedTouches[0].clientY - areaBoxTop;
|
||||
this.x = x - this.inBoxXY.x;
|
||||
this.y = y - this.inBoxXY.y;
|
||||
this.imgList.forEach((item, idx) => {
|
||||
if (x > item.x && x < item.x + imgSize && y > item.y && y < item.y + imgSize) {
|
||||
this.hoverImgIdx = 'img' + idx
|
||||
}
|
||||
});
|
||||
},
|
||||
toend(e) {
|
||||
this.addJump=false
|
||||
if(this.deleteType){
|
||||
this.deleteImage(this.selectIdx)
|
||||
}else{
|
||||
// 移动结束隐藏可移动方块
|
||||
let beforeIdx = this.selectIdx;
|
||||
let afterIdx = parseInt(this.hoverImgIdx.split('img')[1]);
|
||||
if (this.hoverImgIdx !== '' && beforeIdx !== afterIdx) {
|
||||
this.imgList[beforeIdx] = this.imgList[afterIdx];
|
||||
this.imgList[afterIdx] = this.moveSrc;
|
||||
this.$emit('moveEndList', this.imgList);
|
||||
}
|
||||
}
|
||||
this.moveSrc = '';
|
||||
this.hoverImgIdx = ''
|
||||
this.selectIdx = null
|
||||
this.deleteType=false
|
||||
this.showDelete=false
|
||||
this.$nextTick(()=>{
|
||||
this.setImgXy()
|
||||
})
|
||||
},
|
||||
getDomInfo(id, callBack) {
|
||||
const query = uni.createSelectorQuery().in(this);
|
||||
query.select('#' + id)
|
||||
.boundingClientRect()
|
||||
.exec(function(res) {
|
||||
callBack(res[0]);
|
||||
});
|
||||
},
|
||||
setImgXy(){//设置每个图片的基础xy轴
|
||||
this.getDomInfo('areaBox', info => {
|
||||
this.areaBoxInfo = info;
|
||||
// 设置区域内所有图片的左上角坐标
|
||||
this.imgList.forEach((item, idx) => {
|
||||
this.getDomInfo('img' + idx, res => {
|
||||
item.x = res.left - info.left;
|
||||
});
|
||||
this.getDomInfo('img' + idx, res => {
|
||||
item.y = res.top - info.top;
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.setImgXy()
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.imgItem-play{
|
||||
z-index: 1;
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
width: 80rpx !important;
|
||||
height: 80rpx !important;
|
||||
transform: translate(-50%,-50%);
|
||||
}
|
||||
.movarea {
|
||||
width: 100%;
|
||||
height: 320rpx;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
}
|
||||
.imgBox {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
width: 100%;
|
||||
height: 320rpx;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
.imgItem {
|
||||
position: relative;
|
||||
box-sizing: border-box;
|
||||
left: 0;
|
||||
top: 0;
|
||||
box-sizing: border-box;
|
||||
image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
// transition: all 0.2s;
|
||||
vertical-align: top;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.moveV {
|
||||
opacity: 0.6;
|
||||
z-index: 0;
|
||||
box-sizing: border-box;
|
||||
image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.select {
|
||||
opacity: 0;
|
||||
}
|
||||
.zmm-upload-image-deleteIcon {
|
||||
right: 0rpx;
|
||||
top: 0rpx;
|
||||
position: absolute;
|
||||
background-color: rgba(0, 0, 0, 0.3);
|
||||
width: 36rpx;
|
||||
height: 36rpx;
|
||||
text-align: center;
|
||||
border-radius: 50%;
|
||||
color: white;
|
||||
font-size: 30rpx;
|
||||
z-index: 2;
|
||||
display: flex;flex-direction: row;align-items: center;justify-content: center;
|
||||
}
|
||||
.delete{
|
||||
position: absolute;
|
||||
bottom: 0rpx;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 80rpx;
|
||||
line-height: 80rpx;
|
||||
background: #C04A42;
|
||||
text-align: center;
|
||||
transition: all 0.3s;
|
||||
}
|
||||
.delete text{
|
||||
color: #fff;
|
||||
}
|
||||
.deleteType{
|
||||
transform: scale(1.1);
|
||||
}
|
||||
.moveWrap{
|
||||
position: relative;
|
||||
}
|
||||
.imgItem-img{
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
</style>
|
||||
431
im-uniapp/components/zmm-upload-image/zmm-upload-image.vue
Normal file
431
im-uniapp/components/zmm-upload-image/zmm-upload-image.vue
Normal file
@@ -0,0 +1,431 @@
|
||||
<template>
|
||||
<view class="zmm-upload-image" v-if="show">
|
||||
<zmm-upload-image-drag :key="key" :rowNum="rows" :imgRadius="imgRadius" :imgSize="imgSize" :imgPadding="imgPadding" :imgList="fileList" @deleteImage="deleteImage" @itemclick="itemclick">
|
||||
<view v-if="showAdd && fileList.length < limit" @tap="chooseTap" :style="{ width: imgSize + 'rpx', height: imgSize + 'rpx',padding:imgPadding+'rpx' }" class="zmm-upload-image-item-slot">
|
||||
<view class="zmm-upload-image-item-slotIcon">
|
||||
<uni-icons type="plusempty" color="#6E6E6E" size="24" />
|
||||
</view>
|
||||
</view>
|
||||
</zmm-upload-image-drag>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import zmmUploadImageDrag from './zmm-upload-image-drag.vue';
|
||||
import http from '@/common/request.js';
|
||||
export default {
|
||||
components: {
|
||||
zmmUploadImageDrag
|
||||
},
|
||||
name: 'zmm-upload-image',
|
||||
emits: ['update:modelValue', 'deleteImage','allComplete','oneComplete'],
|
||||
props: {
|
||||
modelValue: {
|
||||
type: [Array]
|
||||
},
|
||||
chooseType:{
|
||||
type:String,
|
||||
default:'chooseImage'//chooseImage图片 chooseVideo视频 chooseMedia图片或视频
|
||||
},
|
||||
imgSize: {
|
||||
//图片大小
|
||||
type: Number,
|
||||
default: 214
|
||||
},
|
||||
imgPadding: {
|
||||
//图片间距
|
||||
type: Number,
|
||||
default: 6
|
||||
},
|
||||
imgRadius: {
|
||||
//图片圆角
|
||||
type: Number,
|
||||
default: 4
|
||||
},
|
||||
fileList: {
|
||||
//图片数据
|
||||
type: Array,
|
||||
default(){
|
||||
return []
|
||||
}
|
||||
},
|
||||
rowNumber: {
|
||||
//一行多少个图片
|
||||
type: Number,
|
||||
default: 3
|
||||
},
|
||||
showAdd: {
|
||||
//增加按钮
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
show: {
|
||||
//是否显示
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
fileAction: {
|
||||
//后台文件上传接口
|
||||
type: String,
|
||||
default: http.baseUrl + '/file/upload'
|
||||
},
|
||||
videoAction: {
|
||||
//后台上传接口
|
||||
type: String,
|
||||
default: http.baseUrl + '/file/uploadVideo'
|
||||
},
|
||||
formData: {
|
||||
//上传所附带数据
|
||||
type: Object
|
||||
},
|
||||
header: {
|
||||
//自定义头
|
||||
type: Object,
|
||||
default() {
|
||||
return {
|
||||
Authorization: uni.getStorageSync('Authorization'),
|
||||
device: uni.getStorageSync('device'),
|
||||
version: uni.getStorageSync('version')
|
||||
};
|
||||
}
|
||||
},
|
||||
limit: {
|
||||
//图片数量
|
||||
type: Number,
|
||||
default: 9
|
||||
},
|
||||
fileKey: {
|
||||
//后端接受的filekey
|
||||
type: String,
|
||||
default: 'file'
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
key:0,
|
||||
isDestroyed: false,
|
||||
showUploadProgress:true
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
modelValue(val) {
|
||||
console.log(val);
|
||||
},
|
||||
fileList(e){
|
||||
// console.log('变化了list')
|
||||
this.key++
|
||||
},
|
||||
rows(e){
|
||||
this.key++
|
||||
}
|
||||
// fileList: {
|
||||
// deep: true,//深度监听可见听对象中的元素变化例:obj.id
|
||||
// immediate:false,//在进入页面时,第一次绑定值,不会立刻执行监听,只有数据发生改变才会执行handler中的操作
|
||||
// handler(val) {//watch事件
|
||||
// console.log('变化了list')
|
||||
// this.key++
|
||||
// }
|
||||
// }
|
||||
},
|
||||
mounted: function() {},
|
||||
destroyed: function() {
|
||||
this.isDestroyed = true;
|
||||
},
|
||||
computed: {
|
||||
rows() {
|
||||
var buzhu=this.showAdd && this.fileList.length < this.limit ? 1 : 0;
|
||||
var rows=Math.ceil((this.fileList.length+buzhu) / this.rowNumber);
|
||||
return rows
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
itemclick(e,i){
|
||||
if(!e.videoUrl){
|
||||
var imgs=[]
|
||||
for (var i = 0; i < this.fileList.length; i++) {
|
||||
var item=this.fileList[i]
|
||||
if(!item.videoUrl){
|
||||
imgs.push(item.url)
|
||||
}
|
||||
}
|
||||
this.previewImage(imgs,i)
|
||||
}else{
|
||||
this.$fc.plusDownload({onlinePath:e.videoUrl}).then(res=>{
|
||||
this.$fc.plusOpenFile({filePath:res})
|
||||
})
|
||||
}
|
||||
},
|
||||
chooseTap(){
|
||||
switch (this.chooseType){
|
||||
case 'chooseImage':
|
||||
this.selectImage()
|
||||
break;
|
||||
case 'chooseVideo':
|
||||
this.selectVideo()
|
||||
break;
|
||||
case 'chooseMedia':
|
||||
uni.showActionSheet({
|
||||
itemList: ['图片', '视频'],
|
||||
success: (res) => {
|
||||
switch (res.tapIndex){
|
||||
case 0:
|
||||
this.selectImage()
|
||||
break;
|
||||
case 1:
|
||||
this.selectVideo()
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
},
|
||||
selectImage: function() {
|
||||
var _self = this;
|
||||
if (!_self.fileList) {
|
||||
_self.fileList = [];
|
||||
}
|
||||
uni.chooseImage({
|
||||
count: _self.limit ? _self.limit - _self.fileList.length : 999,
|
||||
sourceType: ['album', 'camera'],
|
||||
sizeType:['original','compressed'],
|
||||
success: function(e) {
|
||||
var imagePathArr = e.tempFilePaths;
|
||||
//如果设置了limit限制,在web上count参数无效,这里做判断控制选择的数量是否合要求
|
||||
//在非微信小程序里,虽然可以选多张,但选择的结果会被截掉
|
||||
//在app里,会自动做选择数量的限制
|
||||
if (_self.limit) {
|
||||
var availableImageNumber = _self.limit - _self.fileList.length;
|
||||
if (availableImageNumber < imagePathArr.length) {
|
||||
uni.showToast({
|
||||
title: '图片总数限制为' + _self.limit + '张,当前还可以选' + availableImageNumber + '张',
|
||||
icon: 'none',
|
||||
mask: false,
|
||||
duration: 2000
|
||||
});
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
//检查服务器地址是否设置,设置即表示图片要上传到服务器
|
||||
if (_self.fileAction) {
|
||||
uni.showToast({
|
||||
title: '上传进度:0/' + imagePathArr.length,
|
||||
icon: 'none',
|
||||
mask: false
|
||||
});
|
||||
|
||||
var remoteIndexStart = _self.fileList.length - imagePathArr.length;
|
||||
var promiseWorkList = [];
|
||||
var keyname = _self.fileKey ? _self.fileKey : 'upload-images';
|
||||
var completeImages = 0;
|
||||
|
||||
for (let i = 0; i < imagePathArr.length; i++) {
|
||||
promiseWorkList.push(
|
||||
new Promise((resolve, reject) => {
|
||||
let remoteUrlIndex = remoteIndexStart + i;
|
||||
uni.uploadFile({
|
||||
url: _self.fileAction,
|
||||
fileType: 'image',
|
||||
header: _self.header,
|
||||
formData: _self.formData,
|
||||
filePath: imagePathArr[i],
|
||||
name: keyname,
|
||||
success: function(res) {
|
||||
if (res.statusCode === 200) {
|
||||
if (_self.isDestroyed) {
|
||||
return;
|
||||
}
|
||||
|
||||
completeImages++;
|
||||
|
||||
if (_self.showUploadProgress) {
|
||||
uni.showToast({
|
||||
title: '上传进度:' + completeImages + '/' + imagePathArr.length,
|
||||
icon: 'none',
|
||||
mask: false,
|
||||
duration: 500
|
||||
});
|
||||
}
|
||||
// console.log('success to upload image: ' + res.data)
|
||||
var resItem=JSON.parse(res.data)
|
||||
_self.$emit('oneComplete', {
|
||||
name: resItem.data.fileName,
|
||||
url: resItem.data.fullPath,
|
||||
type:'IMAGE'
|
||||
},_self.chooseType);
|
||||
resolve(res.data);
|
||||
} else {
|
||||
console.log('fail to upload image:' + res.data);
|
||||
reject('fail to upload image:' + remoteUrlIndex);
|
||||
}
|
||||
},
|
||||
fail: function(res) {
|
||||
uni.showToast({
|
||||
title: '上传失败请检查网络',
|
||||
icon: 'none'
|
||||
});
|
||||
console.log('fail to upload image:' + res);
|
||||
reject('fail to upload image:' + remoteUrlIndex);
|
||||
}
|
||||
});
|
||||
})
|
||||
);
|
||||
}
|
||||
Promise.all(promiseWorkList).then(result => {
|
||||
if (_self.isDestroyed) {
|
||||
return;
|
||||
}
|
||||
var fresult=[]
|
||||
for (let i = 0; i < result.length; i++) {
|
||||
var resItem=JSON.parse(result[i])
|
||||
_self.fileList.push({
|
||||
name: resItem.data.fileName,
|
||||
url: resItem.data.fullPath,
|
||||
type:'IMAGE'
|
||||
});
|
||||
fresult.push({
|
||||
name: resItem.data.fileName,
|
||||
url: resItem.data.fullPath,
|
||||
type:'IMAGE'
|
||||
})
|
||||
}
|
||||
_self.$emit('allComplete', fresult,_self.chooseType);
|
||||
});
|
||||
} else {
|
||||
var testImg='图片地址'
|
||||
for (let i = 0; i < imagePathArr.length; i++) {
|
||||
_self.fileList.push({
|
||||
name: 'avatar'+i+'.jpg',
|
||||
url: testImg
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
selectVideo: function() {
|
||||
var _self = this;
|
||||
if (!_self.fileList) {
|
||||
_self.fileList = [];
|
||||
}
|
||||
uni.chooseVideo({
|
||||
sourceType: ['album', 'camera'],
|
||||
compressed:true,
|
||||
success: function(e) {
|
||||
if (_self.showUploadProgress) {
|
||||
uni.showLoading({
|
||||
title:'上传中...'
|
||||
})
|
||||
}
|
||||
uploadVideo(e).then(res=>{
|
||||
uni.hideLoading()
|
||||
_self.fileList.push(res);
|
||||
_self.$emit('allComplete', res ,_self.chooseType);
|
||||
})
|
||||
function uploadVideo(e){
|
||||
return new Promise((resolve, reject) => {
|
||||
uni.uploadFile({
|
||||
url: _self.videoAction,
|
||||
fileType: 'video',
|
||||
header: _self.header,
|
||||
formData: _self.formData,
|
||||
filePath: e.tempFilePath,
|
||||
name: _self.fileKey,
|
||||
success: function(res) {
|
||||
if (res.statusCode === 200) {
|
||||
if (_self.isDestroyed) {
|
||||
return;
|
||||
}
|
||||
var resItem=JSON.parse(res.data)
|
||||
var fresult={
|
||||
name: resItem.data.fileName,
|
||||
videoUrl: resItem.data.fullPath,
|
||||
url: resItem.data.screenShot,
|
||||
type:'VIDEO'
|
||||
}
|
||||
_self.$emit('oneComplete', {
|
||||
name: resItem.data.fileName,
|
||||
videoUrl: resItem.data.fullPath,
|
||||
url: resItem.data.screenShot,
|
||||
type:'VIDEO'
|
||||
},_self.chooseType);
|
||||
resolve(fresult)
|
||||
} else {
|
||||
reject(res)
|
||||
}
|
||||
},
|
||||
fail: function(res) {
|
||||
uni.showToast({
|
||||
title: '上传失败请检查网络',
|
||||
icon: 'none'
|
||||
});
|
||||
reject(res)
|
||||
}
|
||||
});
|
||||
})
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
deleteImage: function(e) {
|
||||
this.$emit('deleteImage', e);
|
||||
},
|
||||
previewImage: function(arr,index) {
|
||||
uni.previewImage({
|
||||
current: index,
|
||||
indicator: 'number',
|
||||
loop: true,
|
||||
urls: arr
|
||||
});
|
||||
},
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.zmm-upload-image {
|
||||
width: 100%;
|
||||
position: relative;
|
||||
/* display: flex;flex-direction: row;justify-content: center; */
|
||||
}
|
||||
|
||||
.zmm-upload-image-list {
|
||||
/* width: 714rpx; */
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
.zmm-upload-image-item {
|
||||
width: 214rpx;
|
||||
height: 214rpx;
|
||||
margin: 12rpx;
|
||||
box-sizing: border-box;
|
||||
position: relative;
|
||||
border-radius: 4rpx;
|
||||
}
|
||||
.zmm-upload-image-item-img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: 4rpx;
|
||||
}
|
||||
.zmm-upload-image-item-slot{
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.zmm-upload-image-item-slotIcon {
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background-color: #f7f7f7;
|
||||
}
|
||||
|
||||
</style>
|
||||
568
im-uniapp/components/zy-search/zy-search.vue
Normal file
568
im-uniapp/components/zy-search/zy-search.vue
Normal file
@@ -0,0 +1,568 @@
|
||||
<template name="zy-search">
|
||||
<view class="good-search-page" :class="Theme">
|
||||
<view class="good-search-head">
|
||||
|
||||
<input :class="{'clearvalue':clearValuebtn}" :maxlength="maxLength" :style="{'line-height': inputHeight+'px','height': inputHeight+'px'}" :focus="isFocus" type="text" confirm-type="search" @confirm="searchStart()" :placeholder="inputPlaceholder" :confirm-hold="true" v-model="searchText" />
|
||||
<!-- <view v-if="searchText.length>0&&clearValuebtn" class="good-search-icon clearvalue-icon iconfont iconshanchu1" @click="clearvalue()"></view> -->
|
||||
<view class="good-search-icon search-icon2" @click="goback()">取消</view>
|
||||
<view class="good-search-icon search-icon iconfont iconsousuo-copy" @click="searchStart()"></view>
|
||||
<scroll-view class="autocomplay" :style="{'top': inputHeight+5+'px'}" v-if="autocomplaystate" scroll-y>
|
||||
<view class="autocomplay-item" v-for="(item,index) in autocomplayarr" :key="index" @click="tagsClick(item.value)">
|
||||
<rich-text :nodes="item.richtxt"></rich-text>
|
||||
</view>
|
||||
<view style="color: #999;text-align: center;justify-content: center; line-height: 70rpx;" v-if="autocomplayarr.length<1">没有相关信息</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
<view class="good-search-body">
|
||||
<view class="search-history" v-if="hList.length > 0">
|
||||
<view class="header">
|
||||
<text>历史记录</text>
|
||||
<view class="good-search-icon delete-icon iconfont iconshanchu" @click="delhistory()"></view>
|
||||
</view>
|
||||
<view class="list">
|
||||
<view v-for="(item,index) in hList" :key="index" @click="tagsClick(item)">{{item}}</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="search-showhot" v-if="hotList.length>0">
|
||||
<view class="header">
|
||||
<text>猜你想搜的</text>
|
||||
</view>
|
||||
<view class="list">
|
||||
<view v-for="(item,index) in hotList" :key="index" @click="tagsClick(item)">{{item}}</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
clearValuebtn: { //是否显示清空按钮
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
isFocus: { //是否自动获取焦点
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
Theme: { //选择主题class
|
||||
type: String,
|
||||
default: 'good-search-circle'
|
||||
},
|
||||
maxLength: { //字符最大长度
|
||||
type: [String, Number],
|
||||
default: '140'
|
||||
},
|
||||
inputHeight: { //搜索框高度单位px
|
||||
type: [String, Number],
|
||||
default: '35'
|
||||
},
|
||||
inputPlaceholder: { //搜索框默认提示
|
||||
type: String,
|
||||
default: '请输入关键词搜索'
|
||||
},
|
||||
autoComplaylist: { //自动联想数据
|
||||
type: Array,
|
||||
default () {
|
||||
return []
|
||||
}
|
||||
},
|
||||
historyNum: { //历史记录保存数量
|
||||
type: Number,
|
||||
default: 6
|
||||
},
|
||||
hotList: { //推荐列表数据
|
||||
type: Array,
|
||||
default () {
|
||||
return []
|
||||
}
|
||||
},
|
||||
speechEngine: { //语音引擎=>讯飞:iFly,百度:'baidu'
|
||||
type: String,
|
||||
default: 'iFly'
|
||||
},
|
||||
Punctuation: { //是否开启语音识别标点符号
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
callbackTime: { //input回调缓冲时间(不返回500毫秒以内输入的数据,防止每输入一个值就会触发一次)
|
||||
type: Number,
|
||||
default: 500
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
speechengine: this.speechEngine,
|
||||
punctuation: this.Punctuation,
|
||||
historynum: this.historyNum,
|
||||
callbacktime: this.callbackTime,
|
||||
autocomplaylist: this.getcomplaylist(this.autoComplaylist),
|
||||
autocomplayarr: [],
|
||||
autocomplaystate: false,
|
||||
searchText: '',
|
||||
hList: uni.getStorageSync('search_cache'),
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
historyNum: function(val) {
|
||||
this.historynum = val;
|
||||
},
|
||||
speechEngine: function(val) {
|
||||
this.engine = val;
|
||||
},
|
||||
hotList: function(val) {
|
||||
this.hotList = val;
|
||||
},
|
||||
autoComplaylist: function(val) {
|
||||
this.autocomplaylist = this.getcomplaylist(val);
|
||||
if (!this.searchText || this.searchText == '') {
|
||||
this.autocomplaystate = false
|
||||
return
|
||||
}
|
||||
this.autocomplayarr = this.replacekeyword(this.autocomplaylist, this.searchText)
|
||||
this.autocomplaystate = this.autocomplayarr.length > 0 ? true : false;
|
||||
},
|
||||
searchText: function(val) {
|
||||
let _this = this;
|
||||
var searchWords = val.replace(/^ +| +$/g, '');
|
||||
if (!searchWords || searchWords == '') {
|
||||
this.autocomplaystate = false
|
||||
return
|
||||
}
|
||||
if (this.calbacktime) {
|
||||
clearTimeout(_this.calbacktime)
|
||||
}
|
||||
this.calbacktime = setTimeout(function() {
|
||||
_this.inputChange(searchWords)
|
||||
}, _this.callbackTime);
|
||||
this.autocomplayarr = this.replacekeyword(this.autocomplaylist, searchWords)
|
||||
this.autocomplaystate = this.autocomplayarr.length > 0 ? true : false;
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
goback(){
|
||||
uni.navigateBack({
|
||||
delta:1
|
||||
})
|
||||
},
|
||||
clearvalue() { //删除input值
|
||||
let _this = this;
|
||||
setTimeout(function() { //增加延时解决键盘收回时导致的@input事件
|
||||
_this.searchText = ''
|
||||
}, 20);
|
||||
this.searchText = ''
|
||||
},
|
||||
getcomplaylist(arr) { //初始化自动联想数组
|
||||
var data = []
|
||||
for (var i = 0; i < arr.length; i++) {
|
||||
data.push({
|
||||
richtxt: arr[i],
|
||||
value: arr[i]
|
||||
})
|
||||
}
|
||||
return data
|
||||
},
|
||||
replacekeyword(arr, searchWords) { //返回符合关键词的高亮数组
|
||||
var data = []
|
||||
for (var i = 0; i < arr.length; i++) {
|
||||
if (arr[i].richtxt.search(searchWords) != -1) {
|
||||
data.push({
|
||||
richtxt: arr[i].richtxt.replace(searchWords, "<span style='color: #333;font-weight:bold'>" + searchWords +
|
||||
"</span>"),
|
||||
value: arr[i].value
|
||||
})
|
||||
}
|
||||
}
|
||||
return data
|
||||
},
|
||||
tagsClick(item) { //标签点击事件
|
||||
let _this = this;
|
||||
setTimeout(function() { //增加延时解决键盘收回时导致的@input事件
|
||||
_this.searchText = item
|
||||
_this.searchStart()
|
||||
}, 20);
|
||||
this.$emit('tagsClick', item)
|
||||
},
|
||||
inputChange(e) { //input回调
|
||||
this.$emit('inputChange', e)
|
||||
},
|
||||
notSupport() { //不支持提醒
|
||||
uni.showToast({
|
||||
title: '该平台暂不支持',
|
||||
icon: 'none',
|
||||
duration: 1000
|
||||
});
|
||||
},
|
||||
searchStart() { //触发搜索
|
||||
let _this = this;
|
||||
if (_this.searchText == '') {
|
||||
uni.showToast({
|
||||
title: '请输入关键字',
|
||||
icon: 'none',
|
||||
duration: 1000
|
||||
});
|
||||
return false;
|
||||
}
|
||||
// else {
|
||||
// if(this.autocomplayarr.length<1){
|
||||
// this.autocomplaystate=true
|
||||
// return
|
||||
// }
|
||||
// uni.getStorage({
|
||||
// key: 'search_cache',
|
||||
// success(res) {
|
||||
// let list = res.data;
|
||||
// if (list.length >= _this.historynum) {
|
||||
// for (let item of list) {
|
||||
// if (item == _this.searchText) {
|
||||
// return false;
|
||||
// }
|
||||
// }
|
||||
// list.pop();
|
||||
// list.unshift(_this.searchText);
|
||||
// } else {
|
||||
// for (let item of list) {
|
||||
// if (item == _this.searchText) {
|
||||
// return false;
|
||||
// }
|
||||
// }
|
||||
// list.unshift(_this.searchText);
|
||||
// }
|
||||
// _this.hList = list;
|
||||
// uni.setStorage({
|
||||
// key: 'search_cache',
|
||||
// data: _this.hList
|
||||
// });
|
||||
// },
|
||||
// fail() {
|
||||
// _this.hList = [];
|
||||
// _this.hList.push(_this.searchText);
|
||||
// uni.setStorage({
|
||||
// key: 'search_cache',
|
||||
// data: _this.hList
|
||||
// });
|
||||
// }
|
||||
// })
|
||||
// }
|
||||
this.$emit('clickSearch', _this.searchText)
|
||||
},
|
||||
delhistory() { //清空历史记录
|
||||
this.hList = [];
|
||||
uni.setStorage({
|
||||
key: 'search_cache',
|
||||
data: []
|
||||
});
|
||||
this.$emit('delhHistory')
|
||||
},
|
||||
startRecognize() { //语音输入
|
||||
let _this = this;
|
||||
let options = {};
|
||||
options.engine = _this.speechengine;
|
||||
options.punctuation = _this.punctuation; // 是否需要标点符号
|
||||
options.timeout = 1000;
|
||||
plus.speech.startRecognize(options, function(s) {
|
||||
_this.searchText = _this.searchText + s;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
@font-face {
|
||||
font-family: 'iconfont';
|
||||
src: url('data:application/x-font-woff2;charset=utf-8;base64,d09GMgABAAAAAARsAAsAAAAACTAAAAQeAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHEIGVgCDMgqFOIR/ATYCJAMUCwwABCAFhG0HXhshCBEVnP3IfiTGtg+yYk9cckRpaoLn+Ty/c9976WTSnw8NxB3gNgOIO3pXjJjRVmgD9Ab4PpuONYw5YTol8dSz/I/7dt/vpPE4jVIIiZD8//ctbT0e2HotiyTD+1qXxepTJ4rjgALadwoja4DGBsTHZGxxVg7MnJ/5HAI4FKQ80rBxy47YGGidADJs8MDe2B0bZoEj2MbAxFGDrMLCVovVA2Bl8fPyhapig8LS0Na2Axr1o66P31LPSsyiW0ZDfjgPYJ0CDZQHDMiYSd8wdJUrj8YJfs9QF3CwUSgfP9sv7bdMJCBU3ZDBkT5QN/OPp0ECkC4J7Lp5Az6JCAr8bBEE/NKyZX1L2NA60zI4Byq8AakDdnGd+mjadOnkCgUCQZe2JBWQrrOPLDlENBrCKQ7NOhx0lx6dfcRxJB73ZLxDIpGOsVjY60kZ8igzOXw9LgUBGelc6m3cuuVAZsRx5GvKIpG66zZnkSW0fl+aqQyrs2/PC4MqGm3k3o57OnjwGM/GYh13Xl76sMCgA5cKaldtu1A8yVt6VE6qgY0tiXyypWtSP/W45FhtsVi3dUuywx3Tq47MzuWFN8w+ujQr5G1cenhWZsfQenHrt0Nual5cNWf/2RnJgwa45BXXcaVvHjDIwtCj5mC0pbqoUevXj0rVykS01XygQmPGhkWi1q5CD1V4zJiwAgLTK6ixKmnjng+VFzQ3pz5/PqlPaRCoT+KaU6ZLu+LnFx6adKNhoZbr9a1bap1EeNbrdQ2mn6ZhlWmvN9uLq2TsP7U4b5W8FB5bv7F076IbRQtPLDExo9Ibadiy2+o5q1t1pdHrcsP37+hG3bvu21zld1OnSNq6uuWtV79fm/JtF9YYl+plfM3wiugNm1M99VW1huenTU6hsK5/2fz9ay5L1EmqairU5E15Nq0kzL1F8ywu6YspBjsP5znMJAAS1011/YKXvq7rYabb2/VcX9P+QgCB5CWns3um1PxmBw0AT9ymU0Q0kYEv+0/oCeR/Hjmzz4RKslvG701kftwixF9Dp4KSAyQQSufFYQxZ7EYQbLIaUOSgAGhsitMNuzxYBKkOAWzqgEM5PdXpIBlYa8TkBMryFiCk8gFFMpdBk8qXbtg/sMjmDwFSZQ0O4WVcGaSktKcGFplHCXyGVtCklNOfyuYb1mFgtq0suC+0rk1Ckeb9YoUT2kPscLEuvVegLI1wFa/hMBBoSx0Knzbe60uWqakPpYLGxYkGLMR4SAK4GdASyERlo73T4Ps3qBYMGLtAGYi/IMtpJwcKUnIGvdJNLMpLme1EtRLPU/oqxSIj4AoPGmSOAHp6UQcJXkqzQ0a7kGmDFFeXnt4wvsdjgAPNtkSJFiOWBEi7b3fydkLpGqZRkJ7PYym4QEmj2U8UJtGEQ+EtFgsAAA==') format('woff2');
|
||||
}
|
||||
|
||||
.iconfont {
|
||||
font-family: 'iconfont' !important;
|
||||
font-size: 16px;
|
||||
font-style: normal;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
.iconcombinedshapecopy:before {
|
||||
content: "\e616";
|
||||
}
|
||||
|
||||
.iconsousuo-copy:before {
|
||||
content: "\e600";
|
||||
}
|
||||
|
||||
.iconshanchu:before {
|
||||
content: "\e64c";
|
||||
}
|
||||
|
||||
.iconshanchu1:before {
|
||||
content: "\e628";
|
||||
}
|
||||
|
||||
page {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
box-sizing: border-box;
|
||||
background-color: #F5F5F5;
|
||||
}
|
||||
|
||||
view {
|
||||
display: flex;
|
||||
font-size: 28upx;
|
||||
line-height: inherit
|
||||
}
|
||||
|
||||
.good-search-page {
|
||||
box-sizing: border-box;
|
||||
width: 750rpx;
|
||||
padding: 30rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.good-search-head {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.good-search-head input {
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
background-color: #F7F7F7;
|
||||
font-size: 28rpx;
|
||||
border-radius: 50rpx;
|
||||
padding: 0 73rpx;
|
||||
padding-left: 34rpx;
|
||||
padding-right: 160rpx;
|
||||
}
|
||||
.good-search-head input.clearvalue{
|
||||
}
|
||||
.good-search-icon {
|
||||
color: #888;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
font-size: 38rpx;
|
||||
}
|
||||
|
||||
.good-search-head .good-search-icon {
|
||||
width: 73rpx;
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
z-index: 2;
|
||||
top: 0rpx;
|
||||
}
|
||||
|
||||
.good-search-head .voice-icon {
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.good-search-head .search-icon {
|
||||
width: 63rpx;
|
||||
right: 97rpx;
|
||||
}
|
||||
.good-search-head .search-icon2 {
|
||||
font-size: 28rpx;
|
||||
right: 0;
|
||||
width: 73rpx;
|
||||
padding-right: 24rpx;
|
||||
}
|
||||
.good-search-head .clearvalue-icon {
|
||||
width: auto;
|
||||
right: 146rpx;
|
||||
color: #ccc;
|
||||
}
|
||||
|
||||
.good-search-head .autocomplay {
|
||||
left: 0;
|
||||
top: 80rpx;
|
||||
border-radius: 20rpx;
|
||||
height: 70vh;
|
||||
background: #f7f7f7;
|
||||
position: absolute;
|
||||
z-index: 9;
|
||||
}
|
||||
|
||||
.good-search-head .autocomplay .autocomplay-item {
|
||||
padding: 0 24rpx;
|
||||
line-height: 70rpx;
|
||||
height: 70rpx;
|
||||
border-bottom: 1px #eee solid;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.good-search-body {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.good-search-page .search-history {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.good-search-page .search-showhot {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
/* 主题1 */
|
||||
.good-search-rect {}
|
||||
|
||||
.good-search-rect .good-search-head input {
|
||||
border-radius: 0;
|
||||
}
|
||||
.good-search-rect .good-search-head input.clearvalue{
|
||||
}
|
||||
.good-search-rect .good-search-head .voice-icon {}
|
||||
|
||||
.good-search-rect .good-search-head .search-icon {}
|
||||
|
||||
.good-search-rect .good-search-head .clearvalue-icon {}
|
||||
|
||||
.good-search-rect .header {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
margin: 24rpx 0;
|
||||
padding: 0 12rpx;
|
||||
}
|
||||
|
||||
.good-search-rect .header text {
|
||||
color: #666;
|
||||
font-weight: bold;
|
||||
font-size: 32rpx;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
|
||||
.good-search-rect .list {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.good-search-rect .list view {
|
||||
display: block;
|
||||
width: 49%;
|
||||
color: #8A8A8A;
|
||||
font-size: 28rpx;
|
||||
box-sizing: border-box;
|
||||
text-align: center;
|
||||
padding: 20rpx;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
background-color: #F7F7F7;
|
||||
margin: 0.5%;
|
||||
}
|
||||
|
||||
.good-search-rect .search-showhot {}
|
||||
|
||||
/* 主题2 */
|
||||
.good-search-circle {}
|
||||
|
||||
.good-search-circle .good-search-head input {
|
||||
border-radius: 50rpx;
|
||||
}
|
||||
.good-search-circle .good-search-head input.clearvalue{
|
||||
}
|
||||
.good-search-circle .good-search-head .voice-icon {}
|
||||
|
||||
.good-search-circle .good-search-head .search-icon {}
|
||||
|
||||
.good-search-circle .good-search-head .clearvalue-icon {}
|
||||
.good-search-circle .header {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
margin: 24rpx 0;
|
||||
padding: 0 12rpx;
|
||||
}
|
||||
|
||||
.good-search-circle .header text {
|
||||
color: #666;
|
||||
font-weight: bold;
|
||||
font-size: 32rpx;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
|
||||
.good-search-circle .list {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.good-search-circle .list view {
|
||||
display: block;
|
||||
padding: 8rpx 18rpx;
|
||||
margin: 12rpx;
|
||||
margin-top: 0;
|
||||
font-size: 28rpx;
|
||||
color: #8A8A8A;
|
||||
background-color: #F7F7F7;
|
||||
box-sizing: border-box;
|
||||
text-align: center;
|
||||
border-radius: 20rpx;
|
||||
}
|
||||
|
||||
.good-search-circle .search-showhot {}
|
||||
|
||||
/* 主题3 */
|
||||
.good-search-tb {}
|
||||
|
||||
.good-search-tb .good-search-head input {
|
||||
border-radius: 0;
|
||||
}
|
||||
.good-search-tb .good-search-head input.clearvalue{
|
||||
padding-right: 133rpx;
|
||||
}
|
||||
.good-search-tb .good-search-head .voice-icon {}
|
||||
|
||||
.good-search-tb .good-search-head .search-icon {
|
||||
background: #FF9A33;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.good-search-tb .good-search-head .clearvalue-icon {
|
||||
width: 60rpx;
|
||||
}
|
||||
.good-search-tb .header {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
margin: 24rpx 0;
|
||||
padding: 0 12rpx;
|
||||
}
|
||||
|
||||
.good-search-tb .header text {
|
||||
color: #666;
|
||||
font-weight: bold;
|
||||
font-size: 32rpx;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
|
||||
.good-search-tb .list {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.good-search-tb .list view {
|
||||
display: block;
|
||||
padding: 8rpx 30rpx;
|
||||
margin: 12rpx;
|
||||
margin-top: 0;
|
||||
font-size: 28rpx;
|
||||
color: #8A8A8A;
|
||||
background-color: #F7F7F7;
|
||||
box-sizing: border-box;
|
||||
text-align: center;
|
||||
border-radius: 20rpx;
|
||||
}
|
||||
|
||||
.good-search-tb .search-showhot {}
|
||||
</style>
|
||||
Reference in New Issue
Block a user