Files
2025-04-30 14:08:39 +08:00

1220 lines
34 KiB
Vue
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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 class="page" :style="themeColor">
<view
class="flex flex-direction flex-wrap align-stretch benben-position-layout flex demandDetails_flex_0"
:style="{ height: 88 + StatusBarRpx + 'rpx', paddingTop: StatusBarRpx + 'rpx' }"
>
<view class="flex flex-wrap align-center demandDetails_fd0_0">
<view class="flex flex-wrap align-center demandDetails_fd0_0_c0" @tap.stop="handleJumpDiy" data-type="back" data-url="1">
<text class="fu-iconfont2 demandDetails_fd0_0_c0_c0">&#xE794;</text>
</view>
<view class="flex flex-wrap align-center justify-center flex-sub">
<view class="names">{{ toName }}</view>
</view>
<view class="flex align-center justify-end" @click="handleReport">
举报
</view>
</view>
</view>
<!-- <view :style="{ height: 500 + StatusBarRpx + 'rpx' }"></view> -->
<!---flex布局flex布局开始-->
<view class="content" @touchstart="hideDrawer" >
<scroll-view
class="msg-list"
scroll-y="true"
:style="{paddingTop:88 + StatusBarRpx + 'rpx'}"
:scroll-with-animation="scrollAnimation"
:scroll-top="scrollTop"
:scroll-into-view="scrollToView"
@scrolltoupper="loadHistory"
upper-threshold="50"
>
<!-- 加载历史数据waitingUI -->
<!-- <view class="loading" v-if="msgList.length">
<view class="spinner">
<view class="rect1"></view>
<view class="rect2"></view>
<view class="rect3"></view>
<view class="rect4"></view>
<view class="rect5"></view>
</view>
</view> -->
<view class="row" v-for="(row, index) in msgList" :key="index" :id="'msg' + row.aid">
<!-- 系统消息 -->
<!-- <block v-if="row.type == 'system'">
<view class="system">
<view v-if="row.msg.type == 'text'" class="text">{{ row.msg.content.text }}</view>
</view>
</block> -->
<!-- 用户消息 -->
<block>
<!-- 消息类型 0 文字 1图片 2 视频 3录音 -->
<!-- 自己发出的消息 -->
<view class="my" v-if="row.uid == myuid">
<!-- 左-消息 -->
<view class="left">
<!-- 文字消息 -->
<view v-if="row.content.type == '0'" class="bubble"><rich-text :nodes="row.content.text"></rich-text></view>
<!-- 语言消息 :class="playMsgid == row.aid ? 'play' : ''"-->
<view v-else-if="row.content.type == '3'" class="bubble voice" @tap="playVoice(row)">
<view class="length">{{ row.content.length }}</view>
<view class="icon my-voice"></view>
</view>
<view v-if="row.content.type == '4'" class="bubble">
<!-- <jyf-parser :html="row.content.text"></jyf-parser> -->
<rich-text :nodes="row.content.text"></rich-text>
</view>
<!-- 图片消息 -->
<view v-else-if="row.content.type == '1'" class="bubble img" @tap="showPic(row.content.url)">
<image mode="aspectFit" :src="row.content.url" :style="{ width: row.content.w + 'px', height: row.content.h + 'px' }"></image>
</view>
<!-- <view class="bubble" style="background-color: transparent;" v-else-if="row.type == '4'"><telInfo :obj="row.content"></telInfo></view> -->
</view>
<!-- 右-头像 -->
<view class="right"><image mode="aspectFill" :src="row.avatar"></image></view>
</view>
<!-- 别人发出的消息 -->
<view class="other" v-if="row.uid != myuid">
<!-- 左-头像 -->
<view class="left"><image mode="aspectFill" :src="row.avatar"></image></view>
<!-- 右-用户名称-时间-消息 -->
<view class="right">
<view class="username">
<view class="name">{{ row.nickname }}</view>
<view class="time">{{ row.create_time }}</view>
</view>
<!-- 文字消息 -->
<view v-if="row.content.type == '0'" class="bubble"><rich-text :nodes="row.content.text"></rich-text></view>
<!-- 语音消息 :class="playMsgid == row.aid ? 'play' : ''" -->
<view v-if="row.content.type == 3" class="bubble voice" @tap="playVoice(row)">
<view class="icon other-voice"></view>
<view class="length">{{ row.content.length }}</view>
</view>
<view v-if="row.content.type == '4'" class="bubble">
<rich-text v-html="row.content.text" ></rich-text>
<!-- <jyf-parser :html="row.content.text"></jyf-parser> -->
</view>
<!-- 图片消息 -->
<view v-else-if="row.content.type == '1'" class="bubble img" @tap="showPic(row.content.url)">
<image mode="aspectFit" :src="row.content.url" :style="{ width: row.content.w + 'rpx', height: row.content.h + 'rpx' }"></image>
</view>
<view v-else-if="row.content.type == '6'" class="bubble flex align-center" @tap.stop="handleJumpDiy"
data-type="navigateTo" :data-url="`/pages/shouye/healthEncyclopediaDetails/healthEncyclopediaDetails?id=` + row.content.cycId">
<image style="width: 108rpx;height: 108rpx;" v-if="row.content.url" :src='row.content.url'></image>
<view class="margin-left-sm flex flex-sub">
{{row.content.title}}
</view>
</view>
<!-- <view class="bubble" style="background-color: transparent;" v-else-if="row.type == '4'"><telInfo :obj="row.content"></telInfo></view> -->
</view>
</view>
</block>
</view>
</scroll-view>
</view>
<!-- <view class="" style="font-size: 36rpx;">
😀😃😄😁😆😅🤣😠 😂🙂🙃😉😊😇😕😟 🙁😮😯😲😳🥺😦😧 😨😰😥😢😭😱😖😣 😞😓😩😫🥱😤😡🤬 😈👿😗😚😙😋😛😜 🤪😝🤑🤗🤭🤫🤔🤐 🤨😐😑😶😶‍😏😒🙄 😬🤥😌😔😪🤤😴😷 🤒🤕🤢🤮🤧🥵🥴😵
🤯🤠🥳😎🤓🧐🙏👍
</view> -->
<!-- 抽屉栏 -->
<view class="popup-layer" v-if="mytype==1" :class="popupLayerClass" @touchmove.stop.prevent="discard">
<!-- -->
<!-- <view class="" style="width: 100%;height: 40vw;background-color: darkred;">
<scroll-view scroll-y="true">
<view class="popup-layer-list">
<block v-for="(item, i) in emojArr" :key="i">
<view class="popup-layer-list-item" @tap="addEmoji(item)" style="font-size: 50rpx;display: inline-block;line-height: 80rpx;margin-right: 20rpx;">
{{ item }}
</view>
</block>
</view>
</scroll-view>
</view>
-->
<!-- 表情 -->
<swiper class="emoji-swiper" :class="{ hidden: hideEmoji }" indicator-dots="true" duration="150">
<swiper-item v-for="(page, pid) in emojArr" :key="pid">
<view style="font-size: 48rpx;" v-for="(em, eid) in page" :key="eid" @tap="addEmoji(em)">{{ em }}</view>
</swiper-item>
</swiper>
<!-- 更多功能 相册-拍照-红包 -->
<view class="more-layer" :class="{ hidden: hideMore }">
<view class="list">
<view class="list-box">
<view class="box" @tap="chooseImage"><view class="icon tupian2"></view></view>
<view class="list-box-title">图片</view>
</view>
<view class="list-box">
<view class="box" @tap="camera"><view class="icon paizhao"></view></view>
<view class="list-box-title">拍摄</view>
</view>
<!-- <view class="list-box">
<view class="box" @tap="shangpin">
<image mode="aspectFit" src="https://ljzp-files.oss-cn-hangzhou.aliyuncs.com/wxImage/lianjie.png" style="width: 35px;height: 35px;"></image>
</view>
<view class="list-box-title">{{i18n['商品']}}</view>
</view> -->
<!-- <view class="box" @tap="handRedEnvelopes"><view class="icon hongbao"></view></view> -->
</view>
</view>
</view>
<!-- 底部输入栏 -->
<view class="input-box" :class="{ activesss: isIos, popupLayerClass }" @touchmove.stop.prevent="discard" v-if="mytype==1">
<!-- H5下不能录音输入栏布局改动一下 -->
<!-- #ifndef H5 -->
<!-- <view class="voice"><view class="icon" :class="isVoice ? 'jianpan' : 'yuyin'" @tap="switchVoice"></view></view> -->
<!-- #endif -->
<!-- #ifdef H5 -->
<view class="more" @tap="showMore"><view class="icon add"></view></view>
<!-- #endif -->
<view class="textbox">
<view
class="voice-mode"
:class="[isVoice ? '' : 'hidden', recording ? 'recording' : '']"
@touchstart="voiceBegin"
@touchmove.stop.prevent="voiceIng"
@touchend="voiceEnd"
@touchcancel="voiceCancel"
>
{{ voiceTis }}
</view>
<view class="text-mode" :class="isVoice ? 'hidden' : ''">
<view class="box">
<textarea auto-height="true" :cursor-spacing="20" :adjust-position="true" v-model="textMsg" @focus="textareaFocus" />
</view>
<!-- <view class="em" @tap="chooseEmoji"><view class="icon biaoqing"></view></view> -->
</view>
</view>
<!-- #ifndef H5 -->
<view class="more" @tap="showMore"><view class="icon add"></view></view>
<!-- #endif -->
<view class="send" :class="isVoice ? 'hidden' : ''" @tap="sendText"><view class="btn">发送</view></view>
</view>
<!-- 录音UI效果 -->
<view class="record" :class="recording ? '' : 'hidden'">
<view class="ing" :class="willStop ? 'hidden' : ''"><view class="icon luyin2"></view></view>
<view class="cancel" :class="willStop ? '' : 'hidden'"><view class="icon chehui"></view></view>
<view class="tis" :class="willStop ? 'change' : ''">{{ recordTis }}</view>
</view>
<!-- 举报弹窗 -->
<benben-position-popup ref="benbenPositionPopup1666085213316" :width="142" :height="65" :mask-hide="false" popup-origin="left top">
<view class="flex flex-direction align-stretch benben-flex-position-popup flex myComments_popup_2">
<view class="flex flex-wrap align-center justify-center myComments_positionPopup2_c0" @click="goReplorts">
<image class="myComments_positionPopup2_c0_c0" mode="aspectFit" :src="STATIC_URL + '75.png'"></image>
<text class="myComments_positionPopup2_c0_c1">{{ i18n['举报'] }}</text>
</view>
</view>
</benben-position-popup>
</view>
</template>
<script>
import { mapGetters } from 'vuex';
import telInfo from './tel-info.vue';
import { host } from '../../../common/config.js'
export default {
components: {
telInfo
},
data() {
return {
//文字消息
textMsg: '',
//消息列表
isHistoryLoading: false,
scrollAnimation: false,
scrollTop: 0,
scrollToView: '',
msgList: [],
msgImgList: [],
myuid: 0,
//录音相关参数
// #ifndef H5
//H5不能录音
RECORDER: uni.getRecorderManager(),
// #endif
isVoice: false,
voiceTis: '按住 说话',
recordTis: '手指上滑 取消发送',
recording: false,
willStop: false,
initPoint: { identifier: 0, Y: 0 },
recordTimer: null,
recordLength: 0,
//播放语音相关参数
AUDIO: uni.createInnerAudioContext(),
playMsgid: null,
VoiceTimer: null,
// 抽屉参数
popupLayerClass: '',
// more参数
hideMore: true,
//表情定义
hideEmoji: true,
isIos: false,
//
//
//
//
//
// 😴
// 🤒🤕🤢🤮🤧
// 🤠🥳😎🤓🧐🙏👍
emojArr: [
['😎', '😃', '😄', '😁', '😆', '😅', '🤣', '🙄', '😠', '😂', '🙂', '🙃', '😉', '😊', '😇', '😬', '😕', '😟', '🙁', '😮', '😯', '😲', '😳', '😬'],
['😬', '😦', '😧', '😨', '😰', '😥', '😢', '😵', '😭', '😱', '😖', '😣', '😞', '😓', '😬', '🤤', '😷', '😔', '😤', '😡', '🤬', '😈', '😴', '🤯'],
['😗', '😚', '😙', '😋', '😛', '😜', '🤪', '🤥', '😝', '🤑', '🤗', '🤭', '🤫', '🤔', '🤐', '😌', '🤨', '😐', '😑', '😶', ' 😶', '👍', '😏', '😪']
// '😒',
// '','','','','','','','',
// '','','','','','','','',
// '','','','','','','','',
],
emojiList: [
[
{ url: '100.gif', alt: '[微笑]' },
{ url: '101.gif', alt: '[伤心]' },
{ url: '102.gif', alt: '[美女]' },
{ url: '103.gif', alt: '[发呆]' },
{ url: '104.gif', alt: '[墨镜]' },
{ url: '105.gif', alt: '[哭]' },
{ url: '106.gif', alt: '[羞]' },
{ url: '107.gif', alt: '[哑]' },
{ url: '108.gif', alt: '[睡]' },
{ url: '109.gif', alt: '[哭]' },
{ url: '110.gif', alt: '[囧]' },
{ url: '111.gif', alt: '[怒]' },
{ url: '112.gif', alt: '[调皮]' },
{ url: '113.gif', alt: '[笑]' },
{ url: '114.gif', alt: '[惊讶]' },
{ url: '115.gif', alt: '[难过]' },
{ url: '116.gif', alt: '[酷]' },
{ url: '117.gif', alt: '[汗]' },
{ url: '118.gif', alt: '[抓狂]' },
{ url: '119.gif', alt: '[吐]' },
{ url: '120.gif', alt: '[笑]' },
{ url: '121.gif', alt: '[快乐]' },
{ url: '122.gif', alt: '[奇]' },
{ url: '123.gif', alt: '[傲]' }
],
[
{ url: '124.gif', alt: '[饿]' },
{ url: '125.gif', alt: '[累]' },
{ url: '126.gif', alt: '[吓]' },
{ url: '127.gif', alt: '[汗]' },
{ url: '128.gif', alt: '[高兴]' },
{ url: '129.gif', alt: '[闲]' },
{ url: '130.gif', alt: '[努力]' },
{ url: '131.gif', alt: '[骂]' },
{ url: '132.gif', alt: '[疑问]' },
{ url: '133.gif', alt: '[秘密]' },
{ url: '134.gif', alt: '[乱]' },
{ url: '135.gif', alt: '[疯]' },
{ url: '136.gif', alt: '[哀]' },
{ url: '137.gif', alt: '[鬼]' },
{ url: '138.gif', alt: '[打击]' },
{ url: '139.gif', alt: '[bye]' },
{ url: '140.gif', alt: '[汗]' },
{ url: '141.gif', alt: '[抠]' },
{ url: '142.gif', alt: '[鼓掌]' },
{ url: '143.gif', alt: '[糟糕]' },
{ url: '144.gif', alt: '[恶搞]' },
{ url: '145.gif', alt: '[什么]' },
{ url: '146.gif', alt: '[什么]' },
{ url: '147.gif', alt: '[累]' }
]
],
//表情图片图床名称 ,由于我上传的第三方图床名称会有改变,所以有此数据来做对应,您实际应用中应该不需要
onlineEmoji: {
'100.gif': 'AbNQgA.gif',
'101.gif': 'AbN3ut.gif',
'102.gif': 'AbNM3d.gif',
'103.gif': 'AbN8DP.gif',
'104.gif': 'AbNljI.gif',
'105.gif': 'AbNtUS.gif',
'106.gif': 'AbNGHf.gif',
'107.gif': 'AbNYE8.gif',
'108.gif': 'AbNaCQ.gif',
'109.gif': 'AbNN4g.gif',
'110.gif': 'AbN0vn.gif',
'111.gif': 'AbNd3j.gif',
'112.gif': 'AbNsbV.gif',
'113.gif': 'AbNwgs.gif',
'114.gif': 'AbNrD0.gif',
'115.gif': 'AbNDuq.gif',
'116.gif': 'AbNg5F.gif',
'117.gif': 'AbN6ET.gif',
'118.gif': 'AbNcUU.gif',
'119.gif': 'AbNRC4.gif',
'120.gif': 'AbNhvR.gif',
'121.gif': 'AbNf29.gif',
'122.gif': 'AbNW8J.gif',
'123.gif': 'AbNob6.gif',
'124.gif': 'AbN5K1.gif',
'125.gif': 'AbNHUO.gif',
'126.gif': 'AbNIDx.gif',
'127.gif': 'AbN7VK.gif',
'128.gif': 'AbNb5D.gif',
'129.gif': 'AbNX2d.gif',
'130.gif': 'AbNLPe.gif',
'131.gif': 'AbNjxA.gif',
'132.gif': 'AbNO8H.gif',
'133.gif': 'AbNxKI.gif',
'134.gif': 'AbNzrt.gif',
'135.gif': 'AbU9Vf.gif',
'136.gif': 'AbUSqP.gif',
'137.gif': 'AbUCa8.gif',
'138.gif': 'AbUkGQ.gif',
'139.gif': 'AbUFPg.gif',
'140.gif': 'AbUPIS.gif',
'141.gif': 'AbUZMn.gif',
'142.gif': 'AbUExs.gif',
'143.gif': 'AbUA2j.gif',
'144.gif': 'AbUMIU.gif',
'145.gif': 'AbUerq.gif',
'146.gif': 'AbUKaT.gif',
'147.gif': 'AbUmq0.gif'
},
toUserID: '',
toName: '',
page: 1,
ossObj: uni.getStorageSync('jianadaOss'),
myuid: '',
user: '',
msg_id: '',
showEmji: false,
showHandle: true,
mytype:1,
userInfo:""
};
},
computed: {
themeColor() {
return this.$store.getters.themeColor;
},
...mapGetters(['isLogin', 'userInfo', 'token', 'getLNG', 'getLAT', 'getCurrentAddress'])
},
onLoad(options) {
const self = this;
this.toName = options.name;
this.toUserID = options.id;
this.mytype = options.mytype?options.mytype:1;
let platform = uni.getSystemInfoSync().platform;
if (platform == 'android') {
this.isIos = false;
} else {
this.isIos = true;
}
// if (this.toUserID == this.userInfo.user_id) {
// uni.showToast({
// title: i18n['不能和自己聊天'],
// mask: true,
// icon: 'none',
// duration: 1500
// });
// setTimeout(() => {
// uni.navigateBack({
// delta: 1
// });
// }, 1500);
// }
this.getMsgList();
//语音自然播放结束
this.AUDIO.onEnded(res => {
this.playMsgid = null;
});
// #ifndef H5
//录音开始事件
this.RECORDER.onStart(e => {
this.recordBegin(e);
});
//录音结束事件
this.RECORDER.onStop(e => {
this.recordEnd(e);
});
//#endif
let user_data = uni.getStorageSync('USER_INFO');
this.userInfo = uni.getStorageSync('USER_INFO');
console.log(user_data)
if (user_data) {
this.myuid = 'user-' + user_data.id;
this.user = {
id: user_data.id,
name: user_data.store_name,
avatar: user_data.logo
};
}
uni.$on('receiveMsg', data => {
// this.is_show1 = true;
// this.is_show = false;
console.log('receiveMsg=======', data);
console.log(this.myuid)
if (data.user_id == this.myuid) return;
if (data.type == '0') {
console.log(1111111111111)
// let msgContent = self.replaceEmoji(data.content.text);
data.content = data.contents;
data.uid = data.user_id;
data.avatar = data.head_img;
self.msgList.push(data);
} else {
data.uid = data.user_id;
data.avatar = data.head_img;
self.msgList.push(data);
}
console.log('------msglist', self.msgList);
self.$nextTick(function() {
self.scrollTop = this.scrollTop += 999;
self.scrollAnimation = true;
});
});
},
onShow() {
this.scrollTop = 9999999;
},
onUnload() {
uni.$off('chatChange');
},
onBackPress(e) {
uni.$off('receiveMsg');
uni.$emit('backEmit');
},
methods: {
handleReport() {
let that = this
uni.showModal({
title: "温馨提示",
content: '确定要进行举报?',
cancelText:"取消",
confirmText:"确定",
confirmColor:"#FF9300",
success(res) {
if (res.confirm) {
that.$message.info('您已举报成功, 请等待处理结果')
}
}
});
},
getValue(item){
let data = JSON.parse(item)
data = `<div class="flex flex-wrap align-stretch" style="display: flex;flex-wrap: wrap;align-items: stretch;">
<img class="imghddd" style="width: 140rpx;height: 120rpx;" src="${data.thumb}" />
<div class="p2" style="width: calc(100% - 180rpx);display: -webkit-box;-webkit-box-orient: vertical;-webkit-line-clamp: 3;overflow: hidden;margin-left: 10rpx;">${data.name}</div>
</div>`
data = {text:data}
this.sendMsg(data,4)
console.log()
},
shangpin(){
uni.navigateTo({
url: '/pages/market/mallSearchResults/mallSearchResults?type=1'
});
},
goReplorts() {
const self = this;
uni.navigateTo({
url: '/pages/circle/report/report?source=4&id=' + self.userInfo.user_id
});
self.$refs.benbenPositionPopup1666085213316.close();
},
//触发滑动到顶部(加载历史信息记录)
loadHistory(e) {
const self = this;
if (this.isHistoryLoading) {
return;
}
this.isHistoryLoading = true; //参数作为进入请求标识,防止重复请求
this.scrollAnimation = false; //关闭滑动动画
console.log('加载下一页');
this.$api
.post(global.apiUrls.post5f601350edaa4, {
// page: self.page,
toid: 'user-' + self.toUserID,
msg_id: this.msg_id,
list_rows: 15
})
.then(res => {
console.log(res, '聊天记录列表');
if (res.data.code == 1) {
let newlist = res.data.data.reverse();
for (var i = 0; i < newlist.length; i++) {
newlist[i].content = JSON.parse(newlist[i].content);
}
console.log(newlist);
if (newlist.length) this.msg_id = newlist[0].msgid;
this.msgList = [...newlist, ...this.msgList];
}
});
uni.stopPullDownRefresh();
setTimeout(() => {
this.isHistoryLoading = false;
}, 500);
},
// 加载初始页面消息
getMsgList() {
// 消息列表
const self = this;
var urls = '';
urls = global.apiUrls.post5f601350edaa4;
var data1 = {
toid: 'user-' + self.toUserID,
list_rows: 15
};
self.$api
.post(urls, data1)
.then(res => {
if (res.data.code == 1) {
var data = res.data.data;
for (var i = 0; i < data.length; i++) {
data[i].content = JSON.parse(data[i].content);
}
console.log('聊天记录====', data);
uni.$emit('read');
self.msgList = data.reverse();
console.log('asasas', self.msgList);
self.msg_id = self.msgList[0].msgid;
self.$nextTick(function() {
self.scrollTop = 99999;
self.scrollAnimation = true;
});
}
})
.catch(err => {});
},
//处理图片尺寸,如果不处理宽高,新进入页面加载图片时候会闪
setPicSize(content) {
// 让图片最长边等于设置的最大长度短边等比例缩小图片控件真实改变区别于aspectFit方式。
let maxW = uni.upx2px(350); //350是定义消息图片最大宽度
let maxH = uni.upx2px(350); //350是定义消息图片最大高度
if (content.w > maxW || content.h > maxH) {
let scale = content.w / content.h;
content.w = scale > 1 ? maxW : maxH * scale;
content.h = scale > 1 ? maxW / scale : maxH;
}
return content;
},
//更多功能(点击+弹出)
showMore() {
this.isVoice = false;
this.hideEmoji = true;
if (this.hideMore) {
this.hideMore = false;
this.openDrawer();
} else {
this.hideDrawer();
}
},
// 打开抽屉
openDrawer() {
this.popupLayerClass = 'showLayer';
},
// 隐藏抽屉
hideDrawer() {
this.popupLayerClass = '';
setTimeout(() => {
this.hideMore = true;
this.hideEmoji = true;
}, 150);
},
// 选择图片发送
chooseImage() {
this.getImage('album');
},
//拍照发送
camera() {
this.getImage('camera');
},
//选照片 or 拍照
getImage(type) {
const self = this;
this.hideDrawer();
uni.chooseImage({
sourceType: [type],
count: 1,
sizeType: ['original', 'compressed'], //可以指定是原图还是压缩图,默认二者都有
success: res => {
for (let i = 0; i < res.tempFilePaths.length; i++) {
uni.getImageInfo({
src: res.tempFilePaths[i],
success: image => {
let msg = { url: res.tempFilePaths[i], w: image.width, h: image.height };
self.updatePic(msg);
}
});
}
}
});
},
updatePic(picUrl) {
const self = this;
uni.showLoading({
title: i18n['加载中'],
mask: true
});
// console.log(self.globalUrl , global.apiUrls.UPLOAD_IMAGE_URL,111111111111)
uni.uploadFile({
url: host + '/api/' + global.apiUrls.UPLOAD_IMAGE_URL,
filePath: picUrl.url,
methods: 'post',
name: 'file',
header: {
'user-token': uni.getStorageSync('USER_TOKEN')
},
success: function(uploadFileRes) {
uni.hideLoading();
if (uploadFileRes.statusCode == 200) {
let resData = JSON.parse(uploadFileRes.data);
if (resData.code == 1) {
picUrl.url = resData.data[0].path;
self.sendMsg(picUrl, '1');
} else {
uni.showToast({
title: resData.msg,
icon: 'none',
mask: true
});
}
}
}
});
},
// 选择表情
chooseEmoji() {
this.hideMore = true;
if (this.hideEmoji) {
this.hideEmoji = false;
this.openDrawer();
} else {
this.hideDrawer();
}
},
//添加表情
addEmoji(em) {
this.textMsg += em;
// this.textMsg += em.alt;
},
//获取焦点如果不是选表情ing,则关闭抽屉
textareaFocus() {
if (this.popupLayerClass == 'showLayer' && this.hideMore == false) {
this.hideDrawer();
}
},
// 发送文字消息
sendText() {
this.hideDrawer(); //隐藏抽屉
if (!this.textMsg) {
return;
}
let content = this.replaceEmoji(this.textMsg);
let msg = { text: content };
this.sendMsg(msg, '0');
this.textMsg = ''; //清空输入框
},
//替换表情符号为图片
replaceEmoji(str) {
let replacedStr = str.replace(/\[([^(\]|\[)]*)\]/g, (item, index) => {
for (let i = 0; i < this.emojiList.length; i++) {
let row = this.emojiList[i];
for (let j = 0; j < row.length; j++) {
let EM = row[j];
if (EM.alt == item) {
//在线表情路径,图文混排必须使用网络路径,请上传一份表情到你的服务器后再替换此路径
//比如你上传服务器后你的100.gif路径为https://www.xxx.com/emoji/100.gif 则替换onlinePath填写为https://www.xxx.com/emoji/
let onlinePath = 'https://s2.ax1x.com/2019/04/12/';
let imgstr = '<img src="' + onlinePath + this.onlineEmoji[EM.url] + '">';
console.log('imgstr: ' + imgstr);
return imgstr;
}
}
}
});
return '<div class="tttt" style="">' + replacedStr + '</div>';
},
// 发送消息
sendMsg(content, type) {
const self = this;
// 消息类型 0 文字 1图片 2 视频 3录音
//实际应用中,此处应该提交长连接,模板仅做本地处理。
var obj = content;
var urls = '';
urls = global.apiUrls.post5f5ee8e86c27b;
var data1 = {};
if(type == 4){
obj.type = 4
data1 = {
toid: 'user-' + self.toUserID,
content: JSON.stringify(obj),
type: type
}
}else{
obj.type = type;
data1 = {
toid: 'user-' + self.toUserID,
content: JSON.stringify(obj),
type: type
}
}
self.$api.post(urls, data1)
.then(res => {
if (res.data.code == 1) {
var data = res.data.data.message;
// this.getMsgList()
let msg = {
user_id: data.uid, //我的ID
type: type,
content: obj,
nickname: data.nickname,
head_img: this.user.avatar,
contents: obj
};
self.$socket.emit('sendmsg', {
uid: 'user-' + self.toUserID,
msg: msg
});
this.showMsg(msg, type);
this.hideKeyboard(); // 隐藏软键盘
this.showHandle = false;
this.showEmji = false;
}
})
.catch(err => {});
},
showMsg(data, type) {
let that = this;
var nowDate = new Date();
let lastid = 0,
content = '';
if (this.msgList.length > 0) {
lastid = Number(this.msgList[this.msgList.length - 1].msgid);
}
console.log('lastid==========', lastid);
lastid++;
content = data.content;
let msg = {
id: lastid,
uid: data.user_id,
username: data.nickname,
avatar: data.head_img,
create_time: nowDate.getHours() + ':' + nowDate.getMinutes(),
type: type ? type : '0',
msg: content,
content: content
};
console.log('mgs===========', msg);
setTimeout(function() {
console.log(1111111111);
if (!that.is_show1) {
that.is_show = true;
that.$nextTick(() => {
that.scrollTop += 9999;
that.scrollAnimation = true;
});
}
}, 1000);
this.screenMsg(msg);
}, // 接受消息(筛选处理)
screenMsg(msg) {
console.log('处理消息', msg);
//从长连接处转发给这个方法,进行筛选处理
if (msg.uid != this.myuid) {
uni.vibrateLong();
}
switch (msg.type) {
case '0':
console.log('添加文字===');
this.addTextMsg(msg);
break;
case '1':
console.log('添加图片');
this.addImgMsg(msg);
break;
case '3':
this.addImgMsg(msg);
break;
}
this.$nextTick(() => {
this.scrollTop += 9999;
this.scrollAnimation = true;
// this.scrollToView = 'msg' + msg.id;
});
// 储存聊天记录
var key = this.kf_id + '-' + this.user.id;
var localMsg = this.getCacheChat(key);
if (localMsg == null || localMsg.length == 0) {
localMsg = [];
}
localMsg.push(msg);
this.setCacheChat({ key: key, data: localMsg });
},
getCacheChat(key) {
return uni.getStorageSync(key);
},
setCacheChat(obj) {
uni.setStorageSync(obj.key, obj.data);
},
// 添加文字消息到列表
addTextMsg(msg) {
this.msgList.push(msg);
},
// 添加语音消息到列表
addVoiceMsg(msg) {
this.msgList.push(msg);
},
// 添加图片消息到列表
addImgMsg(msg) {
console.log('====addImgMsg=======', msg);
msg.content = this.setPicSize(msg.content);
this.msgImgList.push(msg.content);
this.msgList.push(msg);
},
addRedEnvelopeMsg(msg) {
this.msgList.push(msg);
},
// 添加系统文字消息到列表
addSystemTextMsg(msg) {
this.msgList.push(msg);
},
// 预览图片
showPic(msg) {
uni.previewImage({
urls: [msg]
});
// uni.previewImage({
// indicator: 'none',
// current: msg.content.url,
// urls: this.msgImgList
// });
},
// 播放语音
playVoice(msg) {
this.playMsgid = msg.aid;
this.AUDIO.src = msg.content.url;
this.$nextTick(function() {
this.AUDIO.play();
});
},
// 录音开始
voiceBegin(e) {
if (e.touches.length > 1) {
return;
}
this.initPoint.Y = e.touches[0].clientY;
this.initPoint.identifier = e.touches[0].identifier;
this.RECORDER.start({ format: 'mp3' }); //录音开始,
},
//录音开始UI效果
recordBegin(e) {
this.recording = true;
this.voiceTis = '松开 结束';
this.recordLength = 0;
this.recordTimer = setInterval(() => {
this.recordLength++;
}, 1000);
},
// 录音被打断
voiceCancel() {
this.recording = false;
this.voiceTis = '按住 说话';
this.recordTis = '手指上滑 取消发送';
this.willStop = true; //不发送录音
this.RECORDER.stop(); //录音结束
},
// 录音中(判断是否触发上滑取消发送)
voiceIng(e) {
if (!this.recording) {
return;
}
let touche = e.touches[0];
//上滑一个导航栏的高度触发上滑取消发送
if (this.initPoint.Y - touche.clientY >= uni.upx2px(100)) {
this.willStop = true;
this.recordTis = '松开手指 取消发送';
} else {
this.willStop = false;
this.recordTis = '手指上滑 取消发送';
}
},
// 结束录音
voiceEnd(e) {
if (!this.recording) {
return;
}
this.recording = false;
this.voiceTis = '按住 说话';
this.recordTis = '手指上滑 取消发送';
this.RECORDER.stop(); //录音结束
},
//录音结束(回调文件)
recordEnd(e) {
const self = this;
clearInterval(this.recordTimer);
if (!this.willStop) {
console.log('e: ' + JSON.stringify(e));
let msg = {
length: 0,
url: e.tempFilePath
};
let min = parseInt(this.recordLength / 60);
let sec = this.recordLength % 60;
min = min < 10 ? '0' + min : min;
sec = sec < 10 ? '0' + sec : sec;
msg.length = min + ':' + sec;
// {
// "length": "00:03",
// "url": "_doc/uniapp_temp_1671788952633/recorder/1671788965462.mp3"
// }
console.log('录音------------------', msg);
self.updateMp3(msg);
// this.sendMsg(msg, '3');
} else {
console.log('取消发送录音');
}
this.willStop = false;
},
updateMp3(picUrl) {
const self = this;
uni.showLoading({
title: i18n['加载中'],
mask: true
});
var timestamp = new Date().getTime();
let str = 'abcdefghijklmnopqrstuvwxyz9876543210';
let tmp = '',
i = 0,
l = str.length;
for (i = 0; i < 30; i++) {
tmp += str.charAt(Math.floor(Math.random() * l));
}
timestamp = timestamp + tmp;
let uploadTask = uni.uploadFile({
url: self.ossObj.host,
filePath: picUrl.url,
name: 'file',
formData: {
name: timestamp,
key: self.ossObj.key + timestamp,
policy: self.ossObj.policy,
OSSAccessKeyId: self.ossObj.OSSAccessKeyId,
success_action_status: '200', //让服务端返回200,不然默认会返回204
signature: self.ossObj.signature
},
success: res => {
uni.hideLoading();
if (res.statusCode == '200') {
console.log('============', self.ossObj.host + self.ossObj.key + timestamp);
picUrl.url = self.ossObj.host + self.ossObj.key + timestamp;
self.sendMsg(picUrl, '3');
} else {
uni.showToast({
title: '上传失败',
mask: true,
icon: 'none',
duration: 1500
});
}
},
fail: err => {}
});
// {
// "length": "00:03",
// "url": "_doc/uniapp_temp_1671788952633/recorder/1671788965462.mp3"
// }
},
// 切换语音/文字输入
switchVoice() {
this.hideDrawer();
this.isVoice = this.isVoice ? false : true;
},
discard() {
return;
}
}
};
</script>
<style lang="scss" >
@import './HM-chat/css/style.scss';
.imghddd{
width: 140rpx;
height: 120rpx;
}
rich-text {
.imghddd{
width: 140rpx;
height: 120rpx;
}
}
.p2{
width: calc(100% - 180rpx);
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 3;
overflow: hidden;
margin-left: 10rpx;
}
.popup-layer{
top:calc(100% - 20rpx)
}
.popup-layer-list {
width: 100%;
height: 100%;
display: flex;
flex-wrap: wrap;
.popup-layer-list-item {
height: 90rpx;
margin: 0 20rpx 10rpx 0;
width: calc((100% - 60rpx) / 8);
min-width: calc((100% - 60rpx) / 8);
max-width: calc((100% - 60rpx) / 8);
text-align: center;
&:nth-child(8n + 8) {
margin-right: 0;
}
}
}
.page {
width: 100vw;
overflow-x: hidden;
min-height: calc(100vh - var(--window-bottom));
background: #fff;
background-size: 100% auto !important;
background-color: #f6f7f9;
}
.myComments_popup_2 {
background: #fff;
background-size: 100% !important;
box-shadow: 0rpx 4rpx 24rpx rgba(50, 50, 51, 0.12);
border-radius: 8rpx 8rpx 8rpx 8rpx;
width: 142rpx;
height: 65rpx;
background-size: 100% auto !important;
.myComments_positionPopup2_c1_c1 {
color: #1f1f1f;
font-size: 24rpx;
font-weight: 400;
margin: 0rpx 0rpx 0rpx 15rpx;
}
.myComments_positionPopup2_c1_c0 {
width: 28rpx;
height: 28rpx;
}
.myComments_positionPopup2_c1 {
padding: 23rpx 0rpx 22rpx 0rpx;
}
.myComments_positionPopup2_c0_c1 {
color: #1f1f1f;
font-size: 24rpx;
font-weight: 400;
margin: 0rpx 0rpx 0rpx 15rpx;
}
.myComments_positionPopup2_c0_c0 {
width: 28rpx;
height: 28rpx;
}
.myComments_positionPopup2_c0 {
padding: 16rpx 0rpx 19rpx 0rpx;
}
}
.demandDetails_fd0_0_c2_c1 {
height: 48rpx;
width: 48rpx;
}
.demandDetails_flex_0 {
background: #fff;
background-size: 100% !important;
width: 750rpx;
height: 88rpx;
overflow: hidden;
z-index: 10;
top: 0rpx;
background-size: 100% auto !important;
}
.demandDetails_fd0_0_c0_c0 {
font-size: 36rpx;
color: #333;
font-weight: 500;
}
.demandDetails_fd0_0_c0 {
width: 50rpx;
}
.demandDetails_fd0_0 {
padding: 0rpx 32rpx 0rpx 32rpx;
line-height: 88rpx;
}
/deep/ .not_nvue_animation_show {
left: 590rpx !important;
top: 90rpx !important;
}
.names {
max-width: 200px;
font-size: 30rpx;
font-weight: 500;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 1;
word-break: break-all;
word-wrap: break-word;
white-space: normal;
word-break: break-word;
}
.activesss {
padding-bottom: 30rpx;
box-sizing: border-box;
}
</style>