2025-12-15 11:31:18 +00:00
|
|
|
|
'use client';
|
2025-12-09 09:13:46 +00:00
|
|
|
|
|
2025-12-15 11:31:18 +00:00
|
|
|
|
import { IconButton } from '@/components/ui/button';
|
|
|
|
|
|
import { cn } from '@/lib/utils';
|
2025-12-17 10:13:47 +00:00
|
|
|
|
import { useStreamChatStore } from '@/stores/stream-chat';
|
2025-12-15 11:31:18 +00:00
|
|
|
|
import { useState, useRef, useEffect } from 'react';
|
2025-12-09 09:13:46 +00:00
|
|
|
|
|
|
|
|
|
|
const AuthHeightTextarea = (props: React.ComponentProps<'textarea'> & { maxHeight?: number }) => {
|
2025-12-15 11:31:18 +00:00
|
|
|
|
const { maxHeight = 200, className, value, onChange, ...restProps } = props;
|
|
|
|
|
|
const textareaRef = useRef<HTMLTextAreaElement>(null);
|
2025-12-09 09:13:46 +00:00
|
|
|
|
|
|
|
|
|
|
// 调整高度的函数
|
|
|
|
|
|
const adjustHeight = () => {
|
2025-12-15 11:31:18 +00:00
|
|
|
|
const textarea = textareaRef.current;
|
|
|
|
|
|
if (!textarea) return;
|
2025-12-09 09:13:46 +00:00
|
|
|
|
|
|
|
|
|
|
// 先重置高度为 0,这样才能获取真实的 scrollHeight
|
2025-12-15 11:31:18 +00:00
|
|
|
|
textarea.style.height = '0px';
|
2025-12-09 09:13:46 +00:00
|
|
|
|
|
|
|
|
|
|
// 获取内容实际需要的高度
|
2025-12-15 11:31:18 +00:00
|
|
|
|
const scrollHeight = textarea.scrollHeight;
|
2025-12-09 09:13:46 +00:00
|
|
|
|
|
|
|
|
|
|
// 计算新高度:取 scrollHeight 和 maxHeight 的较小值
|
2025-12-15 11:31:18 +00:00
|
|
|
|
const newHeight = Math.min(scrollHeight, maxHeight);
|
|
|
|
|
|
textarea.style.height = `${newHeight}px`;
|
2025-12-09 09:13:46 +00:00
|
|
|
|
|
|
|
|
|
|
// 如果内容超过最大高度,显示滚动条
|
2025-12-15 11:31:18 +00:00
|
|
|
|
textarea.style.overflowY = scrollHeight > maxHeight ? 'auto' : 'hidden';
|
|
|
|
|
|
};
|
2025-12-09 09:13:46 +00:00
|
|
|
|
|
|
|
|
|
|
// 监听内容变化,自动调整高度
|
|
|
|
|
|
useEffect(() => {
|
2025-12-15 11:31:18 +00:00
|
|
|
|
adjustHeight();
|
|
|
|
|
|
}, [value, maxHeight]);
|
2025-12-09 09:13:46 +00:00
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
|
<textarea
|
|
|
|
|
|
ref={textareaRef}
|
|
|
|
|
|
value={value}
|
|
|
|
|
|
onChange={onChange}
|
|
|
|
|
|
className={cn(
|
|
|
|
|
|
'w-full resize-none',
|
|
|
|
|
|
// 移除所有默认样式
|
|
|
|
|
|
'border-none outline-none focus:outline-none',
|
|
|
|
|
|
'bg-transparent',
|
|
|
|
|
|
// 自定义滚动条样式(可选)
|
|
|
|
|
|
'scrollbar-thin scrollbar-thumb-white/20 scrollbar-track-transparent',
|
|
|
|
|
|
className
|
|
|
|
|
|
)}
|
|
|
|
|
|
style={{
|
|
|
|
|
|
minHeight: '24px', // 最小高度,一行文字的高度
|
|
|
|
|
|
height: '24px', // 初始高度
|
|
|
|
|
|
overflow: 'hidden', // 初始隐藏滚动条
|
|
|
|
|
|
}}
|
|
|
|
|
|
{...restProps}
|
|
|
|
|
|
/>
|
2025-12-15 11:31:18 +00:00
|
|
|
|
);
|
|
|
|
|
|
};
|
2025-12-09 09:13:46 +00:00
|
|
|
|
|
|
|
|
|
|
export default function Input() {
|
2025-12-15 11:31:18 +00:00
|
|
|
|
const [isRecording, setIsRecording] = useState(false);
|
|
|
|
|
|
const [inputValue, setInputValue] = useState('');
|
2025-12-17 10:13:47 +00:00
|
|
|
|
const sendMessage = useStreamChatStore((state) => state.sendMessage);
|
2025-12-09 09:13:46 +00:00
|
|
|
|
|
|
|
|
|
|
return (
|
2025-12-15 11:31:18 +00:00
|
|
|
|
<div className="flex flex-col mb-6 items-end gap-4">
|
2025-12-09 09:13:46 +00:00
|
|
|
|
<div></div>
|
|
|
|
|
|
<div className="flex w-full items-end gap-4">
|
|
|
|
|
|
{/* 打电话按钮 */}
|
|
|
|
|
|
<IconButton onClick={() => {}} iconfont="icon-gift-border" />
|
|
|
|
|
|
<div className="flex-1 flex items-end gap-2 min-h-12 py-2 px-2 bg-white/15 rounded-3xl">
|
|
|
|
|
|
{/* 语音录制按钮 */}
|
|
|
|
|
|
<IconButton
|
|
|
|
|
|
variant="ghost"
|
|
|
|
|
|
size="small"
|
|
|
|
|
|
iconfont="icon-voice_msg"
|
|
|
|
|
|
className="flex-shrink-0"
|
|
|
|
|
|
/>
|
|
|
|
|
|
<AuthHeightTextarea
|
|
|
|
|
|
placeholder="Chat"
|
|
|
|
|
|
maxHeight={70}
|
|
|
|
|
|
value={inputValue}
|
|
|
|
|
|
onChange={(e) => setInputValue(e.target.value)}
|
|
|
|
|
|
className="py-1"
|
|
|
|
|
|
/>
|
|
|
|
|
|
{/* 提示词提示按钮 */}
|
|
|
|
|
|
<IconButton
|
|
|
|
|
|
variant="ghost"
|
|
|
|
|
|
size="small"
|
2025-12-17 10:13:47 +00:00
|
|
|
|
onClick={() => null}
|
2025-12-09 09:13:46 +00:00
|
|
|
|
className={cn('bg-surface-element-hover flex-shrink-0')}
|
|
|
|
|
|
iconfont="icon-prompt"
|
|
|
|
|
|
/>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<IconButton
|
|
|
|
|
|
size="large"
|
|
|
|
|
|
loading={false}
|
|
|
|
|
|
iconfont="icon-icon-send"
|
2025-12-17 10:13:47 +00:00
|
|
|
|
onClick={() => sendMessage(inputValue)}
|
2025-12-09 09:13:46 +00:00
|
|
|
|
disabled={false}
|
|
|
|
|
|
className="flex-shrink-0"
|
|
|
|
|
|
/>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
2025-12-15 11:31:18 +00:00
|
|
|
|
);
|
2025-12-09 09:13:46 +00:00
|
|
|
|
}
|