首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >Day3:AI待办Web端完整实现

Day3:AI待办Web端完整实现

原创
作者头像
用户12455232
发布2026-05-03 22:02:23
发布2026-05-03 22:02:23
110
举报

Day3

Step1:初始化环境与依赖(已完成)

代码/命令

  • 安装依赖:pnpm i
  • 安装前端依赖:pnpm --filter @aitodos/web add react-router-dom zustand
  • 安装样式依赖:pnpm --filter @aitodos/web add -D tailwindcss postcss autoprefixer

配置说明

  • apps/web/package.json 已包含:react-router-domzustandtailwindcss@4
  • 当前样式方案使用 Tailwind v4 + Vite 插件(非 v3 的 tailwindcss init -p 流程)

关键代码(示例)

代码语言:bash
复制
pnpm --filter @aitodos/web add react-router-dom zustand
pnpm --filter @aitodos/web add -D tailwindcss postcss autoprefixer

Step2:接入 API-SDK(已完成)

代码

  • packages/api-sdk/src/index.ts
  • apps/web/src/lib/api.ts

代码说明

  • createApiClient(baseUrl) 统一封装 request(),处理 JSON、状态码、错误抛出。
  • 已接入接口:
    • register / login / me
    • getProfile
    • listTodos / createTodo
    • listAiNews / addAiNewsToTodo

配置说明

  • apps/web/.env.localVITE_API_BASE_URL=http://localhost:3000/api
  • VITE_ 前缀表示该变量可在浏览器端访问。

关键代码(示例)

代码语言:ts
复制
// apps/web/src/lib/api.ts
import { createApiClient } from "@aitodos/api-sdk";

const baseUrl = import.meta.env.VITE_API_BASE_URL ?? "http://localhost:3000/api";

export const api = createApiClient(baseUrl);

Step3:Zustand 业务状态(已完成)

代码

  • apps/web/src/store/auth.store.ts
  • apps/web/src/store/todo.store.ts
  • apps/web/src/store/news.store.ts

代码说明

  • auth.store:登录、注册、恢复登录态、拉取 me/profile
  • todo.store:待办拉取、新增。
  • news.store:资讯拉取、一键加入待办。
  • 统一保留 loadingerror 字段,页面直接订阅并展示状态。

配置说明

  • 登录态以 localStorage(aitodos_token) 保存。
  • 当前后端鉴权依赖 x-user-id,前端通过 dev-token-<userId> 解析用户 ID。

关键代码(示例)

代码语言:ts
复制
// apps/web/src/store/auth.store.ts
const TOKEN_KEY = "aitodos_token";

export const extractUserIdFromToken = (token: string | null): string | null => {
  if (!token) return null;
  const prefix = "dev-token-";
  if (!token.startsWith(prefix)) return null;
  return token.slice(prefix.length) || null;
};

restoreSession: () => {
  const token = localStorage.getItem(TOKEN_KEY);
  set({ token, hydrated: true });
}

Step4:注册/登录页(已完成)

代码

  • apps/web/src/pages/LoginPage.tsx
  • apps/web/src/pages/RegisterPage.tsx

代码说明

  • 注册后跳转登录页;登录成功跳转工作台。
  • 表单提交已做类型安全处理,不再使用 deprecated 的 FormEvent 别名。
  • 页面已展示错误反馈信息(如 Failed to fetch / 接口异常)。
  • 已优化登录跳转逻辑:支持登录后回跳来源页面(如 /todos / /ai-news)。
  • 已登录用户访问 /login/register 时自动跳转到 /web

配置说明

  • 注册与登录都走 api-sdk,避免页面直接写 fetch.

关键代码(示例)

代码语言:tsx
复制
// apps/web/src/pages/LoginPage.tsx
const redirectTo = (location.state as { from?: string } | null)?.from ?? "/web";

const onSubmit = async (e: FormSubmitEvent) => {
  e.preventDefault();
  await login({ email, password });
  navigate(redirectTo, { replace: true });
};

Step5:基础登录态与路由守卫(已完成)

代码

  • apps/web/src/App.tsx
  • apps/web/src/main.tsx

代码说明

  • main.tsx 使用 BrowserRouter 包裹 <App />,启用前端路由。
  • App.tsx 使用 ProtectedRoute:无 token 跳登录,有 token 访问业务页。
  • 应用启动时执行 restoreSession(),并在有 token 时执行 fetchMe()
  • 路由结构调整为:/ 门户页(公开) -> /web 工作台(受保护) -> /todos / /ai-news(受保护)。

配置说明

  • 这是 SPA 路由守卫方案;后续迁移 Next.js SSR 时再升级为服务端鉴权策略.

关键代码(示例)

代码语言:tsx
复制
// apps/web/src/main.tsx
<React.StrictMode>
  <BrowserRouter>
    <App />
  </BrowserRouter>
</React.StrictMode>

// apps/web/src/App.tsx
if (!hydrated) return <p className="p-6">恢复登录态中...</p>;
if (!token) return <Navigate to="/login" replace state={{ from: location.pathname }} />;

Step6:首页工作台(已完成)

代码

  • apps/web/src/pages/DashboardPage.tsx
  • apps/web/src/pages/PortalPage.tsx

代码说明

  • 展示个人信息:邮箱、昵称、角色。
  • 展示业务入口:/todos/ai-news
  • 门户页作为软件介绍首页,提供“进入web端”按钮。
  • 工作台模块化展示为:个人信息、TodoList、AI资讯。
  • 已补齐三态反馈:
    • loading:加载个人信息中
    • error:加载失败提示
    • empty:无 user / 无 profile 提示

配置说明

  • 工作台数据来源于 auth.storeuser/profile,非页面内直接请求.

关键代码(示例)

代码语言:tsx
复制
// apps/web/src/pages/DashboardPage.tsx
{loading ? <p className="mb-3 text-sm text-slate-600">加载个人信息中...</p> : null}
{error ? <p className="mb-3 text-sm text-red-600">加载失败:{error}</p> : null}

{!loading && !error && !user ? (
  <p className="mb-3 rounded bg-amber-50 px-3 py-2 text-sm text-amber-700">暂无用户信息,请重新登录后再试。</p>
) : null}

Step7:待办页(已完成)

代码

  • apps/web/src/pages/TodoPage.tsx
  • apps/web/src/store/todo.store.ts
  • apps/web/src/pages/components/TodoCreateForm.tsx
  • apps/web/src/pages/components/TodoQueueSection.tsx
  • apps/web/src/pages/components/DoneQueueSection.tsx

代码说明

  • 已实现完整 CRUD:新增、编辑、完成/改回未完成、删除。
  • 已实现未完成队列与已完成队列分区展示。
  • 已有基础三态展示:loading / empty / error
  • 页面结构已完成组件拆分:创建表单、未完成队列、已完成队列。

配置说明

  • 待办列表数据来源于 todo.storeitems,非页面内直接请求.

关键代码(示例)

代码语言:tsx
复制
// apps/web/src/pages/TodoPage.tsx
<TodoCreateForm
  title={title}
  description={description}
  onTitleChange={setTitle}
  onDescriptionChange={setDescription}
  onSubmit={onCreate}
/>

<TodoQueueSection ... />
<DoneQueueSection ... />

Step8:AI 资讯页(已完成)

代码

  • apps/web/src/pages/AiNewsPage.tsx
  • apps/web/src/store/news.store.ts

代码说明

  • 拉取并展示 AI 资讯列表(后端当前返回最新 5 条)。
  • 每条资讯提供“一键加入待办”按钮。
  • 点击后调用 addToTodo,并在按钮上展示“加入中...”防重复点击。
  • 失败时给出错误消息,成功后给出“已加入待办,正在跳转...”提示并跳转待办页。

配置说明

  • 资讯读取走后端 ai-news 缓存逻辑(Redis 日缓存),前端无需处理缓存细节.

关键代码(示例)

代码语言:tsx
复制
// apps/web/src/pages/AiNewsPage.tsx
const onAdd = async (newsId: string) => {
  if (!userId) return;
  setSubmittingId(newsId);
  await addToTodo(newsId, userId);
  navigate("/todos", { state: { message: "已从 AI 资讯加入待办" } });
};

Step9:一键加入待办全链路(已完成)

代码

  • apps/web/src/pages/AiNewsPage.tsx
  • apps/web/src/store/news.store.ts
  • apps/web/src/store/todo.store.ts
  • apps/web/src/pages/TodoPage.tsx

代码说明

  • 已实现一键加入待办功能,并跳转到待办页。
  • 已实现跨页成功提示:AiNewsPage 通过路由 state 传递消息给 TodoPage
  • TodoPage 显示消息后自动 2 秒消失,避免常驻。

配置说明

  • 一键加入待办功能依赖 news.storeaddToTodotodo.storecreateTodo.

Step10:联调验收(已完成)

验收清单

  • 注册登录完整可用
  • 工作台稳定显示个人信息
  • AI 资讯可见并支持一键加入待办
  • 待办页可见新增项
  • 待办支持编辑 / 完成 / 删除

关键配置补充(当前已生效)

CORS(后端)

  • 文件:apps/server/src/main.ts
  • 说明:已加 app.enableCors(...),放行 http://localhost:5173,解决前后端联调跨域.
代码语言:ts
复制
app.enableCors({
  origin: ["http://localhost:5173"],
  methods: ["GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"],
  allowedHeaders: ["Content-Type", "Authorization", "x-user-id"],
  credentials: false
});

类型检查

  • 命令:pnpm --filter @aitodos/web type-check
  • 当前状态:已通过(tsc --noEmit 无报错).

当前结论

  • Day3 主链路已打通并完成优化:门户 -> 登录 -> 工作台 -> AI 资讯 -> 加入待办 -> 待办 CRUD。
  • 登录体验已优化:支持来源页回跳、已登录自动跳转、门户按登录态展示入口。
  • Todo 页面已完成组件化拆分,便于后续迁移 Next.js / SSR 时复用.

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Day3
    • Step1:初始化环境与依赖(已完成)
      • 代码/命令
      • 配置说明
      • 关键代码(示例)
    • Step2:接入 API-SDK(已完成)
      • 代码
      • 代码说明
      • 配置说明
      • 关键代码(示例)
    • Step3:Zustand 业务状态(已完成)
      • 代码
      • 代码说明
      • 配置说明
      • 关键代码(示例)
    • Step4:注册/登录页(已完成)
      • 代码
      • 代码说明
      • 配置说明
      • 关键代码(示例)
    • Step5:基础登录态与路由守卫(已完成)
      • 代码
      • 代码说明
      • 配置说明
      • 关键代码(示例)
    • Step6:首页工作台(已完成)
      • 代码
      • 代码说明
      • 配置说明
      • 关键代码(示例)
    • Step7:待办页(已完成)
      • 代码
      • 代码说明
      • 配置说明
      • 关键代码(示例)
    • Step8:AI 资讯页(已完成)
      • 代码
      • 代码说明
      • 配置说明
      • 关键代码(示例)
    • Step9:一键加入待办全链路(已完成)
      • 代码
      • 代码说明
      • 配置说明
    • Step10:联调验收(已完成)
      • 验收清单
    • 关键配置补充(当前已生效)
      • CORS(后端)
      • 类型检查
    • 当前结论
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档