From c378339e20ec7b5a5803a47e44d9b23030f0e2ca Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 23 May 2022 16:33:14 +0800 Subject: [PATCH] =?UTF-8?q?=E5=8A=9F=E8=83=BD=E4=BC=98=E5=8C=96-=E5=8F=91?= =?UTF-8?q?=E9=80=81=E6=96=87=E4=BB=B6=E4=B9=8B=E5=89=8D=E4=BA=8C=E6=AC=A1?= =?UTF-8?q?=E7=A1=AE=E8=AE=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/ChatInput/ChatInput.jsx | 135 +++++++++++----- .../components/ChatInput/style.module.css | 54 ++++++- .../components/EmojiPopover/EmojiPopover.jsx | 149 +++++++++++------- .../components/EmojiPopover/style.module.css | 2 +- .../components/FilePopover/FilePopover.jsx | 47 +++--- .../components/MsgBubble/MsgBubble.jsx | 1 + .../components/MsgBubble/style.module.css | 2 +- .../support/conversation/index.jsx | 2 +- .../support/conversation/utils/utils.jsx | 37 ++++- 9 files changed, 297 insertions(+), 132 deletions(-) diff --git a/src/pages/customerservice/support/conversation/components/ChatInput/ChatInput.jsx b/src/pages/customerservice/support/conversation/components/ChatInput/ChatInput.jsx index 762f022..4b35c83 100644 --- a/src/pages/customerservice/support/conversation/components/ChatInput/ChatInput.jsx +++ b/src/pages/customerservice/support/conversation/components/ChatInput/ChatInput.jsx @@ -5,15 +5,14 @@ import React, { } from 'react' import PropTypes from 'prop-types'; import style from './style.module.css' -//import {doEncrypt} from '@/utils/utils' import ChatToolBar from '../ChatToolsBar/ChatToolBar' -import { mouseOverHandle, mouseMoveHandle, mouseDrag, utf16toEntities, closeHTML, imageHandleUtil, doEncrypt} from '../../utils/utils' +import { mouseOverHandle, mouseMoveHandle, mouseDrag, utf16toEntities, isEmojiCharacter,closeHTML, imageHandleUtil, doEncrypt, parseBase64ToBlob} from '../../utils/utils' import { customerserviceAPI as API} from '@/services/customerservice'; -import { Spin, Modal, message } from 'antd'; +import { Spin, Modal, message, Tooltip } from 'antd'; import { useLocation } from 'react-router-dom' -//import {docUp} from '@config/host' import lodash from 'lodash'; import moment from "moment"; +import { cns } from '../../utils/toClass' const ChatInput = ((props) => { const { @@ -94,22 +93,28 @@ const ChatInput = ((props) => { //输入框内容去除样式 if(allElements && allElements.length>0){ for(var i=0; i0){ for(var j=0; j]*src=['"]([^'"]+)[^>]+?>/) @@ -117,7 +122,7 @@ const ChatInput = ((props) => { var findImg = currentVal.indexOf(' { }else{ judge_div.innerHTML = text if(judge_div.innerText.trim()!=''){ - msgArr.push({type:'text',content:text}) + msgArr.push({type:'text',content:closeHTML(text)}) } setLoading(false) const isAllowSend = msgArr && msgArr.length>0 @@ -340,7 +345,6 @@ const keyUpHandle = (e) => { seIsCtrl(false) } } - const mouseUpHandle = () => { window.getSelection().rangeCount>0 && setCachedRange(window.getSelection().getRangeAt(0)) } @@ -379,15 +383,36 @@ const str_substr = (start, end, str)=> { var el = document.createElement('span') el.innerHTML=txt - var allImgs = el.getElementsByTagName('img') + // var allElements = docuemnt.getElementsByTagName('*') + // //输入框内容去除样式 + // if(allElements && allElements.length>0){ + // for(var i=0; i0){ window.getSelection().deleteFromDocument() //如果有选中内容,粘贴时替换 - let range = cachedRange - if(!cachedRange && innerRef.current){ - innerRef.current.focus() - range = window.getSelection().getRangeAt(0) - } + let range = window.getSelection().getRangeAt(0) + // if(!cachedRange && innerRef.current){ + // innerRef.current.focus() + // range = window.getSelection().getRangeAt(0) + // } if(range) { let params={srcArr:allImgs, sig:0, el, range, reformMsg, showPic, resetCachedRange, resetLoadling, imgInputSize, imgMsgSize, imgPreviewSize} imageHandleUtil.pasteImages(params) @@ -406,13 +431,13 @@ const str_substr = (start, end, str)=> { } } if( item && item.kind === 'file' && item.type.match(/^image\//i) ){ - //imgReader(item.getAsFile()); window.getSelection().deleteFromDocument() //如果有选中内容,粘贴时替换 - let range = cachedRange - if(!cachedRange && innerRef.current){ - innerRef.current.focus() - range = window.getSelection().getRangeAt(0) - } + // let range = cachedRange + // if(!cachedRange && innerRef.current){ + // innerRef.current.focus() + // range = window.getSelection().getRangeAt(0) + // } + let range = window.getSelection().getRangeAt(0) if(range) { let params={image:item.getAsFile(), range, reformMsg, showPic, resetCachedRange, resetLoadling, imgInputSize, imgMsgSize, imgPreviewSize} imageHandleUtil.insertImageHandle(params) @@ -428,19 +453,12 @@ const str_substr = (start, end, str)=> { innerRef.current.focus() range = window.getSelection().getRangeAt(0) } - if (range && innerRef.current) { - var wrapped_obj = document.createElement('span') + if (range) { var obj = document.createElement('span') - var obj2 = document.createElement('span') - obj.setAttribute('emoji','emoji') - obj.setAttribute('contentEditable',false) - obj.style.fontSize="20px" + // obj.style.fontSize="26px" obj.innerHTML=emoji - wrapped_obj.appendChild(obj) - wrapped_obj.appendChild(obj2) - - range.insertNode(wrapped_obj) + range.insertNode(obj) setCachedRange(range) range.collapse(false) window.getSelection().removeAllRanges(); @@ -468,6 +486,31 @@ const str_substr = (start, end, str)=> { imageHandleUtil.insertImageHandle(params) } } + //打开本地已上传文件 + const openLocalUploadFile = ()=>{ + let file = uploadFile + var reader = new FileReader(); + reader.readAsDataURL(file); + reader.onloadend = function (e) { + const element = document.createElement("a"); + element.target='_blank' + const content = e.target.result + if(content.indexOf('base64')!=-1){ + const type = uploadFile.type + var arr = content.split(',') //分割为数组,分割到第一个逗号 + let mime = arr[0].match(/:(.*?);/)[1] //获取分割后的base64前缀中的类型 + let myBlob = parseBase64ToBlob(arr[1], mime); + element.href = URL.createObjectURL(myBlob); + if(type.indexOf('text/plain')==-1 && type.indexOf('image')==-1){ + element.download = uploadFile.name; + } + document.body.appendChild(element); // Required for this to work in FireFox + element.click(); + document.body.removeChild(element); + window.URL.revokeObjectURL(myBlob); //释放掉blob对象 + } + }; + } //文件发送 const sendFile = ()=>{ let file = uploadFile @@ -519,7 +562,7 @@ const str_substr = (start, end, str)=> {
{ if(e.target.id=='chatInput'){ mouseOverHandle(e,props.chatUI) @@ -563,7 +606,15 @@ const str_substr = (start, end, str)=> {
{isSendFile && {setIsSendFile(false);sendFile()}} onCancel={()=>setIsSendFile(false)} > -

您确定要上传文件么?【确定】后,文件将无法撤回!

+ +
{e.preventDefault()}} onClick={openLocalUploadFile} className={style.customer_service_uploadfile}> + {uploadFile.name} + {uploadFile.size / 1024>=1024?(uploadFile.size / 1024/1024).toFixed(1)+"M":(uploadFile.size / 1024).toFixed(1)+"K"} + +
+
+
+

您确定要上传文件么?【确定】后,文件将无法撤回!

} diff --git a/src/pages/customerservice/support/conversation/components/ChatInput/style.module.css b/src/pages/customerservice/support/conversation/components/ChatInput/style.module.css index 25a014a..82c0979 100644 --- a/src/pages/customerservice/support/conversation/components/ChatInput/style.module.css +++ b/src/pages/customerservice/support/conversation/components/ChatInput/style.module.css @@ -15,11 +15,14 @@ outline: none; padding: 10px; margin-right: 10px; - font-size: 13px; - line-height: 13px; + font-size: 16px; + line-height: 16px; font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; letter-spacing: 2px; } +.customer_service_content .input_area .emoji{ + font-size: 20px; +} .customer_service_content .input_area::placeholder { color: #999; } @@ -52,4 +55,51 @@ /* border-radius: 4px; */ box-sizing: border-box; background-color: white +} +.customer_service_uploadfile{ + border: 1px solid #CCC; + background-color: white; + width: 200px; + height: 120px; + position: relative; + -display: flex; + -flex-direction: column; + -webkit-touch-callout: none; /* iOS Safari */ + -webkit-user-select: none; /* Chrome/Safari/Opera */ + -khtml-user-select: none; /* Konqueror */ + -moz-user-select: none; /* Firefox */ + -ms-user-select: none; /* Internet Explorer/Edge */ + user-select: none; /* Non-prefixed version, currently + not supported by any browser */ +} +.customer_service_uploadfile:hover{ + cursor: pointer; +} +.customer_service_filename { + height: 45px; + margin-left: 10px; + margin-top: 5px; +} +.customer_service_filesize { + margin-left: 10px; + margin-top: 5px; + color: rgb(153,153,153); +} +.customer_service_ellipsis { + max-width: 150px; + overflow: hidden; + text-overflow: ellipsis; + display:-webkit-box; + -webkit-box-orient:vertical; + -webkit-line-clamp:2; + -white-space: nowrap; +} +.customer_service_uploadicon{ + float: right; + margin-top: 15px; + margin-right: 10px; + width: 40px; + height: 40px; + background-image: url('../../image/uploadFile.png'); + background-size: cover; } \ No newline at end of file diff --git a/src/pages/customerservice/support/conversation/components/EmojiPopover/EmojiPopover.jsx b/src/pages/customerservice/support/conversation/components/EmojiPopover/EmojiPopover.jsx index 56e8429..7d96983 100644 --- a/src/pages/customerservice/support/conversation/components/EmojiPopover/EmojiPopover.jsx +++ b/src/pages/customerservice/support/conversation/components/EmojiPopover/EmojiPopover.jsx @@ -3,23 +3,107 @@ import PropTypes from 'prop-types' import style from './style.module.css' import { cns } from '../../utils/toClass' +// const emojiList = [ +// '😀', +// '😃', +// '😄', +// '😁', +// '😆', +// '😅', +// '😂', +// '🤣', +// '😊', +// '😇', +// '🙂', +// '🙃', +// '😉', +// '😌', +// '😍', +// '🥰', +// '😘', +// '😗', +// '😙', +// '😚', +// '😋', +// '😛', +// '😝', +// '😜', +// '🤪', +// '🤨', +// '🧐', +// '🤓', +// '😎', +// '🤩', +// '🥳', +// '😏', +// '😒', +// '😞', +// '😔', +// '😟', +// '😕', +// '🙁', +// '😣', +// '😖', +// '😫', +// '😩', +// '🥺', +// '😢', +// '😭', +// '😤', +// '😠', +// '😡', +// '🤬', +// '🤯', +// '😳', +// '🥵', +// '🥶', +// '😱', +// '😨', +// '😰', +// '😥', +// '😓', +// '🤗', +// '🤔', +// '🤭', +// '🤫', +// '🤥', +// '😶', +// '😐', +// '😑', +// '😬', +// '🙄', +// '😯', +// '😦', +// '😧', +// '😮', +// '😲', +// '🥱', +// '😴', +// '🤤', +// '😪', +// '😵', +// '🤐', +// '🥴', +// '🤢', +// '🤮', +// '🤧', +// '😷', +// '🤒', +// '🤕', +// ] const emojiList = [ - '😀', '😃', '😄', '😁', '😆', '😅', '😂', - '🤣', '😊', '😇', '🙂', '🙃', '😉', '😌', - '😍', - '🥰', '😘', '😗', '😙', @@ -28,70 +112,15 @@ const emojiList = [ '😛', '😝', '😜', - '🤪', - '🤨', - '🧐', - '🤓', '😎', - '🤩', - '🥳', - '😏', - '😒', - '😞', - '😔', - '😟', - '😕', - '🙁', - '😣', - '😖', - '😫', - '😩', - '🥺', - '😢', - '😭', - '😤', - '😠', - '😡', - '🤬', - '🤯', '😳', - '🥵', - '🥶', '😱', '😨', '😰', '😥', '😓', - '🤗', - '🤔', - '🤭', - '🤫', - '🤥', - '😶', - '😐', - '😑', - '😬', - '🙄', - '😯', - '😦', - '😧', - '😮', - '😲', - '🥱', - '😴', - '🤤', - '😪', - '😵', - '🤐', - '🥴', - '🤢', - '🤮', - '🤧', - '😷', - '🤒', - '🤕', -] +] export default function EmojiPopover(props) { const {onSelect} = props const [visible, setVisible] = useState(false) diff --git a/src/pages/customerservice/support/conversation/components/EmojiPopover/style.module.css b/src/pages/customerservice/support/conversation/components/EmojiPopover/style.module.css index 15299cc..83064eb 100644 --- a/src/pages/customerservice/support/conversation/components/EmojiPopover/style.module.css +++ b/src/pages/customerservice/support/conversation/components/EmojiPopover/style.module.css @@ -30,7 +30,7 @@ left: -14.5px; } .customer_service_content .emoji_item { - font-size: 20px; + font-size: 22px; box-sizing: border-box; padding: 0px 7px 0px 3px; } diff --git a/src/pages/customerservice/support/conversation/components/FilePopover/FilePopover.jsx b/src/pages/customerservice/support/conversation/components/FilePopover/FilePopover.jsx index dc66605..4d1cdad 100644 --- a/src/pages/customerservice/support/conversation/components/FilePopover/FilePopover.jsx +++ b/src/pages/customerservice/support/conversation/components/FilePopover/FilePopover.jsx @@ -1,29 +1,27 @@ -import React, {useRef } from 'react' +import React, {useRef, useState } from 'react' import PropTypes from 'prop-types' import style from './style.module.css' -import { message, } from 'antd'; - +import { message, Modal, Tooltip} from 'antd'; export default function FilePopover(props) { const { onFile } = props const fileSelector = useRef() - const isUpload = (file) => { - /* - let name = file.name; - let type; - if (name.lastIndexOf(".") > 0) { - type = name - .substr(name.lastIndexOf(".") + 1, name.length) - .toLocaleLowerCase(); - } - let isType = ["pdf", "png", "jpg", "jpeg"].indexOf(type) === -1; - if (isType) { - message.error("上传格式错误"); - }*/ + // /* + // let name = file.name; + // let type; + // if (name.lastIndexOf(".") > 0) { + // type = name + // .substr(name.lastIndexOf(".") + 1, name.length) + // .toLocaleLowerCase(); + // } + // let isType = ["pdf", "png", "jpg", "jpeg"].indexOf(type) === -1; + // if (isType) { + // message.error("上传格式错误"); + // }*/ const isType = false - const isLt50M = file.size / 1024 / 1024 < 50; + const isLt50M = file.size / 1024 / 1024 < 20; if (!isLt50M) { - message.error("文件大小不能超过50MB"); + message.error("文件大小不能超过20MB"); } const bool = !isType && isLt50M; return bool @@ -46,17 +44,18 @@ export default function FilePopover(props) { const fileHandle = (event) => { const files = event.target.files //console.log(files[0]) - if(files && files[0] && (files[0].type.indexOf('application/')!=-1 || files[0].type.indexOf('text/plain')!=-1 )){ - beforeUpload(files[0]) - }else{ - message.error('上传文件格式不支持') - } + // if(files && files[0] && (files[0].type.indexOf('application/')!=-1 || files[0].type.indexOf('text/plain')!=-1 )){ + // beforeUpload(files[0]) + // }else{ + // message.error('上传文件格式不支持') + // } + beforeUpload(files[0]) } return (
diff --git a/src/pages/customerservice/support/conversation/components/MsgBubble/MsgBubble.jsx b/src/pages/customerservice/support/conversation/components/MsgBubble/MsgBubble.jsx index 5b73002..1b860f3 100644 --- a/src/pages/customerservice/support/conversation/components/MsgBubble/MsgBubble.jsx +++ b/src/pages/customerservice/support/conversation/components/MsgBubble/MsgBubble.jsx @@ -35,6 +35,7 @@ export default function MsgBubble(props) { document.body.appendChild(element); // Required for this to work in FireFox element.click(); document.body.removeChild(element); + window.URL.revokeObjectURL(myBlob); //释放掉blob对象 }else{ if(data.content.fileId!=''){ onDownload(data.content.fileId) diff --git a/src/pages/customerservice/support/conversation/components/MsgBubble/style.module.css b/src/pages/customerservice/support/conversation/components/MsgBubble/style.module.css index af9daca..5bfdc1b 100644 --- a/src/pages/customerservice/support/conversation/components/MsgBubble/style.module.css +++ b/src/pages/customerservice/support/conversation/components/MsgBubble/style.module.css @@ -15,7 +15,7 @@ max-width: 100%; word-wrap: break-word; word-break: break-all; - font-size: 13px; + font-size: 15px; font-family:sans-serif; letter-spacing: 2px; } diff --git a/src/pages/customerservice/support/conversation/index.jsx b/src/pages/customerservice/support/conversation/index.jsx index 17f03ca..6cfff11 100644 --- a/src/pages/customerservice/support/conversation/index.jsx +++ b/src/pages/customerservice/support/conversation/index.jsx @@ -85,7 +85,7 @@ const conversation = (props) => { user: { id: data.serverNo, avatar: serverAvatar, - name: '供应链客服', + name: data.serverName? data.serverName: '供应链客服', }, message: { type: type, content: content }, } diff --git a/src/pages/customerservice/support/conversation/utils/utils.jsx b/src/pages/customerservice/support/conversation/utils/utils.jsx index 5d0cf76..cfa1c0f 100644 --- a/src/pages/customerservice/support/conversation/utils/utils.jsx +++ b/src/pages/customerservice/support/conversation/utils/utils.jsx @@ -283,7 +283,9 @@ export function parseBase64ToBlob (data, fileType) { while (n--) { u8arr[n] = bstr.charCodeAt(n) } - return new Blob([u8arr], { type: fileType }) + if(fileType=='text/plain') + return new Blob(['\ufeff', u8arr], { type: fileType }) + else return new Blob([u8arr], { type: fileType }) } // 表情解码 export function entitiestoUtf16 (strObj) { @@ -330,6 +332,39 @@ str = str.replace(patt, (char) => { return str; } +export function isEmojiCharacter(substring) { + for ( var i = 0; i < substring.length; i++) { + var hs = substring.charCodeAt(i); + if (0xd800 <= hs && hs <= 0xdbff) { + if (substring.length > 1) { + var ls = substring.charCodeAt(i + 1); + var uc = ((hs - 0xd800) * 0x400) + (ls - 0xdc00) + 0x10000; + if (0x1d000 <= uc && uc <= 0x1f77f) { + return true; + } + } + } else if (substring.length > 1) { + var ls = substring.charCodeAt(i + 1); + if (ls == 0x20e3) { + return true; + } + } else { + if (0x2100 <= hs && hs <= 0x27ff) { + return true; + } else if (0x2B05 <= hs && hs <= 0x2b07) { + return true; + } else if (0x2934 <= hs && hs <= 0x2935) { + return true; + } else if (0x3297 <= hs && hs <= 0x3299) { + return true; + } else if (hs == 0xa9 || hs == 0xae || hs == 0x303d || hs == 0x3030 + || hs == 0x2b55 || hs == 0x2b1c || hs == 0x2b1b + || hs == 0x2b50) { + return true; + } + } + } +} //补齐html标签 export function closeHTML(str){ var arrTags=["span","font","b","u","i","h1","h2","h3","h4","h5","h6","p","li","ul","table","div"];