import { useEffect, useMemo, useState } from 'react' import type { ReactNode } from 'react' import { Button, Card, Empty, Grid, Space, Typography } from '@arco-design/web-react' import { IconBook, IconCheckCircle, IconCompass, IconFire, IconLink, IconMessage, IconRefresh, IconRobot, IconStar, } from '@arco-design/web-react/icon' import type { InboxItem, Project, ProjectWorkspace } from './projects/project-types' const { Row, Col } = Grid const { Title, Text, Paragraph } = Typography type ExploreArticle = InboxItem & { project: Project } type DataSource = { name: string count: number icon: ReactNode color: string } export function WorkspaceExplorePage({ workspaces, onSelectItem, }: { workspaces: ProjectWorkspace[] onSelectItem: (title: string) => void }) { const articles = useMemo( () => workspaces.flatMap((workspace) => workspace.inbox.map((item) => ({ ...item, project: workspace.project, })), ), [workspaces], ) const sources = useMemo(() => dataSources(articles), [articles]) const [activeArticleID, setActiveArticleID] = useState(articles[0]?.id ?? null) useEffect(() => { if (articles.length === 0) { setActiveArticleID(null) return } if (!activeArticleID || !articles.some((article) => article.id === activeArticleID)) { setActiveArticleID(articles[0].id) } }, [activeArticleID, articles]) const selected = articles.find((article) => article.id === activeArticleID) ?? articles[0] return (
探索 多个外部数据源的集中阅读页,采集文章、AI 总结并沉淀到项目。
{sources.map((source) => ( {source.icon} {source.name} {source.count} 条 ))} {selected ? (
{sourceName(selected)} - 最新文章
{articles.map((article) => ( ))}
{selected.title} {sourceInitial(sourceName(selected))} {sourceName(selected)} - 最新文章 {selected.time}
{workspaces.slice(0, 8).map((workspace) => ( {workspace.project.short} ))} +{Math.max(workspaces.length - 8, 0)}
AI 总结 {selected.summary || '暂无正文摘要。同步数据源后,系统会在这里沉淀文章核心观点、风险点和可转化为项目计划的线索。'}
推荐:将外部文章中的项目机会、风险提示和资料线索归档到对应项目,形成可追踪的计划和知识资产。
) : ( )}
) } function dataSources(articles: ExploreArticle[]): DataSource[] { const counts = new Map() articles.forEach((article) => counts.set(sourceName(article), (counts.get(sourceName(article)) ?? 0) + 1)) const iconSet = [ { icon: , color: 'blue' }, { icon: , color: 'green' }, { icon: , color: 'orange' }, ] return Array.from(counts.entries()) .slice(0, 3) .map(([name, count], index) => ({ name, count, icon: iconSet[index]?.icon ?? , color: iconSet[index]?.color ?? 'blue', })) } function sourceName(article: ExploreArticle) { return article.meta?.replace(/^来源:/, '') || article.project.name } function sourceInitial(name: string) { return name.trim().slice(0, 1) || '源' }