2023-10-21 09:39:29 +08:00

666 lines
16 KiB
Vue
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<view style="background-color: #F6F7FD;">
<u-loading-page :loading="showLoading" v-if="showLoading"></u-loading-page>
<!-- 消息 -->
<view class="content" @click="showPlus=false" id="content" v-show='!showLoading'>
<view class="">
<u-loadmore :status="status" :loadmore-text="`你正在与${manager_nmae}聊天`" />
</view>
<view class="task-li" v-for="item,index in list" :key="index">
<view class="" v-if="index %5 ==0" style="text-align: center;">
{{timeFn(item.create_time)}}
</view>
<!-- 对方消息 -->
<view v-if="item.from_user_id!=fromId">
<view class="task-li-r">
<view class="" style="margin-right: 10rpx;">
<u--image :showLoading="true" :src="item.from_user_avatar" shape="circle" width="40px"
height="40px"></u--image>
</view>
<view @longpress="copyText(item.content)" class="task-li-content" v-if="item.type=='text'"
style="margin-right: 10rpx;">
<view style="color: #576B95;" @click="href(item.content)" v-if="isLink(item.content)">
{{item.content}}
</view>
<view class="" v-else>
{{item.content}}
</view>
</view>
<!-- 图片 -->
<view class="task-li-content" v-if="item.type=='image'" style="margin-right: 10rpx;"
@tap="previewImage(item.content)">
<image :src="item.content" style="width:200rpx" mode="widthFix"></image>
</view>
<!-- 视频 -->
<view class="task-li-content" v-if="item.type=='video'"
style="margin-right: 10rpx;position: relative;"
@tap="showOverLayFn(item.content,item.type)">
<u--image :showLoading="true"
:src=" item.content+'?x-oss-process=video\/snapshot,t_1000,m_fast,w_800,f_png' "
width="100px" height="80px"></u--image>
<view class="yl-text">
<u-icon name="play-circle" color='white' size='30'></u-icon>
</view>
</view>
</view>
<view class="send-time">
{{item.sendTime}}
</view>
</view>
<!-- 我的消息 -->
<view class="task-li-l" v-else>
<!-- 文字 -->
<view class="task-li-content" @longpress="copyText(item.content)" v-if="item.type=='text'"
style="margin-right: 10rpx;">
<!-- {{item.content}} -->
<view style="color: #576B95;" @click="href(item.content)" v-if="isLink(item.content)">
{{item.content}}
</view>
<view class="" v-else>
{{item.content}}
</view>
<!-- <a href="item.content" target="_blank"> {{item.content}}</a> -->
</view>
<!-- 图片 -->
<view class="task-li-content" v-if="item.type=='image'" style="margin-right: 10rpx;"
@tap="previewImage(item.content)">
<image :src="item.content" style="width:200rpx" mode="widthFix"></image>
</view>
<!-- 视频 -->
<view class="task-li-content" v-if="item.type=='video'"
style="margin-right: 10rpx;position: relative;" @tap="showOverLayFn(item.content,item.type)">
<u--image :showLoading="true"
:src=" item.content+'?x-oss-process=video\/snapshot,t_1000,m_fast,w_800,f_png' "
width="100px" height="80px"></u--image>
<view class="yl-text">
<u-icon name="play-circle" color='white' size='30'></u-icon>
</view>
</view>
<view class="">
<u--image :showLoading="true" :src="a" shape="circle" width="40px" height="40px"></u--image>
</view>
</view>
</view>
<!-- 本地 -->
<view v-show="item.status" v-for="(item,index) in local">
<view class="localTask" v-if="item.localType=='video'">
<view class="task-li-content" style="margin-right: 10rpx;">
<video :src="item.localSrc" controls id="vi1" style="width: 400rpx; height: 100px;"></video>
<!-- <image :src="" style="width:200rpx" mode="widthFix"></image> -->
<u-loadmore status="loading" loading-text="努力上传中" />
</view>
<view class="" style="margin-right: 10rpx;">
<u--image :showLoading="true" shape="circle" :src="a" width="40px" height="40px"></u--image>
</view>
</view>
<view class="localTask" v-if="item.localType=='image'">
<view class="task-li-content" style="margin-right: 10rpx;">
<image :src="item.localSrc" style="width:200rpx" mode="widthFix"></image>
<u-loadmore status="loading" loading-text="努力上传中" />
</view>
<view class="" style="margin-right: 10rpx;">
<u--image :showLoading="true" shape="circle" :src="a" width="40px" height="40px"></u--image>
</view>
</view>
</view>
<view style="height: 300rpx;background-color: #F6F7FD;" v-if="showPlus">
</view>
<view style="height: 150rpx;background-color: #F6F7FD;" v-else>
</view>
</view>
<!-- 底部 -->
<view class="bottom">
<!-- -->
<view class="send-col">
<input type="text" class="send-ipt" @focus="scrollFn" v-model="value" placeholder="请输入聊天内容"
placeholder-style="color:#DDD;" :cursor-spacing="6">
<u--image :showLoading="true" src="/static/img/bussness/Plus.png" width="32px" height="32px"
@click="showPlusFn"></u--image>
<button class="send" @tap="sendFn">发送</button>
</view>
<!-- 发送照片 -->
<view class="plus" v-if="showPlus">
<view class="plus_li">
<u--image :showLoading="true" src="/static/img/bussness/XC.png" width="120rpx" height="120rpx"
@click="choseImgFn"></u--image>
<text>图片</text>
</view>
<view class="plus_li">
<u--image :showLoading="true" src="/static/img/bussness/SP.png" width="120rpx" height="120rpx"
@click="choseVideoFn"></u--image>
<text>视频</text>
</view>
</view>
</view>
<!-- 遮罩图 -->
<u-overlay :show="show" @click="show = false">
<view class="warp">
<view class="rect" @tap.stop v-if="overLayType=='video'">
<video :src="overLaySrc" controls :autoplay="true"></video>
</view>
</view>
</u-overlay>
</view>
</template>
<script>
import {
FILE_URL_IM
} from "@/api/file.js"
import {
sendMsgApi,
getMsgListApi,
bindScoket,
sendFileApi,
getAreaManagerApi
} from "@/api/bussness.js"
export default {
data() {
return {
showLoading: true,
a: "https://img1.baidu.com/it/u=716638254,3920932970&fm=253&app=138&size=w931&n=0&f=JPEG&fmt=auto?sec=1695920400&t=aeec3d0e86c23759d5f82b3757e9b442",
list: [],
bind: false,
value: "",
showPlus: false,
scollNum: 500000000000,
client_id: "",
fromId: "",
toId: "",
name: "",
status: "loadmore",
page_no: 1,
limit: 10,
show: false,
overLaySrc: "",
overLayType: "",
local: [],
localType: "",
imageList: [],
sendData: {},
manager_nmae: "",
msg_id: "",
aaa: false,
}
},
methods: {
isLink(text) {
var pattern = /^(https?:\/\/|www\.|.*\.com).*$/i;
return pattern.test(text);
},
href(url) {
// uni.navigate
plus.runtime.openURL(url);
// plus.runtime.openUrl(url)
},
previewImage(src) {
this.imageList[0] = src
uni.previewImage({
urls: this.imageList,
})
},
generateRandId() {
var d = new Date().getTime();
var uuid = "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function(c) {
var r = (d + Math.random() * 16) % 16 | 0;
d = Math.floor(d / 16);
return (c == "x" ? r : r & 0x3 | 0x8).toString(16);
});
// return uuid;
this.msg_id = uuid
console.log("改变id")
},
timeFn(time) {
time = time * 1000
const currentDate = new Date(); // 当前日期对象
const targetDate = new Date(time);
if (this.isSameDay(currentDate, targetDate)) {
const hours = targetDate.getHours(); // 小时
const minutes = targetDate.getMinutes(); // 分钟
return hours + ':' + (minutes >= 10 ? minutes : '0' + minutes);
} else if (this.isYesterday(currentDate, targetDate)) {
return '昨天';
}
const month = targetDate.getMonth() + 1; // 月份注意月份从0开始需要加1
const day = targetDate.getDate(); // 日期
return month + '月' + day + '日';
},
isSameDay(date1, date2) {
return (
date1.getFullYear() === date2.getFullYear() &&
date1.getMonth() === date2.getMonth() &&
date1.getDate() === date2.getDate()
);
},
isYesterday(currentDate, targetDate) {
const yesterday = new Date(currentDate.getFullYear(), currentDate.getMonth(), currentDate.getDate() - 1);
return this.isSameDay(yesterday, targetDate);
},
toast(msg) {
uni.showToast({
title: msg,
icon: 'none'
});
},
saveImage(src) {
uni.saveImageToPhotosAlbum({
filePath: src,
success() {
uni.showToast({
title: '保存成功',
icon: 'none'
});
},
fail() {
this.toast('保存失败')
}
});
},
copyText(value) {
const text = value;
uni.setClipboardData({
data: text,
success() {
uni.showToast({
title: '复制成功',
icon: 'none'
});
}
});
},
showOverLayFn(src, type) {
this.show = true
this.overLaySrc = src
this.overLayType = type
},
getListFn() {
getMsgListApi({
from_user_id: this.fromId,
to_user_id: this.toId,
scene: 0,
page_no: this.page_no,
page_size: 10
}).then(res => {
if (res.data.length <= 0) {
uni.stopPullDownRefresh();
this.status = "nomore"
return
}
this.list = res.data.reverse().concat(this.list)
uni.stopPullDownRefresh();
})
},
scrollFn() {
let that = this
this.scollNum += 100
setTimeout(() => {
uni.pageScrollTo({
scrollTop: that.scollNum, // 滚动的实际距离
success: function() {
console.log('滚动')
}
})
}, 100)
},
sendFn() {
let that = this
if (!this.value) {
this.toast("消息不能为空")
return
}
let data = {
from_user_id: this.fromId,
to_user_id: this.toId,
type: "text",
content: this.value,
scene: 0,
create_time: (Date.now() / 1000),
msg_id: this.msg_id
}
sendMsgApi({
...data
}).then(res => {
console.log(data)
this.list.push(data)
this.scrollFn(100)
this.value = ""
this.generateRandId()
}).catch(err => {
this.toast('发送失败')
this.generateRandId()
})
},
showPlusFn() {
this.showPlus = !this.showPlus
this.scrollFn()
},
choseImgFn() {
this.generateRandId()
let time = Date.now()
let that = this
uni.chooseImage({
count: 1, // 最多可以选择的图片张数
success: res => {
const tempFilePath = res.tempFilePaths[0];
that.local.push({
localType: 'image',
localSrc: tempFilePath,
status: true,
msg_id: that.msg_id
})
that.showPlus = false
that.scrollFn()
console.log(that.local)
uni.uploadFile({
url: FILE_URL_IM,
filePath: tempFilePath, // 选择的图片文件路径
name: 'file',
header: {
"Authorization": uni.getStorageSync("TOKEN")
},
formData: {
from_user_id: that.fromId,
to_user_id: that.toId,
scene: 0,
msg_id: that.msg_id,
type: 'image'
},
success: function(uploadRes) {
let data = JSON.parse(uploadRes.data).data
var localIndex = that.local.findIndex(function(element) {
return element.msg_id === data.msg_id;
});
that.local[localIndex].status = false
that.list.push(data)
},
fail: function(error) {
this.toast('上传失败')
}
});
},
fail: err => {
this.toast('操作取消')
}
});
},
choseVideoFn() {
this.generateRandId()
let that = this
uni.chooseVideo({
sourceType: ['album', 'camera'], // 视频选择的来源,可以是相册或摄像头
maxDuration: 600, // 视频的最大时长(单位:秒)
camera: 'back', // 摄像头类型,可以是前置或后置
success: res => {
const tempFilePath = res.tempFilePath;
that.local.push({
localType: 'video',
localSrc: tempFilePath,
status: true,
msg_id: that.msg_id
})
that.showPlus = false
that.scrollFn()
uni.uploadFile({
url: FILE_URL_IM,
filePath: tempFilePath, // 选择的图片文件路径
name: 'file',
header: {
"Authorization": uni.getStorageSync("token")
},
formData: {
from_user_id: that.fromId,
to_user_id: that.toId,
scene: 0,
msg_id: that.msg_id,
type: 'video'
}, // 服务端接收文件的字段名
success: function(uploadRes) {
let data = JSON.parse(uploadRes.data).data
var localIndex = that.local.findIndex(function(element) {
return element.msg_id === data.msg_id;
});
that.local[localIndex].status = false
that.list.push(data)
// 处理上传成功的逻辑
},
fail: function(error) {
console.log(error)
uni.showToast({
title: '视频不能超过60s',
duration: 2000,
icon: 'none'
});
// that.local = false
}
});
},
fail: err => {
// uni.showToast({
// title: '视频不能超过60s',
// duration: 2000,
// icon: 'none'
// });
}
});
},
},
onShow() {
this.page_no = 1
this.generateRandId()
this.fromId = JSON.parse(uni.getStorageSync("USER_INFO")).id
getAreaManagerApi({
user_id: this.fromId
}).then(res => {
this.toId = res.data.to_user_id
this.manager_nmae = res.data.manager_name
getMsgListApi({
from_user_id: this.fromId,
to_user_id: this.toId,
scene: 0,
page_no: 1,
page_size: 10
}).then(res => {
this.showLoading = false
this.list = res.data.reverse()
this.scrollFn()
})
})
},
async onPullDownRefresh() {
let that = this
this.status = "loading"
this.page_no++
await this.getListFn()
this.status = "loadmore"
},
onLoad() {
let user = JSON.parse(uni.getStorageSync('USER_INFO'))
this.a = user.avatar
console.log(user.avatar)
uni.connectSocket({
url: 'wss://ceshi-worker-task.lihaink.cn/im'
});
uni.onSocketOpen(function(res) {
console.log('WebSocket连接已打开');
});
uni.onSocketError(function(res) {
console.log('WebSocket连接打开失败请检查');
});
let that = this
uni.onSocketMessage(function(res) {
let data = JSON.parse(res.data)
if (data.client_id) {
let client_id = data.client_id
if (!that.bind) {
bindScoket({
client_id: client_id,
user_id: that.fromId,
scene: 0,
}).then(res => {
that.bind = true
})
}
}
// 收到消息
else if (data.type != 'ping') {
console.log(data)
that.list.push(data)
that.scrollFn()
}
});
this.generateRandId()
},
}
</script>
<style lang="scss">
.yl-text {
position: absolute;
color: white;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
font-size: 24rpx;
}
.topflag {
height: 80rpx;
background-color: #F6F7FD;
}
.content {
padding: 0 20rpx;
min-height: 95vh;
background-color: #F6F7FD;
padding-top: 10rpx;
.task-li {
margin-bottom: 20rpx;
}
.task-li-l {
display: flex;
justify-content: flex-end;
}
.task-li-r {
display: flex;
}
.task-li-content {
background-color: white;
padding: 10rpx 20rpx;
line-height: 50rpx;
// line-height: 30rpx;
border-radius: 20rpx;
// color: white;
word-break: break-all;
max-width: 535rpx;
overflow-wrap: break-word;
}
}
.bottom {
background-color: white;
padding: 20rpx 0;
position: fixed;
box-sizing: border-box;
bottom: 0px;
padding-bottom: 10px;
/* #ifndef APP-PLUS */
// bottom: 40px;
/* #endif */
.send-col {
display: flex;
align-items: center;
justify-content: space-around;
.send-ipt {
width: 70vw;
background-color: #F5F5F5;
height: 60rpx;
border-radius: 20rpx;
padding-left: 20rpx;
}
}
.send {
background-color: #2573fb;
color: #fff;
height: 64rpx;
margin-left: 20rpx;
border-radius: 6rpx;
padding: 0;
width: 120rpx;
line-height: 62rpx;
&:active {
background-color: #1573fb;
}
}
.plus {
display: flex;
background-color: white;
padding: 20rpx;
.plus_li {
display: flex;
flex-direction: column;
align-items: center;
margin-right: 20rpx;
flex-wrap: wrap;
}
}
}
.warp {
display: flex;
align-items: center;
justify-content: center;
height: 100%;
}
.rect {}
.localTask {
display: flex;
justify-content: flex-end;
}
</style>