叶子聊天室vue
<template><div class="coust-wx-chart-wrtap"><TopHeader :custom-title="toInfo.realname"><!-- 返回按钮 --><i slot="backBtn" class="iconfont icon-fanhui">...
·
<template>
<div class="coust-wx-chart-wrtap">
<TopHeader :custom-title="toInfo.realname">
<!-- 返回按钮 -->
<i slot="backBtn" class="iconfont icon-fanhui"></i>
</TopHeader>
<div class="hint">
<p>提示:长按对话框中的聊天信息,可翻译成英文</p>
<p>Tip: long press the chat message in the dialog box, which can be translated into English</p>
</div>
<div class="wx-contont" :class="faceShow?'padd-340':(cameraShow?'padd-300':'')" ref="box" id="data-list-content" @click="clickEvent()">
<ul class="w-info-" v-show="charList.length>0">
<div>
<div class="look-more" v-show="isMore">查看更多</div>
<div class="char-info" v-for="(info,key) in charList" :key="key">
<p class="wx-c-timer">{{info.add_time |formatDate}}</p>
<li :class="info.sender==1 ? 'right-info-wrap':'lef-info-wrap'">
<img v-if="info.sender==2" class="-info-icon" :src="toInfo.avatar" />
<img v-if="info.msg_type==2" class="up-img" :src="info.content" @click="showBigPic(info.content)"/>
<span v-else="" class="-info-msg" @touchstart.prevent="touchin(1,key,info.content)">{{info.content}}</span>
<img v-if="info.sender==1" class="-info-icon" :src="from_info.avatar" />
</li>
<div class="tranfrom-msg" :class="info.sender==1 ? 'ri-tranfrom':'lef-tranfrom'" v-if="info.isEnglish"> {{info.english}}</div>
</div>
</div>
</ul>
<ul class="w-info-" v-show="list.length>0">
<div>
<div class="char-info" v-for="(info,key) in list" :key="key">
<p class="wx-c-timer">{{info.add_time |formatDate}}</p>
<li :class="info.sender==1 ? 'right-info-wrap':'lef-info-wrap'">
<img v-if="info.sender==2" class="-info-icon" :src="toInfo.avatar" />
<img v-if="info.say_type==2" class="up-img" :src="info.content" @click="showBigPic(info.content)"/>
<span v-else="" class="-info-msg" @touchstart.prevent="touchin(2,key,info.content)">{{info.content}}</span>
<img v-if="info.sender==1" class="-info-icon" :src="from_info.avatar" />
</li>
<div class="tranfrom-msg" :class="info.sender==1 ? 'ri-tranfrom':'lef-tranfrom'" v-if="info.isEnglish"> {{info.english}}</div>
</div>
</div>
</ul>
</div>
<!-- footer start -->
<div class="footer-wrap">
<div class="foot-box">
<div class="foot-box-input">
<input class="-box-input1" type="text" placeholder="请输入您要表达的内容" v-model="textConent" @focus="getFocus"/>
<div class="icon-wrap">
<span class="icon-cont">
<i class="iconfont icon-jia3" v-show="!cameraShow" @click="showCamera()"></i>
</span>
<span class="icon-cont">
<i class="iconfont icon-xiaolian " v-show="!faceShow" @click="sendMemes()"></i>
<i class="iconfont icon-jianpan" v-show="faceShow" @click="sendMemes()"></i>
</span>
</div>
</div>
<input type="button" class="foot-btn" value="发送" @click="sendMessage()" />
</div>
<div class="camera-wrap info_window" v-show="cameraShow">
<van-uploader multiple :after-read="afterRead"/>
</div>
<!-- 表情包开始 -->
<div class="info_window" v-show="faceShow">
<div class="im_face">
<div class="scene_scroll">
<div class="scene">
<li class="face" v-for="(item,index) in faceList" :key="index" @click="getBrow(index)">{{item}}</li>
</div>
</div>
</div>
</div>
<!-- 表情结束 -->
</div>
<!-- footer end -->
</div>
</template>
<script>
import TopHeader from "@/pages/common/header/TopHeader";
import { ImagePreview } from 'vant';
// 导入JSON格式的表情库
const appData = require("@/assets/emojis.json");
export default {
components:{
TopHeader
},
data(){
return{
timer:'',
list:[], //对话信息
charList:[], //聊天记录
doctorInfo:{},
textConent: "", //存放输入的内容
getBrowString:"", //存放表情
faceList: [], //表情库
fsConent:"",
from_info:{},
toInfo:{},
fileList:[], //图片数组
fileImg:'', //转换后的图片
isMore:false, //查看更多
faceShow:false, //表情包
cameraShow:false, //上传图片
Loop:0 //手指长按
}
},
created(){
this.getDotaInfo()
for (let i in appData) {
this.faceList.push(appData[i].char);
}
},
mounted(){
var userMessag =JSON.parse(localStorage.getItem('userMessage'))
if(userMessag !=null || 'undefined' !=typeof(userMessag)){
this.userInfo=userMessag
}
},
methods:{
showBigPic(img){
ImagePreview([img]);
},
touchin(type,index,msg){
var that=this;
this.Loop = setTimeout(function() {
that.Loop = 0;
msg =that.$commons.removeSpace(msg)
that.$axios.post('doctor/youdao_transLate',{
'word':msg
}).then((res)=>{
var info =res.data
if(res.status==200){
if(type==1){
if(that.charList[index].msg_type==1){
that.$set(that.charList[index],'english',info)
that.$set(that.charList[index],'isEnglish',true)
}
else{
that.$toast("只能翻译文字哦")
}
}else{
if(that.list[index].say_type==1){
that.$set(that.list[index],'english',info)
that.$set(that.list[index],'isEnglish',true)
}
else{
that.$toast("只能翻译文字哦")
}
}
}
})
}, 700);
that.$forceUpdate()
// that.scrollToBottom()
return false;
},
getFocus(){
this.textConent =''
this.faceShow=false
this.cameraShow=false
},
clickEvent(){
this.faceShow=false
this.cameraShow=false
},
showCamera(){
this.textConent =''
this.faceShow =false
this.cameraShow =!this.cameraShow
this.scrollToBottom()
},
afterRead(file){
var that =this
that.fileList=[]
if(/\/(?:jpeg|png)/i.test(file.file.type) && file.file.size > 1500000) {
let canvas = document.createElement('canvas') // 创建Canvas对象(画布)
let context = canvas.getContext('2d')
let img = new Image() // 创建新的图片对象
// 指定图片的DataURL(图片的base64编码数据)
img.src = file.content
img.onload =() =>{
canvas.width =400
canvas.height =300
context.drawImage(img,0,0,400,300)
file.content =canvas.toDataURL(file.file.type,0.92)
that.$axios.post('doctor/create_img',{
token:that.$store.getters.optuser.Authorization,
image:file.content
}).then((res)=>{
that.fileList.push(res.data)
that.wxChart(false,true)
})
}
}else{
that.$axios.post('doctor/create_img',{
token:that.$store.getters.optuser.Authorization,
image:file.content
}).then((res)=>{
// console.log(res.data)
that.fileList.push(res.data)
that.wxChart(false,true)
})
}
},
scrollToBottom () {
this.$nextTick(() => {
setTimeout(() => {
var scrollTop = this.$el.querySelector('.wx-contont')
scrollTop.scrollTop = scrollTop.scrollHeight
}, 13)
})
},
getChart(){
let that=this
that.$axios.post('doctor/load',{
token:that.$store.getters.optuser.Authorization,
toid:that.$route.query.id
}).then((res)=>{
var list = res.data
if(list.status===200){
if(list.data.length>10){
that.isMore =true
}
for(var i in list.data){
if(list.data[i].msg_type==5){
list.data[i].content =that.getEmojis(list.data[i].content)
}
list.data[i].isEnglish=false
list.data[i].english=''
}
that.charList =list.data;
that.scrollToBottom()
}
else if(list.status == 999){
that.$store.commit('del_token'); //清除token;
setTimeout(()=>{
that.$router.push('/Login')
},1000)
}
else{
that.$toast(list.msg)
}
})
},
getEmojis(data){
data =data.split(',')
var cont =''
for(var i in data){
for(var j in this.faceList){
if(j == data[i]){
cont +=this.faceList[j]
}
}
}
return cont
},
getBrow(index) {
for (let i in this.faceList) {
if (index == i) {
this.getBrowString += ','+index
this.fsConent +=this.faceList[index]
this.textConent = this.fsConent
}
}
},
getDotaInfo(){
let that=this
that.$axios.post('doctor/get_userinfo',{
toid:this.$route.query.id,
sender:1,
token:this.$store.getters.optuser.Authorization
}).then((res)=>{
var list = res.data
if(list.status===200){
that.doctorInfo =list.data;
that.from_info =list.data.from_info
that.toInfo =list.data.to_info
that.getChart()
that.wxChart(true)
}
else if(list.status == 999){
that.$store.commit('del_token'); //清除token;
setTimeout(()=>{
that.$router.push('/Login')
},1000)
}
else{
that.$toast(list.msg)
}
})
},
onDivInput($event){
this.inpumsg2 =$event.data
},
sendMessage(){
var that =this
if (this.textConent == "") return that.$toast("请输入内容"); // 清空input数据
this.wxChart(false,false)
},
sendMemes(){
this.textConent =''
this.fsConent=""
this.cameraShow=false
this.faceShow = !this.faceShow;
this.scrollToBottom()
},
wxChart(isFrist,isImg) {
let that = this;
var timer=''
var timer =that.$commons.timeStemp(false,true)
if (window.WebSocket){
var domain='medicine_doctor.zhifengwangluo.com'
let ws =new WebSocket("ws://"+domain+":7272")
ws.onopen = function (e) {
console.log("链接服务器成功");
if(isFrist){ //初始化时执行
var login_data = '{"type":"login","client_name":"'+that.from_info.realname+'","ud_type":"1","ud_id":"'+that.from_info.id+'"}'
}else{
if(isImg){
var login_data = '{"type":"say","say_type":"2","to_client_name":"'+that.from_info.realname+'","content":"'+that.fileList[0].replace(/"/g, '\\"').replace(/\n/g,'\\n').replace(/\r/g, '\\r')+'","ud_type":"1","ud_id":"'+that.from_info.id+'","to_id":"'+that.$route.query.id+'"}';
that.list.push({add_time:timer,sender:1,say_type:2,content:that.fileList[0],isEnglish:false,english:''})
}else{
// var cont =that.textConent
var cont =that.$commons.removeSpace(that.textConent)
var say_type =1
if(that.getBrowString!=""){
cont=that.getBrowString
say_type =5
}
var login_data = '{"type":"say","say_type":"'+say_type+'","to_client_name":"'+that.from_info.realname+'","content":"'+cont.replace(/"/g, '\\"').replace(/\n/g,'\\n').replace(/\r/g, '\\r')+'","ud_type":"1","ud_id":"'+that.from_info.id+'","to_id":"'+that.$route.query.id+'"}';
that.list.push({add_time:timer,sender:1,say_type:say_type,content:cont,isEnglish:false,english:''})
}
}
ws.send(login_data);
that.textConent = ""
that.getBrowString=[]
that.fsConent = ""
that.faceShow = false
that.cameraShow =false
};
ws.onclose = function (e) {
console.log("服务器关闭")
that.$toast("网络出错,服务器关闭")
};
ws.onerror = function () {
console.log("服务器出错")
that.$toast("服务器出错,自动关闭")
};
ws.onmessage = function (e) {
console.log(e)
var info =JSON.parse(e.data)
if(info.type==="ping"){
ws.send('{"type":"pong"}');
return
}
console.log(info)
var cont =info.content
// var say_type =1
if(info.type=="say" && info.to_client_id !=null){
if(info.say_type==5){
cont =that.getEmojis(info.content)
}
that.list =[...that.list, {add_time:timer,sender:2,say_type:info.say_type,content:cont,isEnglish:false,english:''}]
}
}
}
},
closeSendMemes(){
this.faceShow=false
}
},
filters: {
// 日期格式化
formatDate: function (time) {
let date = new Date(time*1000);
let y = date.getFullYear();
let MM = date.getMonth() + 1;
MM = MM < 10 ? ('0' + MM) : MM;
let d = date.getDate();
d = d < 10 ? ('0' + d) : d;
let h = date.getHours();
h = h < 10 ? ('0' + h) : h;
let m = date.getMinutes();
m = m < 10 ? ('0' + m) : m;
let s = date.getSeconds();
s = s < 10 ? ('0' + s) : s;
return y + '-' + MM + '-' + d + ' '+h+':'+m+':'+s;
}
},
watch: {
//监听list,当有修改的时候进行div的屏幕滚动,确保能看到最新的聊天
list: function () {
this.scrollToBottom()
//加setTimeout的原因:由于vue采用虚拟dom,我每次生成新的消息时获取到的div的scrollHeight的值是生成新消息之前的值,所以造成每次都是最新的那条消息被隐藏掉了
}
},
}
</script>
<style scoped lang="stylus">
.coust-wx-chart-wrtap
width 100%
height 100vh
position relative
overflow hidden
.hint
background rgba(255,255,255,0.7)
position absolute
z-index 100
padding 10px
font-size 24px
letter-spacing 2px
box-shadow 0 0 10px #ccc
p
margin-bottom 10px
.wx-contont
width 100%
height 100%
position absolute
left 0
top 0
padding 240px 24px 110px
box-sizing border-box
overflow-y auto
overflow-x hidden
font-size 28px
.look-more
text-align center
color #999
line-height 44px
margin 4px auto
font-size 22px
.char-info
width 100%
overflow hidden
.wx-c-timer
text-align center
font-size 22px
color #777
padding 10px 0
.padd-340
padding-bottom 340px
.padd-300
padding-bottom 300px
.lef-info-wrap,.right-info-wrap
display flex
width 100%
position relative
align-items center
margin-bottom 22px
.-info-icon
width 80px
height 80px
border-radius 50%
object-fit contain
border 2px solid #7981d4
.up-img
width 90px
height 90px
margin 0 26px
border-radius 10px
border 2px solid #ccc
padding 3px
.-info-msg
display block
max-width 70%
margin-left 23px
line-height 50px
background-color #e6e8f7
border-radius 30px 30px 30px 0px
padding 6px 12px
font-size 28px
letter-spacing 2px
display flex
align-items center
.-info-msg /deep/ .icon-sty ,.-info-msg /deep/ .icon-sty
width 40px
height 40px
margin 0 4px
.tranfrom-msg
background #fff
border-radius 6px
margin-bottom 10px
display inline-block
.lef-tranfrom
margin-left 90px
padding 6px 12px
.ri-tranfrom
margin-right 90px
padding 6px 12px
float right
.right-info-wrap
justify-content flex-end
.-info-msg
margin-right 23px
background-color #777ec0
border-radius 30px 30px 0px 30px
color #fff
.footer-wrap
position absolute
bottom 0
left 0
z-index 10
width 100%
.foot-box
background #6771ce
height 88px
display flex
align-items center
justify-content center
.foot-box-input
width 570px
height 50px
background #fff
position relative
border-radius 25px
padding 0 13px
box-sizing border-box
margin-right 22px
.-box-input1
width 490px
height 50px
line-height 50px
.-box-input3
overflow-x auto
overflow-y hidden
outline none
.-box-input3 /deep/ .icon-sty
width 40px
height 40px
margin 0 2px
.icon-wrap
position absolute
right 5px
font-size 42px
top 0
line-height 50px
height 50px
font-size 0
.iconfont
font-size 45px
.foot-btn
width 113px
height 50px
background-color #2b337e
border-radius 25px
text-align center
color #fff
.info_window
// display none
width 100%
text-align center
overflow hidden
height 240px
overflow-y auto
overflow-x hidden
padding-bottom 8px
background #fff
.scene_scroll
width 100%
.scene
display flex
flex-wrap wrap
width 100%
.face
display block
width 70px
height 70px
font-size 45px
img
width 100%
height 100%
.camera-wrap
height 200px
display flex
align-items center
justify-content center
.camera-wrap /deep/ .van-uploader__upload
margin 0
</style>
<style lang="stylus">
.van-image-preview__overlay
background-color: rgba(0,0,0,.6);
.van-image-preview__image
position: absolute
top: 0
right: 0
bottom: 0
left: 0
width: 70%
height: 70%
margin: auto
object-fit: contain
</style>
更多推荐
已为社区贡献5条内容
所有评论(0)