功能优化-发送文件之前二次确认

This commit is contained in:
unknown
2022-05-23 16:33:14 +08:00
parent 93105830e0
commit c378339e20
9 changed files with 297 additions and 132 deletions

View File

@ -5,15 +5,14 @@ import React, {
} from 'react' } from 'react'
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import style from './style.module.css' import style from './style.module.css'
//import {doEncrypt} from '@/utils/utils'
import ChatToolBar from '../ChatToolsBar/ChatToolBar' 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 { 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 { useLocation } from 'react-router-dom'
//import {docUp} from '@config/host'
import lodash from 'lodash'; import lodash from 'lodash';
import moment from "moment"; import moment from "moment";
import { cns } from '../../utils/toClass'
const ChatInput = ((props) => { const ChatInput = ((props) => {
const { const {
@ -96,11 +95,17 @@ const ChatInput = ((props) => {
for(var i=0; i<allElements.length;i++){ for(var i=0; i<allElements.length;i++){
let el = allElements[i] let el = allElements[i]
if(el.tagName!="IMG"){ if(el.tagName!="IMG"){
if(!el.hasAttribute('emoji')){ // if(el.tagName=="SPAN"){
// if(isEmojiCharacter(el.innerHTML)){
// el.style.fontSize='26px'
// }else{
// el.removeAttribute('style')
// el.style.fontSize='15px'
// }
// }else{
// el.removeAttribute('style')
// }
el.removeAttribute('style') el.removeAttribute('style')
}else if(el.getAttribute('emoji')!='emoji'){
el.removeAttribute('style')
}
el.removeAttribute('className') el.removeAttribute('className')
el.removeAttribute('class') el.removeAttribute('class')
} }
@ -137,7 +142,7 @@ const ChatInput = ((props) => {
}else{ }else{
judge_div.innerHTML = text judge_div.innerHTML = text
if(judge_div.innerText.trim()!=''){ if(judge_div.innerText.trim()!=''){
msgArr.push({type:'text',content:text}) msgArr.push({type:'text',content:closeHTML(text)})
} }
setLoading(false) setLoading(false)
const isAllowSend = msgArr && msgArr.length>0 const isAllowSend = msgArr && msgArr.length>0
@ -340,7 +345,6 @@ const keyUpHandle = (e) => {
seIsCtrl(false) seIsCtrl(false)
} }
} }
const mouseUpHandle = () => { const mouseUpHandle = () => {
window.getSelection().rangeCount>0 && setCachedRange(window.getSelection().getRangeAt(0)) window.getSelection().rangeCount>0 && setCachedRange(window.getSelection().getRangeAt(0))
} }
@ -379,15 +383,36 @@ const str_substr = (start, end, str)=> {
var el = document.createElement('span') var el = document.createElement('span')
el.innerHTML=txt el.innerHTML=txt
var allImgs = el.getElementsByTagName('img')
// var allElements = docuemnt.getElementsByTagName('*')
// //输入框内容去除样式
// if(allElements && allElements.length>0){
// for(var i=0; i<allElements.length;i++){
// let el = allElements[i]
// console.log(el)
// if(el.tagName!="IMG"){
// if(el.tagName=="SPAN"){
// if(isEmojiCharacter(el.innerHTML)){
// el.style.fontSize='20px'
// }else{
// el.removeAttribute('style')
// el.style.fontSize='13px'
// }
// }
// el.removeAttribute('className')
// el.removeAttribute('class')
// }
// }
// }
var allImgs = el.getElementsByTagName('img')
if(allImgs && allImgs.length>0){ if(allImgs && allImgs.length>0){
window.getSelection().deleteFromDocument() //如果有选中内容,粘贴时替换 window.getSelection().deleteFromDocument() //如果有选中内容,粘贴时替换
let range = cachedRange let range = window.getSelection().getRangeAt(0)
if(!cachedRange && innerRef.current){ // if(!cachedRange && innerRef.current){
innerRef.current.focus() // innerRef.current.focus()
range = window.getSelection().getRangeAt(0) // range = window.getSelection().getRangeAt(0)
} // }
if(range) { if(range) {
let params={srcArr:allImgs, sig:0, el, range, reformMsg, showPic, resetCachedRange, resetLoadling, imgInputSize, imgMsgSize, imgPreviewSize} let params={srcArr:allImgs, sig:0, el, range, reformMsg, showPic, resetCachedRange, resetLoadling, imgInputSize, imgMsgSize, imgPreviewSize}
imageHandleUtil.pasteImages(params) imageHandleUtil.pasteImages(params)
@ -406,13 +431,13 @@ const str_substr = (start, end, str)=> {
} }
} }
if( item && item.kind === 'file' && item.type.match(/^image\//i) ){ if( item && item.kind === 'file' && item.type.match(/^image\//i) ){
//imgReader(item.getAsFile());
window.getSelection().deleteFromDocument() //如果有选中内容粘贴时替换 window.getSelection().deleteFromDocument() //如果有选中内容粘贴时替换
let range = cachedRange // let range = cachedRange
if(!cachedRange && innerRef.current){ // if(!cachedRange && innerRef.current){
innerRef.current.focus() // innerRef.current.focus()
range = window.getSelection().getRangeAt(0) // range = window.getSelection().getRangeAt(0)
} // }
let range = window.getSelection().getRangeAt(0)
if(range) { if(range) {
let params={image:item.getAsFile(), range, reformMsg, showPic, resetCachedRange, resetLoadling, imgInputSize, imgMsgSize, imgPreviewSize} let params={image:item.getAsFile(), range, reformMsg, showPic, resetCachedRange, resetLoadling, imgInputSize, imgMsgSize, imgPreviewSize}
imageHandleUtil.insertImageHandle(params) imageHandleUtil.insertImageHandle(params)
@ -428,19 +453,12 @@ const str_substr = (start, end, str)=> {
innerRef.current.focus() innerRef.current.focus()
range = window.getSelection().getRangeAt(0) range = window.getSelection().getRangeAt(0)
} }
if (range && innerRef.current) { if (range) {
var wrapped_obj = document.createElement('span')
var obj = document.createElement('span') var obj = document.createElement('span')
var obj2 = document.createElement('span') // obj.style.fontSize="26px"
obj.setAttribute('emoji','emoji')
obj.setAttribute('contentEditable',false)
obj.style.fontSize="20px"
obj.innerHTML=emoji obj.innerHTML=emoji
wrapped_obj.appendChild(obj) range.insertNode(obj)
wrapped_obj.appendChild(obj2)
range.insertNode(wrapped_obj)
setCachedRange(range) setCachedRange(range)
range.collapse(false) range.collapse(false)
window.getSelection().removeAllRanges(); window.getSelection().removeAllRanges();
@ -468,6 +486,31 @@ const str_substr = (start, end, str)=> {
imageHandleUtil.insertImageHandle(params) 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 = ()=>{ const sendFile = ()=>{
let file = uploadFile let file = uploadFile
@ -563,7 +606,15 @@ const str_substr = (start, end, str)=> {
</div> </div>
{isSendFile && {isSendFile &&
<Modal title="提醒" getContainer={false} visible={isSendFile} onOk={()=>{setIsSendFile(false);sendFile()}} onCancel={()=>setIsSendFile(false)} > <Modal title="提醒" getContainer={false} visible={isSendFile} onOk={()=>{setIsSendFile(false);sendFile()}} onCancel={()=>setIsSendFile(false)} >
<p>您确定要上传文件么确定文件将无法撤回!</p> <Tooltip title='点击查看文件' placement='topRight'>
<div onDragOver={(e)=>{e.preventDefault()}} onClick={openLocalUploadFile} className={style.customer_service_uploadfile}>
<span className={cns([style.customer_service_filename, style.customer_service_ellipsis])}>{uploadFile.name}</span>
<span className={style.customer_service_filesize}>{uploadFile.size / 1024>=1024?(uploadFile.size / 1024/1024).toFixed(1)+"M":(uploadFile.size / 1024).toFixed(1)+"K"}</span>
<span className={style.customer_service_uploadicon}></span>
</div>
</Tooltip>
<br/>
<p style={{color:'red'}}>您确定要上传文件么确定文件将无法撤回!</p>
</Modal> </Modal>
} }
</Spin> </Spin>

View File

@ -15,11 +15,14 @@
outline: none; outline: none;
padding: 10px; padding: 10px;
margin-right: 10px; margin-right: 10px;
font-size: 13px; font-size: 16px;
line-height: 13px; line-height: 16px;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
letter-spacing: 2px; letter-spacing: 2px;
} }
.customer_service_content .input_area .emoji{
font-size: 20px;
}
.customer_service_content .input_area::placeholder { .customer_service_content .input_area::placeholder {
color: #999; color: #999;
} }
@ -53,3 +56,50 @@
box-sizing: border-box; box-sizing: border-box;
background-color: white 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;
}

View File

@ -3,23 +3,107 @@ import PropTypes from 'prop-types'
import style from './style.module.css' import style from './style.module.css'
import { cns } from '../../utils/toClass' import { cns } from '../../utils/toClass'
// const emojiList = [
// '😀',
// '😃',
// '😄',
// '😁',
// '😆',
// '😅',
// '😂',
// '🤣',
// '😊',
// '😇',
// '🙂',
// '🙃',
// '😉',
// '😌',
// '😍',
// '🥰',
// '😘',
// '😗',
// '😙',
// '😚',
// '😋',
// '😛',
// '😝',
// '😜',
// '🤪',
// '🤨',
// '🧐',
// '🤓',
// '😎',
// '🤩',
// '🥳',
// '😏',
// '😒',
// '😞',
// '😔',
// '😟',
// '😕',
// '🙁',
// '😣',
// '😖',
// '😫',
// '😩',
// '🥺',
// '😢',
// '😭',
// '😤',
// '😠',
// '😡',
// '🤬',
// '🤯',
// '😳',
// '🥵',
// '🥶',
// '😱',
// '😨',
// '😰',
// '😥',
// '😓',
// '🤗',
// '🤔',
// '🤭',
// '🤫',
// '🤥',
// '😶',
// '😐',
// '😑',
// '😬',
// '🙄',
// '😯',
// '😦',
// '😧',
// '😮',
// '😲',
// '🥱',
// '😴',
// '🤤',
// '😪',
// '😵',
// '🤐',
// '🥴',
// '🤢',
// '🤮',
// '🤧',
// '😷',
// '🤒',
// '🤕',
// ]
const emojiList = [ const emojiList = [
'😀',
'😃', '😃',
'😄', '😄',
'😁', '😁',
'😆', '😆',
'😅', '😅',
'😂', '😂',
'🤣',
'😊', '😊',
'😇', '😇',
'🙂', '🙂',
'🙃', '🙃',
'😉', '😉',
'😌', '😌',
'😍',
'🥰',
'😘', '😘',
'😗', '😗',
'😙', '😙',
@ -28,70 +112,15 @@ const emojiList = [
'😛', '😛',
'😝', '😝',
'😜', '😜',
'🤪',
'🤨',
'🧐',
'🤓',
'😎', '😎',
'🤩',
'🥳',
'😏',
'😒',
'😞',
'😔',
'😟',
'😕',
'🙁',
'😣',
'😖',
'😫',
'😩',
'🥺',
'😢',
'😭',
'😤',
'😠',
'😡',
'🤬',
'🤯',
'😳', '😳',
'🥵',
'🥶',
'😱', '😱',
'😨', '😨',
'😰', '😰',
'😥', '😥',
'😓', '😓',
'🤗',
'🤔',
'🤭',
'🤫',
'🤥',
'😶',
'😐',
'😑',
'😬',
'🙄',
'😯',
'😦',
'😧',
'😮',
'😲',
'🥱',
'😴',
'🤤',
'😪',
'😵',
'🤐',
'🥴',
'🤢',
'🤮',
'🤧',
'😷',
'🤒',
'🤕',
]
]
export default function EmojiPopover(props) { export default function EmojiPopover(props) {
const {onSelect} = props const {onSelect} = props
const [visible, setVisible] = useState(false) const [visible, setVisible] = useState(false)

View File

@ -30,7 +30,7 @@
left: -14.5px; left: -14.5px;
} }
.customer_service_content .emoji_item { .customer_service_content .emoji_item {
font-size: 20px; font-size: 22px;
box-sizing: border-box; box-sizing: border-box;
padding: 0px 7px 0px 3px; padding: 0px 7px 0px 3px;
} }

View File

@ -1,29 +1,27 @@
import React, {useRef } from 'react' import React, {useRef, useState } from 'react'
import PropTypes from 'prop-types' import PropTypes from 'prop-types'
import style from './style.module.css' import style from './style.module.css'
import { message, } from 'antd'; import { message, Modal, Tooltip} from 'antd';
export default function FilePopover(props) { export default function FilePopover(props) {
const { onFile } = props const { onFile } = props
const fileSelector = useRef() const fileSelector = useRef()
const isUpload = (file) => { const isUpload = (file) => {
/* // /*
let name = file.name; // let name = file.name;
let type; // let type;
if (name.lastIndexOf(".") > 0) { // if (name.lastIndexOf(".") > 0) {
type = name // type = name
.substr(name.lastIndexOf(".") + 1, name.length) // .substr(name.lastIndexOf(".") + 1, name.length)
.toLocaleLowerCase(); // .toLocaleLowerCase();
} // }
let isType = ["pdf", "png", "jpg", "jpeg"].indexOf(type) === -1; // let isType = ["pdf", "png", "jpg", "jpeg"].indexOf(type) === -1;
if (isType) { // if (isType) {
message.error("上传格式错误"); // message.error("上传格式错误");
}*/ // }*/
const isType = false const isType = false
const isLt50M = file.size / 1024 / 1024 < 50; const isLt50M = file.size / 1024 / 1024 < 20;
if (!isLt50M) { if (!isLt50M) {
message.error("文件大小不能超过50MB"); message.error("文件大小不能超过20MB");
} }
const bool = !isType && isLt50M; const bool = !isType && isLt50M;
return bool return bool
@ -46,17 +44,18 @@ export default function FilePopover(props) {
const fileHandle = (event) => { const fileHandle = (event) => {
const files = event.target.files const files = event.target.files
//console.log(files[0]) //console.log(files[0])
if(files && files[0] && (files[0].type.indexOf('application/')!=-1 || files[0].type.indexOf('text/plain')!=-1 )){ // 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]) beforeUpload(files[0])
}else{
message.error('上传文件格式不支持')
}
} }
return ( return (
<div className={style.customer_service_content} onClick={selectImg}> <div className={style.customer_service_content} onClick={selectImg}>
<input <input
type="file" type="file"
accept="application/*,text/plain" //accept="application/*,text/plain"
ref={fileSelector} ref={fileSelector}
onChange={fileHandle} onChange={fileHandle}
/> />

View File

@ -35,6 +35,7 @@ export default function MsgBubble(props) {
document.body.appendChild(element); // Required for this to work in FireFox document.body.appendChild(element); // Required for this to work in FireFox
element.click(); element.click();
document.body.removeChild(element); document.body.removeChild(element);
window.URL.revokeObjectURL(myBlob); //释放掉blob对象
}else{ }else{
if(data.content.fileId!=''){ if(data.content.fileId!=''){
onDownload(data.content.fileId) onDownload(data.content.fileId)

View File

@ -15,7 +15,7 @@
max-width: 100%; max-width: 100%;
word-wrap: break-word; word-wrap: break-word;
word-break: break-all; word-break: break-all;
font-size: 13px; font-size: 15px;
font-family:sans-serif; font-family:sans-serif;
letter-spacing: 2px; letter-spacing: 2px;
} }

View File

@ -85,7 +85,7 @@ const conversation = (props) => {
user: { user: {
id: data.serverNo, id: data.serverNo,
avatar: serverAvatar, avatar: serverAvatar,
name: '供应链客服', name: data.serverName? data.serverName: '供应链客服',
}, },
message: { type: type, content: content }, message: { type: type, content: content },
} }

View File

@ -283,7 +283,9 @@ export function parseBase64ToBlob (data, fileType) {
while (n--) { while (n--) {
u8arr[n] = bstr.charCodeAt(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) { export function entitiestoUtf16 (strObj) {
@ -330,6 +332,39 @@ str = str.replace(patt, (char) => {
return str; 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标签 //补齐html标签
export function closeHTML(str){ export function closeHTML(str){
var arrTags=["span","font","b","u","i","h1","h2","h3","h4","h5","h6","p","li","ul","table","div"]; var arrTags=["span","font","b","u","i","h1","h2","h3","h4","h5","h6","p","li","ul","table","div"];