位置: 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设置待机时间长怎么在哪里设置)

  • 华为手机怎么隔空截屏(华为手机怎么隔空刷视频)

    华为手机怎么隔空截屏(华为手机怎么隔空刷视频)

  • 微信如何通过手机号转账(微信如何通过手机号找回密码)

    微信如何通过手机号转账(微信如何通过手机号找回密码)

  • 有微信号但搜不到对方(有微信号但搜不到对方怎样加为好友)

    有微信号但搜不到对方(有微信号但搜不到对方怎样加为好友)

  • 华为怎么换图标的图案(华为怎么换图标和名字图片)

    华为怎么换图标的图案(华为怎么换图标和名字图片)

  • 手机卡封号影响信用吗(手机卡封号影响什么)

    手机卡封号影响信用吗(手机卡封号影响什么)

  • wps文字效果为什么不能用(wps字体突然变了什么情况)

    wps文字效果为什么不能用(wps字体突然变了什么情况)

  • cpu中控制器的功能是什么(cpu中控制器的基本功能是什么)

    cpu中控制器的功能是什么(cpu中控制器的基本功能是什么)

  • 淘宝会员码被刷了会提醒吗(淘宝会员码被别人扫了怎么办)

    淘宝会员码被刷了会提醒吗(淘宝会员码被别人扫了怎么办)

  • 4k显示器对显卡的要求(4k显示器对显卡配置的要求)

    4k显示器对显卡的要求(4k显示器对显卡配置的要求)

  • 小米8青春版怎么打开快充(小米8青春版怎么样值得买吗)

    小米8青春版怎么打开快充(小米8青春版怎么样值得买吗)

  • omo模式是什么意思啊(omo模式产品)

    omo模式是什么意思啊(omo模式产品)

  • 绑定pid是什么意思(绑定eip的作用)

    绑定pid是什么意思(绑定eip的作用)

  • 苹果8省电模式怎么设置(苹果8省电模式怎么开)

    苹果8省电模式怎么设置(苹果8省电模式怎么开)

  • iphonex快充损害电池吗(苹果x快充会不会损坏电池)

    iphonex快充损害电池吗(苹果x快充会不会损坏电池)

  • 什么叫密保手机号(什么叫密保手机号码视频)

    什么叫密保手机号(什么叫密保手机号码视频)

  • 酷狗歌曲怎么传到陌陌(酷狗歌曲怎么传到网易云)

    酷狗歌曲怎么传到陌陌(酷狗歌曲怎么传到网易云)

  • 微信怎么开美颜vivox20(微信怎么开美颜视频聊天vivo手机)

    微信怎么开美颜vivox20(微信怎么开美颜视频聊天vivo手机)

  • iphone11pro与iphone11区别(iPhone11pro与iPhone12哪个好)

    iphone11pro与iphone11区别(iPhone11pro与iPhone12哪个好)

  • p30国行版什么时候发(华为p30pro国行型号)

    p30国行版什么时候发(华为p30pro国行型号)

  • 苹果手机怎样取消软件的消息推送(苹果手机怎样取消自动续费的功能)

    苹果手机怎样取消软件的消息推送(苹果手机怎样取消自动续费的功能)

  • 华为rne一al00什么型号(华为rne一al00什么型号手机)

    华为rne一al00什么型号(华为rne一al00什么型号手机)

  • 手机wifi总是断断续续的掉线(oppo手机wifi总是断)

    手机wifi总是断断续续的掉线(oppo手机wifi总是断)

  • nerf训练自己的数据,过程记录十分详细(nerf 怎么瞄准)

    nerf训练自己的数据,过程记录十分详细(nerf 怎么瞄准)

  • 税前扣除的项目包括
  • 价外税怎么理解
  • 金蝶软件中怎么增加固定资产
  • 对账结算流程
  • 小规模企业免税怎么做账
  • 小规模纳税人现金折扣算增值税吗
  • 内账月末怎样结转
  • 残保金是谁支付给单位?
  • 固定资产的净值等于
  • 收到进度款开票如何做账务处理合适呢?
  • 佣金支出和手续费税前扣除相关政策依据及会计处理
  • 普通发票红字冲销发票怎么操作
  • 商场预付卡是什么意思
  • 用银行存款上交上月税金会计分录
  • 前年的票发现要不得,可以冲红吗
  • 资产一次性摊销
  • 机器设备的损耗属于什么会计科目类别
  • 租赁车辆维修费谁承担
  • 小型连锁药店需要报国税吗?
  • 劳务建筑公司一年可以赚多少
  • 公司注销增值税在借方有余额怎么处理
  • 小规模纳税人附加税会计分录
  • 电子账本excel模板
  • 自制材料入库计划成本
  • 增值税进项留抵退税的账务处理
  • 货款已经收到
  • php使用memcache
  • 安置残疾人就业单位城镇土地使用税
  • adblock规则编写
  • 预付款不退如何投诉
  • 所得税返还计入什么科目
  • 盛开的樱花和姬子的故事
  • 预付装修费的会计处理分录
  • php filesize
  • 开具负数发票的流程
  • 十四届智能车规则
  • js删除
  • 顺丰快递电子运单打印模板
  • 残保金补申报后处罚会自动取消吗
  • 不是自己生产的产品可以用自己的商标吗
  • 美容店销售收入预测表12个月表格
  • js array.fill
  • access如何设置宏的功能
  • 增值税税率调整为13%从什么时候开始实行
  • 信用卡的还款方式怎么查
  • 企业所得税资产总额季初季末怎么填
  • 未分配利润是怎么来的
  • 收到预收款开具发票如何入账
  • 无形资产的有效期限与法定保护期限相等
  • 期末调汇的会计怎么做账
  • 航信服务费减免怎么填
  • 给供应商支付货款的付款申请由谁提出
  • 无发票材料可以入材料账吗
  • 售后维修费会计分录
  • 受托方受托代销商品会计分录
  • 同花顺为什么有钱没法买
  • 固定资产报废的变卖收入计入哪个科目
  • 基本生产成本和生产成本
  • 支付厂房租赁费现金流
  • 税前税后利润弥补亏损的会计分录
  • 营业外收入属于借方还是贷方
  • mysql导入导出sql文件
  • java调用jni
  • mysql数据库简单介绍
  • freebsd ports安装
  • 电脑没有系统了如何重装系统
  • linux acl设置
  • linux乱码怎么办
  • win7系统命令大全
  • Extjs4 Treegrid 使用心得分享(经验篇)
  • Node.js中的construct构造函数
  • shell 输出
  • python抓取网络数据
  • Node.js中的什么模块是用于处理文件和目录的
  • jquery中ajax处理跨域的三大方式
  • 怎么看物理内存
  • jquery有哪些
  • python按位与操作
  • 国税和地税现在合并了吗
  • 税务2021年认真落实各项工作
  • 免责声明:网站部分图片文字素材来源于网络,如有侵权,请及时告知,我们会第一时间删除,谢谢! 邮箱:opceo@qq.com

    鄂ICP备2023003026号

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

    友情链接: 武汉网站建设