From d3ae9697eff9fecbd27b85368bacd647105d5fba Mon Sep 17 00:00:00 2001 From: ittoview Date: Sat, 23 May 2026 03:39:40 +0100 Subject: [PATCH] feat: add ITTO text highlight filter --- src/pages/IttoCollectionsPage.tsx | 144 ++++++++++++++++++++++++------ 1 file changed, 115 insertions(+), 29 deletions(-) diff --git a/src/pages/IttoCollectionsPage.tsx b/src/pages/IttoCollectionsPage.tsx index dfb7c7c..dea4845 100644 --- a/src/pages/IttoCollectionsPage.tsx +++ b/src/pages/IttoCollectionsPage.tsx @@ -1,6 +1,6 @@ import { useMemo, useState } from 'react' import { motion } from 'framer-motion' -import { FileOutput, FileText, Wrench } from 'lucide-react' +import { FileOutput, FileText, Wrench, X } from 'lucide-react' import { artifactMap, knowledgeAreas, @@ -12,12 +12,17 @@ import type { Process, ProcessRef } from '@/types/itto' type ViewKey = 'inputs' | 'tools' | 'outputs' +type CollectionItem = { + label: string + details: string[] +} + type CollectionRow = { processId: string processCode: string processName: string processNameEn: string - items: string[] + items: CollectionItem[] } type CollectionArea = { @@ -45,14 +50,13 @@ const itemVariants = { visible: { opacity: 1, y: 0 }, } -function formatRef(ref: ProcessRef, viewKey: ViewKey) { +function formatRef(ref: ProcessRef, viewKey: ViewKey): CollectionItem { const normalized = normalizeProcessRef(ref) const entity = viewKey === 'tools' ? toolMap.get(normalized.id) : artifactMap.get(normalized.id) - const name = entity?.name ?? normalized.id - const detail = normalized.detail?.map((item) => item.label).filter(Boolean) ?? [] + const label = entity?.name ?? normalized.id + const details = normalized.detail?.map((item) => item.label).filter(Boolean) ?? [] - if (!detail.length) return name - return `${name}(${detail.join('、')})` + return { label, details } } function getRefsByView(process: Process, viewKey: ViewKey) { @@ -61,8 +65,67 @@ function getRefsByView(process: Process, viewKey: ViewKey) { return process.outputs } -function uniqueItems(items: string[]) { - return Array.from(new Set(items)) +function uniqueItems(items: CollectionItem[]) { + const seen = new Set() + return items.filter((item) => { + const key = `${item.label}__${item.details.join('、')}` + if (seen.has(key)) return false + seen.add(key) + return true + }) +} + +function itemMatchesSelected(item: CollectionItem, selectedText: string | null) { + if (!selectedText) return false + return item.label === selectedText || item.details.includes(selectedText) +} + +function renderSelectableText( + text: string, + selectedText: string | null, + onSelect: (text: string) => void +) { + const isSelected = selectedText === text + + return ( + + ) +} + +function renderCollectionItems( + items: CollectionItem[], + selectedText: string | null, + onSelect: (text: string) => void +) { + return items.map((item, itemIndex) => ( + + {itemIndex > 0 && } + {renderSelectableText(item.label, selectedText, onSelect)} + {item.details.length > 0 && ( + + + {item.details.map((detail, detailIndex) => ( + + {detailIndex > 0 && } + {renderSelectableText(detail, selectedText, onSelect)} + + ))} + + + )} + + )) } function buildCollection(viewKey: ViewKey): CollectionArea[] { @@ -91,6 +154,7 @@ function buildCollection(viewKey: ViewKey): CollectionArea[] { export function IttoCollectionsPage() { const [activeTab, setActiveTab] = useState('inputs') + const [selectedText, setSelectedText] = useState(null) const collection = useMemo(() => buildCollection(activeTab), [activeTab]) const activeLabel = tabs.find((tab) => tab.key === activeTab)?.label @@ -124,6 +188,20 @@ export function IttoCollectionsPage() { + {selectedText && ( +
+ 标签:{selectedText} + +
+ )} + - {area.rows.map((row) => ( - - -
- - {row.processCode} - -
-
{row.processName}
-
{row.processNameEn}
+ {area.rows.map((row) => { + const rowMatched = row.items.some((item) => itemMatchesSelected(item, selectedText)) + return ( + + +
+ + {row.processCode} + +
+
{row.processName}
+
{row.processNameEn}
+
-
- - - {row.items.join(';')} - - - ))} + + + {renderCollectionItems(row.items, selectedText, setSelectedText)} + + + ) + })}