R34: 收口搜索查看更多跳转与采购 submit 二次减重
这个提交包含在:
@@ -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>
|
||||
))}
|
||||
|
||||
在新工单中引用
屏蔽一个用户