feat: 前端UI标题栏优化与配置更新

- 更新.gitignore,添加frontend/.next/忽略
- 优化RecordModal、index、recurring、search、stats页面标题栏样式
- 新增frontend/lib/utils.js工具函数
- 更新useCategories.js钩子
- 添加代码优化计划文档

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Developer
2026-03-18 16:33:29 +08:00
co-authored by Claude
parent ad6387e49e
commit 127f491167
9 changed files with 2350 additions and 48 deletions
+14 -6
View File
@@ -7,12 +7,20 @@ import RecordModal from '../components/RecordModal';
import { useToast } from '../components/ToastProvider';
import { useConfirm } from '../components/ConfirmProvider';
import { useCategories } from '../hooks/useCategories';
import { formatMoney, parseDateTime, getDatePart } from '../lib/utils';
export default function Search() {
const router = useRouter();
const { showToast } = useToast();
const confirm = useConfirm();
const { categories } = useCategories();
const { categories, error: categoriesError } = useCategories();
// 显示分类加载错误
useEffect(() => {
if (categoriesError) {
showToast('分类加载失败', { tone: 'error' });
}
}, [categoriesError]);
const [keyword, setKeyword] = useState('');
const [results, setResults] = useState([]);
const [loading, setLoading] = useState(false);
@@ -40,6 +48,8 @@ export default function Search() {
useEffect(() => {
if (router.isReady && router.query.q) {
const q = decodeURIComponent(router.query.q);
// Skip if already have results for this keyword (prevents double API call)
if (keyword === q && results.length > 0) return;
setKeyword(q);
// 自动搜索
const doSearch = async () => {
@@ -56,7 +66,7 @@ export default function Search() {
};
doSearch();
}
}, [router.isReady, router.query.q]);
}, [router.isReady, router.query.q, keyword, results]);
const handleSearch = async (e) => {
e.preventDefault();
@@ -81,7 +91,7 @@ export default function Search() {
};
const openEditModal = (record) => {
const [datePart, timePart] = record.date.split(' ');
const { datePart, timePart } = parseDateTime(record.date);
setEditingRecord(record);
setFormData({
type: record.type,
@@ -165,12 +175,10 @@ export default function Search() {
}
};
const formatMoney = (num) => (num || 0).toFixed(2);
const groupedResults = useMemo(() => {
if (!Array.isArray(results)) return {};
return results.reduce((groups, record) => {
const date = record.date.split(' ')[0];
const date = getDatePart(record.date);
if (!groups[date]) groups[date] = [];
groups[date].push(record);
return groups;