针对im输入框的一种处理方式
复制<template>
<div class="chatInput">
<div
id="edit"
ref="edit"
contenteditable
@compositionstart="doing = true"
@compositionend="handleSearch"
@input="handleKey"
@keyup="carReply"
@paste.prevent.trim="paste"
>
{{ splitContent.trim() }}
</div>
<div class="btn_wrap flex-end">
按Ctrl+Enter换行,按Enter输出
<el-button @click="send" type="primary"> 发送</el-button>
</div>
</div>
</template>
<script setup lang="ts" name="chatInput">
import { ref, onMounted } from "vue";
import { httpRequest } from "../chatUtil";
import { fileUpload } from "@/api/modules/chat";
interface PropsInterface {
send: any;
}
const props = defineProps<PropsInterface>();
const doing = ref(false);
const edit = ref() as any;
let splitContent = "";
let lastEditRange = null as any;
onMounted(() => {
const editDom = document.querySelector("#edit") as any;
editDom.addEventListener("blur", (e: any) => setSection());
editDom.focus();
setSection();
});
const setSection = () => {
let selection = getSelection() as any;
if (selection.getRangeAt && selection.rangeCount) {
lastEditRange = selection.getRangeAt(0);
}
};
const handleSearch = () => {
doing.value = false;
};
const handleKey = () => {
const e = window.event as any;
if (!doing.value) {
}
};
const carReply = () => {
const e = window.event as any;
if (e.ctrlKey && e.keyCode == 13) {
document.execCommand("insertText", false, "\n");
} else if (e.keyCode == 13) {
send();
}
};
const paste = (e: any) => {
const clipdata = e.clipboardData || (window as any).clipboardData;
const files = clipdata.files;
const text = clipdata.getData("text/plain");
text && document.execCommand("insertHTML", false, text);
if (files.length) {
Array.from(files).forEach((file: any) => {
if (file.type.match(/^image\//)) {
const windowURL = window.URL || window.webkitURL;
const url = windowURL.createObjectURL(file);
document.execCommand("insertImage", true, url);
}
});
}
};
const send = () => {
const edit = document.querySelector("#edit") as any;
if (edit.childNodes.length == 0) {
return;
}
const _arr = Array.from(edit.childNodes) as any;
contentRevese(_arr);
splitContent && props.send(splitContent);
splitContent = "";
edit.textContent = "";
};
const contentRevese: any = async (_arr: any) => {
for (let i = 0; i < _arr.length; i++) {
if (_arr[i].childNodes.length > 0) {
contentRevese(Array.from(_arr[i].childNodes));
} else {
if (_arr[i].tagName == "IMG") {
props.send(splitContent);
splitContent = "";
let img = (await httpRequest(_arr[i].src)) as any;
const windowURL = window.URL || window.webkitURL;
windowURL.revokeObjectURL(_arr[i].src);
const formData = new FormData() as any;
formData.append("files", img);
formData.append("type", "3");
const { data } = (await fileUpload(formData)) as any;
props.send(`img[${data.url}][${data.file_name}][size:${data.size}]`);
} else {
splitContent += _arr[i].textContent + "\n";
}
}
}
};
</script>
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 25岁的心里话
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现