Files
ftb-project-management/apps/web/components/SearchInput.tsx
Script Generator 52a88626d4 feat(版本): 完善计划覆盖与工作台待办
关键改动:

- 增加计划日志汇总、需求覆盖草稿校验与对应测试

- 抽取工作台工作项 Hook,补充待办计数能力

- 优化版本详情中计划、任务、测试用例和 Bug 的筛选与展示

Co-Authored-By: Codex GPT-5 <codex@openai.com>
2026-06-30 13:43:18 +08:00

49 lines
1.6 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

'use client';
import { Search, X } from 'lucide-react';
interface Props {
value: string;
onChange: (v: string) => void;
placeholder?: string;
className?: string;
}
/**
* 列表搜索框(标题 + 编号模糊匹配,外部需配合 useDebouncedValue 防抖)
*/
export function SearchInput({ value, onChange, placeholder = '搜索标题或编号', className = '' }: Props) {
return (
<div className={`relative inline-flex items-center ${className}`}>
<Search className="absolute left-2.5 h-3.5 w-3.5 text-[var(--ink-muted)] pointer-events-none" />
<input
type="text"
value={value}
onChange={(e) => onChange(e.target.value)}
placeholder={placeholder}
className="h-8 w-72 rounded-lg border border-[var(--line)] bg-[var(--bg-card)] pl-8 pr-7 text-[12px] text-[var(--ink)] placeholder:text-[var(--ink-muted)] focus:border-[var(--accent)] focus:outline-none"
/>
{value && (
<button
onClick={() => onChange('')}
className="absolute right-1.5 p-0.5 rounded hover:bg-[var(--bg-subtle)]"
title="清除"
>
<X className="h-3 w-3 text-[var(--ink-muted)]" />
</button>
)}
</div>
);
}
/**
* 标题 + 编号模糊匹配case-insensitive
*/
export function matchTitleOrNo(item: { title: string; no?: string }, keyword: string): boolean {
if (!keyword) return true;
const k = keyword.trim().toLowerCase();
if (!k) return true;
if (item.title.toLowerCase().includes(k)) return true;
if (item.no && item.no.toLowerCase().includes(k)) return true;
return false;
}