位置: IT常识 - 正文

【移动端聊天功能模板】Vue实现H5聊天系统,实现上下固定中间滚动布局,微信授权功能,自动滚动到底部【详细注释,一看就会】(移动有聊天室平台吗)

编辑:rootadmin
【移动端聊天功能模板】Vue实现H5聊天系统,实现上下固定中间滚动布局,微信授权功能,自动滚动到底部【详细注释,一看就会】 前言

推荐整理分享【移动端聊天功能模板】Vue实现H5聊天系统,实现上下固定中间滚动布局,微信授权功能,自动滚动到底部【详细注释,一看就会】(移动有聊天室平台吗),希望有所帮助,仅作参考,欢迎阅读内容。

文章相关热门搜索词:移动有聊天室平台吗,移动有个聊天软件叫什么,移动端设备 找聊天记录,移动端设备 找聊天记录,移动即时聊天,移动即时聊天,移动即时聊天,移动聊天工具,内容如对您有帮助,希望把文章链接给更多的朋友!

最近刚好在做这方面的功能,就网上看了下,发现很多种写法,但是有些写的很乱, 我也看的很麻烦,干脆就自己写一个简单的静态版本放在这, 以后需要用到的时候可以直接拿着改改就能用。 后面我还会继续更新有交互逻辑的模拟聊天室, 包括pc端的聊天室也会写,这里就先从移动端的微信聊天窗口开始。

pc版本的也有了

我也写了个pc版本的聊天功能模板,包含websocket功能,需要的点击下面跳转或者直接去我主页查看 点击这里 跳转PC端聊天功能模板

小程序版本也有了【移动端聊天功能模板】Vue实现H5聊天系统,实现上下固定中间滚动布局,微信授权功能,自动滚动到底部【详细注释,一看就会】(移动有聊天室平台吗)

小程序版本搭配websocket写法发布了 点击这里

效果图

1,这个是聊天窗的大体样式布局,我们通过flex布局让他分左右 其实思路也简单,就是后期后端返回的数据中有一个字段是左右, 后端判断是你自己的信息就右边,别人发的信息就左边。 我们拿到字段调用对应不同的样式就行了。 2,这里是输入框,当他输入到超过一定高度的时候就会出现滚动条。 这里可以调整,是vant的组件。

注意事项

因为我这里用了百分比的高度。这样可以自适应好一点。 但有可能会出现一个问题,就是你使用这个代码,发现高度不对。 那你需要看一下你的html和body有没有设置高百分百,不然这里无法继承到。 如何设置呢,就是直接去app.vue页面,然后这样,把html,body和#app都设置一下百分百高度就可以了

<style>* { padding: 0; margin: 0;}html,body,#app { height: 100%; width: 100%;}</style>

这里用了一些vant框架的组件,所以如果没有下载的安装一下vant就可以了 这是vue2版本的,如果想要vue3的自己去官网下载安装

npm i vant@latest-v2 -S

然后main.js引入

import Vue from 'vue';import Vant from 'vant';import 'vant/lib/index.css';Vue.use(Vant);代码部分(目前静态页面)<template> <div class="wrap"> <div class="title"> <div> <van-icon name="arrow-left" size="20" style="margin-left: 10px" @click="onClickLeft" /> </div> <div>{{ userName }}</div> <div> <van-icon name="ellipsis" size="22" style="margin-right: 10px" @click="onClickRight" /> </div> </div> <div class="content_box" id="box" ref="scrollBox"> <div class="timer">2022-08-02 11:08:07</div> <div :class="item.position == 'left' ? 'userbox2' : 'userbox'" v-for="(item, index) in chatList" :key="index" > <div :class="item.position == 'left' ? 'nameInfo2' : 'nameInfo'"> <div style="font-size: 14px">{{ item.username }}</div> <div :class="item.position == 'left' ? 'contentText2' : 'contentText'" > {{ item.content }} </div> </div> <div> <van-image round width="50px" height="50px" :src="item.url" /> </div> </div> </div> <div class="bottom"> <van-field v-model="inputValue" center type="textarea" :autosize="{ maxHeight: 100, minHeight: 25 }" placeholder="请输入内容" rows="1" > <template #button> <van-button size="small" type="primary" @click="sendOut">发送</van-button> </template> </van-field> </div> </div></template><script>export default { data() { return { //聊天数据 chatList: [ { url: "https://www.yuucn.com/wp-content/uploads/2023/05/1683878137-cd3745170198b3f.jpeg", username: "张三", content: "模拟数据123模拟数据123模拟数据123模拟数据123", position: "left", }, { url: "https://www.yuucn.com/wp-content/uploads/2023/05/1683878144-cd3745170198b3f.jpeg", username: "李四", content: "模拟数据123模拟数据123模拟数据123模拟数据123模拟数据123", position: "right", }, { url: "https://www.yuucn.com/wp-content/uploads/2023/05/1683878137-cd3745170198b3f.jpeg", username: "张三", content: "模拟数据123", position: "left", }, { url: "https://www.yuucn.com/wp-content/uploads/2023/05/1683878144-cd3745170198b3f.jpeg", username: "李四", content: "模拟数据123模拟数据", position: "right", }, { url: "https://www.yuucn.com/wp-content/uploads/2023/05/1683878137-cd3745170198b3f.jpeg", username: "张三", content: "模拟数据123", position: "left", }, { url: "https://www.yuucn.com/wp-content/uploads/2023/05/1683878144-cd3745170198b3f.jpeg", username: "李四", content: "模拟数据123模拟数据", position: "right", }, { url: "https://www.yuucn.com/wp-content/uploads/2023/05/1683878137-cd3745170198b3f.jpeg", username: "张三", content: "模拟数据123", position: "left", }, { url: "https://www.yuucn.com/wp-content/uploads/2023/05/1683878144-cd3745170198b3f.jpeg", username: "李四", content: "模拟数据123模拟数据", position: "right", }, { url: "https://www.yuucn.com/wp-content/uploads/2023/05/1683878137-cd3745170198b3f.jpeg", username: "张三", content: "模拟数据123", position: "left", }, { url: "https://www.yuucn.com/wp-content/uploads/2023/05/1683878144-cd3745170198b3f.jpeg", username: "李四", content: "模拟数据123模拟数据", position: "right", }, { url: "https://www.yuucn.com/wp-content/uploads/2023/05/1683878137-cd3745170198b3f.jpeg", username: "张三", content: "模拟数据123", position: "left", }, { url: "https://www.yuucn.com/wp-content/uploads/2023/05/1683878144-cd3745170198b3f.jpeg", username: "李四", content: "模拟数据123模拟数据", position: "right", }, { url: "https://www.yuucn.com/wp-content/uploads/2023/05/1683878137-cd3745170198b3f.jpeg", username: "张三", content: "模拟数据123", position: "left", }, { url: "https://www.yuucn.com/wp-content/uploads/2023/05/1683878144-cd3745170198b3f.jpeg", username: "李四", content: "模拟数据123模拟数据", position: "right", }, ], //用户名 userName: "张三", //输入内容 inputValue: "", //滚动条距离顶部距离 scrollTop:0 }; }, mounted(){ this.setPageScrollTo() //创建监听内容部分滚动条滚动 this.$refs.scrollBox.addEventListener('scroll',this.srTop) }, methods: { //返回 onClickLeft() { console.log("返回"); }, //更多 onClickRight() { console.log("按钮"); }, //滚动条默认滚动到最底部 setPageScrollTo(s, c) { //获取中间内容盒子的可见区域高度 this.scrollTop = document.querySelector("#box").offsetHeight; setTimeout((res) => { //加个定时器,防止上面高度没获取到,再获取一遍。 if (this.scrollTop != this.$refs.scrollBox.offsetHeight) { this.scrollTop = document.querySelector("#box").offsetHeight; } }, 100); //scrollTop:滚动条距离顶部的距离。 //把上面获取到的高度座位距离,把滚动条顶到最底部 this.$refs.scrollBox.scrollTop = this.scrollTop; }, //滚动条到达顶部 srTop(){ //判断:当滚动条距离顶部为0时代表滚动到顶部了 if(this.$refs.scrollBox.scrollTop==0){ //逻辑简介: //到顶部后请求后端的方法,获取第二页的聊天记录,然后插入到现在的聊天数据前面。 //如何插入前面:可以先把获取的数据保存在 A 变量内,然后 this.chatList=A.concat(this.chatList)把数组合并进来就可以了 //拿聊天记录逻辑: //第一次调用一个请求拉历史聊天记录,发请求时参数带上页数 1 传过去,拿到的就是第一页的聊天记录,比如一次拿20条。你显示出来 //然后向上滚动到顶部时,触发新的请求,在请求中把分页数先 +1 然后再请求,这就拿到了第二页数据,然后通过concat合并数组插入进前面,依次类推,功能完成! console.log('到顶了,滚动条位置 :',this.$refs.scrollBox.scrollTop); } }, sendOut(){ console.log('发送成功'); } },};</script><style scoped>.wrap { height: 100%; width: 100%; position: relative;}.title { height: 40px; width: 100%; background-color: #eaeaea; display: flex; justify-content: space-between; align-items: center;}.bottom { min-height: 50px; width: 100%; border-top: 1px solid #eaeaea; position: fixed; bottom: 0;}.content_box { /* 中间栏计算高度,110是包含了上下固定的两个元素高度90 这里padding:10px造成的上下够加了10,把盒子撑大了,所以一共是20要减掉 然后不知道是边框还是组件的原因,导致多出了一些,这里再减去5px刚好。不然会出现滚动条到顶或者底部的时候再滚动的话就会报一个错,或者出现滚动条变长一下的bug */ height: calc(100% - 115px); overflow: auto; padding: 10px;}.timer { text-align: center; color: #c2c2c2;}/* 发送的信息样式 *//* 右边消息思路解释:首先大盒子userbox内放两个盒子,一个放头像,一个放用户名和发送的内容,我们先用flex让他横向排列。然后把写文字的大盒子设置flex:1。这个属性的意思就是让这个元素撑满父盒子剩余位置。然后我们再把文字盒子设置flex,并把他对齐方式设置为尾部对齐就完成了基本的结构,然后微调一下就可以了*/.userbox { width: 100%; display: flex; margin-bottom: 10px;}.nameInfo { /* 用flex:1把盒子撑开 */ flex: 1; margin-right: 10px; /* 用align-items把元素靠右对齐 */ display: flex; flex-direction: column; align-items: flex-end;}.contentText { background-color: #9eea6a; /* 把内容部分改为行内块元素,因为盒子flex:1把盒子撑大了,所以用行内块元素让内容宽度不根据父盒子来 */ display: inline-block; /* 这四句是圆角 */ border-top-left-radius: 10px; border-top-right-radius: 0px; border-bottom-right-radius: 10px; border-bottom-left-radius: 10px; /* 最大宽度限定内容输入到百分61换行 */ max-width: 61%; padding: 5px 10px; /* 忽略多余的空白,只保留一个空白 */ white-space: normal; /* 换行显示全部字符 */ word-break: break-all; margin-top: 3px; font-size: 14px;}/* 接收的信息样式 *//* 左边消息思路解释:跟上面一样,就是换一下位置,首先通过把最外层大盒子的排列方式通过flex-direction: row-reverse;属性翻转,也就是头像和文字盒子换位置然后删除掉尾部对齐方式,因为不写这个默认是左对齐的。我们写的左边就没必要再写了。*/.userbox2 { width: 100%; display: flex; flex-direction: row-reverse; margin-bottom: 10px;}.nameInfo2 { /* 用flex:1把盒子撑开 */ flex: 1; margin-left: 10px;}.contentText2 { background-color: #9eea6a; /* 把内容部分改为行内块元素,因为盒子flex:1把盒子撑大了,所以用行内块元素让内容宽度不根据父盒子来 */ display: inline-block; /* 这四句是圆角 */ border-top-left-radius: 0px; border-top-right-radius: 10px; border-bottom-right-radius: 10px; border-bottom-left-radius: 10px; /* 最大宽度限定内容输入到百分61换行 */ max-width: 61%; padding: 5px 10px; /* 忽略多余的空白,只保留一个空白 */ white-space: normal; /* 换行显示全部字符 */ word-break: break-all; margin-top: 3px; font-size: 14px;}</style>

到这里静态页面结束

H5实战项目版本,更新2022-11-8

这里注意点: 1,v-cloak防止页面闪烁的 2,滚动条方法要用nextTick不能用定时器,不然会页面闪烁 3,微信授权方法,记得改appid,redirect_uri,state。具体不会的可以看我另一个帖子,微信登录授权。

<!DOCTYPE html><html><head> <meta charset='UTF-8'> <meta name="viewport" content="width=device-width,initial-scale=1.0"> <meta name="viewport" content="maximum-scale=1.0,minimum-scale=1.0,user-scalable=0,width=device-width,initial-scale=1.0" /> <meta name="format-detection" content="telephone=no,email=no,date=no,address=no"> <meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no" /> <!-- vue --> <script src="/statics/vue_element/vue.js"></script> <script src="/statics/vue_element/element.js"></script> <script src="/statics/vue_element/axios.js"></script> <!-- 滚动 --> <link rel="stylesheet" href="/statics/vue_element/new.css"> <link rel="stylesheet" href="/statics/vue_element/index.css"> <link rel="stylesheet" href="/statics/vue_element/element.css"> <title>在线咨询</title></head><body> <div id="app"> <div class="wrap" v-cloak> <div class="content_box" id="box" ref="scrollBox"> <div class="timer">{{add_time}}</div> <div :class="item.uid == wechatInfo.tag_uid ? 'userbox' : 'userbox2'" v-for="(item, index) in chatList" :key="index" :id='"item"+index'> <div :class="item.uid == wechatInfo.tag_uid ? 'nameInfo' : 'nameInfo2'"> <!-- <div style="font-size: 14px">{{ item.nickname }}</div> --> <div :class="item.uid == wechatInfo.tag_uid ? 'contentText' : 'contentText2'"> {{ item.msn }} </div> <div style="display: inline-block;" v-show="item.uid == wechatInfo.tag_uid&&chatShow==item.chatShow"> <i class="el-icon-loading" v-show="jzshow==1"></i> <i class="el-icon-warning" style="color:red" v-show="jzshow==2" @click="resend(item.msn)"></i> </div> </div> <div> <image class="touxiang" :src="item.avatar" /> </div> </div> </div> <div class="bottom"> <textarea name="输入框" id="1" cols="20" rows="5" class="areaBox" v-model="inputValue"></textarea> <button class="fasong" @click="sendOut">发送</button> </div> </div> </div></body><script> new Vue({ el: '#app', data() { return { page: 1, //聊天历史记录分页 chatList: [], //聊天信息 userName: "", //用户名 inputValue: "", //输入内容 scrollTop: 0, //滚动条距离顶部距离 infoList: null, //用户信息 kfInfo: [], //客服信息 wechatInfo: '', //双方用户信息 add_time: '', jzshow: 0, //加载图标icon jzshowtimer: null, //加载图标定时器 chatShow: 2, //加载图标显示 path: "wss://test.123456.com/msg", //websocket链接地址(这里地址都是乱写的,自行修改) ws: null, //建立的连接 lockReconnect: false, //是否真正建立连接 timeout: 10 * 1000, //30秒一次心跳 timeoutObj: null, //心跳心跳倒计时 serverTimeoutObj: null, //心跳倒计时 timeoutnum: null, //断开 重连倒计时 closeType: 1, //断开判断:0代表不重连,1代表重连 }; }, created() { this.closeType = 1 //进入改为1,代表如果断开链接自动重连 let type = sessionStorage.getItem('wechatInfo') //本地如果有值就获取,没有值就微信授权后获取 if (type && type !== 'undefined') { this.wechatInfo = JSON.parse(sessionStorage.getItem('wechatInfo')) //双方用户信息 console.log('用户信息', this.wechatInfo); this.initWebpack(); //ws链接 this.getList() //客服列表 } else { this.oAuth() //微信授权 } }, mounted() { this.$refs.scrollBox.removeEventListener("scroll", this.srTop); }, methods: { //H5授权 oAuth() { // snsapi_userinfo (授权页面) location.href = `https://open.weixin.qq.com/connect/oauth2/authorize?appid=wx3cbfddebd1123021&redirect_uri=https://test.123456.com/model/chat/loading.html&response_type=code&scope=snsapi_userinfo&state=wx3cbfddebd1123021#wechat_redirect`; }, // 初始化websocket链接 initWebpack() { if (typeof WebSocket === "undefined") { alert("您的浏览器不支持socket"); } else { this.ws = new WebSocket(this.path); //实例 this.ws.onopen = this.onopen; //监听链接成功 this.ws.onmessage = this.onmessage; //监听后台返回消息 this.ws.onclose = this.onclose; //监听链接关闭 this.ws.onerror = this.onerror; //监听链接异常 } }, //重新连接 reconnect() { var that = this; //防止重复链接 if (that.lockReconnect) { return; } that.lockReconnect = true; //没连接上会一直重连,设置延迟避免请求过多 that.timeoutnum && clearTimeout(that.timeoutnum); that.timeoutnum = setTimeout(function () { that.initWebpack(); //新连接 that.lockReconnect = false; }, 5000); }, //重置心跳 reset() { var that = this; clearTimeout(that.timeoutObj); //清除心跳倒计时 clearTimeout(that.serverTimeoutObj); //清除超时关闭倒计时 that.start(); //重启心跳 }, //开启心跳 start() { var self = this; self.timeoutObj && clearTimeout(self.timeoutObj); //心跳倒计时如果有值就清除掉,防止重复 self.serverTimeoutObj && clearTimeout(self.serverTimeoutObj); //超时关闭倒计时如果有值就清除掉,防止重复 self.timeoutObj = setTimeout(function () { if (self.ws.readyState == 1) { self.ws.send(JSON.stringify({ type: "ping" })); } else { self.reconnect(); } //如果超时了就关闭连接 self.serverTimeoutObj = setTimeout(function () { self.ws.close(); }, self.timeout); }, self.timeout); }, //连接成功 onopen() { let that = this console.log("连接成功"); if (that.ws.readyState == 1) { that.ws.send(JSON.stringify({ //发送消息到后台,和send一样,这是微信的写法 type: "login", data: { token: this.wechatInfo.token, id: this.wechatInfo.id, channel_type: 'wechat', uid: this.wechatInfo.uid, openid: this.wechatInfo.openid } })) that.ws.send(JSON.stringify({ type: "online", data: { online: 1, user_type: 'user', is_tourist: this.wechatInfo.uid ? 0 : 1 } })) } this.start(); //链接成功后开启心跳 }, //接受后台信息回调 onmessage(res) { let type = JSON.parse(res.data) //后台返回消息,通过type字段判断是不是别人发送给我的消息 if (type.type == 'chat') { clearTimeout(this.jzshowtimer); this.chatShow = 1 //this.chatList.push(type.data) //把消息添加到信息列表渲染 this.jzshow = 0 //隐藏加载icon this.$nextTick(() => { // 一定要用nextTick this.setPageScrollTo(); //页面滚动条距离顶部高度等于这个盒子的高度 this.$refs.scrollBox.scrollTop = this.$refs.scrollBox.scrollHeight; }) console.log("收到后台信息:", JSON.parse(res.data)); } else if (type.type == 'reply') { this.chatList.push(type.data) } this.reset(); //收到服务器信息,心跳重置 }, //关闭连接回调 onclose(e) { console.log("连接关闭"); //断开链接时判断 if (this.closeType == 0) { return } this.reconnect(); //重连 }, //连接异常回调 onerror(e) { console.log("出现错误"); this.reconnect(); //重连 }, // 重新发送 resend(msn) { this.inputValue = msn this.jzshow = 1 let parms = { msn: this.inputValue, to_uid: this.kfInfo[0].kf_id, type: 1, form_type: 'wechat', is_tourist: 0 } //通过websocket发送信息到后台 this.ws.send(JSON.stringify({ type: "chat", data: parms })) this.jzshowtimer = setTimeout((res) => { this.jzshow = 2 }, 3000); this.inputValue = '' //点击发送后清空输入框 }, //客服列表信息 getList() { axios.post('/gzh/crmebchat/chatUserList', { type: 'user', tag_uid: this.wechatInfo.tag_uid || 0, wechat_user_id: this.wechatInfo.id || 0, avatar: this.wechatInfo.headimgurl, nickname: this.wechatInfo.nickname }).then(res => { // console.log('客服信息:', res); this.kfInfo = res.data.data //客服信息 this.ws.send(JSON.stringify({ type: "to_chat", data: { id: this.kfInfo } })); this.getlishiList() }).catch(error => { console.log(error, '请求失败'); }) }, //获取历史记录 getlishiList(type) { axios.post('/gzh/crmebchat/chatMessageList', { to_uid: this.kfInfo, uid: this.wechatInfo.tag_uid, page: this.page, limit: 10, }).then(res => { // console.log('历史记录:', res); this.add_time = res.data.data[0]._add_time || '-' let a = res.data.data this.chatList = a.concat(this.chatList) //用拿到的数据合并现有的数据,这样当加载第二页历史记录时,顺序不会乱 if (type == 1) { //滚动到顶部触发方法会传入1,此时不需要调用滚动到最底部的方法 return } this.$nextTick(() => { // 一定要用nextTick this.setPageScrollTo(); //页面滚动条距离顶部高度等于这个盒子的高度 this.$refs.scrollBox.scrollTop = this.$refs.scrollBox.scrollHeight; }) }).catch(error => { console.log(error, '请求失败'); }) }, //发送 sendOut() { this.chatList.push({ msn: this.inputValue, uid: this.wechatInfo.tag_uid, avatar: this.wechatInfo.headimgurl, nickname: this.wechatInfo.nickname, chatShow: 2 }) this.jzshow = 1 let parms = { msn: this.inputValue, to_uid: this.kfInfo, type: 1, form_type: 'wechat', is_tourist: 0 } //通过websocket发送信息到后台 this.ws.send(JSON.stringify({ type: "chat", data: parms })) this.jzshowtimer = setTimeout((res) => { this.jzshow = 2 }, 3000); this.inputValue = '' //点击发送后清空输入框 console.log('发送成功', this.inputValue); // 页面滚动到底部 this.$nextTick(() => { // 一定要用nextTick this.setPageScrollTo(); //页面滚动条距离顶部高度等于这个盒子的高度 this.$refs.scrollBox.scrollTop = this.$refs.scrollBox.scrollHeight; }) }, //滚动条默认滚动到最底部 setPageScrollTo(s, c) { //获取中间内容盒子的可见区域高度 this.scrollTop = document.querySelector("#box").offsetHeight; setTimeout((res) => { //加个定时器,防止上面高度没获取到,再获取一遍。 if (this.scrollTop != this.$refs.scrollBox.offsetHeight) { this.scrollTop = document.querySelector("#box").offsetHeight; } }, 100); console.log('滚动', this.scrollTop); //scrollTop:滚动条距离顶部的距离。 //把上面获取到的高度座位距离,把滚动条顶到最底部 this.$refs.scrollBox.scrollTop = this.scrollTop; //判断是否有滚动条,有滚动条就创建一个监听滚动事件,滚动到顶部触发srTop方法 if (this.$refs.scrollBox.scrollTop > 0) { this.$refs.scrollBox.addEventListener("scroll", this.srTop); } }, //滚动条到达顶部 srTop() { //判断:当滚动条距离顶部为0时代表滚动到顶部了 if (this.$refs.scrollBox.scrollTop == 0) { this.page++ this.getlishiList(1) } } }, })</script><style scoped> * { margin: 0; padding: 0; } /* 防止闪烁 */ [v-cloak] { display: none; } .wrap { height: 100%; width: 100%; position: relative; } .touxiang { width: 50px; height: 50px; border-radius: 50%; } .areaBox { height: 30px; width: 80%; border: none; resize: none; outline: none; padding: 5px; } .title { height: 40px; width: 100%; background-color: #eaeaea; display: flex; justify-content: center; align-items: center; } .bottom { min-height: 40px; width: 100%; border-top: 1px solid #eaeaea; background-color: #F1F1F1; position: fixed; bottom: 0; display: flex; justify-content: space-between; align-items: center; padding: 0 5px; border-radius: 10px; } .fasong { height: 30px; padding: 2px 7px; border-radius: 5px; text-align: center; color: #58df4d; background-color: #eaeaea; font-size: 14px; line-height: 30px; border: none; resize: none; outline: none; margin-right: 15px; } .content_box { height: calc(100% - 95px); overflow: auto; padding: 10px 10px 20px 10px; } .timer { text-align: center; color: #c2c2c2; } .userbox { width: 100%; display: flex; margin-bottom: 10px; } .nameInfo { /* 用flex:1把盒子撑开 */ flex: 1; margin-right: 10px; /* 用align-items把元素靠右对齐 */ display: flex; align-items: baseline; flex-direction: row-reverse; } .contentText { background-color: #9eea6a; display: inline-block; /* 这四句是圆角 */ border-top-left-radius: 10px; border-top-right-radius: 0px; border-bottom-right-radius: 10px; border-bottom-left-radius: 10px; /* 最大宽度限定内容输入到百分61换行 */ max-width: 61%; padding: 5px 10px; /* 忽略多余的空白,只保留一个空白 */ white-space: normal; /* 换行显示全部字符 */ word-break: break-all; margin-top: 3px; font-size: 14px; margin-left: 10px; margin-top: 15px; } .userbox2 { width: 100%; display: flex; flex-direction: row-reverse; margin-bottom: 10px; } .nameInfo2 { /* 用flex:1把盒子撑开 */ flex: 1; margin-left: 10px; } .contentText2 { background-color: #9eea6a; display: inline-block; /* 这四句是圆角 */ border-top-left-radius: 0px; border-top-right-radius: 10px; border-bottom-right-radius: 10px; border-bottom-left-radius: 10px; /* 最大宽度限定内容输入到百分61换行 */ max-width: 61%; padding: 5px 10px; /* 忽略多余的空白,只保留一个空白 */ white-space: normal; /* 换行显示全部字符 */ word-break: break-all; margin-top: 3px; font-size: 14px; margin-right: 10px; margin-top: 15px; }</style></html>
本文链接地址:https://www.jiuchutong.com/zhishi/282785.html 转载请保留说明!

上一篇:DVDRegionFree.exe进程是安全程序吗 DVDRegionFree进程查询(dvd.rom)

下一篇:win10待机设置(win10设置待机时间长怎么在哪里设置)

  • 小米1s和小米1s青春版(小米1s和青春版的区别)(小米1s和小米pro哪个好)

    小米1s和小米1s青春版(小米1s和青春版的区别)(小米1s和小米pro哪个好)

  • 华为手机悬浮球怎么关(华为手机悬浮球怎么关闭)

    华为手机悬浮球怎么关(华为手机悬浮球怎么关闭)

  • 监控的初始密码一般是多少(监控的初始密码一般是什么)

    监控的初始密码一般是多少(监控的初始密码一般是什么)

  • 第一次充电没充满有影响吗(第一次充电没充满第二天再充可以吗)

    第一次充电没充满有影响吗(第一次充电没充满第二天再充可以吗)

  • designedforaseries是什么手机(DESIGNEDFORASERIES是oppo哪一款产品)

    designedforaseries是什么手机(DESIGNEDFORASERIES是oppo哪一款产品)

  • 三星A60开不了机(三星a60开不了机怎么回事)

    三星A60开不了机(三星a60开不了机怎么回事)

  • 为什么蓝牙耳机不能k歌(为什么蓝牙耳机连不上手机)

    为什么蓝牙耳机不能k歌(为什么蓝牙耳机连不上手机)

  • 拼多多违规关店保证金和货款能退回来吗(拼多多违规关店,什么时候可以再开店)

    拼多多违规关店保证金和货款能退回来吗(拼多多违规关店,什么时候可以再开店)

  • 抖音多少点赞才算是热门(抖音多少点赞才有流量)

    抖音多少点赞才算是热门(抖音多少点赞才有流量)

  • 华为深色模式怎么设置(华为深色模式怎么对应APP)

    华为深色模式怎么设置(华为深色模式怎么对应APP)

  • 小红书笔记的文字怎么复制(小红书笔记的文字怎么写)

    小红书笔记的文字怎么复制(小红书笔记的文字怎么写)

  • 闲鱼突然没有流量什么原因造成的(闲鱼没浏览量是怎么回事)

    闲鱼突然没有流量什么原因造成的(闲鱼没浏览量是怎么回事)

  • 激活时无法接通服务器(无法激活因为无法接通激活服务器怎样解决)

    激活时无法接通服务器(无法激活因为无法接通激活服务器怎样解决)

  • 芯片组的架构类型有哪些(芯片架构有哪几种)

    芯片组的架构类型有哪些(芯片架构有哪几种)

  • 不兼容的应用程序怎么解决(不兼容的应用程序怎么卸载)

    不兼容的应用程序怎么解决(不兼容的应用程序怎么卸载)

  • vivo手机出现支付风险怎么办(vivo手机出现这种情况怎么办)

    vivo手机出现支付风险怎么办(vivo手机出现这种情况怎么办)

  • word 增加新的一条目录(word新加一页怎么设置)

    word 增加新的一条目录(word新加一页怎么设置)

  • 红魔3呼吸灯怎么关(红魔5s呼吸灯)

    红魔3呼吸灯怎么关(红魔5s呼吸灯)

  • apple music怎么用(apple music怎么用美区)

    apple music怎么用(apple music怎么用美区)

  • 万能钥匙里的红包是真的吗?可提现吗?(万能钥匙上的红点怎么回事)

    万能钥匙里的红包是真的吗?可提现吗?(万能钥匙上的红点怎么回事)

  • cgx是什么意思在qq上(cggx是什么)

    cgx是什么意思在qq上(cggx是什么)

  • 小米音量键变成悬浮怎么设置(小米音量键变成触摸)

    小米音量键变成悬浮怎么设置(小米音量键变成触摸)

  • Vivox27手机返回键怎么设置(vivox27手机返回键)

    Vivox27手机返回键怎么设置(vivox27手机返回键)

  • 如何打开uc隐藏相册(uc怎么隐藏菜单)

    如何打开uc隐藏相册(uc怎么隐藏菜单)

  • 怎么删除自动回复内容(怎么删除自动回复qq信息)

    怎么删除自动回复内容(怎么删除自动回复qq信息)

  • 搜电充电宝怎么退押金(搜电充电宝怎么改成自己充电)

    搜电充电宝怎么退押金(搜电充电宝怎么改成自己充电)

  • word怎么标注引用(word怎么标注引用的句子)

    word怎么标注引用(word怎么标注引用的句子)

  • iphone6拍照技巧(iphone6拍照使用技巧)(苹果6拍照如何)

    iphone6拍照技巧(iphone6拍照使用技巧)(苹果6拍照如何)

  • 用Python举例实现逆波兰表达式(用python写)

    用Python举例实现逆波兰表达式(用python写)

  • 领用工程物资的账务处理
  • 个人独资企业生活费用和经营费用混在一起的
  • 中华人民共和国宪法
  • 远期交易怎么结算
  • 企业所得税季末从业人数怎么填
  • 电梯维保费属于建筑服务吗
  • 增值税年底如何计算
  • 个体工商户如何注册
  • 建筑行业挂靠代扣税款如何入账?
  • 私募基金款打到什么账户
  • 一般纳税人进项发票认证操作流程
  • 核销的方式
  • 账本印花税税金及附加怎么入账?
  • 科技型中小企业享受优惠税收政策2023
  • 文化用品有哪些种类
  • 卷烟批发环节消费税计算
  • 管理费用职工福利费
  • 购入商品入库时发现实收物多余应收数计入什么科目
  • 借方与贷方区别
  • 金蝶k3购货发票怎么点击记账
  • 资产总额和净资本的关系
  • 鸿蒙系统字体不太好看
  • 公司固定资产出售给个人
  • 8款应用
  • 固定资产折旧计提时间
  • 多交的社保怎么做分录
  • PHP:bzdecompress()的用法_Bzip2函数
  • uniapp单选功能
  • 应收股利的主要特点
  • 营改增开始时间
  • 行政事业单位会计职责
  • chrome谷歌浏览器
  • php中session和cookie
  • chat form
  • 华为od机试无法测用例
  • bom也称为
  • @enable
  • 帝国cms功能
  • 个人电子发票怎么查询
  • 自产自销农产品免税备案取消
  • 免税不可以开专票吗
  • 依法无需办理税务登记证
  • 织梦怎么用
  • 收入和成本的原则是什么
  • 发票认证后总局没信息
  • 费用支出要求
  • 一次性扣除固定资产出售处理
  • 应收账款是指的资产吗
  • 公司维修费计入什么科目
  • 房地产采取按揭销售的,其销售的入账时间为
  • 技术服务费是否可以开具专票
  • 关于幼儿园的会议内容
  • 以前年度损益调整结转到哪里
  • 工会经费可以购买办公用品吗?
  • 银行代扣水电费发票到哪里打
  • 工程施工企业的会计科目如何设置
  • 不需要缴纳税款的企业
  • 错误凭证如何处理
  • 个人向公司账户存现金
  • 已经开了发票需要退款怎么处理?
  • 保洁阿姨工资怎么扣税
  • 预收账款是什么资产
  • iis配置asp网站
  • windows XP+Fedora 8+solaris 11三系统安装攻略
  • lsass exe
  • xp系统怎么设置自动重启
  • win10系统用正版有什么好处
  • win10升级win1
  • 如何禁用ipv6地址
  • 逐一介绍班子成员表现
  • nodejs视频教程大集合
  • 一起学ap
  • unity3d功能
  • python基础教程chm
  • 用js自动判断浏览记录
  • python中的堆和栈
  • 残疾人企业如何申请补贴
  • 预付建造固定资产的工程价款
  • 江苏几个地级市几个县级市
  • 十堰市税务大厅
  • 免责声明:网站部分图片文字素材来源于网络,如有侵权,请及时告知,我们会第一时间删除,谢谢! 邮箱:opceo@qq.com

    鄂ICP备2023003026号

    网站地图: 企业信息 工商信息 财税知识 网络常识 编程技术

    友情链接: 武汉网站建设