mirror of
https://github.com/RuoJi6/ARTEX.git
synced 2026-10-27 17:03:49 +08:00
- #34: 任务发现页进入漏洞报告详情后,「←返回」回到该任务的发现页 (/function/tasks/detail?id=<task>&tab=findings),而非全局发现列表。 任务自身的 FindingCaseList 与原始上报列表「详情」链接均携带 context_task。 - #38: 情报搜索除标题/上报者外,同时匹配内容(content)与来源证据(evidence)。 - #38: 修复「查看对话」点击无反应:任务详情页标签切换同步写入 URL 的 tab 参数, 使跳转 tab=sessions&session=... 时能正确切换到会话并打开对应会话。 Closes #34 Closes #38
This commit is contained in:
1 parent
620ca5d96c
commit
0a327328f3
5 files changed
+20
-13
No files matched your search
+2
-2
@@ -260,8 +260,8 @@ func (d *DB) ListIntelligence(ctx context.Context, f IntelligenceFilter) (*Intel
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Search titles and reporters; return the recorded content directly in each row.
|
||||
where := scope + ` AND ($3='' OR kind=$3) AND ($4='' OR i.status=$4) AND ($5='' OR i.title ILIKE '%'||$5||'%' OR i.worker ILIKE '%'||$5||'%')`
|
||||
// Search titles, content, evidence, and reporters; return the recorded content directly in each row.
|
||||
where := scope + ` AND ($3='' OR kind=$3) AND ($4='' OR i.status=$4) AND ($5='' OR i.title ILIKE '%'||$5||'%' OR i.content ILIKE '%'||$5||'%' OR i.evidence ILIKE '%'||$5||'%' OR i.worker ILIKE '%'||$5||'%')`
|
||||
args = append(args, f.Kind, f.Status, f.Query)
|
||||
if err = d.QueryRowContext(ctx, `SELECT count(*)`+where, args...).Scan(&page.Total); err != nil {
|
||||
return nil, err
|
||||
|
||||
@@ -58,6 +58,7 @@ function FindingDetailInner() {
|
||||
const searchParams = useSearchParams();
|
||||
const id = searchParams.get("id") ?? "";
|
||||
const contextTaskId = searchParams.get("context_task") ?? "";
|
||||
const backHref = contextTaskId ? `/function/tasks/detail?id=${contextTaskId}&tab=findings` : "/function/findings";
|
||||
const [finding, setFinding] = React.useState<Finding | null>(null);
|
||||
const [loaded, setLoaded] = React.useState(false);
|
||||
const [tab, setTab] = React.useState("overview");
|
||||
@@ -117,7 +118,7 @@ function FindingDetailInner() {
|
||||
<p className="text-muted-foreground">{loaded ? `未找到发现 ${id}` : "加载中…"}</p>
|
||||
{loaded && (
|
||||
<Button asChild variant="outline">
|
||||
<Link href="/function/findings">
|
||||
<Link href={backHref}>
|
||||
<ArrowLeftIcon /> 返回发现列表
|
||||
</Link>
|
||||
</Button>
|
||||
@@ -135,7 +136,7 @@ function FindingDetailInner() {
|
||||
<div className="flex flex-wrap items-center gap-2">
|
||||
<SidebarTrigger className="-ml-1" />
|
||||
<Button asChild variant="ghost" size="icon" className="size-7">
|
||||
<Link href="/function/findings">
|
||||
<Link href={backHref}>
|
||||
<ArrowLeftIcon />
|
||||
</Link>
|
||||
</Button>
|
||||
|
||||
@@ -113,11 +113,7 @@ function Row({
|
||||
</span>
|
||||
{f.finding_id && (
|
||||
<Link
|
||||
href={
|
||||
f.inherited
|
||||
? `/function/findings/detail?id=${f.finding_id}&context_task=${contextTaskId}`
|
||||
: `/function/findings/detail?id=${f.finding_id}`
|
||||
}
|
||||
href={`/function/findings/detail?id=${f.finding_id}&context_task=${contextTaskId}`}
|
||||
className="text-muted-foreground hover:text-primary inline-flex shrink-0 items-center gap-0.5 text-xs"
|
||||
title="查看漏洞详情"
|
||||
>
|
||||
@@ -190,7 +186,7 @@ export function FindingsTab({ taskId }: { taskId: string }) {
|
||||
|
||||
return (
|
||||
<div className="flex flex-col gap-4">
|
||||
<FindingCaseList query={{ task: taskId, sort: "time" }} />
|
||||
<FindingCaseList query={{ task: taskId, sort: "time" }} contextTask={taskId} />
|
||||
{[
|
||||
...new Set(
|
||||
items
|
||||
|
||||
@@ -354,7 +354,17 @@ function TaskDetailInner() {
|
||||
);
|
||||
|
||||
return (
|
||||
<Tabs value={tab} onValueChange={setTab} className="flex flex-1 flex-col gap-0">
|
||||
<Tabs
|
||||
value={tab}
|
||||
onValueChange={(value) => {
|
||||
setTab(value);
|
||||
const params = new URLSearchParams(searchParams.toString());
|
||||
params.set("tab", value);
|
||||
params.delete("session");
|
||||
router.replace(`/function/tasks/detail?${params.toString()}`, { scroll: false });
|
||||
}}
|
||||
className="flex flex-1 flex-col gap-0"
|
||||
>
|
||||
{/* Top fixed area */}
|
||||
<header className="sticky top-0 z-10 flex flex-col gap-2 border-b bg-background/95 px-4 py-2.5 backdrop-blur lg:px-6">
|
||||
<div className="flex items-center gap-2">
|
||||
|
||||
@@ -193,8 +193,8 @@ export function IntelligencePanel({
|
||||
</Tabs>
|
||||
<div className="flex flex-wrap items-center gap-2">
|
||||
<Input
|
||||
aria-label="搜索情报标题或上报者"
|
||||
placeholder="搜索标题或上报者"
|
||||
aria-label="搜索情报标题、内容或上报者"
|
||||
placeholder="搜索标题、内容或上报者"
|
||||
value={search}
|
||||
maxLength={200}
|
||||
onChange={(e) => setSearch(e.target.value)}
|
||||
|
||||
Reference in new issue
Block a user