Remove all voice input related UI elements, speech recognition logic, and external RecordingWaveBtn dependency from the chat input area, simplifying the component to only support text input.
155 lines
4.6 KiB
Vue
155 lines
4.6 KiB
Vue
<template>
|
||
<div class="input-area-wrapper" @touchend="handleVoiceTouchEndFromContainer"
|
||
@touchcancel="handleVoiceTouchEndFromContainer">
|
||
<div
|
||
class="mx-[8px] mb-[6px] flex min-h-[42px] items-center rounded-[21px] bg-white px-[8px] py-[6px] shadow-[0_2px_12px_rgba(18,39,75,0.06)]">
|
||
<div class="flex h-[30px] w-[30px] shrink-0 items-center justify-center">
|
||
<img class="h-[22px] w-[22px]" src="https://oss.nianxx.cn/mp/static/version_101/home/input_keyboard_icon.png" />
|
||
</div>
|
||
|
||
<!-- 输入框 -->
|
||
<div class="flex min-h-[30px] min-w-0 flex-1 items-center">
|
||
<textarea ref="textareaRef" v-model="inputMessage" rows="1" maxlength="300" :placeholder="placeholder"
|
||
class="block h-[22px] max-h-[92px] min-h-[22px] w-full resize-none overflow-x-hidden overflow-y-auto border-0 bg-transparent p-0 text-[14px] leading-[22px] text-[#333] outline-none appearance-none placeholder:text-[#A5AAB4] scrollbar-none [&::-webkit-scrollbar]:hidden"
|
||
@input="adjustTextareaHeight" @focus="handleFocus" @blur="handleBlur" @touchstart="handleTouchStart"
|
||
@touchend="handleTouchEnd" />
|
||
</div>
|
||
|
||
<div class="flex h-[30px] w-[34px] shrink-0 items-center justify-end">
|
||
<div
|
||
class="flex h-[30px] w-[30px] items-center justify-center rounded-full [background:radial-gradient(39%_39%_at_97%_81%,#79dffb_0%,rgba(138,227,252,0)_100%),radial-gradient(54%_54%_at_3%_70%,#8afcf8_0%,rgba(138,252,248,0)_100%),#0CCD58] shadow-[0_4px_10px_rgba(12,205,88,0.22)]"
|
||
@click="sendMessage">
|
||
<div v-if="isSessionActive" class="h-[10px] w-[10px] rounded-[3px] bg-white"> </div>
|
||
<img v-else class="h-[20px] w-[20px]"
|
||
src="https://oss.nianxx.cn/mp/static/version_101/home/input_send_icon.png" />
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="text-center text-[9px] leading-[12px] text-[#A5AAB4] pb-[6px]">
|
||
内容由AI大模型生成,请仔细鉴别
|
||
</div>
|
||
</div>
|
||
</template>
|
||
|
||
<script setup>
|
||
import { ref, computed, watch, nextTick, onMounted, defineExpose, onUnmounted } from "vue";
|
||
|
||
const props = defineProps({
|
||
modelValue: String,
|
||
holdKeyboard: Boolean,
|
||
isSessionActive: Boolean,
|
||
stopRequest: Function,
|
||
});
|
||
const emit = defineEmits([
|
||
"update:modelValue",
|
||
"send",
|
||
"noHideKeyboard",
|
||
"keyboardShow",
|
||
"keyboardHide",
|
||
]);
|
||
|
||
const textareaRef = ref(null);
|
||
const placeholder = ref("快告诉小七您在想什么~");
|
||
const inputMessage = ref(props.modelValue || "");
|
||
const maxTextareaHeight = 92;
|
||
const isFocused = ref(false);
|
||
const keyboardHeight = ref(0);
|
||
|
||
const adjustTextareaHeight = () => {
|
||
const textarea = textareaRef.value;
|
||
if (!textarea) return;
|
||
|
||
textarea.style.height = "22px";
|
||
textarea.style.height = `${Math.min(textarea.scrollHeight, maxTextareaHeight)}px`;
|
||
};
|
||
|
||
// 保持和父组件同步
|
||
watch(
|
||
() => props.modelValue,
|
||
(val) => {
|
||
inputMessage.value = val;
|
||
nextTick(adjustTextareaHeight);
|
||
}
|
||
);
|
||
|
||
// 当子组件的 inputMessage 变化时,通知父组件(但要避免循环更新)
|
||
watch(inputMessage, (val) => {
|
||
// 只有当值真正不同时才emit,避免循环更新
|
||
if (val !== props.modelValue) {
|
||
emit("update:modelValue", val);
|
||
}
|
||
nextTick(adjustTextareaHeight);
|
||
});
|
||
|
||
// 监听键盘高度变化
|
||
onMounted(() => {
|
||
nextTick(adjustTextareaHeight);
|
||
});
|
||
|
||
const hideKeyboardAfterSend = () => {
|
||
isFocused.value = false;
|
||
|
||
const textarea = textareaRef.value;
|
||
if (textarea && typeof textarea.blur === "function") {
|
||
textarea.blur();
|
||
}
|
||
};
|
||
|
||
const sendMessage = () => {
|
||
if (props.isSessionActive) {
|
||
// 如果会话进行中,调用停止请求函数
|
||
if (props.stopRequest) {
|
||
props.stopRequest();
|
||
}
|
||
hideKeyboardAfterSend();
|
||
} else {
|
||
// 否则发送新消息
|
||
if (!inputMessage.value.trim()) return;
|
||
emit("send", inputMessage.value);
|
||
hideKeyboardAfterSend();
|
||
}
|
||
};
|
||
|
||
const handleFocus = () => {
|
||
isFocused.value = true;
|
||
emit("noHideKeyboard");
|
||
};
|
||
|
||
const handleBlur = () => {
|
||
isFocused.value = false;
|
||
};
|
||
|
||
const handleTouchStart = () => {
|
||
emit("noHideKeyboard");
|
||
};
|
||
|
||
const handleTouchEnd = () => {
|
||
emit("noHideKeyboard");
|
||
};
|
||
|
||
// 手动聚焦输入框
|
||
const focusInput = () => {
|
||
isFocused.value = true;
|
||
nextTick(() => {
|
||
const textarea = textareaRef.value;
|
||
if (textarea && typeof textarea.focus === "function") {
|
||
textarea.focus();
|
||
}
|
||
});
|
||
};
|
||
|
||
// 手动失焦输入框
|
||
const blurInput = () => {
|
||
isFocused.value = false;
|
||
|
||
const textarea = textareaRef.value;
|
||
if (textarea && typeof textarea.blur === "function") {
|
||
textarea.blur();
|
||
}
|
||
};
|
||
|
||
// 暴露方法给父组件
|
||
defineExpose({ focusInput, blurInput });
|
||
</script>
|