Files
im/pages/conversation/chating/components/ChatingFooter/CustomEditor.vue
T
cansnow 375917f06c emoji
2025-12-09 09:27:29 +08:00

193 lines
4.3 KiB
Vue

<template>
<view class="editor_wrap">
<editor
:placeholder="placeholder"
id="editor2"
@ready="editorReady"
@focus="editorFocus"
@blur="editorBlur"
@input="editorInput" />
</view>
</template>
<script>
import { forIn } from "lodash";
import {html2Text} from "@/util/common";
export default {
props: {
placeholder: {
type: String,
default: "",
},
},
data() {
return {
editorCtx: null,
lastStr: "",
isInsertingEmoji: false, // 标记是否正在插入表情
hasFocus: false, // 记录编辑器是否有焦点
};
},
methods: {
editorReady() {
uni
.createSelectorQuery()
.select("#editor2")
.context((res) => {
//this.$emit("ready", res);
this.editorCtx = res.context;
})
.exec();
},
editorFocus() {
this.hasFocus = true;
// 如果正在插入表情,不触发 focus 事件,并立即隐藏键盘
if (this.isInsertingEmoji) {
// #ifdef APP-PLUS || H5
uni.hideKeyboard();
// #endif
return;
}
this.$emit("focus");
},
editorBlur() {
this.hasFocus = false;
this.$emit("blur");
},
clear(){
this.editorCtx.clear()
},
insertText(text,successFn,errFn){
// 标记正在插入表情,阻止 focus 事件触发
this.isInsertingEmoji = true;
// 先隐藏键盘,避免插入时键盘弹出
// #ifdef APP-PLUS || H5
uni.hideKeyboard();
// #endif
// 如果编辑器当前有焦点,先让它失焦(通过点击外部区域)
// 但这种方式可能不太可靠,所以我们主要依赖 isInsertingEmoji 标志
// 使用 insertText 插入文本(这是最可靠的方法)
// 虽然会触发焦点,但我们已经通过 isInsertingEmoji 标志阻止了 focus 事件
this.editorCtx.insertText({
text: text,
success: (res) => {
successFn && successFn.call(this, [res]);
console.log("插入文字成功");
// 插入后立即隐藏键盘,防止键盘弹出
// #ifdef APP-PLUS || H5
// 使用多个延迟确保键盘被隐藏
setTimeout(() => {
uni.hideKeyboard();
}, 10);
setTimeout(() => {
uni.hideKeyboard();
}, 50);
setTimeout(() => {
uni.hideKeyboard();
}, 100);
// #endif
// 延迟重置标志,确保 focus 事件被完全忽略
setTimeout(() => {
this.isInsertingEmoji = false;
}, 300);
},
fail: (err) => {
errFn && errFn.call(this, [err]);
console.log("插入文字失败", err);
this.isInsertingEmoji = false;
}
});
},
delete(){
this.editorCtx.getContents({
success({html,text,delta}){
console.log(html,text,delta);
}
})
return ;
//setContents(OBJECT)
let emojiStr = this.editorCtx.getContents();
let emojiArr = [];
emojiStr = emojiStr.replace(/\[([^(\]|\[)]*)\]/g, function(item, index) {
emojiArr.unshift(item);
});
let sendStr ="";
if (emojiArr.length > 0) {
if (this.sendStr.endsWith(emojiArr[0])) {
this.sendStr = this.sendStr.replace(emojiArr[0], "");
} else {
this.sendStr = this.sendStr.slice(0, this.sendStr.length - 1);
}
} else {
this.sendStr = this.sendStr.slice(0, this.sendStr.length - 1);
}
this.editorCtx.setContents({
html:sendStr
})
console.log('delete')
},
editorInput(e) {
let str = e.detail.html;
const oldArr = (this.lastStr ?? '').split("");
let contentStr = str;
oldArr.forEach((str) => {
contentStr = contentStr.replace(str, "");
});
contentStr = html2Text(contentStr);
this.$emit("input", e);
this.lastStr = e.detail.html;
},
},
};
</script>
<style lang="scss" scoped>
.editor_wrap {
position: relative;
}
#editor2 {
background-color: #fff;
min-height: 30px;
max-height: 120px;
height: auto;
word-break: break-all;
}
::v-deep.ql-editor {
img {
vertical-align: sub !important;
}
p {
padding: 4px;
}
}
.canvas_container {
position: fixed;
bottom: -99px;
z-index: -100;
&_name {
max-width: 480rpx;
display: inline-block;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
#atCanvas {
height: 20px;
}
.convas_container_name {
font-size: 16px !important;
}
}
</style>