From 2660bc65bd83737b09740494ed50daf79be98ccf Mon Sep 17 00:00:00 2001 From: yanweidong Date: Mon, 20 Jul 2026 10:50:42 +0800 Subject: [PATCH] Split React client pages into modules --- .../scripts/structure-check.mjs | 37 ++ apps/senlinai-acro-react/src/App.tsx | 569 ------------------ apps/senlinai-acro-react/src/app/App.tsx | 41 ++ .../src/features/projects/project-data.tsx | 53 ++ .../features/projects/project-inspector.tsx | 70 +++ .../src/features/projects/project-rail.tsx | 25 + .../src/features/projects/project-sidebar.tsx | 35 ++ .../features/projects/project-statusbar.tsx | 19 + .../src/features/projects/project-topbar.tsx | 29 + .../src/features/projects/project-types.ts | 21 + apps/senlinai-acro-react/src/main.tsx | 2 +- apps/senlinai-acro-react/src/pages/login.tsx | 87 +++ .../src/pages/overview.tsx | 132 ++++ .../senlinai-acro-react/src/pages/project.tsx | 55 ++ 14 files changed, 605 insertions(+), 570 deletions(-) create mode 100644 apps/senlinai-acro-react/scripts/structure-check.mjs delete mode 100644 apps/senlinai-acro-react/src/App.tsx create mode 100644 apps/senlinai-acro-react/src/app/App.tsx create mode 100644 apps/senlinai-acro-react/src/features/projects/project-data.tsx create mode 100644 apps/senlinai-acro-react/src/features/projects/project-inspector.tsx create mode 100644 apps/senlinai-acro-react/src/features/projects/project-rail.tsx create mode 100644 apps/senlinai-acro-react/src/features/projects/project-sidebar.tsx create mode 100644 apps/senlinai-acro-react/src/features/projects/project-statusbar.tsx create mode 100644 apps/senlinai-acro-react/src/features/projects/project-topbar.tsx create mode 100644 apps/senlinai-acro-react/src/features/projects/project-types.ts create mode 100644 apps/senlinai-acro-react/src/pages/login.tsx create mode 100644 apps/senlinai-acro-react/src/pages/overview.tsx create mode 100644 apps/senlinai-acro-react/src/pages/project.tsx diff --git a/apps/senlinai-acro-react/scripts/structure-check.mjs b/apps/senlinai-acro-react/scripts/structure-check.mjs new file mode 100644 index 0000000..a6197e8 --- /dev/null +++ b/apps/senlinai-acro-react/scripts/structure-check.mjs @@ -0,0 +1,37 @@ +import { existsSync, readFileSync } from 'node:fs' + +const requiredFiles = [ + 'src/app/App.tsx', + 'src/pages/login.tsx', + 'src/pages/project.tsx', + 'src/pages/overview.tsx', + 'src/features/projects/project-data.tsx', + 'src/features/projects/project-rail.tsx', + 'src/features/projects/project-sidebar.tsx', + 'src/features/projects/project-topbar.tsx', + 'src/features/projects/project-inspector.tsx', + 'src/features/projects/project-statusbar.tsx', + 'src/features/projects/project-types.ts', +] + +const failures = requiredFiles.filter((file) => !existsSync(file)).map((file) => `missing ${file}`) + +if (existsSync('src/App.tsx')) { + failures.push('legacy src/App.tsx should be removed after page split') +} + +if (existsSync('src/app/App.tsx')) { + const appSource = readFileSync('src/app/App.tsx', 'utf8') + for (const forbidden of ['function LoginPage', 'function Workbench', 'function OverviewContent']) { + if (appSource.includes(forbidden)) { + failures.push(`src/app/App.tsx still contains ${forbidden}`) + } + } +} + +if (failures.length) { + console.error(failures.join('\n')) + process.exit(1) +} + +console.log('structure ok') diff --git a/apps/senlinai-acro-react/src/App.tsx b/apps/senlinai-acro-react/src/App.tsx deleted file mode 100644 index 8a92c79..0000000 --- a/apps/senlinai-acro-react/src/App.tsx +++ /dev/null @@ -1,569 +0,0 @@ -import type { CSSProperties, ReactElement } from 'react' -import { useMemo, useState } from 'react' -import { - Avatar, - Badge, - Button, - Card, - ConfigProvider, - Divider, - Form, - Grid, - Input, - Layout, - Message, - Space, - Tabs, - Tag, - Typography, -} from '@arco-design/web-react' -import { - IconApps, - IconArrowLeft, - IconArrowRight, - IconBook, - IconCalendar, - IconCheckCircleFill, - IconClockCircle, - IconDashboard, - IconEmail, - IconFile, - IconHome, - IconLaunch, - IconLink, - IconList, - IconMessage, - IconMoon, - IconMore, - IconNotification, - IconPlus, - IconQuestionCircle, - IconRobot, - IconSafe, - IconSearch, - IconSettings, - IconStorage, - IconSun, - IconThunderbolt, - IconUserGroup, -} from '@arco-design/web-react/icon' -import '@arco-design/web-react/dist/css/arco.css' -import './App.css' - -const { Header, Sider, Content, Footer } = Layout -const { Row, Col } = Grid -const { Title, Text, Paragraph } = Typography - -type Screen = 'login' | 'workbench' -type Theme = 'light' | 'dark' -type ChannelKey = 'overview' | 'inbox' | 'tasks' | 'ai' | 'notes' | 'cron' | 'research' | 'design' - -const projects = [ - { id: 'a1', name: '项目 A1', short: 'A1', badge: 635, urgent: true, color: '#165DFF' }, - { id: 'a2', name: '项目 A2', short: 'PM', badge: 36, color: '#00B42A' }, - { id: 'b1', name: '项目 B1', short: 'DS', badge: 4, urgent: true, color: '#722ED1' }, - { id: 'c3', name: '项目 C3', short: 'OP', badge: 45, color: '#FF7D00' }, -] - -const channels: Array<{ key: ChannelKey; label: string; count?: number; icon: ReactElement }> = [ - { key: 'overview', label: '概况', count: 635, icon: }, - { key: 'inbox', label: 'Inbox 消息流', count: 36, icon: }, - { key: 'tasks', label: '工作计划', count: 12, icon: }, - { key: 'ai', label: 'AI 会话', count: 4, icon: }, - { key: 'notes', label: '笔记资料', count: 343, icon: }, - { key: 'cron', label: 'Cron 计划任务', count: 45, icon: }, - { key: 'research', label: '客户研究频道', icon: }, - { key: 'design', label: '产品设计频道', icon: }, -] - -const inbox = [ - { title: '竞争对手定价更新监控', meta: '来源:产品研究 · 竞品追踪', owner: '李明', time: '2 小时前', tag: '市场情报' }, - { title: '客户反馈:导出功能报错', meta: '来源:客户支持 · 工单 #CS-1287', owner: '王芳', time: '4 小时前', tag: '客户反馈' }, - { title: 'API 调用策略评估建议', meta: '来源:后端架构讨论', owner: '张伟', time: '6 小时前', tag: '架构' }, - { title: '更新需求文档 v1.3.2', meta: '来源:产品需求 · 文档评审', owner: '陈晨', time: '昨天', tag: '需求文档' }, -] - -const tasks = [ - { title: '智能报表导出功能', owner: '张伟', progress: '60%', due: '2026-07-24', tag: '进行中' }, - { title: '企业版权限体系梳理', owner: '李明', progress: '30%', due: '2026-07-28', tag: '进行中' }, - { title: 'Q3 营销策略制定', owner: '王芳', progress: '45%', due: '2026-07-31', tag: '进行中' }, -] - -const aiSessions = [ - { title: '生成 Q3 营销策略初稿', summary: '基于市场分析和竞品数据,输出 Q3 营销策略重点...', owner: '张伟', time: '今天 08:47' }, - { title: '产品定价模型讨论', summary: '针对企业版与标准版定价模型进行对比分析...', owner: '李明', time: '昨天 16:05' }, - { title: '客户流失原因分析', summary: '分析近三个月客户流失数据与反馈原因...', owner: '王芳', time: '昨天 10:22' }, - { title: '行业趋势与机会洞察', summary: '围绕 AI 在企业协同领域的趋势与机会...', owner: '张伟', time: '7 月 18 日' }, -] - -const notes = [ - { title: '用户权限体系设计文档 v2.1', type: '文档', updated: '2026-07-19', owner: '李明' }, - { title: '导出功能技术方案评审', type: '文档', updated: '2026-07-18', owner: '张伟' }, - { title: '2026 Q3 竞品功能对比表', type: '表格', updated: '2026-07-18', owner: '王芳' }, -] - -const discussions = [ - { name: '李明', time: '2026-07-20 09:12', text: '关于导出报错的问题,已在测试环境复现,初步定位为权限校验逻辑异常。' }, - { name: '张伟', time: '2026-07-20 09:18', text: '@李明 麻烦同步修复预计完成时间,我这边需要同步给客户。' }, - { name: '王芳', time: '2026-07-20 10:05', text: '补充:客户反馈影响范围主要集中在企业版用户。' }, - { name: '系统通知', time: '2026-07-20 10:30', text: '已将此讨论关联到任务:智能报表导出功能。' }, -] - -function App() { - const [screen, setScreen] = useState('login') - const [theme, setTheme] = useState('light') - const [activeProject, setActiveProject] = useState(projects[0]) - const [activeChannel, setActiveChannel] = useState('overview') - const [selectedItem, setSelectedItem] = useState('Inbox 待处理(36)') - - const dark = theme === 'dark' - - return ( - -
- {screen === 'login' ? ( - setScreen('workbench')} /> - ) : ( - setTheme(dark ? 'light' : 'dark')} - /> - )} -
-
- ) -} - -function LoginPage({ onLogin }: { onLogin: () => void }) { - const [server, setServer] = useState('https://10.0.0.15:8080') - - return ( -
- -
-
- S - SenlinAI -
- 私有部署 · 安全可控的智能协作平台 - 知识沉淀 · 团队协作 · AI 助理 - - v1.0.0 - 隐私政策 - 服务协议 - 关于 SenlinAI - -
- -
- 登录到您的 SenlinAI - 连接私有工作台 -
- - } /> - - - - - - - -
- - - 记住服务器地址 - - -
- -
- -
- 连接正常 - 已连接到 {server} -
- -
-
-
- -
- 安全 · 专注 · 高效 - - SenlinAI 是面向知识工作者与内部团队的私有部署工作台,帮助团队在统一空间中收集信息、整理知识、协同决策。 - - } title="私有部署,数据自有" desc="所有数据与模型运行在您的环境中,安全可控。" /> - } title="知识沉淀,结构清晰" desc="从收集到整理,形成可复用的团队知识库。" /> - } title="协同高效,聚焦成果" desc="围绕项目与任务协同,减少沟通成本,专注交付。" /> -
-
-
- ) -} - -function ValuePoint({ icon, title, desc }: { icon: ReactElement; title: string; desc: string }) { - return ( -
- {icon} -
- {title} - {desc} -
-
- ) -} - -function Workbench({ - activeProject, - activeChannel, - selectedItem, - theme, - onSelectProject, - onSelectChannel, - onSelectItem, - onToggleTheme, -}: { - activeProject: (typeof projects)[number] - activeChannel: ChannelKey - selectedItem: string - theme: Theme - onSelectProject: (project: (typeof projects)[number]) => void - onSelectChannel: (key: ChannelKey) => void - onSelectItem: (title: string) => void - onToggleTheme: () => void -}) { - return ( - -
-
- S - SenlinAI -
-
- } placeholder="搜索项目、频道、文档、任务、联系人..." /> - -
- -
- - - - - - ))} - - - ))} - - - -
- 最近会话 - {['需求评审要点整理', '生成 Q3 营销策略初稿', 'npx 安装 skill 至 codex', '产品定价模型讨论'].map((title, index) => ( - - ))} -
- - -
- 标签 - - {['全部', '需求', '设计', '研发', '运营', 'AI'].map((tag) => ( - {tag} - ))} - -
-
- - - - - - - - - - - -
- - c.key === activeChannel)?.label ?? '概况'} /> - - -
-
- - - - - - - -
-
-
- -
-
- -
- 张明 - 在线 -
- - - -
- - 同步完成 - 3 个任务进行中 - AI 队列空闲 - 本地草稿已保存 - - - 系统存储 152GB 可用 - 系统健康 正常 - - -
-
- ) -} - -function IconInteractionFallback() { - return -} - -function OverviewContent({ onSelectItem }: { onSelectItem: (title: string) => void }) { - const metrics = useMemo(() => [ - { title: 'Inbox 待处理', value: 36, delta: '较昨日 -8', icon: , color: 'arcoblue' }, - { title: '进行中的任务', value: 12, delta: '较昨日 -2', icon: , color: 'green' }, - { title: 'AI 会话活跃', value: 4, delta: '较昨日 +1', icon: , color: 'purple' }, - { title: '笔记资料总数', value: 343, delta: '较昨日 +5', icon: , color: 'cyan' }, - { title: '计划任务', value: 45, delta: '较昨日 +0', icon: , color: 'orange' }, - ], []) - - return ( -
-
-
- 项目整体快照,帮助你快速了解项目动态 - 概况 -
- - -
- - - {metrics.map((metric) => ( - - - - {metric.icon} -
- {metric.title} - {metric.value} - {metric.delta} -
-
-
- - ))} -
- - - - - -
- ) -} - -function QueueSection({ title, items, onSelectItem }: { title: string; items: typeof inbox; onSelectItem: (title: string) => void }) { - return ( - -
- {title} - -
- {items.map((item) => ( - - ))} -
- ) -} - -function TaskSection({ onSelectItem }: { onSelectItem: (title: string) => void }) { - return ( - -
- 进行中的任务(12) - -
- {tasks.map((task) => ( - - ))} -
- ) -} - -function AISessionSection({ onSelectItem }: { onSelectItem: (title: string) => void }) { - return ( - -
- AI 会话(4) - -
- {aiSessions.map((session) => ( - - ))} -
- ) -} - -function NoteSection({ onSelectItem }: { onSelectItem: (title: string) => void }) { - return ( - -
- 最近笔记资料(5) - -
- {notes.map((note) => ( - - ))} -
- ) -} - -function InspectorDiscussion({ selectedItem }: { selectedItem: string }) { - return ( -
-
- 关于「{selectedItem}」 -
- 注:同一对象的讨论与协作记录 - - - {discussions.map((item) => ( -
- {item.name.slice(0, 1)} -
- - {item.name} - {item.time} - - {item.text} - -
-
- ))} -
-
- -
- - -
-
-
- ) -} - -function IconAttachmentFallback() { - return -} - -function Property({ label, value }: { label: string; value: string }) { - return ( -
- {label} - {value} -
- ) -} - -export default App diff --git a/apps/senlinai-acro-react/src/app/App.tsx b/apps/senlinai-acro-react/src/app/App.tsx new file mode 100644 index 0000000..b89f6b4 --- /dev/null +++ b/apps/senlinai-acro-react/src/app/App.tsx @@ -0,0 +1,41 @@ +import { useState } from 'react' +import { ConfigProvider } from '@arco-design/web-react' +import '@arco-design/web-react/dist/css/arco.css' +import '../App.css' +import { LoginPage } from '../pages/login' +import { ProjectPage } from '../pages/project' +import { projects } from '../features/projects/project-data' +import type { ChannelKey, Screen, Theme } from '../features/projects/project-types' + +function App() { + const [screen, setScreen] = useState('login') + const [theme, setTheme] = useState('light') + const [activeProject, setActiveProject] = useState(projects[0]) + const [activeChannel, setActiveChannel] = useState('overview') + const [selectedItem, setSelectedItem] = useState('Inbox 待处理(36)') + + const dark = theme === 'dark' + + return ( + +
+ {screen === 'login' ? ( + setScreen('workbench')} /> + ) : ( + setTheme(dark ? 'light' : 'dark')} + /> + )} +
+
+ ) +} + +export default App diff --git a/apps/senlinai-acro-react/src/features/projects/project-data.tsx b/apps/senlinai-acro-react/src/features/projects/project-data.tsx new file mode 100644 index 0000000..d010aac --- /dev/null +++ b/apps/senlinai-acro-react/src/features/projects/project-data.tsx @@ -0,0 +1,53 @@ +import { IconClockCircle, IconEmail, IconFile, IconHome, IconLink, IconList, IconRobot, IconUserGroup } from '@arco-design/web-react/icon' +import type { Project, ProjectChannel } from './project-types' + +export const projects: Project[] = [ + { id: 'a1', name: '项目 A1', short: 'A1', badge: 635, urgent: true, color: '#165DFF' }, + { id: 'a2', name: '项目 A2', short: 'PM', badge: 36, color: '#00B42A' }, + { id: 'b1', name: '项目 B1', short: 'DS', badge: 4, urgent: true, color: '#722ED1' }, + { id: 'c3', name: '项目 C3', short: 'OP', badge: 45, color: '#FF7D00' }, +] + +export const channels: ProjectChannel[] = [ + { key: 'overview', label: '概况', count: 635, icon: }, + { key: 'inbox', label: 'Inbox 消息流', count: 36, icon: }, + { key: 'tasks', label: '工作计划', count: 12, icon: }, + { key: 'ai', label: 'AI 会话', count: 4, icon: }, + { key: 'notes', label: '笔记资料', count: 343, icon: }, + { key: 'cron', label: 'Cron 计划任务', count: 45, icon: }, + { key: 'research', label: '客户研究频道', icon: }, + { key: 'design', label: '产品设计频道', icon: }, +] + +export const inbox = [ + { title: '竞争对手定价更新监控', meta: '来源:产品研究 · 竞品追踪', owner: '李明', time: '2 小时前', tag: '市场情报' }, + { title: '客户反馈:导出功能报错', meta: '来源:客户支持 · 工单 #CS-1287', owner: '王芳', time: '4 小时前', tag: '客户反馈' }, + { title: 'API 调用策略评估建议', meta: '来源:后端架构讨论', owner: '张伟', time: '6 小时前', tag: '架构' }, + { title: '更新需求文档 v1.3.2', meta: '来源:产品需求 · 文档评审', owner: '陈晨', time: '昨天', tag: '需求文档' }, +] + +export const tasks = [ + { title: '智能报表导出功能', owner: '张伟', progress: '60%', due: '2026-07-24', tag: '进行中' }, + { title: '企业版权限体系梳理', owner: '李明', progress: '30%', due: '2026-07-28', tag: '进行中' }, + { title: 'Q3 营销策略制定', owner: '王芳', progress: '45%', due: '2026-07-31', tag: '进行中' }, +] + +export const aiSessions = [ + { title: '生成 Q3 营销策略初稿', summary: '基于市场分析和竞品数据,输出 Q3 营销策略重点...', owner: '张伟', time: '今天 08:47' }, + { title: '产品定价模型讨论', summary: '针对企业版与标准版定价模型进行对比分析...', owner: '李明', time: '昨天 16:05' }, + { title: '客户流失原因分析', summary: '分析近三个月客户流失数据与反馈原因...', owner: '王芳', time: '昨天 10:22' }, + { title: '行业趋势与机会洞察', summary: '围绕 AI 在企业协同领域的趋势与机会...', owner: '张伟', time: '7 月 18 日' }, +] + +export const notes = [ + { title: '用户权限体系设计文档 v2.1', type: '文档', updated: '2026-07-19', owner: '李明' }, + { title: '导出功能技术方案评审', type: '文档', updated: '2026-07-18', owner: '张伟' }, + { title: '2026 Q3 竞品功能对比表', type: '表格', updated: '2026-07-18', owner: '王芳' }, +] + +export const discussions = [ + { name: '李明', time: '2026-07-20 09:12', text: '关于导出报错的问题,已在测试环境复现,初步定位为权限校验逻辑异常。' }, + { name: '张伟', time: '2026-07-20 09:18', text: '@李明 麻烦同步修复预计完成时间,我这边需要同步给客户。' }, + { name: '王芳', time: '2026-07-20 10:05', text: '补充:客户反馈影响范围主要集中在企业版用户。' }, + { name: '系统通知', time: '2026-07-20 10:30', text: '已将此讨论关联到任务:智能报表导出功能。' }, +] diff --git a/apps/senlinai-acro-react/src/features/projects/project-inspector.tsx b/apps/senlinai-acro-react/src/features/projects/project-inspector.tsx new file mode 100644 index 0000000..de2b565 --- /dev/null +++ b/apps/senlinai-acro-react/src/features/projects/project-inspector.tsx @@ -0,0 +1,70 @@ +import { Avatar, Button, Divider, Input, Layout, Message, Space, Tabs, Typography } from '@arco-design/web-react' +import { IconLink, IconMessage, IconMore } from '@arco-design/web-react/icon' +import { channels, discussions } from './project-data' +import type { ChannelKey, Project } from './project-types' + +const { Sider } = Layout +const { Title, Text, Paragraph } = Typography + +export function ProjectInspector({ activeProject, activeChannel, selectedItem }: { activeProject: Project; activeChannel: ChannelKey; selectedItem: string }) { + return ( + + + +
c.key === activeChannel)?.label ?? '概况'} />
+ +
+
+ ) +} + +function InspectorDiscussion({ selectedItem }: { selectedItem: string }) { + return ( +
+
+ 关于「{selectedItem}」 +
+ 注:同一对象的讨论与协作记录 + + + {discussions.map((item) => ( +
+ {item.name.slice(0, 1)} +
+ + {item.name} + {item.time} + + {item.text} + +
+
+ ))} +
+
+ +
+ + +
+
+
+ ) +} + +function IconAttachmentFallback() { + return +} + +function Property({ label, value }: { label: string; value: string }) { + return ( +
+ {label} + {value} +
+ ) +} diff --git a/apps/senlinai-acro-react/src/features/projects/project-rail.tsx b/apps/senlinai-acro-react/src/features/projects/project-rail.tsx new file mode 100644 index 0000000..cc33df7 --- /dev/null +++ b/apps/senlinai-acro-react/src/features/projects/project-rail.tsx @@ -0,0 +1,25 @@ +import type { CSSProperties } from 'react' +import { Badge, Button, Layout, Space } from '@arco-design/web-react' +import { IconDashboard, IconPlus } from '@arco-design/web-react/icon' +import { projects } from './project-data' +import type { Project } from './project-types' + +const { Sider } = Layout + +export function ProjectRail({ activeProject, onSelectProject }: { activeProject: Project; onSelectProject: (project: Project) => void }) { + return ( + + + + ))} + + + ))} + + +
+ 最近会话 + {['需求评审要点整理', '生成 Q3 营销策略初稿', 'npx 安装 skill 至 codex', '产品定价模型讨论'].map((title, index) => ( + + ))} +
+ +
+ 标签 + {['全部', '需求', '设计', '研发', '运营', 'AI'].map((tag) => {tag})} +
+
+ ) +} diff --git a/apps/senlinai-acro-react/src/features/projects/project-statusbar.tsx b/apps/senlinai-acro-react/src/features/projects/project-statusbar.tsx new file mode 100644 index 0000000..5969f5d --- /dev/null +++ b/apps/senlinai-acro-react/src/features/projects/project-statusbar.tsx @@ -0,0 +1,19 @@ +import { Avatar, Button, Layout, Space, Typography } from '@arco-design/web-react' +import { IconApps, IconCalendar, IconCheckCircleFill, IconMessage, IconRobot, IconSettings, IconStorage, IconThunderbolt, IconUserGroup } from '@arco-design/web-react/icon' + +const { Footer } = Layout +const { Text } = Typography + +export function ProjectStatusbar() { + return ( +
+
张明在线
+ 同步完成 3 个任务进行中 AI 队列空闲 本地草稿已保存 + 系统存储 152GB 可用系统健康 正常 +
+ ) +} + +function IconInteractionFallback() { + return +} diff --git a/apps/senlinai-acro-react/src/features/projects/project-topbar.tsx b/apps/senlinai-acro-react/src/features/projects/project-topbar.tsx new file mode 100644 index 0000000..4f01e84 --- /dev/null +++ b/apps/senlinai-acro-react/src/features/projects/project-topbar.tsx @@ -0,0 +1,29 @@ +import { Badge, Button, Input, Layout, Space, Typography } from '@arco-design/web-react' +import { IconApps, IconArrowLeft, IconArrowRight, IconMoon, IconNotification, IconQuestionCircle, IconSearch, IconSun } from '@arco-design/web-react/icon' +import type { Theme } from './project-types' + +const { Header } = Layout +const { Text } = Typography + +export function ProjectTopbar({ theme, onToggleTheme }: { theme: Theme; onToggleTheme: () => void }) { + return ( +
+
+ S + SenlinAI +
+
+ } placeholder="搜索项目、频道、文档、任务、联系人..." /> + +
+ +
+ ) +} diff --git a/apps/senlinai-acro-react/src/features/projects/project-types.ts b/apps/senlinai-acro-react/src/features/projects/project-types.ts new file mode 100644 index 0000000..3951b49 --- /dev/null +++ b/apps/senlinai-acro-react/src/features/projects/project-types.ts @@ -0,0 +1,21 @@ +import type { ReactElement } from 'react' + +export type Screen = 'login' | 'workbench' +export type Theme = 'light' | 'dark' +export type ChannelKey = 'overview' | 'inbox' | 'tasks' | 'ai' | 'notes' | 'cron' | 'research' | 'design' + +export type Project = { + id: string + name: string + short: string + badge: number + urgent?: boolean + color: string +} + +export type ProjectChannel = { + key: ChannelKey + label: string + count?: number + icon: ReactElement +} diff --git a/apps/senlinai-acro-react/src/main.tsx b/apps/senlinai-acro-react/src/main.tsx index bef5202..e99750c 100644 --- a/apps/senlinai-acro-react/src/main.tsx +++ b/apps/senlinai-acro-react/src/main.tsx @@ -1,7 +1,7 @@ import { StrictMode } from 'react' import { createRoot } from 'react-dom/client' import './index.css' -import App from './App.tsx' +import App from './app/App.tsx' createRoot(document.getElementById('root')!).render( diff --git a/apps/senlinai-acro-react/src/pages/login.tsx b/apps/senlinai-acro-react/src/pages/login.tsx new file mode 100644 index 0000000..10ec27c --- /dev/null +++ b/apps/senlinai-acro-react/src/pages/login.tsx @@ -0,0 +1,87 @@ +import type { ReactElement } from 'react' +import { useState } from 'react' +import { Button, Card, Form, Input, Space, Typography } from '@arco-design/web-react' +import { IconBook, IconCheckCircleFill, IconLaunch, IconSafe, IconUserGroup } from '@arco-design/web-react/icon' + +const { Title, Text, Paragraph } = Typography + +export function LoginPage({ onLogin }: { onLogin: () => void }) { + const [server, setServer] = useState('https://10.0.0.15:8080') + + return ( +
+ +
+
+ S + SenlinAI +
+ 私有部署 · 安全可控的智能协作平台 + 知识沉淀 · 团队协作 · AI 助理 + + v1.0.0 + 隐私政策 + 服务协议 + 关于 SenlinAI + +
+ +
+ 登录到您的 SenlinAI + 连接私有工作台 +
+ + } /> + + + + + + + +
+ + + 记住服务器地址 + + +
+ +
+ +
+ 连接正常 + 已连接到 {server} +
+ +
+
+
+ +
+ 安全 · 专注 · 高效 + + SenlinAI 是面向知识工作者与内部团队的私有部署工作台,帮助团队在统一空间中收集信息、整理知识、协同决策。 + + } title="私有部署,数据自有" desc="所有数据与模型运行在您的环境中,安全可控。" /> + } title="知识沉淀,结构清晰" desc="从收集到整理,形成可复用的团队知识库。" /> + } title="协同高效,聚焦成果" desc="围绕项目与任务协同,减少沟通成本,专注交付。" /> +
+
+
+ ) +} + +function ValuePoint({ icon, title, desc }: { icon: ReactElement; title: string; desc: string }) { + return ( +
+ {icon} +
+ {title} + {desc} +
+
+ ) +} diff --git a/apps/senlinai-acro-react/src/pages/overview.tsx b/apps/senlinai-acro-react/src/pages/overview.tsx new file mode 100644 index 0000000..b286d03 --- /dev/null +++ b/apps/senlinai-acro-react/src/pages/overview.tsx @@ -0,0 +1,132 @@ +import { useMemo } from 'react' +import { Button, Card, Grid, Space, Tag, Typography } from '@arco-design/web-react' +import { IconCalendar, IconCheckCircleFill, IconClockCircle, IconEmail, IconFile, IconMore, IconRobot } from '@arco-design/web-react/icon' +import { aiSessions, inbox, notes, tasks } from '../features/projects/project-data' + +const { Row, Col } = Grid +const { Title, Text } = Typography + +export function OverviewPage({ onSelectItem }: { onSelectItem: (title: string) => void }) { + const metrics = useMemo(() => [ + { title: 'Inbox 待处理', value: 36, delta: '较昨日 -8', icon: , color: 'arcoblue' }, + { title: '进行中的任务', value: 12, delta: '较昨日 -2', icon: , color: 'green' }, + { title: 'AI 会话活跃', value: 4, delta: '较昨日 +1', icon: , color: 'purple' }, + { title: '笔记资料总数', value: 343, delta: '较昨日 +5', icon: , color: 'cyan' }, + { title: '计划任务', value: 45, delta: '较昨日 +0', icon: , color: 'orange' }, + ], []) + + return ( +
+
+
+ 项目整体快照,帮助你快速了解项目动态 + 概况 +
+ + +
+ + + {metrics.map((metric) => ( + + + + {metric.icon} +
+ {metric.title} + {metric.value} + {metric.delta} +
+
+
+ + ))} +
+ + + + + +
+ ) +} + +function QueueSection({ title, items, onSelectItem }: { title: string; items: typeof inbox; onSelectItem: (title: string) => void }) { + return ( + +
+ {title} + +
+ {items.map((item) => ( + + ))} +
+ ) +} + +function TaskSection({ onSelectItem }: { onSelectItem: (title: string) => void }) { + return ( + +
+ 进行中的任务(12) + +
+ {tasks.map((task) => ( + + ))} +
+ ) +} + +function AISessionSection({ onSelectItem }: { onSelectItem: (title: string) => void }) { + return ( + +
+ AI 会话(4) + +
+ {aiSessions.map((session) => ( + + ))} +
+ ) +} + +function NoteSection({ onSelectItem }: { onSelectItem: (title: string) => void }) { + return ( + +
+ 最近笔记资料(5) + +
+ {notes.map((note) => ( + + ))} +
+ ) +} diff --git a/apps/senlinai-acro-react/src/pages/project.tsx b/apps/senlinai-acro-react/src/pages/project.tsx new file mode 100644 index 0000000..fde7a32 --- /dev/null +++ b/apps/senlinai-acro-react/src/pages/project.tsx @@ -0,0 +1,55 @@ +import { Layout } from '@arco-design/web-react' +import { OverviewPage } from './overview' +import { ProjectInspector } from '../features/projects/project-inspector' +import { ProjectRail } from '../features/projects/project-rail' +import { ProjectSidebar } from '../features/projects/project-sidebar' +import { ProjectStatusbar } from '../features/projects/project-statusbar' +import { ProjectTopbar } from '../features/projects/project-topbar' +import type { ChannelKey, Project, Theme } from '../features/projects/project-types' + +const { Content } = Layout + +export function ProjectPage({ + activeProject, + activeChannel, + selectedItem, + theme, + onSelectProject, + onSelectChannel, + onSelectItem, + onToggleTheme, +}: { + activeProject: Project + activeChannel: ChannelKey + selectedItem: string + theme: Theme + onSelectProject: (project: Project) => void + onSelectChannel: (key: ChannelKey) => void + onSelectItem: (title: string) => void + onToggleTheme: () => void +}) { + return ( + + + + + + + + + + + + + + + + + + ) +}