根据 design 设计稿,对照 apps/web/src 现有代码,完成以下三件事并沉淀为可复盘记录:
已逐一核对以下 4 组页面设计稿(桌面 + 移动):
design/Portal/desktop.htmldesign/Portal/mobile.htmldesign/Todos/desktop.htmldesign/Todos/mobile.htmldesign/AiNews/desktop.htmldesign/AiNews/mobile.htmldesign/Info/desktop.htmldesign/Info/mobile.html已确认 apps/web/src/App.tsx 中页面路由与设计稿主题对应关系:
/ -> 门户页(Portal)/todos -> 待办页(Todos)/ai-news -> 资讯页(AiNews)/web -> 个人信息页(Info/Profile)对应实现文件:
apps/web/src/pages/PortalPage.tsxapps/web/src/pages/TodoPage.tsxapps/web/src/pages/AiNewsPage.tsxapps/web/src/pages/DashboardPage.tsx统一采用响应式分支:
lg:hiddenhidden lg:block并在桌面端通过 DesktopShellLayout.tsx 统一左侧导航与头部骨架,保证 Todos / AiNews / Profile 三页视觉一致性。
在 PortalPage.tsx 已复现设计稿核心结构与视觉:
已对齐设计稿中的关键风格特征:
涉及文件:
apps/web/src/pages/TodoPage.tsxapps/web/src/pages/AiNewsPage.tsxapps/web/src/pages/DashboardPage.tsxapps/web/src/pages/components/DesktopShellLayout.tsxapps/web/src/pages/components/NavIcons.tsx已覆盖设计稿强调的主要交互状态:
在 apps/web/src/lib/api.ts 中通过 @aitodos/api-sdk 创建客户端:
createApiClient(baseUrl)baseUrl 来源:VITE_API_BASE_URLhttp://localhost:3000/api在 apps/web/src/store/news.store.ts 已落地三类能力:
fetchNews:读取资讯列表(api.listAiNews())refreshNewsFromCloud:从云端抓取最新资讯(api.refreshAiNews())addToTodo:资讯一键加入待办(api.addAiNewsToTodo(newsId, userId))并包含基础状态管理:items / loading / error。
在 apps/web/src/pages/AiNewsPage.tsx 已完成接入与交互:
fetchNews()refreshNewsFromCloud()actionMessage)结论:云端资讯获取链路已打通,具备“拉取最新资讯 -> 展示 -> 转待办”的完整闭环。
基于 docs/Todo/day5.md 与 design/Admin/*.html 设计稿,沉淀一份可直接执行的开发步骤,确保:
建议页面文件:
apps/admin/src/pages/AdminDashboardPage.tsxapps/admin/src/pages/AdminUsersPage.tsxapps/admin/src/pages/AdminAiNewsPage.tsxapps/admin/src/pages/AdminSystemPage.tsx建议路由:
/admin/dashboard/admin/users/admin/ai-news/admin/system// apps/admin/src/App.tsx
import { Navigate, Route, Routes } from 'react-router-dom'
import { AdminShellLayout } from './components/admin/AdminShellLayout'
import { AdminDashboardPage } from './pages/AdminDashboardPage'
import { AdminUsersPage } from './pages/AdminUsersPage'
import { AdminAiNewsPage } from './pages/AdminAiNewsPage'
import { AdminSystemPage } from './pages/AdminSystemPage'
export default function App() {
return (
<Routes>
<Route path="/admin" element={<AdminShellLayout />}>
<Route index element={<Navigate to="dashboard" replace />} />
<Route path="dashboard" element={<AdminDashboardPage />} />
<Route path="users" element={<AdminUsersPage />} />
<Route path="ai-news" element={<AdminAiNewsPage />} />
<Route path="system" element={<AdminSystemPage />} />
</Route>
</Routes>
)
}关键说明:
index -> dashboard 保证进入后台就有默认页面。lg 及以上):左侧 SideNav + 顶部 TopBarlg 以下):简化 Header + 底部 BottomTabBar// apps/admin/src/components/admin/AdminShellLayout.tsx
import { NavLink, Outlet } from 'react-router-dom'
const tabs = [
{ to: '/admin/dashboard', label: '仪表盘' },
{ to: '/admin/users', label: '用户' },
{ to: '/admin/ai-news', label: '资讯' },
{ to: '/admin/system', label: '系统' },
]
export function AdminShellLayout() {
return (
<div className="bg-slate-50 min-h-screen text-slate-800">
<header className="lg:hidden fixed top-0 inset-x-0 h-16 bg-white/90 backdrop-blur border-b border-slate-200 z-50" />
<div className="flex pt-16 lg:pt-0 pb-24 lg:pb-0 min-h-screen">
<aside className="hidden lg:flex w-64 shrink-0 border-r border-slate-200 bg-white fixed inset-y-0" />
<div className="flex-1 lg:pl-64 flex flex-col">
<header className="hidden lg:flex h-16 border-b border-slate-200 bg-white/80 backdrop-blur items-center px-8">
<p className="text-sm text-slate-400 italic">管理员仪表盘 - 数据监控中</p>
</header>
<main className="flex-1 p-4 lg:p-8">
<Outlet />
</main>
</div>
</div>
<nav className="lg:hidden fixed bottom-0 inset-x-0 h-[68px] bg-white/95 border-t border-slate-200 z-50 flex items-center justify-around">
{tabs.map((tab) => (
<NavLink key={tab.to} to={tab.to} className="text-xs">
{tab.label}
</NavLink>
))}
</nav>
</div>
)
}关键说明:
pb-24 防止移动端内容被底部导航遮挡。NavLink 的 isActive 控制品牌色。// tailwind.config.ts
export default {
theme: {
extend: {
colors: {
brand: {
50: '#f0fdfa',
100: '#ccfbf1',
200: '#99f6e4',
500: '#14b8a6',
600: '#0d9488',
},
},
fontFamily: {
sans: ['Inter', 'sans-serif'],
},
},
},
}// apps/admin/src/lib/api.ts
import { createApiClient } from '@aitodos/api-sdk'
export const api = createApiClient(
import.meta.env.VITE_API_BASE_URL || 'http://localhost:3000/api'
)关键说明:
fetch,统一走 SDK,便于后续鉴权、拦截、错误处理。statsApi / userAdminApi / aiNewsApi / systemApi。type Overview = {
totalUsers: number
addedUserCount: number
totalAiNewsCount: number
newsToTodoRate: number
}// apps/admin/src/store/adminDashboard.store.ts
import { create } from 'zustand'
import { api } from '../lib/api'
type State = {
overview: Overview | null
loading: boolean
error: string | null
fetchOverview: () => Promise<void>
}
export const useAdminDashboardStore = create<State>((set) => ({
overview: null,
loading: false,
error: null,
fetchOverview: async () => {
set({ loading: true, error: null })
try {
const data = await api.statsApi.getOverview()
set({ overview: data, loading: false })
} catch {
set({ error: '加载概览数据失败', loading: false })
}
},
}))关键说明:
loading/empty/error 三态。GET /admin/usersPATCH /admin/users/:id/rolePATCH /admin/users/:id/status样板交互代码(伪代码):
await updateUserRole(userId, role)
toast.success('角色更新成功')
await fetchUsers()GET /ai-newsPOST /ai-news/refresh样板代码(刷新按钮):
<button disabled={refreshing} onClick={refreshNews}>
{refreshing ? '同步中...' : '立即同步抓取'}
</button>GET /admin/system/profileGET /admin/system/logsPATCH /admin/system/settingsPOST /admin/system/cache/clear页面包含三块:
关键说明:
systemApi)。Day5 的核心不是“把页面画出来”,而是把 Admin 的实现路径标准化:
按本文步骤执行,可直接进入 apps/admin 的 Step2 开发阶段。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。