WebSocket私信聊天(无群聊天)

WebSocket私信聊天(无群聊天),第1张

//php 后端  
on('open', function (Swoole\WebSocket\Server $server, $request) {
    //$server->push($request->fd, '欢迎进入我们的聊天室~');
});

//接收客户端发送的信息
//$frame 是 Swoole\WebSocket\Frame 对象,包含了客户端发来的数据帧信息
//$frame->fd 代表客户端的唯一标识 客户id
//$frame->data  代表客户端发送的消息
$server->on('message', function (Swoole\WebSocket\Server $server, $frame) {

    //获取客户端发送的消息
    $type = json_decode($frame->data,true);
    if($type['type'] != 'active'){
        $result['data'] = $frame->data;
        $types = 1;
        $framedata = json_decode($frame->data,true);
        $openid  = $framedata['openid'];
        $endopenid  = $framedata['endopenid'];
        $imgtype  = $framedata['imgtype'];
        $url = 'http://www.xxx.com/';
        $wxapp = '/app/index.php?i=2&t=0&v=1.01&from=wxapp&c=entry&a=wxapp';
        // 会话列表创建会话接口
        $socket_add = '&do=chat_socket_add&m=gc_school&';
        //会话信息查询接口
        $socket_find = '&do=chat_socket_find&m=gc_school&';
        //用户openid 绑定会话 fd 接口
        $user_fid = '&do=chat_user_find&m=gc_school&';
        //存储消息记录
        $socket_log = '&do=socket_log&m=gc_school&';
        //重置fd为0
        $socket_isfd = '&do=socket_isfd&m=gc_school&';
        //查询对方的fd
        $user_endfind = '&do=chat_user_endfind&m=gc_school&';
        //查询用户信息
        $Socket_users = '&do=Socket_users&m=gc_school&';

        //如果不存在会话id 就去创建会话ID

// var_dump( f r a m e − > r e l a t i o n ) ; d i e ; i f ( frame->relation);die; if( frame>relation);die;if(framedata[‘relation’]){
u s e s s = ′ i d s = ′ . usess = 'ids='. usess=ids=.framedata[‘relation’];
//如果存在会话id就去查询会话id的信息
$relation_url = u r l . url. url.wxapp. s o c k e t f i n d . socket_find. socketfind.usess;
r e l a t i o n d a t a = f i l e g e t c o n t e n t s ( relationdata = file_get_contents( relationdata=filegetcontents(relation_url); // 查询会话信息
}else{
u s e s s = ′ o p e n i d = ′ . usess = 'openid='. usess=openid=.openid.‘&endopenid=’.$endopenid;
//拼接创建会话id信息并请求接口
$relation_url = u r l . url. url.wxapp. s o c k e t a d d . socket_add. socketadd.usess;
r e l a t i o n d a t a = f i l e g e t c o n t e n t s ( relationdata = file_get_contents( relationdata=filegetcontents(relation_url); // 建立会话信息
}
j s o n f d = j s o n d e c o d e ( json_fd = json_decode( jsonfd=jsondecode(relationdata,true);
//openid 和 fd 一起查询,以当前的fd为准每次发消息
if($openid){
f d d a t a = ′ r e l a t i o n = ′ . fddata = 'relation='. fddata=relation=.json_fd[‘data’][‘id’].‘&fd=’.KaTeX parse error: Expected 'EOF', got '&' at position 12: frame->fd.'&̲openid='.openid;
$relationurlfd = u r l . url. url.wxapp. u s e r f i d . user_fid. userfid.fddata;
u s e r f d = f i l e g e t c o n t e n t s ( user_fd = file_get_contents( userfd=filegetcontents(relationurlfd); // fd信息
}
//查询对方的fd
if($openid){
e n d f d d a t a = ′ r e l a t i o n = ′ . endfddata = 'relation='. endfddata=relation=.json_fd[‘data’][‘id’].‘&fd=’.KaTeX parse error: Expected 'EOF', got '&' at position 12: frame->fd.'&̲openid='.openid;
$endrelationurlfd = u r l . url. url.wxapp. u s e r e n d f i n d . user_endfind. userendfind.endfddata;
e n d u s e r f d = f i l e g e t c o n t e n t s ( enduser_fd = file_get_contents( enduserfd=filegetcontents(endrelationurlfd); // fd信息
}
e n d r e = j s o n d e c o d e ( endre = json_decode( endre=jsondecode(enduser_fd,true);
// file_get_contents($url);
// file_get_contents();
r e = j s o n d e c o d e ( re = json_decode( re=jsondecode(user_fd,true);
c o n t e n t = j s o n d e c o d e ( content = json_decode( content=jsondecode(frame->data,true);
s o c k e t l o g d a t a = ′ r e l a t i o n = ′ . socket_logdata = 'relation='. socketlogdata=relation=.json_fd[‘data’][‘id’].‘&content=’.KaTeX parse error: Expected 'EOF', got '&' at position 21: …nt['content'].'&̲type='.framedata[‘typess’].‘&openid=’.KaTeX parse error: Expected 'EOF', got '&' at position 9: openid.'&̲endopenid='.endopenid.‘&imgtype=’. i m g t y p e ; / / 添 加 聊 天 记 录 i f ( imgtype; // 添加聊天记录 if( imgtype;//if(type[‘type’] != ‘active’){
$relationurl = u r l . url. url.wxapp. s o c k e t l o g . socket_log. socketlog.socket_logdata;
file_get_contents($relationurl); // fd
}

        //查询用信息
        $fds = 'openid='.$openid;
        $users = $url.$wxapp.$Socket_users.$fds;
        $udata = file_get_contents($users);
        $uc = json_decode($udata,true);

        $content['users'] = $uc['data'];

// r e = j s o n d e c o d e ( re = json_decode( re=jsondecode(result[‘data’],true);
// $re[‘users’] = $content;
r e s u l t [ ′ d a t a ′ ] = j s o n e n c o d e ( result['data'] = json_encode( result[data]=jsonencode(content);
// $result[‘data’][‘users’] = $content;
$data = [
‘msg’ => ‘ *** 作成功’,
‘data’ => $result,
‘fd’ => f r a m e − > f d , ′ e r r o r c o d e ′ = > 0 , ′ t y p e s ′ = > frame->fd, 'error_code' => 0, 'types'=> frame>fd,errorcode=>0,types=>types,
‘imgtype’=>$imgtype,

        ];
        // 检测fd 是否在线
        if ($server->isEstablished($endre['data']['fd'])) {
            $server->push($frame->fd, json_encode($data)); // 推给自己
            $server->push($endre['data']['fd'], json_encode($data)); // 推给对方
        }else{
            $fds = 'ids='.$endre['data']['id'];
            $isfd = $url.$wxapp.$socket_isfd.$fds;
            file_get_contents($isfd); // 推送对方用户不在线重置fd为0
            $server->push($frame->fd, json_encode($data)); // 推给自己
        }
    }else{
        $types = 0;
        $data = [
            'msg' => ' *** 作成功',
            'data' => [],
            'fd' => $frame->fd,
            'error_code' => 0,
            'types'=>$types,
        ];

        $server->push($frame->fd, json_encode($data)); // 定时任务推送自己防止断线

    }

});

$server->on('close', function ($ser, $fd) {
    echo "client {$fd} closed\n";
});

$server->start();

//具体消息接口这些东西需要自行写入目前逻辑仅代表个人观点 每次修改切记运行下php文件(不是访问切记)

宝塔反向代理
upstream websocket{
hash KaTeX parse error: Expected 'EOF', got '}' at position 87: …l_timeout=30s; }̲ server { list… https://$host$1 permanent;
}
server
{
# listen 80;
listen 443 ssl http2;
server_name socket.flyccampus.com;
index index.php index.html index.htm default.php default.htm default.html;
root /www/wwwroot/socket.flyccampus.com;

#SSL-START SSL相关配置,请勿删除或修改下一行带注释的404规则
#error_page 404/404.html;
ssl_certificate    /www/server/panel/vhost/cert/socket.flyccampus.com/fullchain.pem;
ssl_certificate_key    /www/server/panel/vhost/cert/socket.flyccampus.com/privkey.pem;
ssl_protocols TLSv1.1 TLSv1.2 TLSv1.3;
ssl_ciphers EECDH+CHACHA20:EECDH+CHACHA20-draft:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!MD5;
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
add_header Strict-Transport-Security "max-age=31536000";
error_page 497  https://$host$request_uri;

#SSL-END

#ERROR-PAGE-START  错误页配置,可以注释、删除或修改
#error_page 404 /404.html;
#error_page 502 /502.html;
#ERROR-PAGE-END

#PHP-INFO-START  PHP引用配置,可以注释或修改
#清理缓存规则

location / {
if (!-e KaTeX parse error: Expected '}', got '#' at position 26: …lename) { #̲一级目录 rewri… /index.php?s=$1 last;
break;
}
#wss配置
client_max_body_size 100m;
proxy_redirect off;
proxy_set_header Host $host;# http请求的主机域名
proxy_set_header X-Real-IP $remote_addr;# 远程真实IP地址
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;#反向代理之后转发之前的IP地址
proxy_read_timeout 604800s;#websocket心跳时间,默认是60s
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection “Upgrade”;

	proxy_pass http://websocket;#反向代理转发地址
	}

location ~ /purge(/.*) {
    proxy_cache_purge cache_one $host$is_args$args;
    #access_log  /www/wwwlogs/socket.flyccampus.com_purge_cache.log;
}
#引用反向代理规则,注释后配置的反向代理将无效
include /www/server/panel/vhost/nginx/proxy/socket.flyccampus.com/*.conf;

include enable-php-00.conf;
#PHP-INFO-END

#REWRITE-START URL重写规则引用,修改后将导致面板设置的伪静态规则失效
include /www/server/panel/vhost/rewrite/socket.flyccampus.com.conf;
#REWRITE-END

#禁止访问的文件或目录
location ~ ^/(\.user.ini|\.htaccess|\.git|\.svn|\.project|LICENSE|README.md)
{
    return 404;
}

#一键申请SSL证书验证目录相关设置
location ~ \.well-known{
    allow all;
}

access_log  /www/wwwlogs/socket.flyccampus.com.log;
error_log  /www/wwwlogs/socket.flyccampus.com.error.log;

}

//前端代码
utils/config.js
module.exports = {

// 请求域名 格式: https://您的域名
HTTP_REQUEST_URL:‘http://socket.flyccampus.com’,
// Socket链接 暂不做配置
WSS_SERVER_URL:‘wss://xxx.com’,
//JWT token 名称
TOKEN_NAME:‘token’,
//用户注册id 名称
USER_ID:‘uid’,
//用户注册openid 名称
OPEN_ID:‘openid’,
// 以下配置非开发者,无需修改
// 请求头
HEADER:{
‘content-type’: ‘application/json’
},

}
utils/websocket.js

import {WSS_SERVER_URL} from “config.js”

//定时标识
let timing = false

function connect(user, func) {
wx.connectSocket({
url: ${WSS_SERVER_URL}?type=ask&fid=${user.id}&tid=100,
header: { ‘content-type’: ‘application/json’ },
success: function () {
console.log(‘websocket连接成功~’)
},
fail: function () {
console.log(‘websocket连接失败~’)
}
})
wx.onSocketOpen(function (res) {
// wx.showToast({
// title: ‘websocket已开通~’,
// icon: “success”,
// duration: 2000
// })
//接受服务器消息
wx.onSocketMessage(func);//func回调可以拿到服务器返回的数据
});

//启动心跳包
linkWebsocketXin(40000, true)

wx.onSocketError(function (res) {
wx.showToast({
title: ‘websocket连接失败,请检查!’,
icon: “none”,
duration: 1000
})
})
}
//心跳包
function linkWebsocketXin(time, status) {
if (status == true) {
timing = setInterval(function () {
console.log(“当前心跳已重新连接”);
//循环执行代码
wx.sendSocketMessage({
data: JSON.stringify({
type: ‘active’,
}),
fail(res) {
// console.log(res)
}
});
}, time) //循环时间,注意不要超过1分钟
} else {
//关闭定时器
clearInterval(timing);
console.log(“当前心跳已关闭”);
}
}
//发送消息
function send(msg) {
//关闭心跳包定时器
linkWebsocketXin(40000, false)
wx.sendSocketMessage({
data: msg,
success:res=>{
//重启心跳包
linkWebsocketXin(40000, true)
}
});
}
module.exports = {
connect: connect,
send: send,
linkWebsocketXin:linkWebsocketXin
}

utils/util.js

const formatTime = date => {
const year = date.getFullYear()
const month = date.getMonth() + 1
const day = date.getDate()
const hour = date.getHours()
const minute = date.getMinutes()
const second = date.getSeconds()

return ${[year, month, day].map(formatNumber).join('/')} ${[hour, minute, second].map(formatNumber).join(':')}
}

const formatNumber = n => {
n = n.toString()
return n[1] ? n : 0${n}
}

module.exports = {
formatTime
}

/聊天列表
chat.js
const app = getApp()
var websocket = require(‘…/…/…/utils/websocket.js’);
var utils = require(‘…/…/…/utils/util.js’);

import {HTTP_REQUEST_URL, HEADER, USER_ID, OPEN_ID} from “…/…/…/utils/config.js”

Page({
/**

  • 页面的初始数据
    /
    data: {
    newslist: [],
    userInfo: {},
    scrollTop: 0,
    increase: false,//图片添加区域隐藏
    aniStyle: true,//动画效果
    message: “”,
    previewImgList: [],
    relation:0, // 会话id
    openid:‘’,
    endopenid:‘’,
    img:‘’,
    imgtype:0,
    toView:‘msg-0’,
    top:0,
    pages:1,
    moban:‘’
    },
    /
    *

  • 生命周期函数–监听页面加载
    */
    onLoad: function (options) {
    this.getfd()
    this.getmoban()
    this.setData({
    openid: wx.getStorageSync(‘openid’) // 本用户的openid
    })
    if(options.relation){ // 如果有会话id
    this.setData({
    relation: options.relation // 赋值会话id
    })
    this.getlist()
    }
    if(this.data.relation == 0){
    this.setData({
    endopenid: options.openid // 赋值需要聊天人的openid
    })
    this.getrelation()
    }

    var that = this
    if (app.globalData.userInfo) {
    this.setData({
    userInfo: app.globalData.userInfo
    })
    }
    //调通接口
    websocket.connect(this.data.userInfo, function (res) {
    console.log(res,‘—’)
    var list = []
    list = that.data.newslist
    var data = JSON.parse(res.data)
    console.log(data.types,‘datatype----’)
    if(data.types != 0) {
    var datas = JSON.parse(data.data.data)
    console.log(datas.content,‘data----’)
    // list = datas.content
    // } else {
    list.push(datas)
    }
    that.setData({
    newslist: list
    })
    // that.bottom()
    })

},
// 页面卸载
onUnload() {

wx.closeSocket();
// wx.showToast({
//   title: '连接已断开~',
//   icon: "none",
//   duration: 2000
// })

},
onPullDownRefresh(){
console.log(111)
this.getpagedata()
},
getrelation(){
var that = this;
app.util.request({
url: ‘entry/wxapp/socket_users_socket’,
data: {
openid:that.data.openid,
endopenid:that.data.endopenid
},
success(res) {
console.log(res.data.data,‘—lll—’)
if(res.data.errno == 0){
that.setData({
relation: res.data.data.id // 赋值会话id
})
that.getlist()
}

  }
})

},
//加载历史消息
getpagedata(){
var that = this;
app.util.request({
url: ‘entry/wxapp/socket_user_log’,
data: {
openid:that.data.openid,
relation:that.data.relation,
page:that.data.pages
},
success(res) {
console.log(res.data.data,‘—lll—’)
that.setData({
newslist: [
…res.data.data,
…that.data.newslist
],
// newslist:res.data.data,
pages:that.data.pages+=1
})
// setTimeout(()=>{
// that.pageScrollToBottom();
// },500)
}
})
},
getfd(){
let msg = {
type:‘active’,//咨询
openid:this.data.openid,
endopenid:this.data.endopenid,
relation:this.data.relation // 会话id
};
websocket.send(JSON.stringify(msg))
},
//图片上传
choose()
{
wx.chooseImage({
count: 1,
sizeType: [‘original’, ‘compressed’], //可以指定是原图还是压缩图,默认二者都有
sourceType: [‘album’], //从相册选择
success: (res) => {
console.log(‘path’,res)
this.uploads(res)

      }
    })
  },
  uploads(res) {
    var that = this;
    wx.showLoading({
      title: '上传中',
    })
    wx.uploadFile({
      url: app.util.url() + 'c=entry&a=wxapp&do=ImgPost&m=gc_school', // 仅为示例,非真实的接口地址
      filePath: res.tempFilePaths[0],
      header: {
        'content-type': 'application/x-www-form-urlencoded'
      },
      name: 'file',
      success: (result) => {
        wx.hideLoading()
        var resu = JSON.parse(result.data)
        console.log(resu)
        if(resu.errno==0)
        {
          that.setData({
            img:resu.data
          })
          that.setData({
            imgtype:1
          })
          that.send()
        }else{
          wx.showToast({
            title: resu.message,
            icon:'none'
          })
        }
        
      }
    })
  },

getlist(){
var that = this;
app.util.request({
url: ‘entry/wxapp/socket_user_log’,
data: {
openid:that.data.openid,
relation:that.data.relation,
page:that.data.pages
},
success(res) {
console.log(res.data.data,‘—lll—’)
that.setData({
newslist:res.data.data,
pages:2
})
setTimeout(()=>{
that.pageScrollToBottom();
},1000)
}
})
},
//图片预览
preview(e)
{
// this.setData({
// freshen:false
// })
console.log(e.currentTarget.dataset.index,‘—’)
var content = this.data.newslist[e.currentTarget.dataset.index].content;
console.log(content,‘—’)
wx.previewImage({
current:content,
urls: [content],
})
},
//事件处理函数
send: function () {
var flag = this
let uid = wx.getStorageSync(USER_ID)
if(this.data.img.trim() == “” && this.data.imgtype == 1){
wx.showToast({
title: ‘图片不能为空哦~’,
icon: “none”,
duration: 2000
})
return
}

if (this.data.message.trim() == "" && this.data.imgtype == 0) {
  wx.showToast({
    title: '消息不能为空哦~',
    icon: "none",
    duration: 2000
  })
  return 
}

  setTimeout(function () {
    flag.setData({
      increase: false
    })
  }, 1000)
 if(flag.data.imgtype == 1){
  var msg = {
    content:this.data.img,
    date:utils.formatTime(new Date()),
    type:'ask',//咨询
    fid:uid,
    imgtype:1,
    tid:100,
    openid:this.data.openid,
    endopenid:this.data.endopenid,
    relation:this.data.relation // 会话id
};
 }else{
  var msg = {
    content:this.data.message,
    date:utils.formatTime(new Date()),
    type:'ask',//咨询
    fid:uid,
    imgtype:0,
    tid:100,
    openid:this.data.openid,
    endopenid:this.data.endopenid,
    relation:this.data.relation // 会话id
};
 }

  flag.setData({
    imgtype: 0
  })
  websocket.send(JSON.stringify(msg))
  
  /*
  websocket.send('{ "content": "' + this.data.message + '", "date": "' + utils.formatTime(new Date()) + '","type":"text", "nickName": "' + this.data.userInfo.nickName + '", "avatarUrl": "' + this.data.userInfo.avatarUrl + '" }')
  */
 //发完消息值改为空
 this.setData({
  message: '',
})
 setTimeout(()=>{
  flag.pageScrollToBottom();
 },1000)
  // this.bottom()

},
//监听input值的改变
bindChange(res) {
this.setData({
message: res.detail.value
})
},
cleanInput() {
//button会自动清空,所以不能再次清空而是应该给他设置目前的input值
this.setData({
message: this.data.message
})
},
increase() {
this.setData({
increase: true,
aniStyle: true
})
},
//点击空白隐藏message下选框
outbtn() {
this.setData({
increase: false,
aniStyle: true
})
},
//发送图片
chooseImage() {
var that = this
wx.chooseImage({
count: 1, // 默认9
sizeType: [‘original’, ‘compressed’], // 可以指定是原图还是压缩图,默认二者都有
sourceType: [‘album’, ‘camera’], // 可以指定来源是相册还是相机,默认二者都有
success: function (res) {
// 返回选定照片的本地文件路径列表,tempFilePath可以作为img标签的src属性显示图片
var tempFilePaths = res.tempFilePaths
// console.log(tempFilePaths)
wx.uploadFile({
url: ‘wss://www.xxx.cn’, //服务器地址
filePath: tempFilePaths[0],
name: ‘file’,
headers: {
‘Content-Type’: ‘form-data’
},
success: function (res) {
if (res.data) {
that.setData({
increase: false
})
websocket.send(‘{“images”:"’ + res.data + ‘“,“date”:”’ + utils.formatTime(new Date()) + ‘“,“type”:“image”,“nickName”:”’ + that.data.userInfo.nickName + ‘“,“avatarUrl”:”’ + that.data.userInfo.avatarUrl + ‘"}’)
that.bottom()
}
}
})
}
})
},
//图片预览
previewImg(e) {
var that = this
//必须给对应的wxml的image标签设置data-set=“图片路径”,否则接收不到
var res = e.target.dataset.src
var list = this.data.previewImgList //页面的图片集合数组
//判断res在数组中是否存在,不存在则push到数组中, -1表示res不存在
if (list.indexOf(res) == -1) {
this.data.previewImgList.push(res)
}
wx.previewImage({
current: res, // 当前显示图片的http链接
urls: that.data.previewImgList // 需要预览的图片http链接列表
})
},
//聊天消息始终显示最底端
bottom: function () {
this.setData({
message: ‘’,
})
var query = wx.createSelectorQuery()
query.select(‘#flag’).boundingClientRect()
query.selectViewport().scrollOffset()
query.exec(function (res) {
wx.pageScrollTo({
scrollTop: res[0].bottom // #the-id节点的下边界坐标
})
res[1].scrollTop // 显示区域的竖直滚动位置
})
},
pageScrollToBottom: function() {
wx.createSelectorQuery().select(‘#flag’).boundingClientRect(function(rect){
// 使页面滚动到底部
wx.pageScrollTo({
scrollTop: rect.bottom
})
}).exec()
},
getmoban(){
var that = this;
app.util.request({
url: ‘entry/wxapp/template_comment’,
data: {
},
success(res) {
console.log(res.data.data,‘—lll—’)
if(res.data.errno == 0){
that.setData({
moban: res.data.data.template_comment // 赋值会话id
})
that.getlist()
}

  }
})

},
ticing(){

console.log("d出框")
var self = this;
// self.chuo()
				wx.getSetting({
					withSubscriptions:true,
					success (res) {
						console.log("设置",res)
						console.log(res.subscriptionsSetting)
					}
				})
				wx.requestSubscribeMessage({
					tmplIds: [self.data.moban], // 此处可填写多个模板 ID,但低版本微信不兼容只能授权一个
					success (res) {
						self.chuo()
					}
				})

},
chuo(){
var that = this;
app.util.request({
url: ‘entry/wxapp/tsuisong’,
data: {
‘openid’:that.data.openid,
‘relation’:that.data.relation
},
success(res) {
console.log(res.data.data,‘—lll—’)
if(res.data.errno == 0){
that.setData({
moban: res.data.data.template_comment // 赋值会话id
})
that.getlist()
}

  }
})

}
})
chat.json
{
“usingComponents”: {},
“enablePullDownRefresh”: true
}
chat.wxml

返回聊天

{{item.content}} {{item.date}} {{item.content}}
{{item.date}}





发送

chat.wxss
/* pages/socks/socks.wxss */
page {
background-color: #f7f7f7;
height: 100%;
}

/* 聊天内容 /
.news {
padding-top: 30rpx;
text-align: center;
/
height:100%; */
box-sizing: border-box;
}

#flag {
margin-bottom: 100rpx;
height: 30rpx;
}

.chat-notice {
text-align: center;
font-size: 30rpx;
padding: 10rpx 0;
color: #666;
}

.historycon {
height: 100%;
width: 100%;
/* flex-direction: column; */
display: flex;
border-top: 0px;
}

/* 聊天 */
.chat-news {
width: 100%;
overflow: hidden;
}

.chat-news .my_right {
float: right;
/* right: 40rpx; */
padding: 10rpx 10rpx;
}

.chat-news .name {
margin-right: 10rpx;
}

.chat-news .you_left {
float: left;
/* left: 5rpx; */
padding: 10rpx 10rpx;
}

.selectImg {
display: inline-block;
width: 150rpx;
height: 150rpx;
margin-left: 50rpx;
}

.my_right .selectImg {
margin-right: 80rpx;
}

.new_img {
width: 60rpx;
height: 60rpx;
border-radius: 50%;
vertical-align: middle;
margin-right: 10rpx;
}

.new_txt {
max-width: 300rpx;
display: inline-block;
border-radius: 6rpx;
line-height: 60rpx;
background-color: #95d4ff;
padding: 5rpx 20rpx;
margin: 0 10rpx;
margin-left: 50rpx;
}

.my_right .new_txt {
margin-right: 60rpx;
}

.you {
background-color: lightgreen;
}

.my {
border-color: transparent transparent transparent #95d4ff;
}

.you {
border-color: transparent #95d4ff transparent transparent;
}

.hei {
margin-top: 50px;
height: 20rpx;
}

.history {
height: 100%;
margin-top: 15px;
padding: 10rpx;
font-size: 14px;
line-height: 40px;
word-break: break-all;
}

::-webkit-scrollbar {
width: 0;
height: 0;
color: transparent;
z-index: -1;
}

/* 信息输入区域 */
.message {
position: fixed;
bottom: 0;
width: 100%;
}

.sendMessage {

height: 80rpx;
padding: 10rpx 10rpx;
background-color: #fff;
border-top: 2rpx solid #eee;
border-bottom: 2rpx solid #eee;
/z-index: 3;/
}

.sendMessage input {
float: left;
height: 42px;
line-height: 100%;
border-bottom: 1rpx solid #ccc;
padding: 0 10rpx;
font-size: 35rpx;
color: #666;
}

.sendMessage button {
float: right;
font-size: 35rpx;
}

.sendMessage view {
display: inline-block;
width: 80rpx;
height: 80rpx;
line-height: 80rpx;
font-size: 60rpx;
text-align: center;
color: #999;
border: 1rpx solid #ccc;
border-radius: 50%;
margin-left: 10rpx;
}

.increased {
width: 100%;
/* height: 150rpx; */
padding: 40rpx 30rpx;
background-color: #fff;
}

.increased .image {
width: 100rpx;
height: 100rpx;
border: 3rpx solid #ccc;
line-height: 100rpx;
text-align: center;
border-radius: 8rpx;
font-size: 35rpx;
}

@keyframes slidedown {
from {
transform: translateY(0);
}

to {
transform: translateY(100%);
}
}

.slidedown {
animation: slidedown 0.5s linear;
}

.slideup {
animation: slideup 0.5s linear;
}

@keyframes slideup {
from {
transform: translateY(100%);
}

to {
transform: translateY(0);
}
}

前端采用colorui样式插件
完成示例图

///注意会话列表是自己写的

有啥问题加我微信或者QQ1446891130 看到有空给你说一下

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/langs/791715.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-05
下一篇 2022-05-05

发表评论

登录后才能评论

评论列表(0条)

保存