149 lines
4.6 KiB
TypeScript
149 lines
4.6 KiB
TypeScript
import { useState, useRef } from 'react';
|
|
|
|
interface CompactSearchBoxProps {
|
|
onSearch: (query: string) => void;
|
|
initialQuery?: string;
|
|
searchTime?: string;
|
|
}
|
|
|
|
export function CompactSearchBox({
|
|
onSearch,
|
|
initialQuery = '',
|
|
searchTime = '搜索用时 0.3秒'
|
|
}: CompactSearchBoxProps) {
|
|
const [searchQuery, setSearchQuery] = useState(initialQuery);
|
|
const textareaRef = useRef<HTMLTextAreaElement>(null);
|
|
|
|
const handleSearchInputChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => {
|
|
const value = e.target.value;
|
|
setSearchQuery(value);
|
|
|
|
// 自动调整高度
|
|
if (textareaRef.current) {
|
|
textareaRef.current.style.height = 'auto';
|
|
textareaRef.current.style.height = Math.max(60, textareaRef.current.scrollHeight) + 'px';
|
|
}
|
|
};
|
|
|
|
const handleSearch = () => {
|
|
if (searchQuery.trim()) {
|
|
onSearch(searchQuery);
|
|
}
|
|
};
|
|
|
|
const handleKeyDown = (e: React.KeyboardEvent<HTMLTextAreaElement>) => {
|
|
if (e.key === 'Enter' && (e.ctrlKey || e.metaKey)) {
|
|
e.preventDefault();
|
|
handleSearch();
|
|
}
|
|
};
|
|
|
|
return (
|
|
<div>
|
|
<div style={{
|
|
|
|
margin: '0',
|
|
background: 'none'
|
|
}}>
|
|
<div style={{
|
|
maxWidth: '600px',
|
|
margin: '0 auto',
|
|
position: 'relative'
|
|
}}>
|
|
<div style={{
|
|
background: 'white',
|
|
border: '2px solid #e5e7eb',
|
|
borderRadius: '8px',
|
|
padding: '12px 16px',
|
|
boxShadow: '0 2px 8px rgba(0, 0, 0, 0.06)',
|
|
transition: 'all 0.3s ease'
|
|
}}>
|
|
<textarea
|
|
ref={textareaRef}
|
|
placeholder="例如:销售合同、设备采购协议、包含违约责任条款的合同..."
|
|
value={searchQuery}
|
|
onChange={handleSearchInputChange}
|
|
onKeyDown={handleKeyDown}
|
|
aria-label="合同模板搜索输入框"
|
|
style={{
|
|
width: '100%',
|
|
minHeight: '60px',
|
|
border: 'none',
|
|
outline: 'none',
|
|
resize: 'vertical',
|
|
fontSize: '14px',
|
|
lineHeight: '1.5',
|
|
background: 'transparent',
|
|
margin: '0',
|
|
padding: '0',
|
|
fontFamily: 'inherit'
|
|
}}
|
|
/>
|
|
|
|
{/* 搜索操作区域 - 水平布局 */}
|
|
<div style={{
|
|
display: 'flex',
|
|
justifyContent: 'space-between',
|
|
alignItems: 'center',
|
|
width: '100%',
|
|
marginTop: '8px',
|
|
paddingTop: '8px',
|
|
borderTop: '1px solid #f0f0f0'
|
|
}}>
|
|
{/* 搜索时间提示 - 左侧 */}
|
|
<div style={{
|
|
fontSize: '11px',
|
|
color: 'rgba(0, 0, 0, 0.45)',
|
|
display: 'flex',
|
|
alignItems: 'center',
|
|
flex: '1'
|
|
}}>
|
|
<i className="ri-time-line" style={{ marginRight: '4px', fontSize: '11px' }}></i>
|
|
{searchTime}
|
|
</div>
|
|
|
|
{/* 重新搜索按钮 - 右侧 */}
|
|
<button
|
|
onClick={handleSearch}
|
|
disabled={!searchQuery.trim()}
|
|
aria-label="重新搜索"
|
|
style={{
|
|
background: '#00684a',
|
|
color: 'white',
|
|
border: 'none',
|
|
borderRadius: '6px',
|
|
padding: '6px 16px',
|
|
fontSize: '14px',
|
|
fontWeight: '500',
|
|
cursor: 'pointer',
|
|
transition: 'all 0.3s ease',
|
|
display: 'flex',
|
|
alignItems: 'center',
|
|
justifyContent: 'center',
|
|
gap: '6px',
|
|
margin: '0',
|
|
flexShrink: '0'
|
|
}}
|
|
onMouseEnter={(e) => {
|
|
if (!e.currentTarget.disabled) {
|
|
e.currentTarget.style.background = '#005a40';
|
|
e.currentTarget.style.transform = 'translateY(-1px)';
|
|
}
|
|
}}
|
|
onMouseLeave={(e) => {
|
|
if (!e.currentTarget.disabled) {
|
|
e.currentTarget.style.background = '#00684a';
|
|
e.currentTarget.style.transform = 'translateY(0)';
|
|
}
|
|
}}
|
|
>
|
|
<i className="ri-search-line" style={{ fontSize: '13px' }}></i>
|
|
重新搜索
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|