Files
agent/apps/senlinai-acro-react/src/api/mappers.tsx

198 lines
5.3 KiB
TypeScript

import { IconClockCircle, IconEmail, IconFile, IconHome, IconLink, IconList, IconRobot, IconUserGroup } from '@arco-design/web-react/icon'
import type {
BackendAISession,
BackendChannel,
BackendCronPlan,
BackendInboxMessage,
BackendNoteSource,
BackendProjectWorkspace,
BackendTask,
} 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: BackendProjectWorkspace, index = 0): ProjectWorkspace {
const project: Project = {
id: String(payload.project.id),
name: payload.project.name,
short: payload.project.initials,
badge: payload.project.unreadCount,
urgent: payload.project.unreadCount > 20,
color: projectColors[index % projectColors.length],
}
return {
project,
channels: payload.channels.filter((channel) => channel.type !== 'inbox').map(mapChannel),
tags: payload.tags.map((tag) => (tag === 'all' ? '全部' : tag)),
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 mapChannel(channel: BackendChannel): 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: BackendChannel) {
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 'Cron 计划任务'
default:
return channel.title
}
}
function channelIcon(channel: BackendChannel) {
switch (channel.type) {
case 'overview':
return <IconHome />
case 'inbox':
return <IconEmail />
case 'tasks':
return <IconList />
case 'ai_sessions':
return <IconRobot />
case 'notes_sources':
return <IconFile />
case 'cron':
return <IconClockCircle />
default:
return channel.icon === 'user' ? <IconUserGroup /> : <IconLink />
}
}
function mapInbox(item: BackendInboxMessage): InboxItem {
return {
id: item.id,
title: item.title,
meta: `来源:${item.source}`,
owner: '系统',
time: item.time,
tag: item.tag || item.status,
summary: item.summary,
status: item.status,
}
}
function mapTask(task: BackendTask): TaskItem {
return {
id: task.id,
title: task.title,
owner: task.owner,
progress: task.completed ? '100%' : '60%',
due: task.due || '未设置',
createdAt: formatCreatedAt(task.createdAt),
tag: task.tag || (task.completed ? '已完成' : '进行中'),
summary: task.summary,
completed: task.completed,
}
}
function formatCreatedAt(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: BackendAISession): AISession {
return {
id: session.id,
title: session.title,
summary: session.summary,
owner: 'AI',
time: session.updatedAt,
}
}
function mapNoteSource(note: BackendNoteSource): NoteSource {
return {
id: note.id,
title: note.title,
type: note.kind === 'note' ? '笔记' : note.source,
updated: note.updatedAt,
owner: note.source,
source: note.source,
}
}
function mapCronPlan(plan: BackendCronPlan): CronJob {
return {
id: plan.id,
name: plan.title,
expr: plan.schedule,
status: plan.enabled ? '运行中' : '暂停',
lastRun: plan.lastResult,
nextRun: plan.nextRun || '暂停中',
owner: plan.owner,
enabled: plan.enabled,
}
}