客户端app

This commit is contained in:
2023-09-24 23:26:20 +08:00
parent 59f7e39791
commit daa9c98598
628 changed files with 87877 additions and 8 deletions

View File

@@ -0,0 +1,638 @@
<template>
<!-- #ifdef APP-NVUE -->
<cell>
<!-- #endif -->
<view class="zfb-tk-item" :class="[{ 'zfb-tk-msgleft': item.type == 1 }, { 'zfb-tk-msgright': item.type == 2 }, { 'zfb-tk-msgcenter': item.type == 3 }]">
<openTool :class="[{ 'openTool-msgleft': item.type == 1 }, { 'openTool-msgright': item.type == 2 }]" :talkTo="talkTo" :ref="'toolx'+itemKey" :data="item" :itemKey="itemKey"></openTool>
<image class="zfb-tk-avatar" @click="gochatOne(item)" v-if="item.type !== 3" :src="item.portrait" mode="aspectFill"></image>
<view class="zfb-tk-item-contentx" @longpress="longpressItem($event,itemKey,item)">
<view class="zfb-tk-item-contentx-c">
<view class="zfb-tk-time-notsend wxfont fssb" @click="tryagin(item, itemKey)" v-if="item.sendtype && item.sendtype == 'error'"></view>
<view class="zfb-tk-item-contentx-c-tool">
<view class="zfb-tk-item-c" v-if="item.msgType == 'TEXT'">
<text>{{ item.content }}</text>
</view>
<view class="zfb-tk-item-c" v-if="item.msgType == 'ALERT'">
<text>{{ item.content }}</text>
</view>
<view class="zfb-tk-item-c-LOCATION" v-if="item.msgType == 'LOCATION'" @click="goMap(returnParse(item.content))">
<view class="zfb-tk-item-c-LOCATION-name">{{ returnParse(item.content).name }}</view>
<view class="zfb-tk-item-c-LOCATION-address">{{ returnParse(item.content).address }}</view>
<image class="zfb-tk-item-c-LOCATION-map" src="../../static/wx/map.png" mode="aspectFit"></image>
</view>
<image class="zfb-tk-item-c-img" v-if="item.msgType == 'IMAGE'" :src="returnParse(item.content).url" mode="aspectFill" @click="$fc.previewImagesolo(returnParse(item.content).url)"></image>
<view v-if="item.msgType == 'VOICE'" class="zfb-tk-item-c-VOICE">
<view class="zfb-tk-item-c-VOICE-msg">
<view class="zfb-tk-item-c-VOICE-tras" @click="showTrs=!showTrs">
<text>转文字</text>
<!-- <view class="zfb-tk-item-c-VOICE-tras-icon"></view> -->
</view>
<view class="zfb-tk-item-c" @click="playVOICE(returnParse(item.content).url)">
<text>{{returnParse(item.content).time}}</text>
<text class="wxfont yuyin" :class="{vmove:paused}"></text>
</view>
</view>
</view>
<view v-if="item.msgType == 'TRTC_VOICE_END'" class="zfb-tk-item-c-TRTC_VOICE_END" @click="sendVoiceCall">
<view class="zfb-tk-TRTC zfb-tk-item-c">
<view class="wxfont yuyin3"></view>
<text>语音通话 时长{{item.content}}</text>
</view>
</view>
<view v-if="item.msgType == 'TRTC_VIDEO_END'" class="zfb-tk-item-c-TRTC_VIDEO_END" @click="sendVideoCall">
<view class="zfb-tk-TRTC zfb-tk-item-c">
<view class="wxfont shipin"></view>
<text>视频通话 时长{{item.content}}</text>
</view>
</view>
<view class="zfb-tk-item-c-video" v-if="item.msgType == 'VIDEO'" @click="openVideo(returnParse(item.content).videoUrl)">
<image class="zfb-tk-item-c-img" :src="returnParse(item.content).url" mode="aspectFill"></image>
<view class="zfb-tk-item-c-video-icon">
<text class="wxfont bofang"></text>
</view>
</view>
<view class="zfb-tk-item-c-CARD" v-if="item.msgType == 'CARD'" @click="goAddfriend(returnParse(item.content))">
<view class="zfb-tk-item-c-CARD-top">
<image class="zfb-tk-item-c-CARD-top-img" :src="returnParse(item.content).avatar" mode=""></image>
<view class="zfb-tk-item-c-CARD-top-content">
<view class="zfb-tk-item-c-CARD-title">{{returnParse(item.content).name}}</view>
<view class="zfb-tk-item-c-CARD-no">{{returnParse(item.content).chatNo}}</view>
</view>
</view>
<view class="zfb-tk-item-c-CARD-card">推荐名片</view>
</view>
<view v-if="showTrs" class="zfb-tk-item-c-VOICE-tras-text">{{returnParse(item.content).text}}</view>
<view class="zfb-tk-time" v-if="item.time">{{ timeDetia(item.time) }}</view>
</view>
</view>
</view>
</view>
<!-- #ifdef APP-NVUE -->
</cell>
<!-- #endif -->
</template>
<script>
// #ifdef APP-PLUS
const TUICalling = uni.requireNativePlugin("TUICallingUniPlugin-TUICallingModule");
// #endif
import openTool from './openTool.vue'
export default {
emits: ['tryagin','longpressItem'],
name: 'chat-item',
components:{
openTool
},
props: {
item: {
type: Object,
default: {}
},
talkTo: {
type: Object,
default: {}
},
itemKey: {
type: Number
},
longTapItemKey: {
type: [Number,String],
default:''
}
},
watch:{
longTapItemKey(v){
if(this.itemKey==v){
this.$refs['toolx'+v].showTab();
}
}
},
data() {
return {
innerAudioContext:'',
paused:false,
showTrs:false,
};
},
methods: {
sendVoiceCall(){
//发起语音
uni.showLoading({
title:'发起语音通话'
})
var formdata={
userId: this.talkTo.userId,
msgType: "TRTC_VOICE_START",
content: "TRTC_VOICE_START"
}
this.$http.request({
url: '/chat/sendMsg',
method: 'POST',
data: JSON.stringify(formdata),
success: (res) => {
if(res.data.code=='200'){
if(res.data.data.status!=='0'){
uni.showToast({
title:res.data.data.statusLabel,
icon:'none'
})
return
}
var userInfo=res.data.data.userInfo
var data={
userId:userInfo.userId,
trtcId:userInfo.trtcId,
nickName:userInfo.nickName,
portrait:userInfo.portrait,
startTime:new Date().getTime(),
type:'audio'
}
uni.setStorage({
key: 'call',
data: JSON.stringify(data),
success: function () {
console.log('success');
TUICalling.call({
userID: userInfo.trtcId,
type: 1
})
}
});
}
}
});
},
sendVideoCall(){
//发起视频
uni.showLoading({
title:'发起视频通话'
})
var formdata={
userId: this.talkTo.userId,
msgType: "TRTC_VIDEO_START",
content: "TRTC_VIDEO_START"
}
this.$http.request({
url: '/chat/sendMsg',
method: 'POST',
data: JSON.stringify(formdata),
success: (res) => {
if(res.data.code=='200'){
if(res.data.data.status!=='0'){
uni.showToast({
title:res.data.data.statusLabel,
icon:'none'
})
return
}
var userInfo=res.data.data.userInfo
var data={
userId:userInfo.userId,
trtcId:userInfo.trtcId,
nickName:userInfo.nickName,
portrait:userInfo.portrait,
startTime:new Date().getTime(),
type:'video'
}
uni.setStorage({
key: 'call',
data: JSON.stringify(data),
success: function () {
console.log('success');
TUICalling.call({
userID: userInfo.trtcId,
type: 2
})
}
});
}
}
});
},
goAddfriend(e){
uni.navigateTo({
url:'../personInfo/detail?param='+e.userId+'&source=2'
})
},
openVideo(e){
this.$fc.plusDownload({onlinePath:e}).then(res=>{
this.$fc.plusOpenFile({filePath:res})
})
},
playVOICE(url){
this.showTrs=false
if(this.paused){
this.innerAudioContext.destroy()
this.paused=!this.paused
return
}
this.innerAudioContext = uni.createInnerAudioContext();
// var url='https://www.w3school.com.cn/i/horse.ogg'
this.innerAudioContext.sessionCategory='soloAmbient'
this.innerAudioContext.src = url;
this.innerAudioContext.play()
this.innerAudioContext.onPlay(() => {
// console.log('播放')
this.paused=true
})
this.innerAudioContext.onPause(() => {
// console.log('暂停')
this.paused=false
this.innerAudioContext.destroy()
})
},
goMap(e) {
uni.openLocation({
latitude: e.latitude,
longitude: e.longitude,
success: function() {}
});
},
returnParse(txt) {
return JSON.parse(txt);
},
tryagin(e, i) {
this.$emit('tryagin', e, i);
},
gochatOne(e) {
var source=e.windowType=="GROUP" ? '7' : '3'
uni.navigateTo({
url:'../personInfo/detail?param='+e.personId+'&source='+source
})
},
longpressItem(e,i,v) {//长按回调
console.log(e)
this.$emit('longpressItem',e,i,v)
if(this.itemKey==this.longTapItemKey){
this.$refs['toolx'+this.itemKey].showTab();
}
},
timeDetia: function(date) {
var time;
var d = new Date(date);
var n = new Date();
//获取时间戳
var dd = d.getTime();
var h = d.getHours();
var m = d.getMinutes();
var Y = d.getFullYear();
var M = d.getMonth() + 1;
var D = d.getDate();
//现在时间
var nn = n.getTime();
var hh = n.getHours();
var mm = n.getMinutes();
var YY = n.getFullYear();
var MM = n.getMonth() + 1;
var DD = n.getDate();
if (D == DD && M == MM && Y == YY) {
if (h < 10) {
h = '0' + h;
}
if (m < 10) {
m = '0' + m;
}
time = h + ':' + m;
return time;
} else if (D + 1 == DD && M == MM && Y == YY) {
if (h < 10) {
h = '0' + h;
}
if (m < 10) {
m = '0' + m;
}
time = '昨天' + ' ' + h + ':' + m;
return time;
} else {
if (M < 10) {
M = '0' + M;
}
if (D < 10) {
D = '0' + D;
}
if (h < 10) {
h = '0' + h;
}
if (m < 10) {
m = '0' + m;
}
time = Y + '年' + M + '月' + D + '日' + ' ' + h + ':' + m;
return time;
}
}
}
};
</script>
<style lang="scss" scoped>
$avatarsize: 80rpx;
$border-radius: 12rpx;
$textcolor: #fff;
$descolor: #999;
$leftbgcolor: #00aaff;
$rightbgcolor: #4cd964;
.zfb-tk-item {
position: relative;
display: flex;
align-items: flex-start;
flex-wrap: wrap;
margin: 5px 0;
}
.zfb-tk-item .zfb-tk-item-c text {
word-break: break-all;
}
.zfb-tk-msgleft,
.zfb-tk-msgright {
text-align: left;
}
.zfb-tk-msgleft {
float: left;
display: flex;
flex-direction: row;
}
.zfb-tk-item .zfb-tk-item-c::after {
position: absolute;
content: '';
width: 14rpx;
height: 14rpx;
top: 34rpx;
transform: rotate(45deg);
}
.zfb-tk-msgleft .zfb-tk-item-c::after {
background: $leftbgcolor;
left: -7rpx;
}
.zfb-tk-msgright .zfb-tk-item-c::after {
background: $rightbgcolor;
right: -7rpx;
}
.zfb-tk-avatar {
min-width: $avatarsize;
width: $avatarsize;
height: $avatarsize;
border-radius: $border-radius;
}
.zfb-tk-msgleft .zfb-tk-avatar {
margin-right: 12rpx;
}
.zfb-tk-msgright .zfb-tk-avatar {
margin-left: 12rpx;
}
.zfb-tk-msgright {
float: right;
display: flex;
flex-direction: row-reverse;
}
.zfb-tk-msgcenter {
font-size: 28rpx;
display: flex;
flex-direction: row;
justify-content: center;
float: left;
width: 100%;
color: $descolor;
}
.zfb-tk-item-c {
box-sizing: border-box;
position: relative;
display: inline-block;
border-radius: $border-radius;
}
.zfb-tk-msgleft .zfb-tk-item-c,
.zfb-tk-msgright .zfb-tk-item-c {
min-height: $avatarsize;
background: $leftbgcolor;
color: $textcolor;
padding: 10px;
}
.zfb-tk-msgright .zfb-tk-item-c {
background: $rightbgcolor;
}
.zfb-tk-username {
color: $descolor;
}
.zfb-tk-time {
font-size: 24rpx;
text-align: center;
color: $descolor;
width: 100%;
box-sizing: border-box;
}
.zfb-tk-msgright .zfb-tk-time {
text-align: right;
}
.zfb-tk-msgleft .zfb-tk-time {
text-align: left;
}
.zfb-tk-time-notsend {
font-size: 64rpx;
color: #fa5151;
margin-top: 8rpx;
}
.zfb-tk-item-c-LOCATION {
border: 1px #f6f6f6 solid;
display: flex;
flex-direction: column;
width: 445rpx;
border-radius: 12rpx;
padding: 24rpx;
}
.zfb-tk-item-c-LOCATION-name {
font-size: 28rpx;
color: #101010;
font-weight: bold;
}
.zfb-tk-item-c-LOCATION-address {
font-size: 26rpx;
color: #666;
margin-bottom: 12rpx;
}
.zfb-tk-item-c-LOCATION-map {
background-color: #e5ffff;
overflow: hidden;
width: 445rpx;
height: 150rpx;
}
.zfb-tk-item-c-img{
border: 1px #eee solid;
max-width: 310rpx;
max-height: 450rpx;
}
.zfb-tk-item-c-video{
position: relative;
}
.zfb-tk-item-c-video-icon{
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%,-50%);
display: flex;flex-direction: row;justify-content: center;align-items: center;
}
.zfb-tk-item-c-video-icon text{
font-size: 64rpx;
color: #dddddd;
text-shadow: 0px 0px 5px rgba(0,0,0,0.3);
}
.zfb-tk-item-c-VOICE{}
.vmove{
animation: scalev 1s linear infinite;
transform: scale(1);
}
@keyframes scalev {
0% {
transform: scale(1);
}
50% {
transform: scale(1.3);
}
100% {
transform: scale(1);
}
}
.zfb-tk-item-c-VOICE-tras{
display: flex;flex-direction: row;align-items: center;
}
.zfb-tk-item-c-VOICE-tras text{
padding:6rpx 12rpx;
font-size: 24rpx;
background-color: #eee;
border-radius: 12rpx;
color: #bcbcbc;
margin:0 12rpx;
}
.zfb-tk-item-c-VOICE-tras-icon{
margin: 6rpx;
width: 16rpx;
height: 16rpx;
border-radius: 50%;
background-color: #fa5151;
position: relative;
}
.zfb-tk-item-c-VOICE-tras-text{
width: 100%;
font-size: 26rpx;
color: #666;
word-break: break-all;
margin-bottom: 12rpx;
}
.zfb-tk-msgright .zfb-tk-item-c-VOICE-tras-text{
text-align: right;
}
.zfb-tk-msgleft .zfb-tk-item-c-VOICE-tras-text{
text-align: left;
}
.zfb-tk-msgleft .zfb-tk-item-c-VOICE-msg{
flex-direction: row-reverse;
}
.zfb-tk-msgleft .zfb-tk-item-c-VOICE-tras{
flex-direction: row-reverse;
}
.zfb-tk-item-c-VOICE-msg .zfb-tk-item-c{
display: flex;flex-direction: row;align-items: center;
}
.zfb-tk-item-c-VOICE-msg{
display: flex;flex-direction: row;align-items: center;
}
.zfb-tk-item-c-CARD{
width: 440rpx;
box-sizing: border-box;
border: 1px #f6f6f6 solid;
padding: 24rpx;
border-radius: 12rpx;
}
.zfb-tk-item-c-CARD-top{
display: flex;flex-direction: row;align-items: center;
}
.zfb-tk-item-c-CARD-top-img{
width: 80rpx;
min-width: 80rpx;
height: 80rpx;
margin-right: 24rpx;
border-radius: 6rpx;
}
.zfb-tk-item-c-CARD-top-content{
overflow: hidden;
display: flex;flex-direction: column;
}
.zfb-tk-item-c-CARD-title{
color: #070707;
font-size: 32rpx;
}
.zfb-tk-item-c-CARD-no{
font-size: 24rpx;
color: #999;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.zfb-tk-item-c-CARD-card{
font-size: 24rpx;
color: #666;
margin-top: 24rpx;
}
.zfb-tk-item-contentx{
position: relative;
display: flex;
flex-direction: column;
max-width: 544rpx;
}
.zfb-tk-item-contentx-name{
color: #7C7C7E;
font-size: 24rpx;
}
.zfb-tk-msgright .zfb-tk-item-contentx{
align-items: flex-end;
}
.zfb-tk-msgleft .zfb-tk-item-contentx{
align-items: flex-start;
}
.zfb-tk-item-contentx-c{
display: flex;
align-items: center;
}
.zfb-tk-msgleft .zfb-tk-item-contentx-c{
flex-direction: row-reverse;
}
.zfb-tk-msgright .zfb-tk-item-contentx-c{
flex-direction: row;
}
.zfb-tk-TRTC{
align-items: center;
display: flex;flex-direction: row;
}
.zfb-tk-TRTC .wxfont{
font-size: 42rpx;
}
.zfb-tk-item-contentx-c-tool{display: flex;flex-direction: column;}
.zfb-tk-msgleft .zfb-tk-item-contentx-c-tool{
align-items: flex-start;
}
.zfb-tk-msgright .zfb-tk-item-contentx-c-tool{
align-items: flex-end;
}
</style>

View File

@@ -0,0 +1,887 @@
<template>
<view>
<watermark></watermark>
<uni-popup ref="popup" type="center">
<view class="popsendCard" :style="'height:' + windowHeight + 'px'"><sendCard @click="sendCardclick"></sendCard></view>
</uni-popup>
<uni-popup ref="popupfavorites" type="center" background-color="#fff" style="background-color: #fff;">
<scroll-view scroll-y :style="'height:' + windowHeight + 'px'"><favorites type="2" @clickitem="clickitem"></favorites></scroll-view>
</uni-popup>
<view class="zfb-tk-main">
<uni-list class="zfb-tk-conent" :border="false" style="background: none;"><chatItem v-for="(v, index) in chatWindowData" :key="'key' + index" :talkTo="talkTo" :itemKey="index" :item="v" @tryagin="tryagin" @longpressItem="longpressItem" :longTapItemKey="longTapItemKey"></chatItem></uni-list>
<view class="autodownView"></view>
</view>
<view :style="'height: ' + keyboardHeight + 'px'"></view>
<view v-if="showtool || showEmojitool" :style="'height:558rpx'"></view>
<view class="zfb-tk-send-tool" :style="'transform: translateY(-' + keyboardHeight + 'px)'">
<view class="zfb-tk-send-tool-c">
<view class="zfb-tk-send-tool-icon wxfont" @click="changeShowVice" :class="showVice ? 'jianpan' : 'yuyin2'"></view>
<view class="zfb-tk-send-tool-vioce" v-if="showVice"><view class="zfb-tk-send-tool-vioce-item" @longpress="startRecord" @touchend="endRecord">按住说话</view></view>
<view v-else class="zfb-tk-send-tool-input-box" @click="msgFocus = true"><textarea @focus="showtool = false" :focus="msgFocus" class="zfb-tk-send-tool-input" :adjust-position="false" v-model="msg" placeholder="" hold-keyboard confirm-type="send" @confirm="sendMsg(msg, 'TEXT')" :maxlength="-1" auto-height /></view>
<view @click="changeEmojiTool" class="zfb-tk-send-tool-more wxfont biaoqing"></view>
<view v-if="msg !== ''" class="zfb-tk-send-tool-text" @touchend.prevent="sendMsg(msg, 'TEXT')" :style="{ background: msg !== '' ? '#1BC418' : '#F7F7F7', color: msg !== '' ? '#fff' : '#ddd', 'border-color': msg !== '' ? '#1BC418' : '#ddd' }">发送</view>
<view v-else @click="changeTool" class="zfb-tk-send-tool-more wxfont gengduo"></view>
</view>
<view v-if="showtool" class="zfb-tk-send-tools">
<view class="zfb-tk-send-tools-item" v-for="(v, i) in toolist" @click="toolClick(v)">
<view class="zfb-tk-send-tools-icon"><view class="wxfont" :class="v.icon"></view></view>
<view class="zfb-tk-send-tools-text">{{ v.title }}</view>
</view>
</view>
<scroll-view :scroll-y="true" v-if="showEmojitool" class="wxemojitool">
<view class="wxemojitool-content">
<view class="wxemojitool-item" @click="addMsg(v)" v-for="(v, i) in emojilist" :key="i">{{ v }}</view>
</view>
</scroll-view>
</view>
<zmm-upload-image chooseType="chooseMedia" :show="false" ref="upload" @allComplete="upLoadallComplete" @oneComplete="upLoadoneComplete"></zmm-upload-image>
<!-- #ifndef H5 -->
<view class="zfb-tk-recorder" v-show="showRecorder"><zmm-recorder :show="showRecorder" ref="rec" @recorderStop="recorderStop"></zmm-recorder></view>
<!-- #endif -->
</view>
</template>
<script>
// #ifdef APP-PLUS
const TUICalling = uni.requireNativePlugin('TUICallingUniPlugin-TUICallingModule');
// #endif
let observer = null;
import favorites from '../favorites/index.vue';
import chatItem from './chat-item.vue';
import sendCard from './sendCard.vue';
export default {
components: {
chatItem,
sendCard,
favorites
},
data() {
return {
isBottomHeight: '',
clickToSubmitSure: null,
autodown: true,
emojilist: ['😁', '😂', '😃', '😄', '😅', '😆', '😉', '😊', '😋', '😌', '😍', '😏', '😒', '😓', '😔', '😖', '😘', '😚', '😜', '😝', '😞', '😠', '😡', '😢', '😣', '😤', '😥', '😨', '😩', '😪', '😫', '😭', '😰', '😱', '😲', '😳', '😵', '😷', '😸', '😹', '😺', '😻', '😼', '😽', '😾', '😿', '🙀', '🙅', '🙆', '🙇', '🙈', '🙉', '🙊', '🙋', '🙌', '🙍', '🙎', '🙏'],
showRecorder: false,
showVice: false,
toolist: [
{
title: '相册',
icon: 'tupian'
},
{
title: '拍摄',
icon: 'xiangji'
},
{
title: '位置',
icon: 'dingwei'
},
{
title: '语音',
icon: 'yrecord'
},
{
title: '名片',
icon: 'mingpian'
},
{
title: '收藏',
icon: 'shoucang'
}
],
msgFocus: false,
showtool: false,
showEmojitool: false,
msg: '',
timer: '',
talkTo: '',
keyboardHeight: 0,
windowHeight: 0,
longTapItemKey: '',
// chatWindowData:[],
localData: {},
showtitleNViewBtns: true
};
},
computed: {
userinfo() {
return this.$store.state.userInfo;
},
chatListInfo() {
return this.$store.state.chatlist[this.talkTo.userId];
},
chatDataState() {
return this.$store.state.chatDataState;
},
chatDataUserId() {
return this.$store.state.chatDataUserId;
},
chatWindowData() {
this.$store.dispatch('getchatDatalist');
if (this.$store.state.chatDatalist[this.talkTo.userId]) {
return this.$store.state.chatDatalist[this.talkTo.userId].list;
}
}
},
watch: {
chatDataState: {
deep: true,
immediate: true,
handler(v) {
if (this.chatDataUserId == this.talkTo.userId) {
this.scrolltoBottom();
this.clickToSubmitSure();
}
}
},
keyboardHeight: {
deep: true,
immediate: true,
handler(v) {
if (v > 0) {
this.showEmojitool = false;
}
}
}
},
onLoad(e) {
this.talkTo = e;
// 根据Id
this.$store
.dispatch('createChatObj', {
userId: this.talkTo.userId,
windowType: this.talkTo.windowType
})
.then(res => {
this.localData = res.data;
if (e.windowType == 'SINGLE') {
uni.setNavigationBarTitle({
title: this.localData.fromInfo.nickName
});
}
this.$store.dispatch('getchatDatalist');
this.$store.dispatch('getChatList');
if (this.localData.fromInfo && this.localData.fromInfo.userType == 'normal') {
this.toolist.push({
title: '音视频',
icon: 'yspin'
});
} else {
this.$fc.setTitleNViewBtns(0, '');
this.showtitleNViewBtns = false;
}
if (this.localData.groupInfo && this.localData.groupInfo.userId) {
this.$fc.setTitleNViewBtns(0, '\ue623');
this.showtitleNViewBtns = true;
}
this.scrolltoBottom();
});
this.clickToSubmitSure = this.$fc.debounce(
() => {
observer = uni.createIntersectionObserver(this);
observer.relativeTo('.zfb-tk-main').observe('.autodownView', res => {
var isBottomH = res.intersectionRect.top + res.intersectionRect.height;
if (!this.isBottomHeight) {
this.isBottomHeight = res.relativeRect.height + res.relativeRect.top - 56;
}
if (parseInt(isBottomH) < parseInt(this.isBottomHeight) + 40) {
this.autodown = true;
} else {
this.autodown = false;
}
});
},
100,
false
);
},
onPageScroll() {
this.clickToSubmitSure();
},
onReady() {},
onShow() {
if (this.chatListInfo && this.chatListInfo.nickName) {
uni.setNavigationBarTitle({
title: this.chatListInfo.nickName
});
}
},
mounted() {
// #ifdef APP-PLUS
uni.onKeyboardHeightChange(res => {
this.keyboardHeight = res.height;
});
// #endif
},
onUnload() {
if (observer) {
observer.disconnect();
}
if (this.chatListInfo) {
this.chatListInfo.num = 0;
this.$store.dispatch('updateChatListInfoById', { userId: this.talkTo.userId, data: this.chatListInfo });
}
},
methods: {
addMsg(e) {
this.msg += e;
},
clickitem(e, i) {
//发送收藏
this.sendMsg(e.content, e.collectType);
this.closepopup('popupfavorites');
},
longpressItem(e, i) {
this.longTapItemKey = i;
},
startRecord() {
this.$refs['rec'].startRecord();
this.showRecorder = true;
},
endRecord() {
this.$refs['rec'].stopRecord();
},
recorderStop(e) {
uni.showLoading({ title: '发送中' });
this.$http.uploadFile({
url: '/file/uploadAudio',
filePath: e.recordFilePath,
name: 'file',
fileType: 'audio',
success: res => {
var data = JSON.parse(res.data);
if (data.code == 200) {
var msg = {
time: e.recordTime,
url: data.data.fullPath,
text: data.data.sourceText
};
this.sendMsg(JSON.stringify(msg), 'VOICE');
}
}
});
this.$refs['rec'].clear(); //清理录音
// 隐藏语音组件
this.showRecorder = false;
// this.showtool=false
},
changeShowVice() {
this.showVice = !this.showVice;
},
upLoadoneComplete(e) {
this.sendMsg(JSON.stringify(e), e.type);
},
upLoadallComplete(e) {
// this.sendMsg(JSON.stringify(e),'IMAGE')
},
changeEmojiTool() {
this.showEmojitool = !this.showEmojitool;
this.showtool = false;
},
changeTool() {
this.showtool = !this.showtool;
this.showEmojitool = false;
},
sendCardclick(e) {
this.$refs.popup.close();
this.sendMsg(JSON.stringify(e.item.data), 'CARD');
},
open() {
uni.getSystemInfo({
success: res => {
this.windowHeight = res.windowHeight;
}
});
this.$refs.popup.open('top');
},
closepopup(e) {
this.$refs[e].close();
},
openpopup(e) {
this.$refs[e].open('top');
},
tryagin(e, i) {
//重新发送
this.chatWindowData.splice(i, 1);
this.chatWindowData.splice(i, 1);
this.$store.dispatch('updateChatById', {
userId: this.talkTo.userId,
data: this.chatWindowData
});
this.$nextTick(() => {
this.sendMsg(e.content, e.msgType);
});
},
sendVoiceCall() {
//发起语音
uni.showLoading({
title: '发起语音通话'
});
var formdata = {
userId: this.talkTo.userId,
msgType: 'TRTC_VOICE_START',
content: 'TRTC_VOICE_START'
};
this.$http.request({
url: '/chat/sendMsg',
method: 'POST',
data: JSON.stringify(formdata),
success: res => {
if (res.data.code == '200') {
if (res.data.data.status !== '0') {
uni.showToast({
title: res.data.data.statusLabel,
icon: 'none'
});
return;
}
var userInfo = res.data.data.userInfo;
var data = {
userId: userInfo.userId,
trtcId: userInfo.trtcId,
nickName: userInfo.nickName,
portrait: userInfo.portrait,
startTime: new Date().getTime(),
type: 'audio'
};
uni.setStorage({
key: 'call',
data: JSON.stringify(data),
success: function() {
TUICalling.call({
userID: userInfo.trtcId,
type: 1
});
}
});
}
}
});
},
sendVideoCall() {
//发起视频
uni.showLoading({
title: '发起视频通话'
});
var formdata = {
userId: this.talkTo.userId,
msgType: 'TRTC_VIDEO_START',
content: 'TRTC_VIDEO_START'
};
this.$http.request({
url: '/chat/sendMsg',
method: 'POST',
data: JSON.stringify(formdata),
success: res => {
if (res.data.code == '200') {
if (res.data.data.status !== '0') {
uni.showToast({
title: res.data.data.statusLabel,
icon: 'none'
});
return;
}
var userInfo = res.data.data.userInfo;
var data = {
userId: userInfo.userId,
trtcId: userInfo.trtcId,
nickName: userInfo.nickName,
portrait: userInfo.portrait,
startTime: new Date().getTime(),
type: 'video'
};
uni.setStorage({
key: 'call',
data: JSON.stringify(data),
success: function() {
TUICalling.call({
userID: userInfo.trtcId,
type: 2
});
}
});
}
}
});
},
toolClick(e) {
switch (e.title) {
case '位置':
uni.chooseLocation({
success: res => {
this.sendMsg(JSON.stringify(res), 'LOCATION');
}
});
break;
case '相册':
this.$refs['upload'].chooseTap();
break;
case '语音':
this.startRecord();
break;
case '名片':
this.open();
break;
case '音视频':
uni.showActionSheet({
itemList: ['视频通话', '语音通话'],
success: res => {
switch (res.tapIndex) {
case 0:
this.sendVideoCall();
break;
case 1:
this.sendVoiceCall();
break;
default:
break;
}
}
});
break;
case '收藏':
this.openpopup('popupfavorites');
uni.getSystemInfo({
success: res => {
// #ifdef APP-PLUS
this.windowHeight = res.windowHeight - res.statusBarHeight - res.safeArea.top - res.safeAreaInsets.top;
// #endif
// #ifndef APP-PLUS
this.windowHeight = res.windowHeight;
// #endif
}
});
break;
case '拍摄':
// #ifdef APP-PLUS
var _this = this;
uni.showActionSheet({
itemList: ['拍摄图片', '拍摄视频'],
success: res => {
switch (res.tapIndex) {
case 0:
getImage();
break;
case 1:
getVideo();
break;
default:
break;
}
},
fail: function(res) {
console.log(res.errMsg);
}
});
function getImage() {
//拍照事件
var cmr = plus.camera.getCamera();
cmr.captureImage(
function(p) {
plus.io.resolveLocalFileSystemURL(
p,
function(entry) {
//读取图片信息
compressImage(entry.toLocalURL(), entry.name); //压缩图片
},
function(e) {
console.log('读取拍照文件错误:' + e.message);
}
);
},
function(e) {
console.log(e);
},
{
filename: 'file:///storage/emulated/0/Documents/weiliao/'
}
);
}
function getVideo() {
//拍摄视频
var cmr = plus.camera.getCamera();
cmr.startVideoCapture(
function(p) {
plus.io.resolveLocalFileSystemURL(
p,
function(entry) {
//读取文件信息
compressVideo(entry.fullPath, entry.name); //压缩视频
},
function(e) {
console.log('读取视频文件错误:' + e.message);
}
);
},
function(e) {
console.log(e);
},
{
filename: 'file:///storage/emulated/0/Documents/weiliao/'
}
);
}
function compressImage(url, filename) {
//压缩图片
var name = 'file:///storage/emulated/0/Documents/weiliao/' + filename;
plus.zip.compressImage(
{
src: url, //src: (String 类型 )压缩转换原始图片的路径
dst: name, //压缩转换目标图片的路径
quality: 60, //quality: (Number 类型 )压缩图片的质量.取值范围为1-100
overwrite: true //overwrite: (Boolean 类型 )覆盖生成新文件
},
function(e) {
//压缩后
// openFile(e.target)
uni.showLoading({ title: '发送中' });
sendPhoto(e.target); //发送
},
function(error) {
console.log('压缩图片失败,请稍候再试');
}
);
}
function compressVideo(url, filename) {
//压缩视频
// var name = 'file:///storage/emulated/0/Documents/weiliao/compress/' + filename;
plus.zip.compressVideo(
{
src: url, //src: (String 类型 )压缩转换原始路径
// filename: name, //压缩后的路径
quality: 'medium' //压缩级别low medium high
},
function(e) {
//压缩后
// openFile(e.tempFilePath)
uni.showLoading({ title: '发送中' });
sendVideo(e.tempFilePath); //发送
},
function(error) {
console.log('压缩视频失败,请稍候再试');
}
);
}
function openFile(filePath) {
//打开文件
let system = uni.getSystemInfoSync().platform;
if (system == 'ios') {
filePath = encodeURI(filePath);
}
uni.openDocument({
filePath,
success: res => {
console.log('打开文件成功');
}
});
}
function sendPhoto(filePath) {
//发送图片
_this.$http.uploadFile({
url: '/file/upload',
filePath: filePath,
name: 'file',
fileType: 'image',
success: res => {
var data = JSON.parse(res.data);
if (data.code == 200) {
var msg = {
name: data.data.fileName,
url: data.data.fullPath
};
_this.sendMsg(JSON.stringify(msg), 'IMAGE');
}
}
});
}
function sendVideo(filePath) {
//发送视频
_this.$http.uploadFile({
url: '/file/uploadVideo',
filePath: filePath,
name: 'file',
fileType: 'video',
success: res => {
var data = JSON.parse(res.data);
if (data.code == 200) {
var msg = {
name: data.data.fileName,
videoUrl: data.data.fullPath,
url: data.data.screenShot
};
_this.sendMsg(JSON.stringify(msg), 'VIDEO');
}
}
});
}
// #endif
break;
default:
break;
}
},
sendMsg(e, msgType) {
if (!e) {
return;
}
this.$fc.pushOutMsg({
msgContent: e,
msgType: msgType,
windowType: this.talkTo.windowType,
userId: this.talkTo.userId
});
this.msg = '';
// #ifdef H5
this.msgFocus = false;
this.$nextTick(() => {
this.msgFocus = true;
});
// #endif
},
startRecognize() {
//语音文本输入
// #ifdef H5
uni.showToast({
title: 'H5暂不支持',
icon: 'none'
});
return;
// #endif
let _this = this;
let options = {};
options.engine = 'baidu';
options.punctuation = false; // 是否需要标点符号
options.timeout = 10 * 1000;
plus.speech.startRecognize(
options,
function(s) {
_this.msg = _this.msg + s;
},
function(e) {
uni.showToast({
title: '语音识别失败:' + e.message,
icon: 'none'
});
}
);
},
scrolltoBottom() {
if (this.autodown) {
this.$nextTick(() => {
this.timer = setTimeout(() => {
uni.pageScrollTo({
scrollTop: 9999999,
duration: 10
});
}, 200);
});
}
}
},
onNavigationBarButtonTap(e) {
if (!this.showtitleNViewBtns) {
return;
}
switch (e.index) {
case 0:
if (this.talkTo.windowType == 'GROUP') {
uni.redirectTo({
url: '../groupInfo/detail?param=' + this.talkTo.userId
});
}
if (this.talkTo.windowType == 'SINGLE') {
uni.redirectTo({
url: '../personInfo/detail?param=' + this.talkTo.userId
});
}
break;
default:
break;
}
}
};
</script>
<style lang="scss" scoped>
.autodownView {
height: 1px;
width: 100%;
opacity: 0;
}
.uni-list {
background: none;
}
.zfb-tk-main {
padding: 0 12px;
padding-bottom: 112rpx;
}
.zfb-tk-send-tool {
background: #f7f7f7;
position: fixed;
left: 0;
bottom: 0;
width: 100%;
transition: all 0.1s;
}
.zfb-tk-send-tools {
height: 558rpx;
width: 100%;
background-color: #f7f7f7;
display: flex;
flex-direction: row;
flex-wrap: wrap;
align-items: center;
}
.zfb-tk-send-tools-item {
padding: 35rpx;
display: flex;
flex-direction: column;
align-items: center;
}
.zfb-tk-send-tools-icon {
background-color: #fff;
width: 110rpx;
height: 110rpx;
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
border-radius: 12rpx;
}
.zfb-tk-send-tools-icon .wxfont {
color: #181818;
font-size: 64rpx;
}
.zfb-tk-send-tools-text {
font-size: 24rpx;
color: #666;
margin-top: 16rpx;
}
.zfb-tk-send-tool-c {
position: relative;
z-index: 3;
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-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;
}
.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-vioce {
box-sizing: border-box;
margin: 0 12rpx;
width: 100%;
height: 75rpx;
border-radius: 24rpx;
background: #fff;
display: flex;
flex-direction: row;
align-items: center;
}
.zfb-tk-send-tool-vioce-item {
text-align: center;
font-size: 24rpx;
line-height: 75rpx;
flex: 1;
}
.zfb-tk-send-tool-vioce-item:nth-child(1) {
border-right: 1px #eee solid;
}
.zfb-tk-send-tool-text {
white-space: nowrap;
padding: 10rpx 24rpx;
border-radius: 12rpx;
border: 1px #ddd solid;
background: #f7f7f7;
color: #ddd;
}
.zfb-tk-send-tool-more {
font-size: 64rpx;
color: #333;
}
.zfb-tk-send-tool-icon {
font-size: 64rpx;
color: #333;
}
.zfb-tk-recorder {
width: 250rpx;
height: 250rpx;
left: 50%;
transform: translateX(-50%);
bottom: 680rpx;
box-sizing: border-box;
text-align: center;
position: fixed;
border-radius: 50%;
background-color: #f8f8f8;
box-shadow: 0px 4px 10px rgba(0, 0, 0, 0.05);
padding: 20rpx;
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
}
.popsendCard {
display: flex;
background-color: #fff;
overflow: auto;
}
.popsendCard-close {
width: 100%;
text-align: center;
height: 70rpx;
line-height: 70rpx;
font-size: 42rpx;
background-color: #fff;
position: fixed;
bottom: 0;
left: 0;
z-index: 9999;
}
.wxemojitool {
height: 558rpx;
}
.wxemojitool-content {
display: flex;
flex-direction: row;
flex-wrap: wrap;
}
.wxemojitool-item {
font-size: 44rpx;
width: 93rpx;
height: 93rpx;
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
}
</style>

View File

@@ -0,0 +1,228 @@
<template>
<view class="openTool" :class="itemKey==0 ? 'frist-openTool' : ''" @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="copyText(data.content)" v-if="data.msgType == 'TEXT'">
<view class="openTool-wx-list-item-icon"><view class="wxfont wxcopy"></view></view>
<view class="text">复制</view>
</view>
<view class="openTool-wx-list-item" @click="shoucang" v-if="data.msgType !== 'TRTC_VOICE_END'&&data.msgType !== 'TRTC_VIDEO_END'">
<view class="openTool-wx-list-item-icon"><view class="wxfont shoucang"></view></view>
<view class="text">收藏</view>
</view>
<view class="openTool-wx-list-item" @click="shanchu">
<view class="openTool-wx-list-item-icon"><view class="wxfont wxdelete"></view></view>
<view class="text">删除</view>
</view>
</view>
<view class="openTool-wx-icon"></view>
</view>
<view class="openTool-wx-model"></view>
</view>
</template>
<script>
export default {
data() {
return {
show:false,
animationData: {}
};
},
props: {
data:{
type:[Object,String]
},
talkTo:{
type:[Object,String,Number]
},
itemKey:{
type:[Object,String,Number]
},
list: {
type: Array,
default() {
return [{}];
}
}
},
onShow() {
},
computed: {
},
mounted() {
var animation = uni.createAnimation({
duration: 300,
timingFunction: 'linear'
});
this.animation = animation;
},
methods: {
copyText(e){
uni.setClipboardData({
data: e,
success: function() {
uni.showToast({
title: '复制成功',
icon: 'none',
position: 'bottom'
})
}
});
},
shoucang(){
this.$http.request({
url: '/collect/add',
method: 'POST',
data:JSON.stringify({
collectType: this.data.msgType,
content: this.data.content
}),
success: (res) => {
if (res.data.code == 200) {
uni.showToast({
title:'收藏成功',
icon:'none'
})
}
}
});
},
shanchu(){
this.$store.dispatch('getchatDatalist');
this.$store.dispatch('getChatList');
var chatWindowData = this.$store.state.chatDatalist[this.talkTo.userId].list
var chatListInfo = this.$store.state.chatlist[this.talkTo.userId]
if((this.itemKey+1)==chatWindowData.length){
chatListInfo['content']=''
this.$store.dispatch('updateChatListInfoById',{
userId: this.talkTo.userId,
data: chatListInfo
});
}
chatWindowData.splice(this.itemKey, 1);
this.$store.dispatch('updateChatById', { userId: this.talkTo.userId,data: chatWindowData });
},
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{
width: 552rpx;
position: absolute;
bottom: 100%;
}
.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%;
padding: 6rpx 24rpx;
box-sizing: border-box;
background-color: #4C4C4C;
border-radius: 10rpx;
display: flex;
flex-direction: row;
justify-content: space-around;
flex-wrap: wrap;
}
.openTool-wx-list-item {
margin:6rpx 24rpx;
display: flex;
flex-direction: column;
align-items: center;
}
.openTool-wx-list-item .text {
color: #fff;
font-size: 28rpx;
border-bottom: 1px #535353 solid;
flex: 1;
}
.openTool-wx-list-item:nth-last-child(1) .text{
border: none;
}
.openTool-wx-list-item-icon {
color: #fff;
margin-bottom: 6rpx;
}
.openTool-wx-icon {
width: 0px;
height: 0px;
border: 5px solid transparent;
border-top-color: #4C4C4C;
margin: 0 auto;
margin-bottom: -5px;
}
.openTool-wx-list-item-icon .wxfont {
font-size: 42rpx;
}
.openTool-msgright{
margin-left: auto;
/* margin-right: 92rpx; */
right: 92rpx;
}
.openTool-msgleft{
margin-right: auto;
/* margin-left: 92rpx; */
left: 92rpx;
}
.openTool-msgright .openTool-wx-icon{
margin-right: 24rpx;
}
.openTool-msgleft .openTool-wx-icon{
margin-left: 24rpx;
}
.frist-openTool{
bottom: auto;
top: 100%;
}
.frist-openTool .openTool-wx{
flex-direction: column-reverse;
}
.frist-openTool .openTool-wx .openTool-wx-icon{
border-bottom-color: #4C4C4C;
border-top-color: transparent;
margin-bottom: 0;
margin-top: -5px;
}
</style>

View File

@@ -0,0 +1,52 @@
<template>
<view class="xw-book">
<watermark></watermark>
<uni-indexed-list-wx :showAdd="false" :options="list" @click="bindClick"></uni-indexed-list-wx>
</view>
</template>
<script>
export default {
emits:['click'],
data() {
return {
list: [],
path:''
}
},
mounted() {
this.getflist()
},
methods: {
bindClick(e){
this.$emit('click',e)
},
getflist(){
this.$http.request({
url: '/friend/friendList',
method: 'POST',
data:JSON.stringify({}),
success: (res) => {
if (res.data.code == 200) {
var data=res.data.data
var list=[]
for (var i = 0; i < data.length; i++) {
var item=data[i]
list.push({
name:item.nickName,
avatar:item.portrait,
userId:item.userId,
chatNo:item.chatNo
})
}
this.list=this.$fc.sortList({list:list,key:'name'})
}
}
});
},
},
}
</script>
<style scoped>
</style>