v1.7.4 编辑框换行符统一为\n
This commit is contained in:
@@ -1,10 +1,10 @@
|
||||
<script>
|
||||
import { toEmojiName, useScopedSlot, clearHtmlExcludeImg } from "utils";
|
||||
const exec = (val, command = "insertHTML") => {
|
||||
import { useScopedSlot, messageToHtml, clearHtmlExcludeImg } from "utils";
|
||||
const command = (command, val) => {
|
||||
document.execCommand(command, false, val);
|
||||
};
|
||||
const selection = window.getSelection();
|
||||
let lastSelectionRange;
|
||||
let range;
|
||||
let emojiData = [];
|
||||
let isInitTool = false;
|
||||
export default {
|
||||
@@ -27,6 +27,12 @@ export default {
|
||||
type: String,
|
||||
default: "发 送",
|
||||
},
|
||||
wrapKey: {
|
||||
type: Function,
|
||||
default: function(e) {
|
||||
return e.keyCode == 13 && e.ctrlKey == false && e.shiftKey == false;
|
||||
},
|
||||
},
|
||||
sendKey: {
|
||||
type: Function,
|
||||
default(e) {
|
||||
@@ -40,20 +46,11 @@ export default {
|
||||
//剪切板图片URL
|
||||
clipboardUrl: "",
|
||||
submitDisabled: true,
|
||||
proxyTools: [],
|
||||
//proxyTools: [],
|
||||
accept: "",
|
||||
};
|
||||
},
|
||||
created() {
|
||||
if (this.tools && this.tools.length > 0) {
|
||||
this.initTools(this.tools);
|
||||
} else {
|
||||
this.initTools([
|
||||
{ name: "emoji" },
|
||||
{ name: "uploadFile" },
|
||||
{ name: "uploadImage" },
|
||||
]);
|
||||
}
|
||||
this.IMUI.$on("change-contact", () => {
|
||||
this.closeClipboardImage();
|
||||
});
|
||||
@@ -156,21 +153,10 @@ export default {
|
||||
</div>
|
||||
);
|
||||
},
|
||||
methods: {
|
||||
closeClipboardImage() {
|
||||
this.clipboardUrl = "";
|
||||
this.clipboardBlob = null;
|
||||
},
|
||||
sendClipboardImage() {
|
||||
if (!this.clipboardBlob) return;
|
||||
this.$emit("upload", this.clipboardBlob);
|
||||
this.closeClipboardImage();
|
||||
},
|
||||
/**
|
||||
* 初始化工具栏
|
||||
*/
|
||||
initTools(data) {
|
||||
if (!data) return;
|
||||
computed: {
|
||||
proxyTools() {
|
||||
console.log("this.tools", this.tools);
|
||||
if (!this.tools) return [];
|
||||
const defaultTools = [
|
||||
{
|
||||
name: "emoji",
|
||||
@@ -198,14 +184,14 @@ export default {
|
||||
},
|
||||
];
|
||||
let tools = [];
|
||||
if (Array.isArray(data)) {
|
||||
if (Array.isArray(this.tools)) {
|
||||
const indexMap = {
|
||||
emoji: 0,
|
||||
uploadFile: 1,
|
||||
uploadImage: 2,
|
||||
};
|
||||
const indexKeys = Object.keys(indexMap);
|
||||
tools = data.map(item => {
|
||||
tools = this.tools.map(item => {
|
||||
if (indexKeys.includes(item.name)) {
|
||||
return {
|
||||
...defaultTools[indexMap[item.name]],
|
||||
@@ -217,20 +203,46 @@ export default {
|
||||
} else {
|
||||
tools = defaultTools;
|
||||
}
|
||||
this.proxyTools = tools;
|
||||
return tools;
|
||||
},
|
||||
_saveLastRange() {
|
||||
lastSelectionRange = selection.getRangeAt(0);
|
||||
},
|
||||
methods: {
|
||||
closeClipboardImage() {
|
||||
this.clipboardUrl = "";
|
||||
this.clipboardBlob = null;
|
||||
},
|
||||
_focusLastRange() {
|
||||
sendClipboardImage() {
|
||||
if (!this.clipboardBlob) return;
|
||||
this.$emit("upload", this.clipboardBlob);
|
||||
this.closeClipboardImage();
|
||||
},
|
||||
saveRangeToLast() {
|
||||
if (!range) {
|
||||
range = document.createRange();
|
||||
}
|
||||
range.selectNodeContents(textarea.value);
|
||||
range.collapse(false);
|
||||
selection.removeAllRanges();
|
||||
selection.addRange(range);
|
||||
},
|
||||
inertContent(val, toLast = false) {
|
||||
if (toLast) saveRangeToLast();
|
||||
this.focusRange();
|
||||
command("insertHTML", val);
|
||||
this.saveRange();
|
||||
},
|
||||
saveRange() {
|
||||
range = selection.getRangeAt(0);
|
||||
},
|
||||
focusRange() {
|
||||
this.$refs.textarea.focus();
|
||||
if (lastSelectionRange) {
|
||||
if (range) {
|
||||
selection.removeAllRanges();
|
||||
selection.addRange(lastSelectionRange);
|
||||
selection.addRange(range);
|
||||
}
|
||||
},
|
||||
_handleClick() {
|
||||
this._saveLastRange();
|
||||
this.saveRange();
|
||||
},
|
||||
_renderEmojiTabs() {
|
||||
const renderImageGrid = items => {
|
||||
@@ -261,10 +273,10 @@ export default {
|
||||
}
|
||||
},
|
||||
_handleSelectEmoji(item) {
|
||||
this._focusLastRange();
|
||||
exec(`<img emoji-name="${item.name}" src="${item.src}"></img>`);
|
||||
this.inertContent(
|
||||
`<img emoji-name="${item.name}" src="${item.src}"></img>`,
|
||||
);
|
||||
this._checkSubmitDisabled();
|
||||
this._saveLastRange();
|
||||
},
|
||||
async selectFile(accept) {
|
||||
this.accept = accept;
|
||||
@@ -279,7 +291,7 @@ export default {
|
||||
if (window.clipboardData) {
|
||||
this.$refs.textarea.innerHTML = text;
|
||||
} else {
|
||||
exec(text, "insertText");
|
||||
command("insertText", text);
|
||||
}
|
||||
} else {
|
||||
const { blob, blobUrl } = this._getClipboardBlob(clipboardData);
|
||||
@@ -301,10 +313,42 @@ export default {
|
||||
return { blob, blobUrl };
|
||||
},
|
||||
_handleKeyup(e) {
|
||||
this._saveLastRange();
|
||||
this.saveRange();
|
||||
this._checkSubmitDisabled();
|
||||
},
|
||||
_handleKeydown(e) {
|
||||
const ATing = false;
|
||||
if (ATing) {
|
||||
if (e.keyCode == 38 || e.keyCode == 40) {
|
||||
e.preventDefault();
|
||||
if (e.keyCode == 38) {
|
||||
ATSelectedPrev();
|
||||
}
|
||||
if (e.keyCode == 40) {
|
||||
ATSelectedNext();
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (e.keyCode == 13) {
|
||||
e.preventDefault();
|
||||
ATSelected();
|
||||
return;
|
||||
}
|
||||
if (e.keyCode == 37 || e.keyCode == 39) {
|
||||
ATPopupClose();
|
||||
}
|
||||
}
|
||||
if (e.keyCode == 13 || (e.keyCode == 13 && e.shiftKey)) {
|
||||
e.preventDefault();
|
||||
}
|
||||
if (this.wrapKey(e)) {
|
||||
e.preventDefault();
|
||||
command("insertLineBreak");
|
||||
}
|
||||
if (this.at && (e.key == "@" || (e.shiftKey && e.keyCode == 229))) {
|
||||
setTimeout(() => (ATing = true), 300);
|
||||
}
|
||||
|
||||
if (this.submitDisabled == false && this.sendKey(e)) {
|
||||
this._handleSend();
|
||||
}
|
||||
|
||||
@@ -105,7 +105,11 @@ export default {
|
||||
activeSidebar: DEFAULT_MENU_LASTMESSAGES,
|
||||
contacts: [],
|
||||
menus: [],
|
||||
editorTools: [],
|
||||
editorTools: [
|
||||
{ name: "emoji" },
|
||||
{ name: "uploadFile" },
|
||||
{ name: "uploadImage" },
|
||||
],
|
||||
};
|
||||
},
|
||||
|
||||
@@ -793,8 +797,9 @@ export default {
|
||||
flatData.forEach(({ name, src }) => (emojiMap[name] = src));
|
||||
},
|
||||
initEditorTools(data) {
|
||||
//this.editorTools = data;
|
||||
this.editorTools = data;
|
||||
this.$refs.editor.initTools(data);
|
||||
//this.$refs.editor.initTools(data);
|
||||
},
|
||||
/**
|
||||
* 初始化左侧按钮
|
||||
|
||||
@@ -1,130 +0,0 @@
|
||||
import { MESSAGE_TYPE, MESSAGE_STATUS, CONTACT_TYPE } from "utils/constant";
|
||||
import { error } from "utils";
|
||||
import { isPlainObject } from "utils/validate";
|
||||
|
||||
const constraintContactBasic = data =>
|
||||
constraintObject(data, {
|
||||
id: true,
|
||||
displayName: true,
|
||||
avatar: true,
|
||||
type: {
|
||||
required: true,
|
||||
has: CONTACT_TYPE
|
||||
}
|
||||
});
|
||||
const constraintMessageBasic = data =>
|
||||
constraintObject(data, {
|
||||
content: true,
|
||||
sendTime: true,
|
||||
type: {
|
||||
required: true,
|
||||
has: MESSAGE_TYPE
|
||||
}
|
||||
});
|
||||
|
||||
// constraintContact({
|
||||
// id: "123",
|
||||
// displayName: "123asd",
|
||||
// avatar: "123",
|
||||
// type: "single",
|
||||
// message: {
|
||||
// unread: 0,
|
||||
// sendTime: 12312312,
|
||||
// content: "12312312",
|
||||
// type: "image"
|
||||
// }
|
||||
// });
|
||||
|
||||
constraintContact({
|
||||
id: "123",
|
||||
displayName: "123asd",
|
||||
avatar: "123",
|
||||
type: "single",
|
||||
unread: 0,
|
||||
lastSendTime: "",
|
||||
subText: "12312312"
|
||||
// message: {
|
||||
// unread: 0,
|
||||
// sendTime: 12312312,
|
||||
// content: "12312312",
|
||||
// type: "image"
|
||||
// }
|
||||
});
|
||||
|
||||
// constraintRecentContact({
|
||||
// fromContactId: 0,
|
||||
// unread: 0,
|
||||
// sendTime: 12312312,
|
||||
// content: "12312312"
|
||||
// });
|
||||
|
||||
constraintMessage({
|
||||
id: "123",
|
||||
status: "succeed",
|
||||
type: "image",
|
||||
sendTime: 12312312312,
|
||||
content: "asdas",
|
||||
fromContactId: "123",
|
||||
fromUser: { id: "123", displayName: "123", avatar: "123", type: "single" }
|
||||
});
|
||||
export function constraintObject(data, options) {
|
||||
if (!data || !isPlainObject(data)) {
|
||||
error("argument must be an object");
|
||||
}
|
||||
Object.keys(options).forEach(k => {
|
||||
const option = options[k];
|
||||
const val = data[k];
|
||||
if ((option === true || option.required === true) && val === undefined) {
|
||||
error(`"${k}" cannot be "${val}" `);
|
||||
} else if (option.has && !option.has.includes(val)) {
|
||||
error(
|
||||
`"${k}" cannot be "${val}",can only be the following data "${
|
||||
option.has
|
||||
}"`
|
||||
);
|
||||
}
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
// export function constraintRecentContact(data) {
|
||||
// constraintContact(data);
|
||||
// constraintMessageBasic(data.message);
|
||||
// constraintObject(data, {
|
||||
// unread: true
|
||||
// });
|
||||
// }
|
||||
export function constraintContact(data) {
|
||||
constraintContactBasic(data);
|
||||
// constraintObject(data, {
|
||||
// unread: true,
|
||||
// lastSendTime: true,
|
||||
// lastContent: true
|
||||
// });
|
||||
}
|
||||
export function constraintMessage(data) {
|
||||
constraintObject(data, {
|
||||
status: {
|
||||
required: true,
|
||||
has: MESSAGE_STATUS
|
||||
},
|
||||
fromContactId: true
|
||||
});
|
||||
constraintMessageBasic(data);
|
||||
constraintContactBasic(data.fromUser);
|
||||
let options = {};
|
||||
switch (data.type) {
|
||||
case "file":
|
||||
options = {
|
||||
fileSize: true,
|
||||
fileName: true
|
||||
};
|
||||
break;
|
||||
case "text":
|
||||
options = {
|
||||
text: true
|
||||
};
|
||||
break;
|
||||
}
|
||||
constraintObject(data, options);
|
||||
}
|
||||
@@ -1,4 +1,6 @@
|
||||
import { isPlainObject, isFunction } from "utils/validate";
|
||||
export function messageToHtml() {}
|
||||
export function messageToText() {}
|
||||
/**
|
||||
* 使用某个组件上的作用域插槽
|
||||
* @param {VueComponent} inject
|
||||
@@ -44,7 +46,7 @@ export function timeFormat(t, format) {
|
||||
padZero(t.getDate().toString()),
|
||||
padZero(t.getHours().toString()),
|
||||
padZero(t.getMinutes().toString()),
|
||||
padZero(t.getSeconds().toString())
|
||||
padZero(t.getSeconds().toString()),
|
||||
];
|
||||
const reg = "ymdhis";
|
||||
for (let i = 0; i < formatArr.length; i++) {
|
||||
@@ -71,12 +73,12 @@ export function arrayIntersect(a, b) {
|
||||
return a.filter(x => b.includes(x));
|
||||
}
|
||||
//清除字符串内的所有HTML标签
|
||||
export function clearHtml(str){
|
||||
return str.replace(/<.*?>/ig,"");
|
||||
export function clearHtml(str) {
|
||||
return str.replace(/<.*?>/gi, "");
|
||||
}
|
||||
//清除字符串内的所有HTML标签,除了IMG
|
||||
export function clearHtmlExcludeImg(str){
|
||||
return str.replace(/<(?!img).*?>/ig, "");
|
||||
export function clearHtmlExcludeImg(str) {
|
||||
return str.replace(/<(?!img).*?>/gi, "");
|
||||
}
|
||||
export function error(text) {
|
||||
throw new Error(text);
|
||||
@@ -122,7 +124,7 @@ export function generateUUID() {
|
||||
d += performance.now(); //use high-precision timer if available
|
||||
}
|
||||
var uuid = "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function(
|
||||
c
|
||||
c,
|
||||
) {
|
||||
var r = (d + Math.random() * 16) % 16 | 0;
|
||||
d = Math.floor(d / 16);
|
||||
|
||||
Reference in New Issue
Block a user