R34: 收口搜索查看更多跳转与采购 submit 二次减重

这个提交包含在:
2026-03-24 23:03:47 +08:00
父节点 509676b714
当前提交 0c7f765201
共修改 4 个文件,包含 115 行新增和 39 行删除
+52 -8
查看文件
@@ -1,7 +1,7 @@
import { useMemo, useState } from "react";
import { useNavigate } from "react-router-dom";
import { useQuery } from "@tanstack/react-query";
import { searchGlobal } from "../api/search";
import { searchGlobal, type GlobalSearchHit } from "../api/search";
import { isApiError } from "../api/types";
import { mapApiErrorMessage } from "../api/errorMessages";
import { Button } from "./ui/button";
@@ -56,10 +56,46 @@ function resolveSearchGroup(entityType: string): SearchGroupKey {
return "other";
}
function resolveBrowseHref(groupKey: SearchGroupKey, items: GlobalSearchHit[]) {
const firstItem = items[0];
if (!firstItem) {
return null;
}
if (groupKey === "people") {
return "/people";
}
if (groupKey === "documents") {
if (firstItem.entityType === "reimbursement") return "/reimbursements";
if (firstItem.entityType === "leave") return "/leave-requests";
if (firstItem.entityType === "purchase_request") return "/purchase-requests";
if (firstItem.entityType === "travel_request") return "/travel-requests";
if (firstItem.entityType === "weekly_report") return "/weekly-reports";
if (firstItem.entityType === "todo") return "/todos";
return null;
}
if (groupKey === "projectAnnouncement") {
return firstItem.entityType === "announcement" ? "/announcements" : "/projects";
}
if (firstItem.entityType === "asset") return "/assets";
if (["contract_registry", "confidential_doc_ref"].includes(firstItem.entityType)) {
return "/contracts-registry";
}
return null;
}
export function GlobalSearchDialog({ open, onOpenChange }: { open: boolean; onOpenChange: (open: boolean) => void }) {
const navigate = useNavigate();
const [keyword, setKeyword] = useState("");
const trimmed = keyword.trim();
const closeAndNavigate = (targetHref: string) => {
onOpenChange(false);
window.setTimeout(() => navigate(targetHref), 0);
};
const searchQuery = useQuery({
enabled: open && trimmed.length >= 2,
queryKey: ["global-search", trimmed],
@@ -74,6 +110,7 @@ export function GlobalSearchDialog({ open, onOpenChange }: { open: boolean; onOp
...group,
total: matches.length,
items: matches.slice(0, 3),
browseHref: resolveBrowseHref(group.key, matches),
};
}).filter((group) => group.total > 0);
}, [searchQuery.data?.items]);
@@ -93,7 +130,7 @@ export function GlobalSearchDialog({ open, onOpenChange }: { open: boolean; onOp
return (
<Dialog open={open} onOpenChange={onOpenChange}>
<DialogContent className="max-w-2xl">
<DialogContent className="max-h-[85vh] max-w-2xl overflow-y-auto">
<DialogHeader>
<DialogTitle>全局搜索</DialogTitle>
</DialogHeader>
@@ -121,10 +158,7 @@ export function GlobalSearchDialog({ open, onOpenChange }: { open: boolean; onOp
key={`${item.entityType}-${item.entityId}`}
type="button"
className="w-full rounded-lg border border-zinc-200 px-3 py-3 text-left hover:bg-zinc-50"
onClick={() => {
onOpenChange(false);
navigate(item.href);
}}
onClick={() => closeAndNavigate(item.href)}
>
<div className="flex items-center justify-between gap-3">
<div className="font-medium text-zinc-900">{item.title}</div>
@@ -136,8 +170,18 @@ export function GlobalSearchDialog({ open, onOpenChange }: { open: boolean; onOp
))}
</div>
{group.total > group.items.length ? (
<div className="text-xs text-zinc-400">查看更多结果</div>
{group.total > group.items.length && group.browseHref ? (
<button
type="button"
className="text-xs font-medium text-zinc-500 transition-colors hover:text-zinc-800"
onClick={() => {
const browseHref = group.browseHref;
if (!browseHref) return;
closeAndNavigate(browseHref);
}}
>
查看更多结果
</button>
) : null}
</section>
))}