import { IconClockCircle, IconEmail, IconFile, IconHome, IconLink, IconList, IconRobot, IconUserGroup } from '@arco-design/web-react/icon' import type { ProjectWorkspaceDTO, WorkspaceAISessionDTO, WorkspaceChannelDTO, WorkspaceCronPlanDTO, WorkspaceInboxDTO, WorkspaceNoteSourceDTO, WorkspaceTaskDTO, } from './projects' import type { AISession, ChannelKey, CronJob, InboxItem, NoteSource, Project, ProjectChannel, ProjectWorkspace, TaskItem } from '../pages/projects/project-types' const projectColors = ['#165DFF', '#00B42A', '#722ED1', '#FF7D00', '#14C9C9', '#F53F3F'] export function mapWorkspace(payload: ProjectWorkspaceDTO, index = 0): ProjectWorkspace { const project: Project = { id: payload.project.id, name: payload.project.name, identifier: payload.project.identifier ?? '', icon: payload.project.icon ?? '', background: payload.project.background ?? '', description: payload.project.description, short: projectIconLabel(payload.project.icon ?? '', payload.project.initials), badge: payload.project.unreadCount, urgent: payload.project.unreadCount > 20, color: projectColor(payload.project.background ?? '', index), } return { project, channels: payload.channels.filter((channel) => channel.type !== 'inbox').map(mapChannel), tags: payload.tags.map((tag) => tag.name), recentSessions: payload.recentSessions.map(mapAISession), inbox: payload.inbox.map(mapInbox), tasks: payload.tasks.map(mapTask), aiSessions: payload.aiSessions.map(mapAISession), notes: payload.notesSources.map(mapNoteSource), cronJobs: payload.cronPlans.map(mapCronPlan), } } function projectIconLabel(icon: string, fallback: string) { const trimmed = icon.trim() if (!trimmed) return fallback const chars = Array.from(trimmed) if (chars.length <= 2) return trimmed return chars.slice(0, 2).join('').toUpperCase() } function projectColor(background: string, index: number) { const trimmed = background.trim() if (trimmed.startsWith('#') || trimmed.startsWith('rgb') || trimmed.startsWith('hsl')) { return trimmed } return projectColors[index % projectColors.length] } function mapChannel(channel: WorkspaceChannelDTO): ProjectChannel { return { id: channel.id, key: mapChannelKey(channel.type, channel.id), label: channelLabel(channel), count: channel.count, icon: channelIcon(channel), url: channel.url, sortOrder: channel.sortOrder, } } function mapChannelKey(type: string, id = ''): ChannelKey { switch (type) { case 'inbox': return 'inbox' case 'tasks': return 'tasks' case 'ai_sessions': return 'ai' case 'notes_sources': return 'notes' case 'cron': return 'cron' case 'overview': return 'overview' default: return `custom:${id || type}` } } function channelLabel(channel: WorkspaceChannelDTO) { switch (channel.type) { case 'overview': return '概况' case 'inbox': return 'Inbox 消息流' case 'tasks': return '工作计划' case 'ai_sessions': return 'AI 会话' case 'notes_sources': return '笔记资料' case 'cron': return '计划任务' default: return channel.title } } function channelIcon(channel: WorkspaceChannelDTO) { switch (channel.type) { case 'overview': return case 'inbox': return case 'tasks': return case 'ai_sessions': return case 'notes_sources': return case 'cron': return default: return channel.icon === 'user' ? : } } function mapInbox(item: WorkspaceInboxDTO): InboxItem { return { id: item.id, title: item.title, meta: `来源:${item.source}`, owner: '系统', time: formatBackendDate(item.time), tag: item.tag || item.status, summary: item.summary, status: item.status, } } function mapTask(task: WorkspaceTaskDTO): TaskItem { return { id: task.id, title: task.title, owner: task.owner, progress: task.completed ? '100%' : '', due: task.due ? formatBackendDate(task.due) : '未设置', createdAt: formatBackendDate(task.createdAt), completedAt: task.completedAt ? formatBackendDate(task.completedAt) : '', duration: '', tag: task.tag || '', summary: task.summary, completed: task.completed, } } function formatBackendDate(value: string) { const date = parseBackendDate(value) if (!date) return '未知时间' const now = new Date() const today = startOfDay(now) const yesterday = new Date(today) yesterday.setDate(today.getDate() - 1) const dateDay = startOfDay(date) const time = `${pad(date.getHours())}:${pad(date.getMinutes())}` if (dateDay.getTime() === today.getTime()) return `今天 ${time}` if (dateDay.getTime() === yesterday.getTime()) return `昨天 ${time}` return `${pad(date.getMonth() + 1)}-${pad(date.getDate())} ${time}` } function parseBackendDate(value: string) { if (!value) return null const normalized = value.includes('T') ? value : `${value.replace(' ', 'T')}Z` const date = new Date(normalized) return Number.isNaN(date.getTime()) ? null : date } function startOfDay(value: Date) { return new Date(value.getFullYear(), value.getMonth(), value.getDate()) } function pad(value: number) { return String(value).padStart(2, '0') } function mapAISession(session: WorkspaceAISessionDTO): AISession { return { id: session.id, title: session.title, summary: session.summary, owner: 'AI', time: formatBackendDate(session.updatedAt), } } function mapNoteSource(note: WorkspaceNoteSourceDTO): NoteSource { return { id: note.id, title: note.title, type: note.kind === 'note' ? '笔记' : note.source, updated: formatBackendDate(note.updatedAt), owner: note.source, source: note.source, } } function mapCronPlan(plan: WorkspaceCronPlanDTO): CronJob { return { id: plan.id, name: plan.title, expr: plan.schedule, status: plan.enabled ? '运行中' : '暂停', lastRun: plan.lastResult, nextRun: plan.nextRun ? formatBackendDate(plan.nextRun) : '暂停中', owner: plan.owner, enabled: plan.enabled, } }