修复滚动条big

This commit is contained in:
unknown
2022-06-10 15:59:57 +08:00
parent 152f0eca13
commit 8e2675fc7d
4 changed files with 220 additions and 170 deletions

View File

@ -226,10 +226,8 @@ const ChatInput = ((props) => {
let msgList = []
let newmsg = sendMsg && sendMsg.length>0 ?sendMsg : lodash.cloneDeep(msg);
newmsg.map((item)=>{
const randomNum = Math.floor(Math.random() * 1000)
//const date = dayjs().unix()
const date = new Date()
const encryption = doEncrypt(`${date}${randomNum}`) //有无更快的加密方法,可以加密图片?这个加密方法加密图片太慢!
const encryption = doEncrypt(Math.floor(Math.random() * 1000)+(new Date()).getTime()) //有无更快的加密方法,可以加密图片?这个加密方法加密图片太慢!
//console.log('加密生成完毕')
let msgData = null
if(item.type=='text'){
@ -279,12 +277,8 @@ const ChatInput = ((props) => {
//发送文件
const sendFileHandle = (msg) => {
let msgList = []
const randomNum = Math.floor(Math.random() * 1000)
//const date = dayjs().unix()
const date = new Date()
const encryption = doEncrypt(`${date}${randomNum}`) //有无更快的加密方法,可以加密图片?这个加密方法加密图片太慢!
//console.log('加密生成完毕')
const encryption = doEncrypt(Math.floor(Math.random() * 1000)+(new Date()).getTime()) //有无更快的加密方法,可以加密图片?这个加密方法加密图片太慢!
const msgData = {
_id: encryption,
date: date,

View File

@ -26,43 +26,43 @@ const ScrollWrapper = (Comp) => (props) => {
const [shadowStyle, setShadowStyle] = useState('')
let { data, viewH, scrollToBottom, switchFlag, style, isMove, isModalVisible, loading, } = this? this.props : props
//let data = props.data
const scrollHandle = () => {
if (scrollView.current) {
setScrollT(scrollView.current.scrollTop)
}
const scrollHandle = () => {
if (scrollView.current) {
setScrollT(scrollView.current.scrollTop)
}
}
const mouseUpHandle = () => {
setIsPressing(false)
const mouseUpHandle = (e) => {
setIsPressing(false)
}
const mouseDownHandle = (e) => {
setIsPressing(true)
}
const mouseMovingHandle = (e) => {
e.persist()
if (isPressing !== true) return
if (scrollT < 0) {
setScrollT(0)
} else if (scrollT > scrollH - viewPortH) {
setScrollT(scrollH - viewPortH)
} else {
setScrollT((preScrollT) => preScrollT + e.movementY / scrollR)
}
}
const mouseDownHandle = () => {
setIsPressing(true)
const thumbHeight = () => viewPortH * scrollR
const transH = () => scrollT * scrollR
useEffect(() => {
addEventListener('mouseup', mouseUpHandle)
return () => {
removeEventListener('mouseup', mouseUpHandle)
}
const mouseMovingHandle = (e) => {
if (isPressing !== true) return
if (scrollT < 0) {
setScrollT(0)
} else if (scrollT > scrollH - viewPortH) {
setScrollT(scrollH - viewPortH)
} else {
setScrollT((preScrollT) => preScrollT + e.movementY / scrollR) //e.nativeEvent.movementY
}
}
const thumbHeight = () => viewPortH * scrollR
const transH = () => scrollT * scrollR
useEffect(() => {
addEventListener('mouseup', mouseUpHandle)
return () => {
removeEventListener('mouseup', mouseUpHandle)
}
}, [])
}, [])
useEffect(() => {
if(isModalVisible){
@ -110,13 +110,14 @@ let { data, viewH, scrollToBottom, switchFlag, style, isMove, isModalVisible, lo
return (
<section
style={style}
className={cns([styles.customer_service_content_wrapper_content, shadowStyle])}
className={cns([styles.customer_service_wrapper_content, shadowStyle])}
id={isMove?"section":""}
>
<div
className={styles.list_block}
ref={scrollView}
onScroll={scrollHandle}>
onScroll={scrollHandle}
>
{useMemo(() => <Comp {...props} />, [data, loading, style])}
</div>
<aside
@ -124,6 +125,7 @@ let { data, viewH, scrollToBottom, switchFlag, style, isMove, isModalVisible, lo
style={{ width: showScrollBar ? 5 : 0 }}>
<span
ref={thumb}
datatype="thumb"
className={cns([styles.scroll_thumb])}
onMouseDown={mouseDownHandle}
onMouseMove={mouseMovingHandle}

View File

@ -1,12 +1,8 @@
@import '../../style/common.css';
.customer_service_content_wrapper_content {
.customer_service_wrapper_content {
display: flex;
box-sizing: border-box;
border-top: solid 1px rgb(226, 226, 226);
border-bottom: solid 1px rgb(226, 226, 226);
}
.customer_service_content_wrapper_content .list_block {
.customer_service_wrapper_content .list_block {
flex: auto;
overflow: auto;
overflow-x: hidden;
@ -14,10 +10,10 @@
-ms-overflow-style: none; /* IE 10+ */
box-sizing: border-box;
}
.customer_service_content_wrapper_content .list_block::-webkit-scrollbar {
.customer_service_wrapper_content .list_block::-webkit-scrollbar {
display: none; /* Chrome Safari */
}
.customer_service_content_wrapper_content .scroll_bar_block {
.customer_service_wrapper_content .scroll_bar_block {
width: 8px;
/* border-radius: 4px; */
overflow: hidden;
@ -25,25 +21,25 @@
box-sizing: border-box;
background-color: rgb(231,229,229);
}
.customer_service_content_wrapper_content .scroll_bar_block:hover {
.customer_service_wrapper_content .scroll_bar_block:hover {
background-color: #eee;
}
.customer_service_content_wrapper_content .scroll_thumb {
.customer_service_wrapper_content .scroll_thumb {
display: block;
width: 100%;
background-color: #aaa;
border-radius: 4px;
}
.customer_service_content_wrapper_content .scroll_thumb:hover {
.customer_service_wrapper_content .scroll_thumb:hover {
cursor: pointer;
}
.customer_service_content_wrapper_content .shadow_top {
.customer_service_wrapper_content .shadow_top {
box-shadow: inset 0px 5px 10px -5px rgba(0, 0, 0, 0.2);
}
.customer_service_content_wrapper_content .shadow_bottom {
.customer_service_wrapper_content .shadow_bottom {
box-shadow: inset 0px -5px 10px -5px rgba(0, 0, 0, 0.2);
}
.customer_service_content_wrapper_content .shadow_vertical {
.customer_service_wrapper_content .shadow_vertical {
box-shadow: inset 0px 5px 10px -5px rgba(0, 0, 0, 0.2),
inset 0px -5px 10px -5px rgba(0, 0, 0, 0.2);
}

View File

@ -2,7 +2,7 @@ import React, { useState, useEffect, useRef } from 'react'
import Chat from './components/Chat/Chat'
import ImgPreview from './components/ImgPreview/ImgPreview'
import SeactList from './components/SeactList'
import {entitiestoUtf16, handleElement } from './utils/utils'
import {entitiestoUtf16, handleElement, doEncrypt } from './utils/utils'
import user from '@/assets/img/cs_user.png'
import client from '@/assets/img/cs_client.png'
import { customerserviceAPI as API} from '@/services/customerservice';
@ -12,6 +12,35 @@ import { connect } from 'dva'
import { disconnect } from 'echarts'
import { history } from 'umi'
//未读消息提醒
window.messageAlert = {
timeout: null,
oldTitle:'招投标系统',
time: 0,
num: 0,
showMessage(msg){
window.messageAlert.num++;
if(window.messageAlert.num==1){
window.messageAlert.timeout = setInterval(function(){
window.messageAlert.time ++;
let title = '';
if(messageAlert.time % 2 === 0){
title = '[   ]我的咨询';
}else{
title = '['+msg+']我的咨询';
}
document.getElementsByTagName('title')[0].innerText = title;
},500);
}
},
stopMessage(){
document.getElementsByTagName('title')[0].innerText = window.messageAlert.oldTitle;
window.messageAlert.num = 0;
clearInterval(window.messageAlert.timeout);
}
};
const conversation = (props) => {
const [msgList, setMsgList] = useState([])
const [scrollToBottom, setScrollToBottom] = useState(true)
@ -53,6 +82,54 @@ const conversation = (props) => {
const {isModalVisible, isCloseWs, closeWin, hideWin, msgAlert, supplierNumber, staffId, staffName, optionsModal, projectModal, closeOptionsModal, closeProjectModal, kfType, questionType, openWin, openProjectWin, roleIds} = props
document.addEventListener('visibilitychange',()=>{ //监听网页是否失焦
var isHidden = document.hidden
window.isBlurForCustomerService = isHidden
if(!isHidden && (window.isConversationURLChanged==undefined || !window.isConversationURLChanged)){
stopMsg()
}
})
//项目信息
const onChange = () => {
setShowLoading(true)
getProject({
projectName: queryParams.projectName==undefined? null: queryParams.projectName,
});
}
const getProject = (params)=>{
API.list(params).then((res)=>{
setShowLoading(false)
if(res && res.success && res.data){
let data = res.data
setProjectData(data)
setPagination({
showQuickJumper: true,
showSizeChanger: false,
pageSize: params.pageSize,
current: params.pageNum,
total: res.data.total,
showTotal: total => `${total}`,
})
}else{
message.warn(res && res.message)
}
})
}
const dataList=[
{ label: '项目名称', value: 'projectName', type: 'input', },
]
const onSearch = (param) => {
setQueryParams(param)
getProject({
projectName: param.projectName,
});
};
const onReset = () => {
getProject({
projectName: null,
});
setQueryParams({})
}
const onMsgRender = ()=>{
let serverAvatar = user
let data = wsMsg
@ -87,7 +164,7 @@ const conversation = (props) => {
}
}
let msgData={
_id: Math.floor(Math.random() * 1000)+new Date(),
_id: doEncrypt(Math.floor(Math.random() * 1000)+ (new Date()).getTime()),
date: new Date(),
user: {
id: data.serverNo,
@ -138,7 +215,7 @@ const conversation = (props) => {
}
}
earlierMsg.push({
_id: Math.floor(Math.random() * 1000)+new Date(),
_id: doEncrypt(Math.floor(Math.random() * 1000)+ (new Date()).getTime()),
date: item.sendingTime,
user: {
id: item.senderUid,
@ -150,8 +227,9 @@ const conversation = (props) => {
})
if(data && data.length>0){
setMsgPage(msgPage+1)
if(pageNum==-1){
setMsgPage(msgPage+1)
}
let count = earlierMsg.length
let arr = [...msgList]
while(count>0){
@ -164,91 +242,16 @@ const conversation = (props) => {
setIsSend(true)
}
} else {
message.warn(res && res.message)
//message.warn(res && res.message)
}
})
}
const onChange = () => {
setShowLoading(true)
getProject({
projectName: queryParams.projectName==undefined? null: queryParams.projectName,
});
}
const getProject = (params)=>{
API.list(params).then((res)=>{
setShowLoading(false)
if(res && res.success && res.data){
let data = res.data
setProjectData(data)
setPagination({
showQuickJumper: true,
showSizeChanger: false,
pageSize: params.pageSize,
current: params.pageNum,
total: res.data.total,
showTotal: total => `${total}`,
})
}else{
message.warn(res && res.message)
}
})
}
const dataList=[
{ label: '项目名称', value: 'projectName', type: 'input', },
]
const onSearch = (param) => {
setQueryParams(param)
getProject({
projectName: param.projectName,
});
};
const onReset = () => {
getProject({
projectName: null,
});
setQueryParams({})
}
//检验连接websocket
const checkWebSocket = ()=>{
if(window.isCloseChatUIModal!=undefined){ //弹窗没有关闭弹窗开着或者隐藏ws不应该断
if(window.webSocketForCustomerService==undefined){
console.log('首次创建websocket')
//获取当前用户token
getToken()
}else{
let ws = window.webSocketForCustomerService
if(ws){
//别的路由切过来ws没断重新监听
let avatar = client
console.log('ws没断重新监听')
setShow(true)
monitorWebSocket(ws)
setCuruser({
id: staffId,
name: staffName,
avatar: avatar,
})
setLoading(true)
getMoreMessage(1)
}else{
console.log('websocket断开重新连接')
if(isModalVisible){ //断连后,用户打开弹窗再发提醒
setConversationId('')
disconnectedAlert()
}
}
}
}else{
delete window.webSocketForCustomerService //释放websocket对象
}
}
//断开连接提醒
const disconnectedAlert = () =>{
let serverAvatar = user
const msg = {
_id: Math.floor(Math.random() * 1000)+new Date(),
_id: doEncrypt(Math.floor(Math.random() * 1000)+ (new Date()).getTime()),
date: new Date(),
user: {
id: serverNo,
@ -259,17 +262,23 @@ const disconnectedAlert = () =>{
}
setMsgList([...msgList, msg])
}
//检验连接websocket
const checkDisconnected = ()=>{
if(window.isCloseChatUIModal!=undefined){ //弹窗没有关闭弹窗开着或者隐藏ws不应该断
console.log('websocket断开重新连接')
if(isModalVisible){ //断连后,用户打开弹窗再发提醒
setConversationId('')
disconnectedAlert()
}
}else{
setConversationId('')
setMsgPage(0)
delete window.webSocketForCustomerService //释放websocket对象
}
}
//获取当前登录者token
const getToken = ()=>{
//登录人的信息的关键字 顺序是固定的。
let avatar = client
//当前用户
setCuruser({
id: staffId,
name: staffName,
avatar: avatar,
})
API.check({
clientNo: staffId,
supplierNo:kfType==1?'EMPTY':agentNumber
@ -279,8 +288,18 @@ const getToken = ()=>{
setLoading(true)
getMoreMessage(1)
}else{
closeWin && closeWin()
message.warn(res && '您已在别的终端建立会话')
if(window.webSocketForCustomerService!=undefined){
//别的路由切过来ws没断重新监听
console.log('ws没断重新监听')
setShow(true)
monitorWebSocket(window.webSocketForCustomerService)
setLoading(true)
getMoreMessage(1)
}else{
closeWin && closeWin()
delete window.isCloseChatUIModal
message.warn(res && '您已在别的终端建立会话')
}
}
})
}
@ -292,34 +311,27 @@ const monitorWebSocket = (ws)=>{
//记录ws
window.webSocketForCustomerService = ws
setShow(true) //连接建立后,才可以显示弹窗、收发消息
//else{
// //发空消息给websocket
// let serverAvatar = user
// const msg = {
// _id: Math.floor(Math.random() * 1000)+new Date(),
// date: new Date(),
// user: {
// id: serverNo,
// avatar: serverAvatar,
// name: '供应链客服',
// },
// message: { type: 'text', content: '您好,欢迎使用供应链客服' },
// }
// setMsgList([...msgList, msg])
// }
}
// 接收服务端数据时触发事件
ws.onmessage = function (res) {
if(res.data){
let data = JSON.parse(res.data)
setWsMsg(data)
if(window.isConversationURLChanged){//路由变化
window.msgAlertForCustomerService = true
showMsg()
}else {
if(window.isBlurForCustomerService){//失焦
showMsg()
}
setWsMsg(data)
}
}
};
// 断开 web socket 连接成功触发事件
ws.onclose = function () {
console.log("连接已关闭...");
checkWebSocket()
checkDisconnected()
};
}
/*websocket*/
@ -329,6 +341,30 @@ const websocketInit = (id)=>{
var ws = new WebSocket(addr+id+'/'+no, [sessionStorage.getItem('Authorization')]);
monitorWebSocket(ws)
}
//消息闪烁提醒
const showMsg = ()=>{
messageAlert.showMessage('新消息');
}
const stopMsg = ()=>{
messageAlert.stopMessage('新消息');
}
useEffect(()=>{
history.listen(location => {
// 最新路由的 location 对象,可以通过比较 pathname 是否相同来判断路由的变化情况
let isChanged = location.pathname.indexOf('/Dashboard')==-1
if(isChanged){
window.isConversationURLChanged = isChanged
}else{
if(window.isConversationURLChanged != undefined){ //路由切换回来
//stopMsg()
window.isConversationURLChanged = isChanged
}
}
})
},[])
useEffect(()=>{
if(!isCloseWs){
if(window.isCloseChatUIModal==undefined){
@ -338,6 +374,15 @@ useEffect(()=>{
},[isCloseWs])
useEffect(() => {
if(isModalVisible){
stopMsg()
//登录人的信息的关键字 顺序是固定的。
let avatar = client
//当前用户
setCuruser({
id: staffId,
name: staffName,
avatar: avatar,
})
//恢复初始值
chatUI.style.width = wid
chatUI.style.height = hei
@ -345,8 +390,16 @@ useEffect(() => {
chatUI.style.top = (document.documentElement.clientHeight - hei)*0.5 +"px"
record.style.height = listHeight + "px"
chatInput.style.height = textHeight + "px"
checkWebSocket()
//清空全局变量
if(window.isConversationURLChanged!=undefined) delete window.isConversationURLChanged
if(window.msgAlertForCustomerService!=undefined) delete window.msgAlertForCustomerService
//校验登录
getToken()
}else{
if(window.msgAlertForCustomerService){
msgAlert && msgAlert() //侧边栏提醒
}
setMsgList([])
}
}, [isModalVisible])
@ -363,14 +416,14 @@ useEffect(() => {
useEffect(() => {
//实时渲染消息
if(wsMsg && wsMsg.clientNo!=undefined){
if((!window.isConversationURLChanged || window.isConversationURLChanged== undefined) && wsMsg && wsMsg.clientNo!=undefined){
if(isModalVisible){ //弹窗开着才渲染
onMsgRender()
}else{
msgAlert && msgAlert() //只提醒,不渲染
msgAlert && msgAlert() //只提醒
}
}
}, [wsMsg])
}, [wsMsg])
const columns=[
{ title: '项目名称', dataIndex: 'projectName', align: 'center', ellipsis:true, width:'40%'},
@ -453,7 +506,12 @@ useEffect(() => {
setImageParams(imageParams)
setIsImgPreviewVisible(true)
}}
reConnect={()=>websocketInit(staffId)}
reConnect={()=>{
websocketInit(staffId)
setLoading(true)
getMoreMessage(1)
}
}
onEarlier={()=>{
setLoading(true)
setScrollToBottom(false)