fix(details): 优化表情选择功能,支持在光标位置插入表情

修复了在评论框中插入表情时无法在光标位置插入的问题,现在可以正确在光标处插入表情符号。同时优化了相关代码结构,提升了用户体验。
This commit is contained in:
DESKTOP-RQ919RC\Pc
2025-12-08 10:51:35 +08:00
parent a70a25428a
commit d9ef642fa2
48 changed files with 511 additions and 384 deletions

View File

@@ -307,7 +307,7 @@
<div class="input-box">
<div class="top flexflex">
<img class="avatar" v-if="user.avatar" :src="user.avatar" />
<textarea class="input-textarea flex1" maxlength="500" v-model="commentInputTop" @focus="judgeLogin" @input="autoResize" @paste="handleInputPaste" placeholder="说说你的想法或疑问…"></textarea>
<textarea class="input-textarea flex1" ref="inputTextareaRef" maxlength="500" v-model="commentInputTop" @focus="judgeLogin" @input="autoResize" @paste="handleInputPaste" placeholder="说说你的想法或疑问…"></textarea>
</div>
<div class="picture-box flexacenter" v-if="picture.length != 0">
@@ -396,7 +396,7 @@
<img class="cross" @click="closeAnswerCommentsChild()" src="@/assets/img/cross-icon.png" />
<div class="top flexflex">
<img class="avatar" v-if="user.avatar" :src="user.avatar" />
<textarea class="input-textarea flex1" maxlength="500" placeholder="说说你的想法或疑问…" v-model="item['commentInput']" @focus="judgeLogin" @input="autoResize" @paste="handleInputPaste($event, index)"></textarea>
<textarea class="input-textarea flex1" :class="[`input-textarea-${item.id}`]" maxlength="500" placeholder="说说你的想法或疑问…" v-model="item['commentInput']" @focus="judgeLogin" @input="autoResize" @paste="handleInputPaste($event, index)"></textarea>
</div>
<div class="picture-box flexacenter" v-if="item?.picture?.length != 0">
@@ -482,7 +482,7 @@
<div class="input-box" v-if="ite['childState']">
<img class="cross" @click="closeAnswerCommentsChild()" src="@/assets/img/cross-icon.png" />
<div class="top flexflex">
<textarea class="input-textarea flex1" maxlength="500" :placeholder="'回复“' + (ite['nickname'] || ite.user['nickname'] || '匿名用户') + '”:'" v-model="ite['commentInput']" @input="autoResize" @paste="handleInputPaste($event, index)"></textarea>
<textarea class="input-textarea flex1" :class="[`input-textarea-${ite.id}`]" maxlength="500" :placeholder="'回复“' + (ite['nickname'] || ite.user['nickname'] || '匿名用户') + '”:'" v-model="ite['commentInput']" @input="autoResize" @paste="handleInputPaste($event, index)"></textarea>
</div>
<div class="picture-box flexacenter" v-if="ite.picture?.length != 0" style="width: 688px">
<div class="picture" v-for="it in ite.picture" :key="it.url">
@@ -2183,20 +2183,82 @@ const closeEmoji = (index, i) => {
editEmojiState.value = false;
};
const inputTextareaRef = ref(null);
// 选择 Emoji
const selectEmoji = (key, index, i) => {
closeEmoji();
if (i != undefined) {
if (!commentList.value[index]["child"][i]["commentInput"]) commentList.value[index]["child"][i]["commentInput"] = "";
commentList.value[index]["child"][i]["commentInput"] += key;
const id = commentList.value[index]["child"][i]?.id;
const textarea = document.querySelector(`.input-textarea-${id}`);
if (textarea) {
const currentValue = textarea.value;
const startPos = textarea.selectionStart || 0;
const endPos = textarea.selectionEnd || 0;
const newValue = currentValue.substring(0, startPos) + key + currentValue.substring(endPos);
commentList.value[index]["child"][i]["commentInput"] = newValue;
nextTick(() => {
textarea.focus();
textarea.selectionStart = textarea.selectionEnd = startPos + key.length;
});
} else commentList.value[index]["child"][i]["commentInput"] += key;
} else if (index != undefined) {
if (!commentList.value[index]["commentInput"]) commentList.value[index]["commentInput"] = "";
commentList.value[index]["commentInput"] += key;
const id = commentList.value[index]?.id;
const textarea = document.querySelector(`.input-textarea-${id}`);
if (textarea) {
const currentValue = textarea.value;
const startPos = textarea.selectionStart || 0;
const endPos = textarea.selectionEnd || 0;
const newValue = currentValue.substring(0, startPos) + key + currentValue.substring(endPos);
commentList.value[index]["commentInput"] = newValue;
nextTick(() => {
textarea.focus();
textarea.selectionStart = textarea.selectionEnd = startPos + key.length;
});
} else commentList.value[index]["commentInput"] += key;
} else {
commentInputTop.value += key;
const textarea = inputTextareaRef.value;
if (!textarea) return;
const currentValue = textarea.value;
const startPos = textarea.selectionStart || 0;
const endPos = textarea.selectionEnd || 0;
const newValue = currentValue.substring(0, startPos) + key + currentValue.substring(endPos);
commentInputTop.value = newValue;
nextTick(() => {
textarea.focus();
textarea.selectionStart = textarea.selectionEnd = startPos + key.length;
});
}
};
// 选择 Emoji
// const selectEmoji = (key, index, i) => {
// closeEmoji();
// if (i != undefined) {
// if (!commentList.value[index]["child"][i]["commentInput"]) commentList.value[index]["child"][i]["commentInput"] = "";
// commentList.value[index]["child"][i]["commentInput"] += key;
// } else if (index != undefined) {
// if (!commentList.value[index]["commentInput"]) commentList.value[index]["commentInput"] = "";
// commentList.value[index]["commentInput"] += key;
// } else {
// commentInputTop.value += key;
// }
// };
// 自动输入框增高
const autoResize = (e) => {
e.target.style.height = "auto"; // 重置高度
@@ -2467,9 +2529,28 @@ const openEditEmoji = (index, i) => {
editEmojiState.value = true;
};
// const selectEditEmoji = (key) => {
// closeEmoji();
// editInput.value += key;
// };
const selectEditEmoji = (key) => {
closeEmoji();
editInput.value += key;
const textarea = editInputRef.value;
if (!textarea) return;
const currentValue = textarea.value;
const startPos = textarea.selectionStart || 0;
const endPos = textarea.selectionEnd || 0;
const newValue = currentValue.substring(0, startPos) + key + currentValue.substring(endPos);
editInput.value = newValue;
nextTick(() => {
textarea.focus();
textarea.selectionStart = textarea.selectionEnd = startPos + key.length;
});
};
const postEditComment = () => {