perf: 长文本消息的处理

This commit is contained in:
kuaifan 2022-06-09 16:06:18 +08:00
parent a11eb11166
commit 0035789951
4 changed files with 84 additions and 48 deletions

49
resources/assets/js/functions/utils.js vendored Executable file
View File

@ -0,0 +1,49 @@
module.exports = {
/**
* 消息格式化处理
* @param text
* @param userid
* @returns {string|*}
*/
textMsgFormat(text, userid) {
if (!text) {
return ""
}
const atReg = new RegExp(`<span class="mention user" data-id="${userid}">`, "g")
text = text.trim().replace(/(\n\x20*){3,}/g, "\n\n");
text = text.replace(/&nbsp;/g, ' ')
text = text.replace(/<p><\/p>/g, '<p><br/></p>')
text = text.replace(/\{\{RemoteURL\}\}/g, $A.apiUrl('../'))
text = text.replace(atReg, `<span class="mention me" data-id="${userid}">`)
// 处理内容连接
if (/https*:\/\//.test(text)) {
text = text.split(/(<[^>]*>)/g).map(string => {
if (string && !/<[^>]*>/.test(string)) {
string = string.replace(/(https*:\/\/)((\w|=|\?|\.|\/|&|-|:|\+|%|;)+)/g, "<a href=\"$1$2\" target=\"_blank\">$1$2</a>")
}
return string;
}).join("")
}
// 处理图片显示尺寸
const array = text.match(/<img\s+[^>]*?>/g);
if (array) {
const widthReg = new RegExp("width=\"(\\d+)\""),
heightReg = new RegExp("height=\"(\\d+)\"")
array.some(res => {
const widthMatch = res.match(widthReg),
heightMatch = res.match(heightReg);
if (widthMatch && heightMatch) {
const width = parseInt(widthMatch[1]),
height = parseInt(heightMatch[1]),
maxSize = res.indexOf("emoticon") > -1 ? 150 : 220;
const scale = $A.scaleToScale(width, height, maxSize, maxSize);
const value = res
.replace(widthReg, `original-width="${width}" width="${scale.width}"`)
.replace(heightReg, `original-height="${height}" height="${scale.height}"`)
text = text.replace(res, value)
}
})
}
return text;
}
}

View File

@ -124,6 +124,7 @@ import WCircle from "../../../components/WCircle";
import {mapState} from "vuex"; import {mapState} from "vuex";
import {Store} from "le5le-store"; import {Store} from "le5le-store";
import longpress from "../../../directives/longpress"; import longpress from "../../../directives/longpress";
import {textMsgFormat} from "../../../functions/utils";
export default { export default {
name: "DialogView", name: "DialogView",
@ -224,10 +225,6 @@ export default {
} }
} }
return classArray; return classArray;
},
atUserReg() {
return new RegExp(`<span class="mention user" data-id="${this.userId}">`, "g")
} }
}, },
@ -292,44 +289,7 @@ export default {
}, },
textMsg(text) { textMsg(text) {
if (!text) { return textMsgFormat(text, this.userId);
return ""
}
text = text.trim().replace(/(\n\x20*){3,}/g, "\n\n");
text = text.replace(/&nbsp;/g, ' ')
text = text.replace(/<p><\/p>/g, '<p><br/></p>')
text = text.replace(/\{\{RemoteURL\}\}/g, $A.apiUrl('../'))
text = text.replace(this.atUserReg, `<span class="mention me" data-id="${this.userId}">`)
//
if (/https*:\/\//.test(text)) {
text = text.split(/(<[^>]*>)/g).map(string => {
if (string && !/<[^>]*>/.test(string)) {
string = string.replace(/(https*:\/\/)((\w|=|\?|\.|\/|&|-|:|\+|%|;)+)/g, "<a href=\"$1$2\" target=\"_blank\">$1$2</a>")
}
return string;
}).join("")
}
//
const array = text.match(/<img\s+[^>]*?>/g);
if (array) {
const widthReg = new RegExp("width=\"(\\d+)\""),
heightReg = new RegExp("height=\"(\\d+)\"")
array.some(res => {
const widthMatch = res.match(widthReg),
heightMatch = res.match(heightReg);
if (widthMatch && heightMatch) {
const width = parseInt(widthMatch[1]),
height = parseInt(heightMatch[1]),
maxSize = res.indexOf("emoticon") > -1 ? 150 : 220;
const scale = $A.scaleToScale(width, height, maxSize, maxSize);
const value = res
.replace(widthReg, `original-width="${width}" width="${scale.width}"`)
.replace(heightReg, `original-height="${height}" height="${scale.height}"`)
text = text.replace(res, value)
}
})
}
return text;
}, },
recordStyle(info) { recordStyle(info) {

View File

@ -570,15 +570,20 @@ export default {
this.onActive(); this.onActive();
// //
let tempId = $A.randomString(16); let tempId = $A.randomString(16);
this.tempMsgs.push({ let tempMsg = {
id: tempId, id: tempId,
dialog_id: this.dialogData.id, dialog_id: this.dialogData.id,
type: 'text', type: 'text',
userid: this.userId, userid: this.userId,
msg: { msg: {
text: msgText, text: $A.stringLength(msgText) > 2000 ? '' : msgText,
}, },
}); };
if (msgText.length > 2000) {
tempMsg.type = 'loading';
tempMsg.msg = { };
}
this.tempMsgs.push(tempMsg);
// //
this.$store.dispatch("call", { this.$store.dispatch("call", {
url: 'dialog/msg/sendtext', url: 'dialog/msg/sendtext',

View File

@ -7,7 +7,10 @@
<TEditor v-else-if="isType('text')" :value="msgDetail.content.content" height="100%" readOnly/> <TEditor v-else-if="isType('text')" :value="msgDetail.content.content" height="100%" readOnly/>
<Drawio v-else-if="isType('drawio')" v-model="msgDetail.content" :title="msgDetail.msg.name" readOnly/> <Drawio v-else-if="isType('drawio')" v-model="msgDetail.content" :title="msgDetail.msg.name" readOnly/>
<Minder v-else-if="isType('mind')" :value="msgDetail.content" readOnly/> <Minder v-else-if="isType('mind')" :value="msgDetail.content" readOnly/>
<AceEditor v-else-if="isType('code')" v-model="msgDetail.content.content" :ext="msgDetail.msg.ext" class="view-editor" readOnly/> <template v-else-if="isType('code')">
<div v-if="isLongText(msgDetail.msg.name)" class="view-code" v-html="longTextFormat(msgDetail.content.content)"></div>
<AceEditor v-else v-model="msgDetail.content.content" :ext="msgDetail.msg.ext" class="view-editor" readOnly/>
</template>
<OnlyOffice v-else-if="isType('office')" v-model="officeContent" :code="officeCode" :documentKey="documentKey" readOnly/> <OnlyOffice v-else-if="isType('office')" v-model="officeContent" :code="officeCode" :documentKey="documentKey" readOnly/>
<iframe v-else-if="isType('preview')" class="preview-iframe" :src="previewUrl"/> <iframe v-else-if="isType('preview')" class="preview-iframe" :src="previewUrl"/>
<div v-else class="no-support">{{$L('不支持单独查看此消息')}}</div> <div v-else class="no-support">{{$L('不支持单独查看此消息')}}</div>
@ -23,7 +26,8 @@
.ace_editor, .ace_editor,
.markdown-preview-warp, .markdown-preview-warp,
.teditor-wrapper, .teditor-wrapper,
.no-support { .no-support,
.view-code {
position: absolute; position: absolute;
top: 0; top: 0;
left: 0; left: 0;
@ -39,6 +43,11 @@
float: none; float: none;
max-width: none; max-width: none;
} }
.view-code {
white-space: pre-wrap;
word-wrap: break-word;
overflow: auto;
}
.view-editor, .view-editor,
.no-support { .no-support {
display: flex; display: flex;
@ -59,6 +68,8 @@
<script> <script>
import Vue from 'vue' import Vue from 'vue'
import Minder from '../../components/Minder' import Minder from '../../components/Minder'
import {textMsgFormat} from "../../functions/utils";
import {mapState} from "vuex";
Vue.use(Minder) Vue.use(Minder)
const MDPreview = () => import('../../components/MDEditor/preview'); const MDPreview = () => import('../../components/MDEditor/preview');
@ -88,6 +99,8 @@ export default {
}, },
}, },
computed: { computed: {
...mapState(['userId']),
msgId() { msgId() {
const {msgId} = this.$route.params; const {msgId} = this.$route.params;
return parseInt(/^\d+$/.test(msgId) ? msgId : 0); return parseInt(/^\d+$/.test(msgId) ? msgId : 0);
@ -150,6 +163,7 @@ export default {
this.loadIng--; this.loadIng--;
}); });
}, },
documentKey() { documentKey() {
return new Promise(resolve => { return new Promise(resolve => {
this.$store.dispatch("call", { this.$store.dispatch("call", {
@ -164,7 +178,15 @@ export default {
resolve(0) resolve(0)
}); });
}); });
} },
isLongText(name) {
return /^LongText-/.test(name)
},
longTextFormat(text) {
return textMsgFormat(text, this.userId)
},
} }
} }
</script> </script>